diff --git a/src/dolores.py b/src/dolores.py index 56e6ae3..5eb4e71 100644 --- a/src/dolores.py +++ b/src/dolores.py @@ -92,6 +92,24 @@ async def handle_news(message): await ctx.reply(embed=embed) +async def handle_question(message): + """ + When someone reacts with a question mark to a message, Dolores will attempt + to explain the contents of the message in an informative simpler way. + Calls generate_explanation in the generation module. + """ + ctx = await bot.get_context(message) + + if os.environ["GENERATION_ENABLED"].lower() == "true": + text_instance = generation(bot) + logger.info(f"Generating explanation for message: {message.clean_content}") + explanation = text_instance.generate_explanation( + message.author.global_name, message.clean_content + ) + if explanation != "": + await ctx.reply(explanation) + + # --------------------------------------------------------------------------- # Discord Events # --------------------------------------------------------------------------- @@ -123,6 +141,18 @@ async def on_command_error(ctx, error): await ctx.send("An error occurred. Please try again.") +@bot.event +async def on_reaction_add(reaction, user): + """ + on_reaction_add is a base function for handling when a reaction is added + to a message. Currently used to check for question mark reaction + """ + if user == bot.user: + return + if reaction.emoji == "❓" or reaction.emoji == "❔": + await handle_question(reaction.message) + + @bot.event async def on_message(message): """ diff --git a/src/modules/generation.py b/src/modules/generation.py index fd20e83..646a1bc 100644 --- a/src/modules/generation.py +++ b/src/modules/generation.py @@ -79,6 +79,41 @@ def generate_reply(self, person, message): return reply + def generate_explanation(self, person, message): + """ + Generates a simpler more informative explanation to a given message. + """ + # Add the user's message to the message history + message_history.append({"role": "user", "content": message, "name": person}) + + message_history.append( + { + "role": "system", + "content": "Attempt to explain the previous message if possible. Expand on what they are saying to provide a more informative response. Essentially, explain the contents of the message for somebody else who may not understand what the message is saying.", + } + ) + + try: + response = openai.chat.completions.create( + model=os.environ["OPENAI_MODEL"], + messages=system_messages + list(message_history), + max_tokens=int(os.environ.get("MAX_TOKENS", 150)), + temperature=float(os.environ.get("TEMPERATURE", 0.9)), + top_p=float(os.environ.get("TOP_P", 1.0)), + frequency_penalty=float(os.environ.get("FREQUENCY_PENALTY", 0.0)), + presence_penalty=float(os.environ.get("PRESENCE_PENALTY", 0.6)), + ) + reply = response.choices[0].message.content + logger.info(f"Explanation generated: {reply}") + # Add the reply to the message history + message_history.append({"role": "assistant", "content": reply}) + except Exception as e: + logger.error(f"Error generating explanation: {e}") + logger.error(f"Messages: {system_messages + list(message_history)}") + reply = "" + + return reply + def generate_snarky_comment(self): """ Generates a snarky comment to be used when a user tries to use a command that does not exist. @@ -183,3 +218,6 @@ async def generate_image(self, ctx, *, prompt: str): except Exception as e: logger.error(e) await ctx.respond(f"Error posting image to Discord: {e}.") + + # @commands.slash_command(description="Restates a given message in a more informative way. Explans something.") + # async def explainthat(self, ctx)