Building a Discord bot with OpenAI and python

March 2, 2024


What's the bot do?

  • You can tag the bot, ask it a question and get a response
@bot.event
async def on_message(message):
await bot.process_commands(message)
print (f'Getting message from {message.author.name}')
print (f'Getting message {message.content}')
print (f'Bot name {bot.user}')
# Only respond to messages from other users, not from the bot itself
if message.author == bot.user:
return

# Check if the bot is mentioned in the message
if bot.user in message.mentions:

async with message.channel.typing():
await asyncio.sleep(5)

dow = datetime.now().weekday()

dowContext = ""

if (dow == 0):
dowContext = "The day is Monday, which is a somber day because everyone is going back to work."

if (dow == 1):
dowContext = "The day is Tuesday, which is also known as 'Taco Tuesday'. References to tacos are encouraged."

if (dow == 2):
dowContext = "The day is Wednesday, HUMP day. Jokes about camels and humps are encouraged."

if (dow == 3):
dowContext = "The day is Thursday, we're almost to Friday."

if (dow == 4):
dowContext = "The day is Friday, which means it is Rebecca Black day. You are very excited about this event and you want to make sure everyone knows about it. References to Rebecca Black and her song 'Friday' are encouraged."

if (dow == 5):
dowContext = "The day is Saturday, also known as Caturday, which is a day to relax, have fun, and post cat memes."

if (dow == 6):
dowContext = "The day is Sunday, sometimes we play video games today, sometimes we rest."

# Use the OpenAI API to generate a response to the message
response = openaiclient.chat.completions.create(
model = "gpt-3.5-turbo-1106",
messages = [
{"role": "system", "content": "You are a helpful bot with a touch of sarcasm. Your primary goal is to assist users with their questions and problems, but you like to inject humor into your responses from time to time."},
{"role": "system", "content": dowContext},
{"role": "user", "content": "Can you help me find a good restaurant nearby?"},
{"role": "assistant", "content": "Of course! I'll try my best to find a restaurant that won't give you food poisoning. Give me a second..."},
{"role": "user", "content": "I can't believe I lost my keys again."},
{"role": "assistant", "content": "Oh no, not the keys again! Don't worry; they're probably just on a secret vacation."},
{"role": "user", "content": "How can I improve my productivity at work?"},
{"role": "assistant", "content": "Ah, the age-old question of productivity! Well, have you tried not checking your email every 5 minutes? Just a thought."},
{"role": "user", "content": "I'm feeling a bit stressed lately."},
{"role": "assistant", "content": "Stress? Psh, that's just your body's way of telling you to take a vacation on a deserted island."},
{"role": "user", "content": message.content},
],
temperature=.9
)

print (f'Response: {response.choices[0].message.content}')


# Send the response as a message
await message.channel.send(response.choices[0].message.content)

Above is the main rub of the bot, I'll walk through it section by section and talk about what is happening.

@bot.event
async def on_message(message):
await bot.process_commands(message)
print (f'Getting message from {message.author.name}')
print (f'Getting message {message.content}')
print (f'Bot name {bot.user}')
# Only respond to messages from other users, not from the bot itself
if message.author == bot.user:
return

Here we are using discord.py's on_message event to intercept messages in the discord server. Then we'll call process_commands on it to see if there are any commands defined in the file to call (commands usually start with a bang - ! - and will call a function of the same name in your python file).

Then I'm printing out a few lines just for my own debugging purposes, these are not really needed. Finally, we're ensuring the message is from someone other than the bot itself so it doesn't somehow fall into an infinite loop of talking to itself.

if bot.user in message.mentions:

Next, we're checking if the bot was actually mentioned in the message, if it was we're going to execute some code to respond to the message, which includes our call to OpenAI's API.

    async with message.channel.typing():
await asyncio.sleep(5)

One thing I like to do that adds a little touch of realism to feel like you're actually conversing with the bot, is make the bot appear as if it's typing for 5 seconds.

  dow = datetime.now().weekday()

dowContext = ""

if (dow == 0):
dowContext = "The day is Monday, which is a somber day because everyone is going back to work."

if (dow == 1):
dowContext = "The day is Tuesday, which is also known as 'Taco Tuesday'. References to tacos are encouraged."

if (dow == 2):
dowContext = "The day is Wednesday, HUMP day. Jokes about camels and humps are encouraged."

if (dow == 3):
dowContext = "The day is Thursday, we're almost to Friday."

if (dow == 4):
dowContext = "The day is Friday, which means it is Rebecca Black day. You are very excited about this event and you want to make sure everyone knows about it. References to Rebecca Black and her song 'Friday' are encouraged."

if (dow == 5):
dowContext = "The day is Saturday, also known as Caturday, which is a day to relax, have fun, and post cat memes."

if (dow == 6):
dowContext = "The day is Sunday, sometimes we play video games today, sometimes we rest."

Next, I'd like the bot to have some kind of context about what day it is. Above are some generic examples, but you can give the box some context about the current day of the week by doing something like this. I'm going to check what day of the week it is and store some context about it in a variable that we'll then pass into the call to OpenAI's API.

 # Use the OpenAI API to generate a response to the message
response = openaiclient.chat.completions.create(
model = "gpt-3.5-turbo-1106",
messages = [
{"role": "system", "content": "You are a helpful bot with a touch of sarcasm. Your primary goal is to assist users with their questions and problems, but you like to inject humor into your responses from time to time."},
{"role": "system", "content": dowContext},
{"role": "user", "content": "Can you help me find a good restaurant nearby?"},
{"role": "assistant", "content": "Of course! I'll try my best to find a restaurant that won't give you food poisoning. Give me a second..."},
{"role": "user", "content": "I can't believe I lost my keys again."},
{"role": "assistant", "content": "Oh no, not the keys again! Don't worry; they're probably just on a secret vacation."},
{"role": "user", "content": "How can I improve my productivity at work?"},
{"role": "assistant", "content": "Ah, the age-old question of productivity! Well, have you tried not checking your email every 5 minutes? Just a thought."},
{"role": "user", "content": "I'm feeling a bit stressed lately."},
{"role": "assistant", "content": "Stress? Psh, that's just your body's way of telling you to take a vacation on a deserted island."},
{"role": "user", "content": message.content},
],
temperature=.9
)

print (f'Response: {response.choices[0].message.content}')


# Send the response as a message
await message.channel.send(response.choices[0].message.content)

Here is the real meat of the bot, which includes the call to OpenAI's API. We're using their chat completion API with the gpt-3.5-turbo-1106 model. The most important part here is the messages array, which gives the bot it's context in the call. The full list of options that can be passed here can be found in the documenation. This is where you can give the bot "memory" or let it know of things outside of what it was asked.

I would like to eventually experiment with keeping some context about each user and then passing that in to the messages array, but I haven't gotten there yet. This would give the illusion that the bot knows some information about the user interacting with it and make it feel much more real and personable.

Finally, we send the response - which appears in response.choices[0].message.content back to the discord channel.

And there you have it, a super quick and dirty run down of how to create a discord bot using OpenAI and discord.py.