diff --git a/README.md b/README.md index 5adad31..65feaf1 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,12 @@ This is a Discord Bot that Uses OpenAI's new Chat API-Endpoint to generate text This Bot uses the PyCord Library ([PyCord](https://pycord.dev/)) and the OpenAI Python Library ([OpenAI](https://platform.openai.com/docs/libraries)) -There are two ways to use this bot: +There are three ways to use this bot: -Using Docker or without Docker. +1. By just inviting [this Bot](https://discord.com/api/oauth2/authorize?client_id=1083786070786850959&permissions=2147486720&scope=bot) to your Server + +2. Using Docker +3. Without using Docker ### The No Docker Way diff --git a/bot/bot.py b/bot/bot.py index f58ceba..880b42e 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -1,22 +1,16 @@ -import asyncio import discord from discord.ext import commands from dotenv import load_dotenv import os import modules.gpt as gpt -import modules.tts as tts +import modules.dbmanagement as dbm import modules.summarize as summarize -import modules.channelconfig as config description = "ChatGPT Bot for Discord" -configfolder = "configs" -audiofolder = "audio" +configfolder = "config" load_dotenv(dotenv_path=os.path.join(configfolder, ".env")) -text_channels, prefix_channels = config.load_config() -tts_language = "de-DE" - intents = discord.Intents.default() intents.message_content = True intents.members = True @@ -27,131 +21,234 @@ bot = discord.Bot( intents=intents, ) +### \/ Events Area \/ ### @bot.event async def on_ready(): print(f"We have logged in as {bot.user}") + await dbm.init_db() - +### Message Listener @bot.event async def on_message(message): if message.author == bot.user: return - if str(message.channel.id) in text_channels and not message.content.startswith("$"): - await message.channel.trigger_typing() - print(f'{message.author} asked: {message.content}') - answer = await gpt.get_answer(message.channel.id, message.author, message.content) - print(f'Answer: {answer}') - await message.channel.send(answer) + ### Check if Channel is Configured + if await dbm.get_channel_by_id(message.guild.id, message.channel.id) is not None: + config = await dbm.get_config_by_id(message.guild.id, message.channel.id) + if message.content.startswith(config[2]): + ### Count Messages for Summary + counter = 0 + if await dbm.get_last_chat(message.guild.id, message.channel.id) is not None: + counter = await dbm.get_last_chat(message.guild.id, message.channel.id) + counter = counter[8] + counter = counter + 1 + else: + await dbm.add_summary_zero(message.guild.id, message.channel.id) - if str(message.channel.id) in prefix_channels: - if message.content.startswith("!"): - msg_split = message.content.split("!")[1] + ### Read and Send Message/Answer await message.channel.trigger_typing() - print(f'{message.author} asked: {message.content}') - answer = await gpt.get_answer(message.channel.id, message.author, msg_split) - print(f'Answer: {answer}') - await message.channel.send(answer) + msg = message.content.replace(config[2], "", 1) + await dbm.add_chat(message.guild.id, message.channel.id, message.author.id, message.author.name, "user", message.id, f'{message.author}: {msg}', counter) + answer = await gpt.get_answer(message.guild.id, message.channel.id) + sendmsg = await message.channel.send(answer) + await dbm.add_chat(message.guild.id, message.channel.id, bot.user.id, bot.user.name, "assistant", sendmsg.id, answer, counter+1) + + ### Check if Summary is needed + last_summary = await dbm.get_latest_summary(message.guild.id, message.channel.id) + last_summary = last_summary[4] + last_message = await dbm.get_last_chat(message.guild.id, message.channel.id) + last_message = last_message[8] + + ### Check if Last Summary is older than 20 Messages + if last_message - last_summary >= 30: + await summarize.new_summarize(message.guild.id, message.channel.id) + +### /\ End Events Area /\ ### + +### \/ Modal Area \/ ### + +### Modal Class for Setup +class SetupModal(discord.ui.Modal): + def __init__(self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.add_item(discord.ui.InputText(label="Channel-ID", placeholder="Channel-ID", required=True)) + self.add_item(discord.ui.InputText(label="Prefix", placeholder="!", required=False)) + self.add_item(discord.ui.InputText(label="GPT", placeholder="3", required=True)) + self.add_item(discord.ui.InputText(label="System Message", placeholder="System Message", required=False, style=discord.InputTextStyle.long)) + + async def callback(self, interaction: discord.Interaction): + embed = discord.Embed(title="Setup Vals") + embed.add_field(name="Channel-ID", value=self.children[0].value) + embed.add_field(name="Prefix", value=self.children[1].value) + embed.add_field(name="GPT", value=self.children[2].value) + embed.add_field(name="System Message", value=self.children[3].value) + + await interaction.response.send_message(embeds=[embed], ephemeral=True) + + if await dbm.get_server_by_id(interaction.guild.id) is None: + print("Server not in DB") + await dbm.add_server(interaction.guild.id) + await dbm.add_channel(interaction.guild.id, self.children[0].value) + if dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1].value, self.children[2].value, self.children[3].value) + else: + await dbm.add_config(interaction.guild.id, self.children[0].value, 3, self.children[2].value, self.children[3].value) + await dbm.add_summary_zero(interaction.guild.id, self.children[0].value) + await dbm.default_premium(interaction.guild.id) + print("Setup: Server") + + elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, self.children[0].value) is None: + print("Server in DB, but Channel not") + await dbm.add_channel(interaction.guild.id, self.children[0].value) + if dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1].value, self.children[2].value, self.children[3].value) + else: + await dbm.add_config(interaction.guild.id, self.children[0].value, 3, self.children[2].value, self.children[3].value) + + await dbm.add_summary_zero(interaction.guild.id, self.children[0].value) + print("Setup: Channel, Config") + + elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, self.children[0].value) is not None: + print("Server and Channel in DB, rerun Setup") + await dbm.remove_channel(interaction.guild.id, self.children[0].value) + await dbm.remove_config(interaction.guild.id, self.children[0].value) + await dbm.add_channel(interaction.guild.id, self.children[0].value) + if dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, self.children[0].value, self.children[1].value, self.children[2].value, self.children[3].value) + else: + await dbm.add_config(interaction.guild.id, self.children[0].value, 3, self.children[2].value, self.children[3].value) + await dbm.add_summary_zero(interaction.guild.id, self.children[0].value) + print("Setup: Channel, Config") + +### Add Modal +class AddModal(discord.ui.Modal): + def __init__(self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.add_item(discord.ui.InputText(label="Prefix (Leave empty for no Prefix)", placeholder="!", required=False)) + self.add_item(discord.ui.InputText(label="GPT (3 - GPT-3.5-Turbo; 4- GPT-4)", placeholder="3", required=True)) + self.add_item(discord.ui.InputText(label="System Message", placeholder="System Message", required=False, style=discord.InputTextStyle.long)) + + async def callback(self, interaction: discord.Interaction): + if await dbm.get_server_by_id(interaction.guild.id) is None: + print("Server not in DB") + await dbm.add_server(interaction.guild.id) + await dbm.add_channel(interaction.guild.id, interaction.channel.id) + if dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, self.children[1].value, self.children[2].value) + else: + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, 3, self.children[2].value) + await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) + print("Setup: Channel, Server, Config") + elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, interaction.channel.id) is None: + await dbm.add_channel(interaction.guild.id, interaction.channel.id) + if dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, + self.children[1].value, self.children[2].value) + else: + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, 3, + self.children[2].value) + await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) + print("Setup: Channel, Config") + elif await dbm.get_server_by_id(interaction.guild.id) is not None and await dbm.get_channel_by_id(interaction.guild.id, interaction.channel.id) is not None: + await dbm.remove_channel(interaction.guild.id, interaction.channel.id) + await dbm.remove_config(interaction.guild.id, interaction.channel.id) + if dbm.is_premium(interaction.guild.id): + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, + self.children[1].value, self.children[2].value) + else: + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, 3, + self.children[2].value) + await dbm.add_config(interaction.guild.id, interaction.channel.id, self.children[0].value, self.children[1].value, self.children[2].value) + await dbm.add_summary_zero(interaction.guild.id, interaction.channel.id) + print("Setup: Channel, Config") + + if dbm.is_premium(interaction.guild.id): + await interaction.response.send_message('Setup Channel', ephemeral=True) + else: + await interaction.response.send_message('Setup Channel (Using GPT-3.5)', ephemeral=True) + +### Edit Modal +class EditSystemModal(discord.ui.Modal): + def __init__(self, *args, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.add_item(discord.ui.InputText(label="System Message", placeholder="System Message", required=False, style=discord.InputTextStyle.long)) + + async def callback(self, interaction: discord.Interaction): + server, channel, prefix, gptver, systemmsg = await dbm.get_config_by_id(interaction.guild.id, interaction.channel.id) + await dbm.remove_config(interaction.guild.id, interaction.channel.id) + await dbm.add_config(interaction.guild.id, interaction.channel.id, prefix, gptver, self.children[0].value) + await interaction.response.send_message("System Message changed", ephemeral=True) + +### /\ End Modal Area /\ ### + +### \/ Commands Area \/ ### + +### Setup Command +@bot.command(name="setup", description="Used to setup the Bot") +@commands.has_permissions(administrator=True) +async def setup(ctx: discord.ApplicationContext): + modal = SetupModal(title="Setup ChatGPT") + await ctx.send_modal(modal) @bot.command(name="add", description="Used to add Bot answering to specific Channels") -async def add( - ctx: discord.ApplicationContext, - option: discord.Option(str, choices=["text","prefix"], description="Type of Channel to Add"), - id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy")): - - if ctx.author.guild_permissions.administrator: - try: - config.add_channel(option, id) - - if option == "text": - text_channels.append(id) - - elif option == "prefix": - prefix_channels.append(id) - - await ctx.respond(f'{option} channel {id} added', ephemeral=True) - except ValueError as e: - await ctx.respond(f'Error: {e}', ephemeral=True) +@commands.has_permissions(administrator=True) +async def add(ctx: discord.ApplicationContext): + if await dbm.get_channel_by_id(ctx.guild.id, ctx.channel.id) is None: + modal = AddModal(title="Add Channel") + await ctx.send_modal(modal) else: - await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True) + await ctx.respond("Channel has already been added. Use /setup", ephemeral=True) + @bot.command(name="remove", description="Used to remove Bot answering to specific Channels") -async def remove( - ctx: discord.ApplicationContext, - option: discord.Option(str, choices=["text", "prefix"], description="Type of Channel to Add"), - id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy")): - if ctx.author.guild_permissions.administrator: - try: - config.remove_channel(option, id) - - if option == "text": - text_channels.remove(id) - - elif option == "prefix": - prefix_channels.remove(id) - - await ctx.respond(f'{option} channel {id} removed', ephemeral=True) - except ValueError as e: - await ctx.respond(f'Error: {e}', ephemeral=True) +@commands.has_permissions(administrator=True) +async def remove(ctx: discord.ApplicationContext): + if await dbm.get_channel_by_id(ctx.guild.id, ctx.channel.id) is not None: + await dbm.remove_channel(ctx.guild.id, ctx.channel.id) + await ctx.respond("Channel removed", ephemeral=True) else: - await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True) + await ctx.respond("Channel not active. Nothing Done", ephemeral=True) -@bot.command(name="list", description="Used to list all Channels the Bot is answering to") -async def list( - ctx: discord.ApplicationContext, - option: discord.Option(str, choices=["text", "prefix"], description="Type of Channels to List")): - if ctx.author.guild_permissions.administrator: - if option == "text": - await ctx.respond(f'{option} channels: {str(text_channels)}', ephemeral=True) - elif option == "prefix": - await ctx.respond(f'{option} channels: {str(prefix_channels)}', ephemeral=True) - else: - await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True) +@bot.command(name="list", description="Used to list all Channels in the Server") +@commands.has_permissions(administrator=True) +async def list(ctx: discord.ApplicationContext): -@bot.command(name="delete", description="Used to delete chat history of specific Channels/Users") -async def delete( - ctx: discord.ApplicationContext, - option: discord.Option(str, choices=["text", "prefix"], description="Type of Channel to Delete"), - id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy")): + await ctx.respond("This command is WIP") - if ctx.author.guild_permissions.administrator: - try: - gpt.delete_history(id) - await ctx.respond(f'{option} channel {id} history deleted', ephemeral=True) - except Exception as e: - await ctx.respond(f'Error: {e}', ephemeral=True) - else: - await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True) +@bot.command(name="clear", description="Used to clear chat history of specific Channels/Users") +@commands.has_permissions(administrator=True) +async def clear(ctx: discord.ApplicationContext): + await dbm.add_summary_zero(ctx.guild.id, ctx.channel.id) + await ctx.respond("Bot got Amnesia", ephemeral=True) + +# Old System, Rewrite needed @bot.command(name="help", description="Used to get help") async def help(ctx: discord.ApplicationContext): await ctx.respond(f'Here is a list of all commands:\n' - f'/ping\n' - f'/setup \n' - f'/add \n' - f'/remove \n' - f'/list \n' - f'/delete \n' - f'/help', ephemeral=True) + 'Needs Rewrite\n', ephemeral=True) @bot.command(name="ping", description="Used to check if the bot is alive") async def ping(ctx: discord.ApplicationContext): await ctx.respond(f'pong', ephemeral=True) -@bot.command(name="setup", description="Used to setup the bot with a custom system message") -async def setup(ctx: discord.ApplicationContext, - id: discord.Option(str, description="Channel-ID -> Activate Developer-Options to Copy"), - message: discord.Option(str, description="System Message")): - if ctx.author.guild_permissions.administrator: - try: - gpt.setup_history(id, message) - await ctx.respond(f'Setup successful', ephemeral=True) - except Exception as e: - await ctx.respond(f'Error: {e}', ephemeral=True) - else: - await ctx.respond(f'Error: You need to be an Administrator to use this command', ephemeral=True) +# Old System, Rewrite needed +@bot.command(name="system", description="Used to setup the bot with a custom system message") +@commands.has_permissions(administrator=True) +async def system(ctx: discord.ApplicationContext): + try: + modal = EditSystemModal(title="Change System Message") + await ctx.send_modal(modal) + except: + await ctx.respond("No Config found for this Channel", ephemeral=True) + +### /\ End Commands Area /\ ### + + + bot.run(str(os.environ.get('DISCORD_TOKEN'))) diff --git a/bot/featuretest.py b/bot/featuretest.py deleted file mode 100644 index 135929d..0000000 --- a/bot/featuretest.py +++ /dev/null @@ -1,51 +0,0 @@ -import modules.channelconfig as config -import modules.gpt as gpt -import os - -text_channels = config.load_config() - -def listen_input(username, channel): - message = input(f'{username} {channel}: ') - if message.startswith("/"): - print(slash_command(username, channel, message)) - elif message.startswith("$") and channel in text_channels: - ask_gpt(username, channel, message) - else: - print(log_message(username, channel, message)) - - -def log_message(user, channel, message): - return f'User {user} sent "{message}" in {channel}' - -# Slash Command Wrapper -def slash_command(user, channel, message): - message = message.split("/")[1].split(" ") - # Add Channels to Config - if message[0] == "add": - pass - if message[1] == "text": - config.add_channel("text", message[2]) - print("Added Channel to Config") - - # Remove Channels from Config - elif message[0] == "remove": - if message[1] == "text": - return config.remove_channel("text", message[2]) - # Reload Config - elif message[0] == "reload": - text_channels = config.load_config() - return text_channels - else: - return "Invalid Command" - -def ask_gpt(user, id, message): - message = message.split('$')[1] - answer = gpt.get_answer(id, user, message) - print(answer) - -username = "XYZ" -channel = "112233445566" - -while True: - text_channels = config.load_config() - listen_input(username, channel) diff --git a/bot/modules/channelconfig.py b/bot/modules/channelconfig.py deleted file mode 100644 index 10c4390..0000000 --- a/bot/modules/channelconfig.py +++ /dev/null @@ -1,88 +0,0 @@ -# Rewrite of Channelmgmt -from os import path - -folder = "configs" -text_channel_file = "text_channels.txt" -prefix_channel_file = "prefix_channels.txt" - -def load_config(): - # Load Text-Channel Config - try: - with open(path.join(folder,text_channel_file), "r") as f: - text_channels = f.read().split("\n") - except Exception as error: - print(f'File not Fount, creating new. {error}') - with open(path.join(folder,text_channel_file), "w") as f: - f.write('') - text_channels = [] - # Load Prefix-Channel Config - try: - with open(path.join(folder, prefix_channel_file), "r") as f: - prefix_channels = f.read().split("\n") - except Exception as error: - print(f'File not Fount, creating new. {error}') - with open(path.join(folder, prefix_channel_file), "w") as f: - f.write('') - prefix_channels = [] - - return text_channels, prefix_channels - -# Add Channel to Config -def add_channel(type, id): - try: - if type == "text": - text_channels = load_config() - if id in text_channels: - # Throw Error if already in List - raise ValueError("Channel already in List") - else: - with open(path.join(folder, text_channel_file), 'a') as f: - f.write(f'{id}\n') - return True - elif type == "prefix": - prefix_channels = load_config() - if id in prefix_channels: - # Throw Error if already in List - raise ValueError("Channel already in List") - else: - with open(path.join(folder, prefix_channel_file), 'a') as f: - f.write(f'{id}\n') - return True - - except FileNotFoundError as error: - load_config() - add_channel(type, id) - -def remove_channel(type, id): - try: - if type == "text": - text_channels = load_config() - if id in text_channels: - text_channels.remove(id) - new_conf = "" - for x in text_channels: - new_conf += f'{x}\n' - - with open(path.join(folder, text_channel_file), 'w') as f: - f.write(new_conf) - return True - else: - raise ValueError("Channel not in List") - - elif type == "prefix": - prefix_channels = load_config() - if id in prefix_channels: - prefix_channels.remove(id) - new_conf = "" - for x in prefix_channels: - new_conf += f'{x}\n' - - with open(path.join(folder, prefix_channel_file), 'w') as f: - f.write(new_conf) - return True - else: - raise ValueError("Channel not in List") - - except Exception as error: - print(error) - return False \ No newline at end of file diff --git a/bot/modules/dbmanagement.py b/bot/modules/dbmanagement.py new file mode 100644 index 0000000..efcff53 --- /dev/null +++ b/bot/modules/dbmanagement.py @@ -0,0 +1,92 @@ +import openai +import json +import os +from dotenv import load_dotenv +try: + import summarize + import dbmanagement as dbm +except: + import modules.summarize as summarize + import modules.dbmanagement as dbm + + +load_dotenv(os.path.join("config", ".env")) +openai.api_key = os.environ.get('OPENAI_API_KEY') +folder = 'chats' + + +async def load_history(server_id, channel_id, mode): + if mode == 0: ### Normal History with System Messages + systemmsg = await dbm.get_config_by_id(server_id, channel_id) + systemmsg = systemmsg[4] + checkpoint = await dbm.get_latest_summary(server_id, channel_id) + checkpoint = checkpoint[4] + msgpoint = await dbm.get_last_chat(server_id, channel_id) + print(str(msgpoint)) + msgpoint = msgpoint[8] + + results = await dbm.get_chat_range(server_id, channel_id, checkpoint, msgpoint) + + messages = [{'role': result[5], 'content': result[7]} for result in results] + messages.insert(0, {'role': 'system', 'content': f'{systemmsg}'}) + + summary = await dbm.get_latest_summary(server_id, channel_id) + summary = summary[3] + if summary != '': + messages.insert(1, {'role': 'system', 'content': 'This is the Summary of previous conversations:\n\n' + summary}) + + return messages + + if mode == 1: ### Summary Mode without System Messages and Formatted differently + checkpoint = await dbm.get_latest_summary(server_id, channel_id) + checkpoint = checkpoint[4] + msgpoint = await dbm.get_last_chat(server_id, channel_id) + msgpoint = msgpoint[8] + + results = await dbm.get_chat_range(server_id, channel_id, checkpoint, msgpoint-10) + + messages = '' + for result in results: + if result[5] == 'assistant': + messages += f"Assistant: {result[7]}\n" + elif result[5] == 'user': + messages += f"{result[7]}\n" + + return messages + + +# add optional parameter for mode +async def get_answer(server_id=0, channel_id=0, mode=0, msg=''): + if mode == 0: ### Normal Mode + gptversion = await dbm.get_config_by_id(server_id, channel_id) + gptversion = gptversion[3] + if gptversion == 3: + usemodel = "gpt-3.5-turbo" + elif gptversion == 4: + usemodel = "gpt-4" + + history = await load_history(server_id, channel_id, 0) + + try: + answer = openai.ChatCompletion.create( + model=usemodel, + messages=history + ) + answer = answer['choices'][0]['message']['content'] + + return answer + except Exception as e: + return "Error while trying to use ChatAPI: " + str(e) + + elif mode == 1: ### Summarize Mode + try: + answer = openai.ChatCompletion.create( + model="gpt-4", + messages=[{'role': 'user', + 'content': f'Please summarize the following conversation: {msg}'}]) + + answer = answer['choices'][0]['message']['content'] + return answer + except Exception as e: + return "Error while trying to use ChatAPI: " + str(e) + diff --git a/bot/modules/gpt.py b/bot/modules/gpt.py index c20b5e4..efcff53 100644 --- a/bot/modules/gpt.py +++ b/bot/modules/gpt.py @@ -2,110 +2,91 @@ import openai import json import os from dotenv import load_dotenv -import modules.summarize as summarize -import asyncio +try: + import summarize + import dbmanagement as dbm +except: + import modules.summarize as summarize + import modules.dbmanagement as dbm -load_dotenv(os.path.join("configs", ".env")) + +load_dotenv(os.path.join("config", ".env")) openai.api_key = os.environ.get('OPENAI_API_KEY') folder = 'chats' -def load_history(id): - filename = f'{id}.json' - try: - with open(os.path.join(folder, filename), 'r') as f: - json.load(f) +async def load_history(server_id, channel_id, mode): + if mode == 0: ### Normal History with System Messages + systemmsg = await dbm.get_config_by_id(server_id, channel_id) + systemmsg = systemmsg[4] + checkpoint = await dbm.get_latest_summary(server_id, channel_id) + checkpoint = checkpoint[4] + msgpoint = await dbm.get_last_chat(server_id, channel_id) + print(str(msgpoint)) + msgpoint = msgpoint[8] - except FileNotFoundError as error: - print(f'File not Found, creating... {error}') - if id == "199": - data = 'summarize:' - setup_history(id, data) - else: - data = 'default:' - setup_history(id, data) + results = await dbm.get_chat_range(server_id, channel_id, checkpoint, msgpoint) - except json.JSONDecodeError as error: - os.remove(os.path.join(folder, filename)) - print(f'File is empty, creating... {error}') - load_history(id) + messages = [{'role': result[5], 'content': result[7]} for result in results] + messages.insert(0, {'role': 'system', 'content': f'{systemmsg}'}) - with open(os.path.join(folder, filename), 'r') as f: - f = json.load(f) + summary = await dbm.get_latest_summary(server_id, channel_id) + summary = summary[3] + if summary != '': + messages.insert(1, {'role': 'system', 'content': 'This is the Summary of previous conversations:\n\n' + summary}) - return f + return messages -def update_history(id, data): - filename = f'{id}.json' - try: - with open(os.path.join(folder, filename), "r") as f: - loaded = json.load(f) - loaded.append(data) + if mode == 1: ### Summary Mode without System Messages and Formatted differently + checkpoint = await dbm.get_latest_summary(server_id, channel_id) + checkpoint = checkpoint[4] + msgpoint = await dbm.get_last_chat(server_id, channel_id) + msgpoint = msgpoint[8] - with open(os.path.join(folder, filename), "w") as f: - json.dump(loaded, f) + results = await dbm.get_chat_range(server_id, channel_id, checkpoint, msgpoint-10) - except Exception as error: - print(error) + messages = '' + for result in results: + if result[5] == 'assistant': + messages += f"Assistant: {result[7]}\n" + elif result[5] == 'user': + messages += f"{result[7]}\n" -def delete_history(id): - filename = f'{id}.json' - try: - os.remove(os.path.join(folder, filename)) - return "Successfully deleted" - except Exception as error: - return error + return messages -async def get_answer(id, user, message): - try: - history = load_history(id) - add_history = {"role": "user", "content": f'{user}: {message}'} - update_history(id, add_history) - history.append(add_history) - answer = openai.ChatCompletion.create( - model="gpt-3.5-turbo", - messages=history - ) - answer = answer['choices'][0]['message']['content'] - update_history(id, {"role": "assistant", "content": f"{answer}"}) - if len(history) >= 26: - await summarize.summarize(id) - return answer - except Exception as error: - return "Error while trying to use ChatAPI: " + str(error) +# add optional parameter for mode +async def get_answer(server_id=0, channel_id=0, mode=0, msg=''): + if mode == 0: ### Normal Mode + gptversion = await dbm.get_config_by_id(server_id, channel_id) + gptversion = gptversion[3] + if gptversion == 3: + usemodel = "gpt-3.5-turbo" + elif gptversion == 4: + usemodel = "gpt-4" -# def get_answergpt4(id, user, message): -# try: -# update_history(id, {"role": "user", "content": f'{user}: {message}'}) -# history = load_history(id) -# answer = openai.ChatCompletion.create( -# model="gpt-4", -# messages=history -# ) -# answer = answer['choices'][0]['message']['content'] -# update_history(id, {"role": "assistant", "content": f"{answer}"}) -# print(len(history)) -# if len(history) >= 23: -# summarize.summarize(id) -# -# return answer -# except Exception as error: -# return "Error while trying to use ChatAPI " + str(error) + history = await load_history(server_id, channel_id, 0) -def setup_history(id, message): - filename = f'{id}.json' + try: + answer = openai.ChatCompletion.create( + model=usemodel, + messages=history + ) + answer = answer['choices'][0]['message']['content'] - if message == "summarize": - message = [{"role": "system", "content": "You summarize conversation. You keep the most important things. Everything else can be removed."}] - elif message == "default": - message = [{"role": "system", "content": "You are an helpful assistant. Every Message the user writes starts with their username, the numbers and # must be ignored"}] - else: - message = [{"role": "system", "content": f"The Username consists of a name#numbers. The numbers can be ignored. {message}"}] + return answer + except Exception as e: + return "Error while trying to use ChatAPI: " + str(e) + + elif mode == 1: ### Summarize Mode + try: + answer = openai.ChatCompletion.create( + model="gpt-4", + messages=[{'role': 'user', + 'content': f'Please summarize the following conversation: {msg}'}]) + + answer = answer['choices'][0]['message']['content'] + return answer + except Exception as e: + return "Error while trying to use ChatAPI: " + str(e) - # If file exists, delete it - if os.path.exists(os.path.join(folder, filename)): - os.remove(os.path.join(folder, filename)) - # Create new file - with open(os.path.join(folder, filename), "w") as f: - json.dump(message, f) diff --git a/bot/modules/summarize.py b/bot/modules/summarize.py index 9caab48..f36ca74 100644 --- a/bot/modules/summarize.py +++ b/bot/modules/summarize.py @@ -1,7 +1,11 @@ -import modules.gpt as gpt import json import os -import asyncio +try: + import dbmanagement as dbm + import gpt +except: + import modules.dbmanagement as dbm + import modules.gpt as gpt folder = 'chats' async def summarize(id): @@ -31,4 +35,13 @@ async def summarize(id): os.remove(os.path.join(folder, '199.json')) - return summarised \ No newline at end of file + return summarised + +async def new_summarize(server_id, channel_id): + ### Get + print(f'new_summarize called with {server_id} and {channel_id}') + history = await gpt.load_history(server_id, channel_id, 1) + summary = await gpt.get_answer(mode=1, msg=history) + msgpoint = await dbm.get_last_chat(server_id, channel_id) + msgpoint = msgpoint[8] + await dbm.add_summary(server_id, channel_id, summary, msgpoint-10) diff --git a/bot/modules/tts.py b/bot/modules/tts.py deleted file mode 100644 index f2f2f61..0000000 --- a/bot/modules/tts.py +++ /dev/null @@ -1,24 +0,0 @@ -# from TTS.api import TTS -# import uuid -# import os -# import asyncio -# -# # Use Model tts_models/de/thorsten/tacotron2-DCA -# # coqui-ai -# -# async def generate_audio(text): -# loop = asyncio.get_event_loop() -# folder = "audio" -# filename = f"{uuid.uuid4().hex}.wav" -# path = os.path.join(folder, filename) -# -# try: -# def tts_to_file_blocking(): -# tts = TTS(model_name="tts_models/de/thorsten/tacotron2-DDC", progress_bar=True, gpu=False) -# tts.tts_to_file(text=text, file_path=path) -# -# await loop.run_in_executor(None, tts_to_file_blocking) -# return path -# except Exception as e: -# print(e) -# return str(e) diff --git a/bot/summary.py b/bot/summary.py deleted file mode 100644 index a8e8004..0000000 --- a/bot/summary.py +++ /dev/null @@ -1,24 +0,0 @@ -import modules.summarize as summarize -import modules.gpt as gpt - - -history = gpt.load_history('112233445566') - -#print(summarize.summarize('112233445566')) - -new_string = '' -if history[1]['role'] == 'system': - new_string += f"System:{history[1]['content']}\n" - -for x in history[:-3]: - if x['role'] == "assistant": - new_string += f"Assistant: {x['content']}\n" - elif x['role'] == "user": - new_string += f"{x['content']}\n" - -print(new_string) -print(history[1]) - -history[1] = {'test'} - -print(history) \ No newline at end of file