|
| 1 | +import logging |
| 2 | +from typing import Optional |
| 3 | + |
| 4 | +import openai |
| 5 | +from discord import AllowedMentions |
| 6 | +from discord.ext import commands |
| 7 | +from discord.ext.commands import Bot, Context |
| 8 | + |
| 9 | +from cogs.commands.openaiadmin import is_author_banned_openai |
| 10 | +from config import CONFIG |
| 11 | +from utils.utils import split_into_messages |
| 12 | + |
| 13 | +LONG_HELP_TEXT = """ |
| 14 | +Too much yapping? Summarise what people have said using the power of the GPT overlords! |
| 15 | +""" |
| 16 | + |
| 17 | +SHORT_HELP_TEXT = """Summarise messages.""" |
| 18 | + |
| 19 | +mentions = AllowedMentions(everyone=False, users=False, roles=False, replied_user=True) |
| 20 | +model = "gpt-4o-mini" |
| 21 | + |
| 22 | +def clean(msg, *prefixes): |
| 23 | + for pre in prefixes: |
| 24 | + msg = msg.strip().removeprefix(pre) |
| 25 | + return msg.strip() |
| 26 | + |
| 27 | + |
| 28 | +class Summarise(commands.Cog): |
| 29 | + def __init__(self, bot: Bot): |
| 30 | + self.bot = bot |
| 31 | + openai.api_key = CONFIG.OPENAI_API_KEY |
| 32 | + self.system_prompt = "People yap too much, I don't want to read all of it. In 200 words or less give me the gist of what is being said. Note that the messages are in reverse chronological order:" |
| 33 | + |
| 34 | + @commands.hybrid_command(help=LONG_HELP_TEXT, brief=SHORT_HELP_TEXT) |
| 35 | + async def tldr( |
| 36 | + self, ctx: Context, number_of_messages: int = 100): |
| 37 | + number_of_messages = 400 if number_of_messages > 400 else number_of_messages |
| 38 | + |
| 39 | + # avoid banned users |
| 40 | + if not await is_author_banned_openai(ctx): |
| 41 | + await ctx.send("You are banned from OpenAI!") |
| 42 | + return |
| 43 | + |
| 44 | + # get the last "number_of_messages" messages from the current channel and build the prompt |
| 45 | + curr_channel = ctx.guild.get_channel(ctx.channel.id) |
| 46 | + messages = curr_channel.history(limit=number_of_messages) |
| 47 | + messages = await self.create_message(messages) |
| 48 | + |
| 49 | + # send the prompt to the ai overlords to process |
| 50 | + async with ctx.typing(): |
| 51 | + response = await self.dispatch_api(messages) |
| 52 | + if response: |
| 53 | + prev = ctx.message |
| 54 | + for content in split_into_messages(response): |
| 55 | + prev = await prev.reply(content, allowed_mentions=mentions) |
| 56 | + |
| 57 | + async def dispatch_api(self, messages) -> Optional[str]: |
| 58 | + logging.info(f"Making OpenAI request: {messages}") |
| 59 | + |
| 60 | + # Make request |
| 61 | + response = await openai.ChatCompletion.acreate(model=model, messages=messages) |
| 62 | + logging.info(f"OpenAI Response: {response}") |
| 63 | + |
| 64 | + # Remove prefix that chatgpt might add |
| 65 | + reply = response.choices[0].message.content |
| 66 | + if CONFIG.AI_INCLUDE_NAMES: |
| 67 | + name = f"{self.bot.user.display_name}: " |
| 68 | + reply = clean(reply, "Apollo: ", "apollo: ", name) |
| 69 | + return reply |
| 70 | + |
| 71 | + async def create_message(self, message_chain): |
| 72 | + # get initial prompt |
| 73 | + initial = self.system_prompt + "\n" |
| 74 | + |
| 75 | + # for each message, append it to the prompt as follows --- author : message \n |
| 76 | + async for msg in message_chain: |
| 77 | + if CONFIG.AI_INCLUDE_NAMES and msg.author != self.bot.user: |
| 78 | + initial += msg.author.name + ":" + msg.content + "\n" |
| 79 | + |
| 80 | + messages = [dict(role="system", content=initial)] |
| 81 | + |
| 82 | + return messages |
| 83 | + |
| 84 | + |
| 85 | +async def setup(bot: Bot): |
| 86 | + await bot.add_cog(Summarise(bot)) |
0 commit comments