How to make a Stable Diffusion discord bot
Learn to craft a Discord bot using the Stable Diffusion API from Mystic AI. Utilize the discord interactions library in Python for dynamic image generation.
Digest time
5 min readPublished
10/11/2022Tags
TutorialAuthor
Paul Hetherington
This post demonstrates how to create a discord bot to generate images with Stable Diffusion. We will be using the Stable Diffusion API provided by pipeline.ai to handle the ML compute. The bot will be created in python using the discord interactions library and can run on your laptop.
Figure 1. Demo of the bot using the /paint
command.
Initial setup
Discord developer setup
Before we can hookup to the Discord API you will first have to create a Discord developer account. Below is a basic set of steps to do this (or you can view a more in-depth guide here).
- Sign in to the discord developer portal (you can use your regular discord account)
- Click the
New Application
on the top right - Once the Application has been created click on
Bot
on the left menu and clickAdd Bot
- To add this bot to your server navigate to
OAuth2/URL Generator
on the left menu and selectbot
on the first scope andUse Slash Commands
under theBot Permissions
. You'll see aGenerated URL
field populated at the bottom of the page, copy and click on it to add it to your server! - Finally, you need to collect your discord bot token under the
Token
tab on your under theBot
tab on the left menu.
Dependencies
There are two main libraries for working with Discord in python:
We will be using interactions.py
, but they are relatively interchangable. The full list of dependencies can be found here requirements.txt. This post uses python 3.9 and should work for later python versions.
You can install the dependencies in your python environment using
pip install -r requirements.txt
# OR
python -m pip install -r requirements.txt
Making the bot
Generating an image with Stable Diffusion
The core code to generate the image with the pipeline.ai library is straight forward as it has native asyncio support for use in production APIs:
pipeline_api = PipelineCloud(token="...")
async def handle_generation(image_prompt: str) -> io.BytesIO:
response = pipeline_api.run_pipeline(
"pipeline_67d9d8ec36d54c148c70df1f404b0369",
[[image_prompt], {"width": 512, "height": 512, "num_inference_steps": 50}],
)
image_b64 = response.result_preview[0][0][0]
image_decoded = base64.decodebytes(image_b64.encode())
buffer = io.BytesIO(image_decoded)
new_uid = str(uuid.uuid4())
buffer.name = new_uid
return buffer
Bot client
To add a command to your bot with the interactions.py
library you create an async function with the @bot.command(...)
decorator:
# For our '/paint' command we only want to take in a single text prompt,
# this is included in the 'options' field below and the name of the option
# is what's used as a key word argument to our function
@bot.command(
name="paint",
description="Paint an image that has never existed...",
options=[
interactions.Option(
name="prompt",
description="Image generation prompt",
type=interactions.OptionType.STRING,
required=True,
),
],
)
async def paint(ctx: interactions.CommandContext, prompt: str) -> None:
# You have to send back a response quickly otherwise
# Discord thinks that the bot has died.
sent_response = await ctx.send("Generating image...")
try:
image_buffer = await handle_generation(prompt)
# Edit the original message sent to now include the image and the prompt
await sent_response.edit(
files=[
interactions.api.models.misc.File(
filename=prompt + ".jpeg", fp=image_buffer
)
],
content=prompt
# You can add another argument 'ephemeral=True' to only show the
# result to the user that sent the request.
)
except:
# If the image generation (or anything else) fails
# for any reason it's best to let the user know
await sent_response.edit(
content="Generation failed, please try again!",
)
# With asyncio you have to call the 'flush=True' on print
print(traceback.format_exc(), flush=True)
Finally we need to add a few things to run the bot and complete our script:
import os
import interactions
import traceback
import base64
import io
import uuid
from pipeline.api.asyncio import PipelineCloud
# The token here is the one we collected earlier from the discord bot
discord_token = os.getenv("DISCORD_TOKEN")
pipeline_token = os.getenv("PIPELINE_API_TOKEN")
bot = interactions.Client(token=discord_token)
pipeline_api = PipelineCloud(token=pipeline_token)
# As defined earlier
async def handle_generation(...) -> None:
...
# As defined earlier
@bot.command(...)
async def paint(...) -> None:
...
bot.start()
This code was saved on my system as sd_discord_bot.py
, and the environment variables can be passed in as follows:
env DISCORD_TOKEN=... PIPELINE_API_TOKEN=... python bot.py
You can now navigate to your discord server and run /paint
!
Docker & docker compose
The bot will run for as long as you have your terminal open, but to run this system continually Docker is a great solution. Docker has a quick start guide here but for this post you will only need it installed and not much further understanding.
br> This section uses the following project directory layout (therequirements.txt
is the one described above):project_dir/
./bot.py
./requirements.txt
./Dockerfile
./docker-compose.yml
./secrets.env
bot.py
copied into it.
Here is the Dockerfile
used for the project:FROM python:3.9-slim
WORKDIR /code
COPY ./requirements.txt /code/
ENV PYTHONDONTWRITEBYTECODE=1
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./bot.py /code/
CMD ["python", "bot.py"]
sudo docker build . -t stable-diffusion-discord-bot:main
sudo docker run --env DISCORD_TOKEN=... --env PIPELINE_API_TOKEN=... stable-diffusion-discord-bot:main
docker-compose.yml
file:version: "3.9"
services:
stable-diffusion-discord-bot:
container_name: stable-diffusion-discord-bot
image:
build:
context: .
dockerfile: ./Dockerfile
env_file:
- secrets.env
DISCORD_TOKEN
& PIPELINE_API_TOKEN
variables. You can run this simply with:sudo docker-compose run --build -d
------------------------------------------------------
If you run into issues, the Pipeline team are always willing to help in any way. Contact us here or join us on Discord!
ABOUT Mystic
Mystic makes it easy to work with ML models and to deploy AI at scale. The self-serve platform provides a fast pay-as-you-go API to run pretrained or proprietory models in production. If you are looking to deploy a large product and would like to sign up as an Enterprise customer please get in touch. In the meantime follow us on Twitter and Linkedin.