From f5e2e37438a7b9d11efc5fcc097c0512046a22f6 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Mon, 24 Feb 2025 20:04:39 -0800 Subject: [PATCH 01/11] Added command to submit trips (current static) Added run_command in agent.py to take in plain text --- agent.py | 13 +++++++++++++ bot.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/agent.py b/agent.py index fb886381..8b1495c5 100644 --- a/agent.py +++ b/agent.py @@ -27,3 +27,16 @@ async def run(self, message: discord.Message): ) return response.choices[0].message.content + # Handle non-discord messages + async def run_command(self, message): + # The simplest form of an agent + # Send the message's content to Mistral's API and return Mistral's response + messages = [ + {"role": "system", "content": SYSTEM_PROMPT}, + {"role": "user", "content": message}, + ] + response = await self.client.chat.complete_async( + model=MISTRAL_MODEL, + messages=messages, + ) + return response.choices[0].message.content diff --git a/bot.py b/bot.py index d146885b..1e6a89b5 100644 --- a/bot.py +++ b/bot.py @@ -26,6 +26,8 @@ # Get the token from the environment variables token = os.getenv("DISCORD_TOKEN") +# Dictionary to store trip preferences (static for now) +trip_preferences = {} @bot.event async def on_ready(): @@ -74,6 +76,37 @@ async def ping(ctx, *, arg=None): else: await ctx.send(f"Pong! Your argument was {arg}") - +# Recommend Trips +@bot.command(name="recommend_trips", help="AI recommends trips") +async def recommend_trips(ctx, *, arg=None): + prompt = "Based on the following travel preferences, suggest a few trip options that balances everyone's inputs" + # Create the dictionary statically for testing + trip_preferences["user_1"] = [] + trip_preferences["user_1"].append({ + "user": "user_1", + "location": "beach", + "budget": "1,000", + "dates": "3/10-3/16", + "mode": "Relax" + }) + trip_preferences["user_2"] = [] + trip_preferences["user_2"].append({ + "user": "user_2", + "location": "washington d.c.", + "budget": "1,500", + "dates": "3/11-3/15", + "mode": "exploring" + }) + # Add to the prompt + for user_prefs in trip_preferences.values(): + for pref in user_prefs: + prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" + print(prompt) + + response = await agent.run_command(prompt) + trip_suggestions = response.split("\n") + full_response = "**AI-Recommended Trips:**\n" + "\n".join([f"{i+1}. {trip}" for i, trip in enumerate(trip_suggestions)]) + await ctx.send(full_response) + # Start the bot, connecting it to the gateway bot.run(token) From 1ad7429b99e50b1d729f02db58f37493e0be0914 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 08:03:46 -0800 Subject: [PATCH 02/11] Added note --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 1e6a89b5..f7db380c 100644 --- a/bot.py +++ b/bot.py @@ -102,7 +102,7 @@ async def recommend_trips(ctx, *, arg=None): for pref in user_prefs: prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" print(prompt) - + # Will need to add that the prompt needs to be formatted response = await agent.run_command(prompt) trip_suggestions = response.split("\n") full_response = "**AI-Recommended Trips:**\n" + "\n".join([f"{i+1}. {trip}" for i, trip in enumerate(trip_suggestions)]) From d0272535e0aaa3fd71a4c67c9e2a0cff4788a70d Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 18:48:52 -0800 Subject: [PATCH 03/11] AI returns JSON so rec trips can be stored --- bot.py | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index f7db380c..9237ee2e 100644 --- a/bot.py +++ b/bot.py @@ -1,6 +1,8 @@ import os import discord import logging +import json +import re from discord.ext import commands from dotenv import load_dotenv @@ -103,9 +105,41 @@ async def recommend_trips(ctx, *, arg=None): prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" print(prompt) # Will need to add that the prompt needs to be formatted + prompt += "Please format the response in JSON with this structure:\n" + prompt += """" + Based on the following travel preferences, suggest a few ideal trip options. + Please format the response in JSON with this structure: + [ + { + "name": "Trip Name", + "dates": "Trip Dates", + "trip_style": "Trip Style", + "budget": "Budget", + "activities": ["Activity 1", "Activity 2", "Activity 3"] + }, + ... + ] + """ + prompt += "\nReturn only the JSON array and no extra text." + response = await agent.run_command(prompt) - trip_suggestions = response.split("\n") - full_response = "**AI-Recommended Trips:**\n" + "\n".join([f"{i+1}. {trip}" for i, trip in enumerate(trip_suggestions)]) + # Remove Markdown code block (```json ... ```) + if response.startswith("```json"): + response = response[7:-3].strip() # Remove ```json at start and ``` at end + elif response.startswith("```"): + response = response[3:-3].strip() # Generic ``` removal if no json tag + try: + trips = json.loads(response.strip()) # Try parsing the JSON output + except json.JSONDecodeError: + await ctx.send("Error: AI response is not valid JSON. Here is what was returned:\n" + response) + return + full_response = "**AI-Recommended Trips:**\n" + for i, trip in enumerate(trips, start=1): + full_response += f"{i}. **{trip['name']}**\n" + full_response += f"Dates: {trip['dates']}\n" + full_response += f"Style: {trip['trip_style']}\n" + full_response += f"Budget: {trip['budget']}\n" + full_response += f"Activities: {', '.join(trip['activities'])}\n\n" await ctx.send(full_response) # Start the bot, connecting it to the gateway From 291f0091ecf88e34232e2b6a509419eca73ab129 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 18:53:27 -0800 Subject: [PATCH 04/11] AI answer is now JSON so it can be stored easily --- bot.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/bot.py b/bot.py index 9237ee2e..af4458a4 100644 --- a/bot.py +++ b/bot.py @@ -99,13 +99,14 @@ async def recommend_trips(ctx, *, arg=None): "dates": "3/11-3/15", "mode": "exploring" }) - # Add to the prompt + + # Add user preferences to the prompt for user_prefs in trip_preferences.values(): for pref in user_prefs: prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" - print(prompt) - # Will need to add that the prompt needs to be formatted - prompt += "Please format the response in JSON with this structure:\n" + + # AI answer is formatted as JSON + prompt += "Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" prompt += """" Based on the following travel preferences, suggest a few ideal trip options. Please format the response in JSON with this structure: @@ -120,19 +121,17 @@ async def recommend_trips(ctx, *, arg=None): ... ] """ - prompt += "\nReturn only the JSON array and no extra text." + prompt += "\nReturn only the JSON array and no extra text. " response = await agent.run_command(prompt) - # Remove Markdown code block (```json ... ```) - if response.startswith("```json"): - response = response[7:-3].strip() # Remove ```json at start and ``` at end - elif response.startswith("```"): - response = response[3:-3].strip() # Generic ``` removal if no json tag + # Try and parse the JSON try: - trips = json.loads(response.strip()) # Try parsing the JSON output + trips = json.loads(response) except json.JSONDecodeError: await ctx.send("Error: AI response is not valid JSON. Here is what was returned:\n" + response) return + + # Print to the channel the recommended trip options full_response = "**AI-Recommended Trips:**\n" for i, trip in enumerate(trips, start=1): full_response += f"{i}. **{trip['name']}**\n" From 0707130e2226add6e948ab2d819e2bb54dd9abab Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 18:55:36 -0800 Subject: [PATCH 05/11] Updated prompt formatting --- bot.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bot.py b/bot.py index af4458a4..b31df8ad 100644 --- a/bot.py +++ b/bot.py @@ -99,7 +99,7 @@ async def recommend_trips(ctx, *, arg=None): "dates": "3/11-3/15", "mode": "exploring" }) - + # Add user preferences to the prompt for user_prefs in trip_preferences.values(): for pref in user_prefs: @@ -108,8 +108,6 @@ async def recommend_trips(ctx, *, arg=None): # AI answer is formatted as JSON prompt += "Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" prompt += """" - Based on the following travel preferences, suggest a few ideal trip options. - Please format the response in JSON with this structure: [ { "name": "Trip Name", @@ -121,8 +119,6 @@ async def recommend_trips(ctx, *, arg=None): ... ] """ - prompt += "\nReturn only the JSON array and no extra text. " - response = await agent.run_command(prompt) # Try and parse the JSON try: From c91e263aab3395ac7cff9a4524a5261d0f5dc007 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 18:57:53 -0800 Subject: [PATCH 06/11] Updated prompt --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index b31df8ad..fc826e88 100644 --- a/bot.py +++ b/bot.py @@ -106,7 +106,7 @@ async def recommend_trips(ctx, *, arg=None): prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" # AI answer is formatted as JSON - prompt += "Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" + prompt += "Based on the following travel preferences, suggest a few ideal trip options. Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" prompt += """" [ { From f2a6223420f21e11273e084c15d4f0a1bcf71dab Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 19:00:19 -0800 Subject: [PATCH 07/11] Updated prompt for more descriptive activity lists --- bot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index fc826e88..25fcb21b 100644 --- a/bot.py +++ b/bot.py @@ -81,7 +81,8 @@ async def ping(ctx, *, arg=None): # Recommend Trips @bot.command(name="recommend_trips", help="AI recommends trips") async def recommend_trips(ctx, *, arg=None): - prompt = "Based on the following travel preferences, suggest a few trip options that balances everyone's inputs" + # Should we add a certain number of recommendations? + prompt = "Based on the following travel preferences, suggest a few trip options that balances everyone's inputs. Make sure the activity list is descriptive." # Create the dictionary statically for testing trip_preferences["user_1"] = [] trip_preferences["user_1"].append({ @@ -106,7 +107,7 @@ async def recommend_trips(ctx, *, arg=None): prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" # AI answer is formatted as JSON - prompt += "Based on the following travel preferences, suggest a few ideal trip options. Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" + prompt += "Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" prompt += """" [ { From 03c8862b9a76fbe2a96efdfcb3fe690685c3cd0f Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 22:17:41 -0800 Subject: [PATCH 08/11] Created command to allow users to submit trips --- bot.py | 56 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/bot.py b/bot.py index 25fcb21b..d15cad52 100644 --- a/bot.py +++ b/bot.py @@ -28,8 +28,27 @@ # Get the token from the environment variables token = os.getenv("DISCORD_TOKEN") -# Dictionary to store trip preferences (static for now) +# Dictionary to store trip preferences trip_preferences = {} +# Create the dictionary statically for testing +''' +trip_preferences["user_1"] = [] +trip_preferences["user_1"].append({ + "user": "user_1", + "location": "beach", + "budget": "1,000", + "dates": "3/10-3/16", + "mode": "Relax" +}) +trip_preferences["user_2"] = [] +trip_preferences["user_2"].append({ + "user": "user_2", + "location": "washington d.c.", + "budget": "1,500", + "dates": "3/11-3/15", + "mode": "exploring" +}) +''' @bot.event async def on_ready(): @@ -78,29 +97,28 @@ async def ping(ctx, *, arg=None): else: await ctx.send(f"Pong! Your argument was {arg}") +# Submit Trips +@bot.command(name="submit_trips", help="Users submit trip ideas and preferences") +async def submit_trips(ctx, location: str, budget: str, dates: str, mode: str): + if ctx.guild.id not in trip_preferences: + trip_preferences[ctx.guild.id] = [] + + trip_preferences[ctx.guild.id].append({ + "user": ctx.author.name, + "location": location, + "budget": budget, + "dates": dates, + "mode": mode.lower() + }) + + await ctx.send(f"{ctx.author.name} submitted travel preferences: Location - {location}, Budget - {budget}, Dates - {dates}, Mode - {mode.capitalize()}.") + # Recommend Trips @bot.command(name="recommend_trips", help="AI recommends trips") async def recommend_trips(ctx, *, arg=None): # Should we add a certain number of recommendations? prompt = "Based on the following travel preferences, suggest a few trip options that balances everyone's inputs. Make sure the activity list is descriptive." - # Create the dictionary statically for testing - trip_preferences["user_1"] = [] - trip_preferences["user_1"].append({ - "user": "user_1", - "location": "beach", - "budget": "1,000", - "dates": "3/10-3/16", - "mode": "Relax" - }) - trip_preferences["user_2"] = [] - trip_preferences["user_2"].append({ - "user": "user_2", - "location": "washington d.c.", - "budget": "1,500", - "dates": "3/11-3/15", - "mode": "exploring" - }) - + # Add user preferences to the prompt for user_prefs in trip_preferences.values(): for pref in user_prefs: From d36554d076dde2af70ecbedb34f395e84e796d09 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Tue, 25 Feb 2025 22:27:54 -0800 Subject: [PATCH 09/11] Able to pass in string or discord messages --- agent.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/agent.py b/agent.py index 8b1495c5..db9c9c92 100644 --- a/agent.py +++ b/agent.py @@ -15,7 +15,6 @@ def __init__(self): async def run(self, message: discord.Message): # The simplest form of an agent # Send the message's content to Mistral's API and return Mistral's response - messages = [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": message.content}, @@ -31,9 +30,14 @@ async def run(self, message: discord.Message): async def run_command(self, message): # The simplest form of an agent # Send the message's content to Mistral's API and return Mistral's response + if isinstance(message, discord.Message): + content = message.content + else: + content = message + messages = [ {"role": "system", "content": SYSTEM_PROMPT}, - {"role": "user", "content": message}, + {"role": "user", "content": content}, ] response = await self.client.chat.complete_async( model=MISTRAL_MODEL, From 9dde23e7c3cfcebed07678af2be38b42ba923cf2 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Wed, 26 Feb 2025 18:28:39 -0800 Subject: [PATCH 10/11] Added ability to vote for trips and remove trips --- bot.py | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/bot.py b/bot.py index d15cad52..edb86ff3 100644 --- a/bot.py +++ b/bot.py @@ -49,6 +49,8 @@ "mode": "exploring" }) ''' +# Dictionary to store trip votes +trip_votes = {} @bot.event async def on_ready(): @@ -86,7 +88,6 @@ async def on_message(message: discord.Message): # Commands - # This example command is here to show you how to add commands to the bot. # Run !ping with any number of arguments to see the command in action. # Feel free to delete this if your project will not need commands. @@ -97,6 +98,12 @@ async def ping(ctx, *, arg=None): else: await ctx.send(f"Pong! Your argument was {arg}") +# Add clear preferences command +@bot.command(name="clear_preferences", help="Remove a user's trip preferences") +async def clear_preferences(ctx, *, arg=None): + trip_preferences[ctx.guild.id] = [] + await ctx.send(f"Removed {ctx.author.name}'s trip preferences") + # Submit Trips @bot.command(name="submit_trips", help="Users submit trip ideas and preferences") async def submit_trips(ctx, location: str, budget: str, dates: str, mode: str): @@ -110,8 +117,13 @@ async def submit_trips(ctx, location: str, budget: str, dates: str, mode: str): "dates": dates, "mode": mode.lower() }) - + # Display all submitted preferences + preferences_message = "**Current Trip Preferences:**\n" + for pref in trip_preferences[ctx.guild.id]: + preferences_message += (f"- {pref['user']}: Location - {pref['location']}, Budget - {pref['budget']}, " + f"Dates - {pref['dates']}, Mode - {pref['mode'].capitalize()}\n") await ctx.send(f"{ctx.author.name} submitted travel preferences: Location - {location}, Budget - {budget}, Dates - {dates}, Mode - {mode.capitalize()}.") + await ctx.send(preferences_message) # Recommend Trips @bot.command(name="recommend_trips", help="AI recommends trips") @@ -125,7 +137,7 @@ async def recommend_trips(ctx, *, arg=None): prompt += f"- {pref['user']} wants to travel to {pref['location']} on a {pref['mode']} trip with a budget of {pref['budget']} during {pref['dates']}.\n" # AI answer is formatted as JSON - prompt += "Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text:\n" + prompt += "Please format the response in JSON with this structure. Return ONLY a raw JSON array. Do NOT use Markdown formatting, triple backticks, or any extra text, again just the raw JSON array:\n" prompt += """" [ { @@ -139,6 +151,11 @@ async def recommend_trips(ctx, *, arg=None): ] """ response = await agent.run_command(prompt) + # Remove markdown + if response.startswith("```json"): + response = response[7:-3].strip() + elif response.startswith("```"): + response = response[3:-3].strip() # Try and parse the JSON try: trips = json.loads(response) @@ -146,6 +163,9 @@ async def recommend_trips(ctx, *, arg=None): await ctx.send("Error: AI response is not valid JSON. Here is what was returned:\n" + response) return + # Add options to trip_votes + trip_votes[ctx.guild.id] = {"trips": trips, "votes": {trip["name"]: 0 for trip in trips}} + # Print to the channel the recommended trip options full_response = "**AI-Recommended Trips:**\n" for i, trip in enumerate(trips, start=1): @@ -155,6 +175,21 @@ async def recommend_trips(ctx, *, arg=None): full_response += f"Budget: {trip['budget']}\n" full_response += f"Activities: {', '.join(trip['activities'])}\n\n" await ctx.send(full_response) - + +# Add vote trips command +@bot.command(name="vote_trip", help="Users vote for trips based on the number") +async def vote_trip(ctx, trip_number:int): + if ctx.guild.id not in trip_votes or "trips" not in trip_votes[ctx.guild.id]: + await ctx.send("No trips available to vote on. Use `!recommend_trips` first.") + return + trip_list = trip_votes[ctx.guild.id]["trips"] + if trip_number < 1 or trip_number > len(trip_list): + await ctx.send("Invalid trip number!") + return + selected_trip = trip_list[trip_number - 1]["name"] + trip_votes[ctx.guild.id]["votes"][selected_trip] += 1 + vote_counts = "\n".join([f"{name}: {count} votes" for name, count in trip_votes[ctx.guild.id]["votes"].items()]) + await ctx.send(f"{ctx.author.name} voted for: {selected_trip}\n \n**Current Vote Count:**\n{vote_counts}") + # Start the bot, connecting it to the gateway bot.run(token) From eb7d66a78aab9e41bc2489b6f07bd91338a2b8a2 Mon Sep 17 00:00:00 2001 From: emmaeescandon Date: Wed, 26 Feb 2025 22:40:28 -0800 Subject: [PATCH 11/11] Added command to finalize trips to get itinerary --- bot.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index edb86ff3..6f49e0c8 100644 --- a/bot.py +++ b/bot.py @@ -98,7 +98,7 @@ async def ping(ctx, *, arg=None): else: await ctx.send(f"Pong! Your argument was {arg}") -# Add clear preferences command +# Clear preferences command @bot.command(name="clear_preferences", help="Remove a user's trip preferences") async def clear_preferences(ctx, *, arg=None): trip_preferences[ctx.guild.id] = [] @@ -176,7 +176,7 @@ async def recommend_trips(ctx, *, arg=None): full_response += f"Activities: {', '.join(trip['activities'])}\n\n" await ctx.send(full_response) -# Add vote trips command +# Vote trips command @bot.command(name="vote_trip", help="Users vote for trips based on the number") async def vote_trip(ctx, trip_number:int): if ctx.guild.id not in trip_votes or "trips" not in trip_votes[ctx.guild.id]: @@ -191,5 +191,34 @@ async def vote_trip(ctx, trip_number:int): vote_counts = "\n".join([f"{name}: {count} votes" for name, count in trip_votes[ctx.guild.id]["votes"].items()]) await ctx.send(f"{ctx.author.name} voted for: {selected_trip}\n \n**Current Vote Count:**\n{vote_counts}") +# Finalize a trip and get the full itinerary +@bot.command(name="finalize_trip", help="Generate a full itinerary for the trip with the most votes") +async def finalize_trip(ctx, *, arg=None): + if ctx.guild.id not in trip_votes or not trip_votes[ctx.guild.id]["votes"]: + await ctx.send("No trips have been voted on yet! Use `!vote_trip` to cast your votes.") + return + best_trip = max(trip_votes[ctx.guild.id]["votes"], key=trip_votes[ctx.guild.id]["votes"].get, default=None) + if not best_trip or trip_votes[ctx.guild.id]["votes"][best_trip] == 0: + await ctx.send("No votes have been cast yet!") + return + + # Include full trip details in the prompt + selected_trip_data = next((trip for trip in trip_votes[ctx.guild.id]["trips"] if trip["name"] == best_trip), None) + if not selected_trip_data: + await ctx.send("Error: Selected trip details not found.") + return + trip_json = json.dumps(selected_trip_data, indent=2) + # Should we ask for more descriptive itineraries? + prompt = f"Generate a detailed travel itinerary for the following trip. Ensure a daily schedule based on the details provided.\nTrip Details:\n{trip_json}" + response = await agent.run_command(prompt) + + # Remove excess blank lines and fix encoding issues + response = response.replace("\n\n\n", "\n").strip() + # Ensure messages do not exceed Discord's 2000 character limit + response_chunks = [response[i:i+1900] for i in range(0, len(response), 1900)] + await ctx.send("Finalized Trip Itinerary:") + for chunk in response_chunks: + await ctx.send(chunk) + # Start the bot, connecting it to the gateway bot.run(token)