Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy ChatInterface as a discord bot #4960

Merged
merged 46 commits into from
Jul 26, 2023

Conversation

freddyaboulton
Copy link
Collaborator

@freddyaboulton freddyaboulton commented Jul 18, 2023

Description

Adds a deploy_discord method to gradio_client.Client for deploying a ChatInterface demo as a discord bot. This isn't entirely a "one-click" deploy since the developer has to create the discord bot application themselves but the information on how to do so is presented to the user. Continue reading for exact details.

The deploy_discord method has the following signature. The long term goal is to support a wider variety of gradio apps but right now only ChatInterface is supported.

    def deploy_discord(
        self,
        discord_bot_token: str | None = None,
        api_names: list[str] | None = None,
        command_names: list[str] | None = None,
        to_id: str | None = None,
        hf_token: str | None = None,
        private: bool = True,
        persist_state: bool = False,
    ):

What happens under the hood

There's a "template" file for the discord bot under gradio_client/templates/ (the idea is to add templates for other types of gradio apps later). The deploy_discord method will fill in the template given the parameter values and push it up to a space.

Explaining the Parameters

  • discord_bot_token: This is the "password" needed to be able to launch the bot. Users can get a token by creating a bot app on the discord website. If run the method without specifying a token, the space will explain how to get one. See here: https://huggingface.co/spaces/freddyaboulton/test-discord-bot-v1.
    no-discord-token
  • If you specify discord_bot_token, the display will automatically display the url you need to visit in order to add the bot to your server. See here: https://huggingface.co/spaces/freddyaboulton/test-discord-bot-v2
    with-discord-toke
  • api_names: In the future this will be the api_names to turn into bot commands. However, this is hardcoded to ['chat']
  • command_names: What the bot command name should be for each api_name. For example, you can set this to bot and then the bot will be triggered by typing !bot ...
  • to_id: The name of the space to create
  • hf_token: self explanatory
  • private: Whether the space is private. Whether the bot is private or not is configured via discord ui.
  • persist_state: Set up persistent storage on the space hosting the bot so that chat history is preserved throughout restarts.

Sample Usage

discord-command-line

Then the bot will be triggered with !chat command
sample_question

TODO

  • Handle Queue Full messages
  • If the upstream space is private, HF_TOKEN env variable should be set
  • CLI command
  • Enable persistent storage
  • Add a discord bot tag to the spaces
  • Create a gallery space of discord bots 😏

🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is an existing issue for this change. If not, please create an issue before you create this PR, unless the fix is very small.

Not adhering to this guideline will result in the PR being closed.

Tests & Changelog

  1. PRs will only be merged if tests pass on CI. To run the tests locally, please set up your Gradio environment locally and run the tests: bash scripts/run_all_tests.sh

  2. You may need to run the linters: bash scripts/format_backend.sh and bash scripts/format_frontend.sh

  3. Unless the pull request is labeled with the "no-changelog-update" label by a maintainer of the repo, all pull requests must update the changelog located in CHANGELOG.md:

Please add a brief summary of the change to the Upcoming Release section of the CHANGELOG.md file and include
a link to the PR (formatted in markdown) and a link to your github profile (if you like). For example, "* Added a cool new feature by [@myusername](link-to-your-github-profile) in [PR 11111](https://github.com/gradio-app/gradio/pull/11111)".

@vercel
Copy link

vercel bot commented Jul 18, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
gradio ✅ Ready (Inspect) Visit Preview Jul 26, 2023 7:55pm

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Jul 18, 2023

All the demos for this PR have been deployed at https://huggingface.co/spaces/gradio-pr-deploys/pr-4960-all-demos


You can install the changes in this PR by running:

pip install https://gradio-builds.s3.amazonaws.com/2b64701f080693a876afd9e00f4a48f7c1bfc088/gradio-3.38.0-py3-none-any.whl

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Jul 19, 2023

Chromatic build pending ⌛

def deploy_discord(
self,
discord_bot_token: str | None = None,
api_names: list[str] | None = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be more foolproof for developers to pass in a dictionary of {"api_name": "command_name"} rather than have to align two separate lists

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be that api_names could be a list[str | tuple[str, str]]. If a tuple is provided, than the command name is the second entry. Would give flexibility to override particular api names but not necessarily all of them

discord_bot_token: This is the "password" needed to be able to launch the bot. Users can get a token by creating a bot app on the discord website. If run the method without specifying a token, the space will explain how to get one. See here: https://huggingface.co/spaces/freddyaboulton/test-discord-bot-v1.
api_names: The api_names of the app to turn into bot commands. This parameter currently has no effect as ChatInterface only has one api_name ('/chat').
command_names: The names of the command the bot will have. Must be the same length as api_names. For gr.ChatInterface, this list must contain one element. For example, if the value is ['bot'], the bot command can be triggered via !bot.
to_id: The name of the space hosting the discord bot. If None, the name will be gradio-discord-bot-{random-substring}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: maybe it should reflect the name of the original Space as well? gradio-discord-bot-{space-id}-{random-substring}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this - the name of the bot space will use the upstream space name and add gradio-discord-bot if to_id is not passed in.

@freddyaboulton
Copy link
Collaborator Author

Thanks for the feedback @aliabid94 ! I added a step-by-step section to the guide that covers how to go from a local app.py file to a working discord bot. It's two separate steps now but I like that we don't couple deployment and the discord bot creation. It allows someone to take any existing app as long as it's over the internet and create a discord bot from it.


@bot.command()
@commands.is_owner()
async def sync(ctx) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly a user experience / QOL suggestion: As brought up in #gradio-technical, you could remove needing to !sync / !chat with a structure like this:

class MyClient(discord.Client):
    """This structure allows slash commands to work instantly (instead of needing to sync global commands for up to an hour)"""

    def __init__(self, *, intents: discord.Intents):
        super().__init__(intents=intents)
        self.tree = app_commands.CommandTree(self)

    async def setup_hook(self):
        # This copies the global commands over to our guild
        self.tree.copy_global_to(guild=MY_GUILD)
        await self.tree.sync(guild=MY_GUILD)  

I'm using it here (test ground for HuggingBots): https://huggingface.co/spaces/lunarflu/modbot/blob/main/app.py
And you can see the initial example here: https://github.com/Rapptz/discord.py/blob/master/examples/app_commands/basic.py

Then basically you could fit more cool commands into a smaller space + reduce number of steps needed for each command or test 💪
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed with @lunarflu offline. Will experiment with this but we don't know the guild id ahead of time so it will be hard to follow his code example.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ended up following your suggestion @lunarflu!


### Step 6: Use your bot!
By default the bot can be called by starting a message with `!chat`, e.g. `!chat <your prompt here>`.
<img src="https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/guide/with_!chat_2.png" height=400 width=800>
Copy link
Collaborator

@aliabid94 aliabid94 Jul 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are these gradio-builds.s3 links? can we put these images in the repo and link them?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's to not bloat the size of the repo with images

Copy link
Collaborator

@aliabid94 aliabid94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guide looks great now!

It's two separate steps now but I like that we don't couple deployment and the discord bot creation

Makes sense. Thanks for the PR, I think this will be 🔥

@aliabid94
Copy link
Collaborator

Nit: do you want to mention in the guide that if either space goes to sleep, the bot will stop working? the auto sleep time is 48 hours for a free space

@freddyaboulton freddyaboulton added t: feat A change that implements a feature t: highlight A change that we wish to highlight and removed t: feat A change that implements a feature no-changelog-update labels Jul 26, 2023
@freddyaboulton
Copy link
Collaborator Author

Thanks everyone for the really helpful comments!!

@freddyaboulton freddyaboulton merged commit 46e4ef6 into main Jul 26, 2023
@freddyaboulton freddyaboulton deleted the deploy-chatinterface-to-discord branch July 26, 2023 20:09
@pngwn pngwn mentioned this pull request Jul 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
t: highlight A change that we wish to highlight
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants