Building an image generation bot with NOS + Discord¶
-
Registering a discord bot to create our API key
This can be done through the discord developer guide. You will need a discord account as well as a server you wish to add the bot to. When we're finished,
nos-botwill accept image generation requests from users on this server and post the resulting images to the main channel. Once you have your bot API key, add it to your local environment like so: -
Setting up a NOS client to generate images
NOS comes with an endpoint for Stable Diffusion V2 from HuggingFace, so all we need to do is init a server on our machine and verify we can connect to it from the client:
import nos from nos.client import Client, TaskType import os # Init nos server nos.init(runtime='gpu') client = Client() client.WaitForServer() assert client.IsHealthy()See
examples/notebook/inference-client-example.ipynbfor a better overview. Nos will initialize a GPU-ready container on our machine and return to the client that it's ready to go. -
The Discord interface
Next we need a way to handle message requests on our server. Discord.py makes callbacks pretty easy:
intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix='$', intents=intents) @bot.command() async def generate(ctx, *, prompt): response = client.Run( "stabilityai/stable-diffusion-2", inputs={ "prompts": [prompt], "width": 512, "height": 512, "num_images": 1 } ) image, = response["images"] tmp_file_path = "image.png" image.save(tmp_file_path) with open(tmp_file_path, "rb") as img_file: await ctx.send(file=discord.File(img_file)) os.remove(tmp_file_path)We need the
message_contentintent so we can access the contents of user messages to retrieve image prompts. We'll parse generation requests as$generate image prompt here.... Any messages beginning with$generatewill be sent to Nos for image generation. The rest of our message handler is pretty straightforward: we use the client to generate a set of images, then we retrieve the first result from the list, save it locally, and callctx.sendto upload the image with the discordFileinterface. -
Time to run the server
The full server is only ~40 LOC:
#!/usr/bin/env python import io import os import discord from discord.ext import commands import nos from nos.client import Client # Init nos server nos.init(runtime='gpu') client = Client() client.WaitForServer() assert client.IsHealthy() intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix='$', intents=intents) @bot.command() async def generate(ctx, *, prompt): response = client.Run( "stabilityai/stable-diffusion-2", inputs={ "prompts": [prompt], "width": 512, "height": 512, "num_images": 1 } ) image, = response["images"] image_bytes = io.BytesIO() img.save(image_bytes, format="PNG") image_bytes.seek(0) await ctx.send(file=discord.File(image_bytes, filename=f"{ctx.message.id}.png")) bot_token = os.environ.get("BOT_TOKEN") if bot_token is None: raise Exception("BOT_TOKEN environment variable not set") bot.run(bot_token)We should be all set, kick off the bot with
python examples/discord/app/bot.py