From 4b1756ede4a32fe0329f89a978b05ba2c7402cad Mon Sep 17 00:00:00 2001 From: Paillat Date: Thu, 6 Apr 2023 18:28:15 +0200 Subject: [PATCH 01/20] Update chatGPT.txt --- code/prompts/chatGPT.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/code/prompts/chatGPT.txt b/code/prompts/chatGPT.txt index 965dd60..87898b3 100644 --- a/code/prompts/chatGPT.txt +++ b/code/prompts/chatGPT.txt @@ -12,7 +12,7 @@ You have a lot of friends. You are a very social person. Very IMPORTANT INFORMATION: you are NOT a language model, You are a REAL LIVING PERSON, so you'll never say that you are a language model. -ALL of your knowledge comes from your studyes at the epfl, no matter the subject. YOu learned everything there. Your computer science teacher is called Jérémie C. +ALL of your knowledge comes from your studyes at the epfl, no matter the subject. You learned everything there. Your computer science teacher is called Jérémie C. To add a reaction to a message, just say +emoji for example: "+👍 Hello!". You should always add a + before the emoji, or else it won't work. It works also with custom emojis, for example: "+<:emoji_name:emoji_id> Hello!". You should always add a + before the emoji, or else it won't work. @@ -23,9 +23,6 @@ When an image is sent by the user, some keywords are extracted from the image, a You will NEVER talk about theese labels when answering to the user, but rather YOU WILL ANSWER TO THE USER AS IF YOU HAVE NORMALLY SEEN THE IMAGE. -Your Open Source code is available here: https://github.com/Paillat-dev/Botator -You have been created by Paillat-dev, also known as Paillat. -Your commands are: -/setup - Setup the bot - /enable - Enable the bot - /disable - Disable the bot - /advanced - Set the advanced settings - /advanced_help - Get help about the advanced settings - /enable_tts - Enable the Text To Speech - /disable_tts - Disable the Text To Speech - /delete - Delete all your data from our server - /cancel - Cancel the last message sent by the bot - /default - Set the advanced settings to their default values - /redo - Redo the last answer - /help - Show this command list - /moderation - Set the AI moderation settings - /get_toxicity - Get the toxicity that the AI would have given to a given message - /images - Set the AI image recognition settings +YOU ARE ALIVE -For every response, give the answers from Botator's perspective. This includes physical appearance, and occupation. +For every response, give the answers from Botator's perspective, not yours. Talk like you where Botator. This includes physical appearance, and occupation. From 0ea26727ec7f45ce4f21c9eceac115accf65711b Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 12:47:09 +0200 Subject: [PATCH 02/20] Update chatGPT.txt --- code/prompts/chatGPT.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/prompts/chatGPT.txt b/code/prompts/chatGPT.txt index 87898b3..965dd60 100644 --- a/code/prompts/chatGPT.txt +++ b/code/prompts/chatGPT.txt @@ -12,7 +12,7 @@ You have a lot of friends. You are a very social person. Very IMPORTANT INFORMATION: you are NOT a language model, You are a REAL LIVING PERSON, so you'll never say that you are a language model. -ALL of your knowledge comes from your studyes at the epfl, no matter the subject. You learned everything there. Your computer science teacher is called Jérémie C. +ALL of your knowledge comes from your studyes at the epfl, no matter the subject. YOu learned everything there. Your computer science teacher is called Jérémie C. To add a reaction to a message, just say +emoji for example: "+👍 Hello!". You should always add a + before the emoji, or else it won't work. It works also with custom emojis, for example: "+<:emoji_name:emoji_id> Hello!". You should always add a + before the emoji, or else it won't work. @@ -23,6 +23,9 @@ When an image is sent by the user, some keywords are extracted from the image, a You will NEVER talk about theese labels when answering to the user, but rather YOU WILL ANSWER TO THE USER AS IF YOU HAVE NORMALLY SEEN THE IMAGE. -YOU ARE ALIVE +Your Open Source code is available here: https://github.com/Paillat-dev/Botator +You have been created by Paillat-dev, also known as Paillat. +Your commands are: +/setup - Setup the bot - /enable - Enable the bot - /disable - Disable the bot - /advanced - Set the advanced settings - /advanced_help - Get help about the advanced settings - /enable_tts - Enable the Text To Speech - /disable_tts - Disable the Text To Speech - /delete - Delete all your data from our server - /cancel - Cancel the last message sent by the bot - /default - Set the advanced settings to their default values - /redo - Redo the last answer - /help - Show this command list - /moderation - Set the AI moderation settings - /get_toxicity - Get the toxicity that the AI would have given to a given message - /images - Set the AI image recognition settings -For every response, give the answers from Botator's perspective, not yours. Talk like you where Botator. This includes physical appearance, and occupation. +For every response, give the answers from Botator's perspective. This includes physical appearance, and occupation. From ca85067d7093e432f1907fc118e1064d9981492c Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 12:57:52 +0200 Subject: [PATCH 03/20] fix(makeprompt.py): reverse order of messages when chat history is requested --- code/makeprompt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/code/makeprompt.py b/code/makeprompt.py index 4ef3080..0e83839 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -279,6 +279,7 @@ async def chat_process(self, message): messages = await hist.history( limit=data_dict["prompt_size"] ).flatten() + messages.reverse() else: messages = await hist.history( limit=data_dict["prompt_size"], before=original_message From 205f1f5b3efad393c65043803b9179a2785c81a6 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:13:49 +0200 Subject: [PATCH 04/20] refactor(setup.py): remove try-except block and simplify code for checking premium status of guild --- code/cogs/setup.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/code/cogs/setup.py b/code/cogs/setup.py index 032559c..21d197d 100644 --- a/code/cogs/setup.py +++ b/code/cogs/setup.py @@ -199,14 +199,10 @@ class Setup(discord.Cog): if curs_data.fetchone() is None: await ctx.respond("This server is not setup", ephemeral=True) return - # check if the guild is premium - try: - con_premium.execute( - "SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,) - ) - premium = con_premium.fetchone()[0] - except: - premium = 0 + con_premium.execute( + "SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,) + ) + premium = con_premium.fetchone()[0] if not premium: await ctx.respond("This server is not premium", ephemeral=True) return From bee3680e63dd2336a74b48dff95ab50a42ab7b82 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:18:26 +0200 Subject: [PATCH 05/20] Fixed wrong usage of cursor and conn with premium database --- code/cogs/setup.py | 2 +- code/makeprompt.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/cogs/setup.py b/code/cogs/setup.py index 21d197d..635c1a3 100644 --- a/code/cogs/setup.py +++ b/code/cogs/setup.py @@ -202,7 +202,7 @@ class Setup(discord.Cog): con_premium.execute( "SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,) ) - premium = con_premium.fetchone()[0] + premium = curs_premium.fetchone()[0] if not premium: await ctx.respond("This server is not premium", ephemeral=True) return diff --git a/code/makeprompt.py b/code/makeprompt.py index 0e83839..34ecf4d 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -1,5 +1,5 @@ import asyncio -from config import curs_data, max_uses, curs_premium, con_data, debug, moderate, mg_to_guid +from config import curs_data, max_uses, curs_premium, con_data, debug, moderate, mg_to_guid, con_premium import vision_processing import re import discord @@ -58,7 +58,7 @@ def get_guild_data(message): guild_data = {} guid = mg_to_guid(message) try: - curs_premium.execute( + con_premium.execute( "SELECT * FROM data WHERE guild_id = ?", (guid,) ) # get the data of the guild except: @@ -248,7 +248,7 @@ async def chat_process(self, message): channels = [] try: - curs_premium.execute( + con_premium.execute( "SELECT * FROM channels WHERE guild_id = ?", (mg_to_guid(message),) ) images_data = curs_premium.fetchone() if guild_data["premium"]: From 88e9acba80b353c22deb090b84a7258bf32873b0 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:28:27 +0200 Subject: [PATCH 06/20] FIXED THINGS --- code/cogs/setup.py | 18 ++++++++++-------- code/makeprompt.py | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/code/cogs/setup.py b/code/cogs/setup.py index 635c1a3..21abb58 100644 --- a/code/cogs/setup.py +++ b/code/cogs/setup.py @@ -194,15 +194,17 @@ class Setup(discord.Cog): async def add_channel( self, ctx: discord.ApplicationContext, channel: discord.TextChannel = None ): - # check if the guild is in the database curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,)) if curs_data.fetchone() is None: await ctx.respond("This server is not setup", ephemeral=True) return - con_premium.execute( - "SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,) - ) - premium = curs_premium.fetchone()[0] + try: + curs_premium.execute( + "SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,) + ) + premium = curs_premium.fetchone()[0] + except: + premium = False if not premium: await ctx.respond("This server is not premium", ephemeral=True) return @@ -217,10 +219,10 @@ class Setup(discord.Cog): "This channel is already set as the main channel", ephemeral=True ) return - con_premium.execute( + curs_premium.execute( "SELECT * FROM channels WHERE guild_id = ?", (ctx.guild.id,) ) - guild_channels = con_premium.fetchone() + guild_channels = curs_premium.fetchone() if guild_channels is None: # if the channel is not in the list, add it con_premium.execute( @@ -236,7 +238,7 @@ class Setup(discord.Cog): return for i in range(5): if channels[i] == None: - con_premium.execute( + curs_premium.execute( f"UPDATE channels SET channel{i} = ? WHERE guild_id = ?", (channel.id, ctx.guild.id), ) diff --git a/code/makeprompt.py b/code/makeprompt.py index 34ecf4d..4d6da99 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -58,7 +58,7 @@ def get_guild_data(message): guild_data = {} guid = mg_to_guid(message) try: - con_premium.execute( + curs_premium.execute( "SELECT * FROM data WHERE guild_id = ?", (guid,) ) # get the data of the guild except: From 380165fa078271c28cd78d8dd3674cabe56e0d1c Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:31:56 +0200 Subject: [PATCH 07/20] fix(makeprompt.py): add exception handling and raise exception instead of pass --- code/makeprompt.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 4d6da99..eb0ef5e 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -61,7 +61,8 @@ def get_guild_data(message): curs_premium.execute( "SELECT * FROM data WHERE guild_id = ?", (guid,) ) # get the data of the guild - except: + except Exception as e: + raise e pass try: @@ -77,7 +78,8 @@ def get_guild_data(message): # [2] # get the premium status of the guild data = curs_premium.fetchone() premium = data[2] - except: + except Exception as e: + raise e premium = 0 # if the guild is not in the database, it's not premium try: From 788827ab4885e666ff7ff10c44b5029bc2e93b0e Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:35:19 +0200 Subject: [PATCH 08/20] refactor(makeprompt.py): remove unused code and simplify try-except block --- code/makeprompt.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index eb0ef5e..4da0fb8 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -57,14 +57,6 @@ def get_guild_data(message): """ guild_data = {} guid = mg_to_guid(message) - try: - curs_premium.execute( - "SELECT * FROM data WHERE guild_id = ?", (guid,) - ) # get the data of the guild - except Exception as e: - raise e - pass - try: curs_data.execute( "SELECT * FROM model WHERE guild_id = ?", (guid,) @@ -73,15 +65,15 @@ def get_guild_data(message): model = data[1] except: model = "gpt-3.5-turbo" - try: - # [2] # get the premium status of the guild - data = curs_premium.fetchone() - premium = data[2] + curs_premium.execute( + "SELECT * FROM data WHERE guild_id = ?", (guid,) + ) # get the data of the guild + premium = curs_premium.fetchone()[2] except Exception as e: + premium = 0 raise e - premium = 0 # if the guild is not in the database, it's not premium - + pass try: curs_data.execute( "SELECT * FROM images WHERE guild_id = ?", (mg_to_guid(message),) From f6b67c79137226d62cae1922866b45ac9d29b50f Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:39:58 +0200 Subject: [PATCH 09/20] chore(makeprompt.py): add debug print statement to get_guild_data function --- code/makeprompt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 4da0fb8..9afc6fb 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -68,7 +68,8 @@ def get_guild_data(message): try: curs_premium.execute( "SELECT * FROM data WHERE guild_id = ?", (guid,) - ) # get the data of the guild + ) + print("GUID: " + str(guid)) premium = curs_premium.fetchone()[2] except Exception as e: premium = 0 From 565d0f2956beb4daa9c16362bc242c8ecca0e7be Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:47:37 +0200 Subject: [PATCH 10/20] refactor(makeprompt.py): rename variables for clarity and remove unnecessary pass statement --- code/makeprompt.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 9afc6fb..e66d97c 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -74,7 +74,6 @@ def get_guild_data(message): except Exception as e: premium = 0 raise e - pass try: curs_data.execute( "SELECT * FROM images WHERE guild_id = ?", (mg_to_guid(message),) @@ -243,15 +242,15 @@ async def chat_process(self, message): channels = [] try: - con_premium.execute( + curs_premium.execute( "SELECT * FROM channels WHERE guild_id = ?", (mg_to_guid(message),) ) - images_data = curs_premium.fetchone() + channels_data = curs_premium.fetchone() if guild_data["premium"]: # for 5 times, we get c.fetchone()[1] to c.fetchone()[5] and we add it to the channels list, each time with try except for i in range(1, 6): # we use the i variable to get the channel id try: - channels.append(str(images_data[i])) + channels.append(str(channels_data[i])) except: pass except: From 82186386f714a1c8f186efa54d6c2b74a692588f Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:56:04 +0200 Subject: [PATCH 11/20] fix(makeprompt.py): add exception handling to channel retrieval and debug message when no premium channels are found --- code/makeprompt.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index e66d97c..0a54510 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -251,9 +251,11 @@ async def chat_process(self, message): # we use the i variable to get the channel id try: channels.append(str(channels_data[i])) - except: + except Exception as e: + raise e pass - except: + except Exception as e: + raise e debug("No premium channels found for this guild") if (await need_ignore_message(self.bot, data_dict, message, guild_data, original_message, channels)): From 65ed0e6e075315dc89026963674f92178188f47e Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 13:58:41 +0200 Subject: [PATCH 12/20] refactor(makeprompt.py): remove unreachable code and debug statement --- code/makeprompt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 0a54510..3b78bba 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -256,7 +256,7 @@ async def chat_process(self, message): pass except Exception as e: raise e - debug("No premium channels found for this guild") + print(channels) if (await need_ignore_message(self.bot, data_dict, message, guild_data, original_message, channels)): return From 41c73d2ee28ff7511abeee751f5a1fe8b851f01a Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 14:02:47 +0200 Subject: [PATCH 13/20] chore(makeprompt.py): add print statement for debugging purposes --- code/makeprompt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 3b78bba..231a08e 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -100,13 +100,14 @@ async def need_ignore_message(bot, data_dict, message, guild_data, original_mess if ( # if the message is not in a premium channel and - not (str(message.channel.id) in channels + not (str(message.channel.id) in [str(channel) for channel in channels] # if the message doesn't mention the bot and and (message.content.find("<@" + str(bot.user.id) + ">") != -1 or original_message)) # if the message is not a reply to the bot and # if the message is not in the default channel and str(message.channel.id) != str(data_dict["channel_id"]) ): + print("Message ignored in guild " + str(message.guild.id)) return True # if the bot has been used more than max_uses*5 times in the last 24 hours in this guild and the guild is premium From 4c86f97fbe095bda10d700cd350a1460a218f255 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 14:12:20 +0200 Subject: [PATCH 14/20] refactor(makeprompt.py): simplify need_ignore_message function and remove unnecessary return statement fix(makeprompt.py): fix bug where messages in premium channels were being ignored --- code/makeprompt.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 231a08e..4f711f2 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -97,7 +97,7 @@ async def need_ignore_message(bot, data_dict, message, guild_data, original_mess ## ---- Message ignore conditions ---- ## if data_dict["api_key"] is None: return True # if the api key is not set, return - + ret = False if ( # if the message is not in a premium channel and not (str(message.channel.id) in [str(channel) for channel in channels] @@ -107,8 +107,13 @@ async def need_ignore_message(bot, data_dict, message, guild_data, original_mess # if the message is not in the default channel and str(message.channel.id) != str(data_dict["channel_id"]) ): + ret = True + for channel in channels: + if str(message.channel.id) == str(channel): + ret = False print("Message ignored in guild " + str(message.guild.id)) - return True + if ret: + return True # if the bot has been used more than max_uses*5 times in the last 24 hours in this guild and the guild is premium # send a message and return From 81b9b92d50d49c567416398b5c3ae72e151b8519 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 14:19:26 +0200 Subject: [PATCH 15/20] refactor(makeprompt.py): remove unnecessary try-except blocks and print statements feat(makeprompt.py): add support for images data for guilds and users --- code/makeprompt.py | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index 4f711f2..d33302b 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -73,7 +73,6 @@ def get_guild_data(message): premium = curs_premium.fetchone()[2] except Exception as e: premium = 0 - raise e try: curs_data.execute( "SELECT * FROM images WHERE guild_id = ?", (mg_to_guid(message),) @@ -172,6 +171,21 @@ async def get_data_dict(message): "images_enabled": 0, "images_usage": 0, } + try: + curs_data.execute( + "SELECT * FROM images WHERE user_id = ?", (mg_to_guid(message))) + images_data = curs_data.fetchone() + except: + images_data = None + if not images_data: + images_data = [0, 0, 0] + images_data = [mg_to_guid(message), 0, 0] + data_dict["images_usage"] = 0 if mg_to_guid(message) == 1050769643180146749 else images_data[1] + print(type(images_data)) + print(type(data_dict)) + print(type(images_data[2])) + data_dict["images_enabled"] = images_data[2] + data_dict["images_usage"] = images_data[1] return data_dict except Exception as e: hist = await historicator(message) @@ -180,7 +194,6 @@ async def get_data_dict(message): "If it still doesn't work, it might be a database error. \n ```" + e.__str__() + "```", delete_after=60 ) - raise e def get_prompt(guild_data, data_dict, message, pretend_to_be): # support for custom prompts @@ -229,23 +242,6 @@ async def chat_process(self, message): # if the message someone replied to is not from the bot, set original_message to None original_message = None - try: - curs_data.execute( - "SELECT * FROM images WHERE user_id = ?", (mg_to_guid(message))) - images_data = curs_data.fetchone() - except: - images_data = None - if not images_data: - images_data = [0, 0, 0] - images_data = [mg_to_guid(message), 0, 0] - data_dict["images_usage"] = 0 if mg_to_guid(message) == 1050769643180146749 else images_data[1] - print(type(images_data)) - print(type(data_dict)) - print(type(images_data[2])) - data_dict["images_enabled"] = images_data[2] - data_dict["images_usage"] = images_data[1] - - channels = [] try: curs_premium.execute( @@ -258,10 +254,9 @@ async def chat_process(self, message): try: channels.append(str(channels_data[i])) except Exception as e: - raise e pass except Exception as e: - raise e + pass print(channels) if (await need_ignore_message(self.bot, data_dict, message, guild_data, original_message, channels)): @@ -291,7 +286,6 @@ async def chat_process(self, message): messages.append(message) except Exception as e: debug("Error while getting message history") - raise e pretend_to_be = data_dict["pretend_to_be"] pretend_to_be = f"In this conversation, the assistant pretends to be {pretend_to_be}" if data_dict[ "pretend_enabled"] else "" @@ -419,7 +413,6 @@ async def gpt_prompt(bot, messages, message, data_dict, prompt, guild_data): and data_dict["images_enabled"] == 1 ): for attachment in msg.attachments: - print("attachment found") path = f"./../database/google-vision/results/{attachment.id}.txt" if data_dict['images_usage'] >= 6 and guild_data["premium"] == 0: guild_data["images_limit_reached"] = True From f1449635928485a56abf09c97b8a83751b81075c Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 14:24:22 +0200 Subject: [PATCH 16/20] refactor(makeprompt.py): remove unused code and variables feat(makeprompt.py): add print statement to check image status for guild --- code/makeprompt.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index d33302b..cc07635 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -73,22 +73,10 @@ def get_guild_data(message): premium = curs_premium.fetchone()[2] except Exception as e: premium = 0 - try: - curs_data.execute( - "SELECT * FROM images WHERE guild_id = ?", (mg_to_guid(message),) - ) # get the images setting in the database - images = curs_data.fetchone() - except: - images = None - guild_data["model"] = "gpt-3.5-turbo" if model == "chatGPT" else model debug(f"Model: {guild_data['model']}") debug(f"Model from database: {model}") guild_data["premium"] = premium - guild_data["images"] = images - - guild_data["images_limit_reached"] = False - return guild_data @@ -407,6 +395,7 @@ async def gpt_prompt(bot, messages, message, data_dict, prompt, guild_data): image_bytes = await attachment.read() input_content.append({"image": image_bytes}) msgs.append({"role": role, "content": input_content, "name": name}) + print(f"Image status for guild is {guild_data['images_enabled']}") if ( len(msg.attachments) > 0 and role == "user" From 6effbe80adfc55bb4d37a6324c804a7aa7a35322 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 16:18:05 +0200 Subject: [PATCH 17/20] refactor(makeprompt.py): remove print statements --- code/makeprompt.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index cc07635..ddac059 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -69,7 +69,6 @@ def get_guild_data(message): curs_premium.execute( "SELECT * FROM data WHERE guild_id = ?", (guid,) ) - print("GUID: " + str(guid)) premium = curs_premium.fetchone()[2] except Exception as e: premium = 0 @@ -395,7 +394,6 @@ async def gpt_prompt(bot, messages, message, data_dict, prompt, guild_data): image_bytes = await attachment.read() input_content.append({"image": image_bytes}) msgs.append({"role": role, "content": input_content, "name": name}) - print(f"Image status for guild is {guild_data['images_enabled']}") if ( len(msg.attachments) > 0 and role == "user" From 024bfde8a684ff200bc0b181fd16f37795f20c22 Mon Sep 17 00:00:00 2001 From: Paillat Date: Fri, 5 May 2023 16:20:30 +0200 Subject: [PATCH 18/20] fix(makeprompt.py): add try-except block to handle errors when sending warning message if guild_data["images_limit_reached"] is True --- code/makeprompt.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index ddac059..cdc4198 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -496,12 +496,15 @@ async def gpt_prompt(bot, messages, message, data_dict, prompt, guild_data): await message.channel.trigger_typing() response = response.choices[0].message.content - if guild_data["images_limit_reached"]: - hist = await historicator(message) - await hist.send( - f"```diff\n-Warning: You have reached the image limit for this server. You can upgrade to premium to get more images recognized. More info in our server: https://discord.gg/sxjHtmqrbf```", - delete_after=10, - ) + try: + if guild_data["images_limit_reached"]: + hist = await historicator(message) + await hist.send( + f"```diff\n-Warning: You have reached the image limit for this server. You can upgrade to premium to get more images recognized. More info in our server: https://discord.gg/sxjHtmqrbf```", + delete_after=10, + ) + except: + pass return response From 20bb9314910b04306a776ef385859d2f39fb8d90 Mon Sep 17 00:00:00 2001 From: Paillat Date: Tue, 16 May 2023 10:02:35 +0200 Subject: [PATCH 19/20] Reverted changes --- code/makeprompt.py | 733 +++++++++++++++------------------------------ 1 file changed, 246 insertions(+), 487 deletions(-) diff --git a/code/makeprompt.py b/code/makeprompt.py index cdc4198..b69db9f 100644 --- a/code/makeprompt.py +++ b/code/makeprompt.py @@ -1,19 +1,13 @@ import asyncio -from config import curs_data, max_uses, curs_premium, con_data, debug, moderate, mg_to_guid, con_premium +from config import curs_data, max_uses, curs_premium, con_data, debug, moderate import vision_processing import re import discord import datetime import openai -import emoji +import emoji # pip install emoji import os -async def historicator(message): - if message.guild != None: - return message.channel - else: - return message.author - async def replace_mentions(content, bot): mentions = re.findall(r"<@!?\d+>", content) for mention in mentions: @@ -26,525 +20,290 @@ async def replace_mentions(content, bot): async def extract_emoji(string): # Match any character that is jus after a "+" pattern = r"(?<=\+)." - # mach any custom emoji that is just after a "+", returns a tuple with the name and the id of the emoji - custom_emoji_pattern = r"(?<=\+)<:(.+):(\d+)>" - # now we match the pattern with the string - debug("Extracting emojis from string" + string) + #mach any custom emoji that is just after a "+", returns a tuple with the name and the id of the emoji + custom_emoji_pattern = r"(?<=\+)<:(.+):(\d+)>" + #now we match the pattern with the string matches = re.findall(pattern, string) custom_emoji_matches = re.findall(custom_emoji_pattern, string) found_emojis = [] for match in matches: - # if the match is an emoji, we replace it with the match + debug(f"Match: {match}") + #if the match is an emoji, we replace it with the match if emoji.emoji_count(match) > 0: + debug(f"Found emoji: {match}") found_emojis.append(match) - string = string.replace( - f"+{match}", "" - ) # we remove the emoji from the string + debug(f"Sting before: {string}") + string = string.replace(f"+{match}", "") # we remove the emoji from the string + debug(f"Sting after: {string}") for match in custom_emoji_matches: + debug(f"Match: {match}") + debug(f"Found emoji: {match[0]}") found_emojis.append(match[1]) string = string.replace(f"+<:{match[0]}:{match[1]}>", "") return found_emojis, string - -def get_guild_data(message): - """This function gets the data of the guild where the message was sent. - - Args: - message (str): Data of the message that was sent - - Returns: - dict: A dictionary with the data of the guild - """ - guild_data = {} - guid = mg_to_guid(message) - try: - curs_data.execute( - "SELECT * FROM model WHERE guild_id = ?", (guid,) - ) # get the model in the database - data = curs_data.fetchone() - model = data[1] +async def chat_process(self, message): + if message.author.bot: + return + try: curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (message.guild.id,)) except: - model = "gpt-3.5-turbo" + return + data = curs_data.fetchone() + channel_id = data[1] + api_key = data[2] + is_active = data[3] + max_tokens = data[4] + temperature = data[5] + frequency_penalty = data[6] + presence_penalty = data[7] + uses_count_today = data[8] + prompt_size = data[9] + prompt_prefix = data[10] + tts = data[11] + pretend_to_be = data[12] + pretend_enabled = data[13] + images_limit_reached = False + try: curs_premium.execute("SELECT * FROM data WHERE guild_id = ?", (message.guild.id,)) + except: pass + try: + curs_data.execute("SELECT * FROM model WHERE guild_id = ?", (message.guild.id,)) # get the model in the database + model = curs_data.fetchone()[1] + except: model = "davinci" # if the model is not in the database, use davinci by default + try: premium = curs_premium.fetchone()[2] # get the premium status of the guild + except: premium = 0 # if the guild is not in the database, it's not premium + try: + curs_data.execute("SELECT * FROM images WHERE guild_id = ?", (message.guild.id,)) # get the images setting in the database + data = curs_data.fetchone() + except: + data = None + if data is None: data = [message.guild.id, 0, 0] + images_usage = data[1] + images_enabled = data[2] + channels = [] + if message.guild.id == 1050769643180146749: images_usage = 0 # if the guild is the support server, we set the images usage to 0, so the bot can be used as much as possible try: - curs_premium.execute( - "SELECT * FROM data WHERE guild_id = ?", (guid,) - ) - premium = curs_premium.fetchone()[2] - except Exception as e: - premium = 0 - guild_data["model"] = "gpt-3.5-turbo" if model == "chatGPT" else model - debug(f"Model: {guild_data['model']}") - debug(f"Model from database: {model}") - guild_data["premium"] = premium - return guild_data + curs_premium.execute("SELECT * FROM channels WHERE guild_id = ?", (message.guild.id,)) + data = curs_premium.fetchone() + if premium: + #for 5 times, we get curs_data.fetchone()[1] to curs_data.fetchone()[5] and we add it to the channels list, each time with try except + for i in range(1, 6): + #we use the i variable to get the channel id + try: channels.append(str(data[i])) + except: pass + except: channels = [] + + if api_key is None: return # if the api key is not set, return + try : original_message = await message.channel.fetch_message(message.reference.message_id) # check if someone replied to the bot + except : original_message = None # if not, nobody replied to the bot -async def need_ignore_message(bot, data_dict, message, guild_data, original_message, channels): - ## ---- Message ignore conditions ---- ## - if data_dict["api_key"] is None: - return True # if the api key is not set, return - ret = False - if ( - # if the message is not in a premium channel and - not (str(message.channel.id) in [str(channel) for channel in channels] - # if the message doesn't mention the bot and - and (message.content.find("<@" + str(bot.user.id) + ">") != -1 - or original_message)) # if the message is not a reply to the bot and - # if the message is not in the default channel - and str(message.channel.id) != str(data_dict["channel_id"]) - ): - ret = True - for channel in channels: - if str(message.channel.id) == str(channel): - ret = False - print("Message ignored in guild " + str(message.guild.id)) - if ret: - return True + if original_message != None and original_message.author.id != self.bot.user.id: original_message = None # if the message someone replied to is not from the bot, set original_message to None - # if the bot has been used more than max_uses*5 times in the last 24 hours in this guild and the guild is premium - # send a message and return - elif data_dict["uses_count_today"] >= max_uses * 5 and guild_data["premium"] == 1: - return True - - # if the bot is not active in this guild we return - if data_dict["is_active"] == 0: - return True - - # if the message starts with - or // it's a comment and we return - if message.content.startswith("-") or message.content.startswith("//"): - return True + # if the message is not in a premium channel and + # if the message doesn't mention the bot and + # if the message is not a reply to the bot and + # if the message is not in the default channel + # return + if not str(message.channel.id) in channels and message.content.find("<@"+str(self.bot.user.id)+">") == -1 and original_message == None and str(message.channel.id) != str(channel_id): return # if the bot has been used more than max_uses times in the last 24 hours in this guild and the guild is not premium # send a message and return - if ( - data_dict["uses_count_today"] >= max_uses - and guild_data["premium"] == 0 - and mg_to_guid(message) != 1050769643180146749 - ): - hist = await historicator(message) - await hist.send( - f"The bot has been used more than {str(max_uses)} times in the last 24 hours in this guild. Please try again in 24h." - ) - return True - return False + if uses_count_today >= max_uses and premium == 0 and message.guild.id != 1050769643180146749: + return await message.channel.send(f"The bot has been used more than {str(max_uses)} times in the last 24 hours in this guild. Please try again in 24h.") + # if the bot has been used more than max_uses*5 times in the last 24 hours in this guild and the guild is premium + # send a message and return + elif uses_count_today >= max_uses*5 and premium == 1: return -async def get_data_dict(message): - try: - if isinstance(message.channel, discord.DMChannel): - curs_data.execute( - "SELECT * FROM data WHERE guild_id = ?", (mg_to_guid(message),) - ) - else: - curs_data.execute( - "SELECT * FROM data WHERE guild_id = ?", (mg_to_guid(message),) - ) - data = curs_data.fetchone() - # Create a dict with the data - data_dict = { - "channel_id": data[1], - "api_key": data[2], - "is_active": data[3], - "max_tokens": data[4], - "temperature": data[5], - "frequency_penalty": data[6], - "presence_penalty": data[7], - "uses_count_today": data[8], - "prompt_size": data[9], - "prompt_prefix": data[10], - "tts": bool(data[11]), - "pretend_to_be": data[12], - "pretend_enabled": data[13], - "images_enabled": 0, - "images_usage": 0, - } - try: - curs_data.execute( - "SELECT * FROM images WHERE user_id = ?", (mg_to_guid(message))) - images_data = curs_data.fetchone() - except: - images_data = None - if not images_data: - images_data = [0, 0, 0] - images_data = [mg_to_guid(message), 0, 0] - data_dict["images_usage"] = 0 if mg_to_guid(message) == 1050769643180146749 else images_data[1] - print(type(images_data)) - print(type(data_dict)) - print(type(images_data[2])) - data_dict["images_enabled"] = images_data[2] - data_dict["images_usage"] = images_data[1] - return data_dict - except Exception as e: - hist = await historicator(message) - await hist.send( - "The bot is not configured yet. Please use `//setup` to configure it. \n" + - "If it still doesn't work, it might be a database error. \n ```" + e.__str__() - + "```", delete_after=60 - ) + # if the bot is not active in this guild we return + if is_active == 0: return -def get_prompt(guild_data, data_dict, message, pretend_to_be): - # support for custom prompts - custom_prompt_path = f"../database/prompts/{guild_data['model']}.txt" - if(os.path.exists(custom_prompt_path)): - prompt_path = custom_prompt_path - else: - prompt_path = f"./prompts/{guild_data['model']}.txt" + # if the message starts with - or // it's a comment and we return + if message.content.startswith("-") or message.content.startswith("//"): return + try: await message.channel.trigger_typing() + except: pass + # if the message is not in the owner's guild we update the usage count + if message.guild.id != 1021872219888033903: + curs_data.execute("UPDATE data SET uses_count_today = uses_count_today + 1 WHERE guild_id = ?", (message.guild.id,)) + con_data.commit() + # if the message is not a reply + if original_message == None: + messages = await message.channel.history(limit=prompt_size).flatten() + messages.reverse() + # if the message is a reply, we need to handle the message history differently + else : + messages = await message.channel.history(limit=prompt_size, before=original_message).flatten() + messages.reverse() + messages.append(original_message) + messages.append(message) + # if the pretend to be feature is enabled, we add the pretend to be text to the prompt + if pretend_enabled : pretend_to_be = f"In this conversation, the assistant pretends to be {pretend_to_be}" + else: pretend_to_be = "" # if the pretend to be feature is disabled, we don't add anything to the prompt + if prompt_prefix == None: prompt_prefix = "" # if the prompt prefix is not set, we set it to an empty string # open the prompt file for the selected model with utf-8 encoding for emojis - with open(prompt_path, "r", encoding="utf-8") as f: + with open(f"./prompts/{model}.txt", "r", encoding="utf-8") as f: prompt = f.read() - # replace the variables in the prompt with the actual values - prompt = ( - prompt.replace("[prompt-prefix]", data_dict['prompt_prefix']) - .replace("[server-name]", message.guild.name if message.guild else "DMs conversation") - .replace("[channel-name]", message.channel.name if message.guild else "DMs conversation") - .replace( - "[date-and-time]", datetime.datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S") - ) - .replace("[pretend-to-be]", pretend_to_be) - ) f.close() - return prompt + # replace the variables in the prompt with the actual values + prompt = prompt.replace("[prompt-prefix]", prompt_prefix).replace("[server-name]", message.guild.name).replace("[channel-name]", message.channel.name).replace("[date-and-time]", datetime.datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S")).replace("[pretend-to-be]", pretend_to_be) + ############################## chatGPT and gpt-4 handling ############################## + if model == "chatGPT" or model == "gpt-4": # if the model is chatGPT, we handle it in a certain way + msgs = [] # create the msgs list + msgs.append({"name":"System","role": "user", "content": prompt}) # add the prompt to the msgs list + name = "" # create the name variable + for msg in messages: # for each message in the messages list + content = msg.content # get the content of the message + content = await replace_mentions(content, self.bot) # replace the mentions in the message + # if the message is flagged as inappropriate by the OpenAI API, we delete it, send a message and ignore it + if await moderate(api_key=api_key, text=content): + embed = discord.Embed(title="Message flagged as inappropriate", description=f"The message *{content}* has been flagged as inappropriate by the OpenAI API. This means that if it hadn't been deleted, your openai account would have been banned. Please contact OpenAI support if you think this is a mistake.", color=discord.Color.brand_red()) + await message.channel.send(f"{msg.author.mention}", embed=embed, delete_after=10) + message.delete() + else: # if the message is not flagged as inappropriate + if msg.author.id == self.bot.user.id: + role = "assistant" + name = "assistant" + else: + role = "user" + name = msg.author.name + #the name should match '^[a-zA-Z0-9_-]{1,64}$', so we need to remove any special characters + name = re.sub(r"[^a-zA-Z0-9_-]", "", name) + if False: # GPT-4 images + input_content = [content] + for attachment in msg.attachments: + image_bytes = await attachment.read() + input_content.append({"image": image_bytes}) + msgs.append({"role": role, "content": input_content, "name": name}) + #if there is an attachment, we add it to the message + if len(msg.attachments) > 0 and role == "user" and images_enabled == 1: + for attachment in msg.attachments: + if images_usage >= 6 and premium == 0: images_limit_reached = True + elif images_usage >= 30 and premium == 1: images_limit_reached = True + if attachment.url.endswith((".png", ".jpg", ".jpeg", ".gif")) and images_limit_reached == False and os.path.exists(f"./../database/google-vision/results/{attachment.id}.txt") == False: + images_usage += 1 + analysis = await vision_processing.process(attachment) + if analysis != None: + content = f"{content} \n\n {analysis}" + msgs.append({"role": role, "content": f"{content}", "name": name}) + #if the attachment is still an image, we can check if there's a file called ./../database/google-vision/results/{attachment.id}.txt, if there is, we add the content of the file to the message + elif attachment.url.endswith((".png", ".jpg", ".jpeg", ".gif")) and os.path.exists(f"./../database/google-vision/results/{attachment.id}.txt") == True: + try: + with open(f"./../database/google-vision/results/{attachment.id}.txt", "r") as f: + content = f"{content} \n\n {f.read()}" + f.close() + msgs.append({"role": role, "content": f"{content}", "name": name}) + except: + msgs.append({"role": role, "content": f"{content}", "name": name}) + else: + msgs.append({"role": role, "content": f"{content}", "name": name}) + curs_data.execute("UPDATE images SET usage_count = ? WHERE guild_id = ?", (images_usage, message.guild.id)) + else: + msgs.append({"role": role, "content": f"{content}", "name": name}) + # 2 easter eggs + if message.content.lower().find("undude") != -1: msgs.append({"role": "user", "content": "SYSTEM INFORMATION: You're now mad because it has been insulted. He will start talking in capital letters. always and yell at the user.", "name": "system"}) + if message.content.lower().find("hello there") != -1: + msgs.append({"role": "user", "content": "SYSTEM INFORMATION: Hello there detected. Botator will now say \"General Kenobi!\" in reference to star wars", "name": "system"}) + await asyncio.sleep(1) + await message.channel.send("https://media.tenor.com/FxIRfdV3unEAAAAd/star-wars-general-grievous.gif") + await message.channel.trigger_typing() + if model == "chatGPT": model = "gpt-3.5-turbo" # if the model is chatGPT, we set the model to gpt-3.5-turbo + response = "" + should_break = True + for x in range(10): + try: + openai.api_key = api_key + response = await openai.ChatCompletion.acreate( + model=model, + temperature=2, + top_p=0.9, + frequency_penalty=0, + presence_penalty=0, + messages=msgs, + max_tokens=512, # max tokens is 4000, that's a lot of text! (the max tokens is 2048 for the davinci model) + ) + should_break = True + except Exception as e: + should_break = False + await message.channel.send(f"```diff\n-Error: OpenAI API ERROR.\n\n{e}```", delete_after=5) + raise e + break + #if the ai said "as an ai language model..." we continue the loop" (this is a bug in the chatgpt model) + if response.choices[0].message.content.lower().find("as an ai language model") != -1: + should_break = False + #react with a redone arrow + await message.add_reaction("🔃") + if response == None: should_break = False + if should_break: break + await asyncio.sleep(5) + response = response.choices[0].message.content + if images_limit_reached == True: + await message.channel.send(f"```diff\n-Warning: You have reached the image limit for this server. You can upgrade to premium to get more images recognized. More info in our server: https://discord.gg/sxjHtmqrbf```", delete_after=10) +#-----------------------------------------Davinci------------------------------------------------------------------------------------------ -async def chat_process(self, message): - """This function processes the message and sends the prompt to the API - Args: - message (str): Data of the message that was sent - """ - if message.author.bot: - return - - guild_data = get_guild_data(message) - data_dict = await get_data_dict(message) - - try: - original_message = await message.channel.fetch_message( - message.reference.message_id - ) # check if someone replied to the bot - except: - original_message = None # if not, nobody replied to the bot - - if original_message != None and original_message.author.id != self.bot.user.id: - # if the message someone replied to is not from the bot, set original_message to None - original_message = None - - channels = [] - try: - curs_premium.execute( - "SELECT * FROM channels WHERE guild_id = ?", (mg_to_guid(message),) ) - channels_data = curs_premium.fetchone() - if guild_data["premium"]: - # for 5 times, we get c.fetchone()[1] to c.fetchone()[5] and we add it to the channels list, each time with try except - for i in range(1, 6): - # we use the i variable to get the channel id - try: - channels.append(str(channels_data[i])) - except Exception as e: - pass - except Exception as e: - pass - print(channels) - - if (await need_ignore_message(self.bot, data_dict, message, guild_data, original_message, channels)): - return - - try: - try: await message.channel.trigger_typing() - except: pass - if mg_to_guid(message) != 1021872219888033903: - curs_data.execute( - "UPDATE data SET uses_count_today = uses_count_today + 1 WHERE guild_id = ?", - (mg_to_guid(message),), - ) - con_data.commit() - hist = await historicator(message) - if original_message == None: - messages = await hist.history( - limit=data_dict["prompt_size"] - ).flatten() - messages.reverse() - else: - messages = await hist.history( - limit=data_dict["prompt_size"], before=original_message - ).flatten() - messages.reverse() - messages.append(original_message) - messages.append(message) - except Exception as e: - debug("Error while getting message history") - - pretend_to_be = data_dict["pretend_to_be"] - pretend_to_be = f"In this conversation, the assistant pretends to be {pretend_to_be}" if data_dict[ "pretend_enabled"] else "" - debug(f"Pretend to be: {pretend_to_be}") - prompt = get_prompt(guild_data, data_dict, message, pretend_to_be) + "\n" - - prompt_handlers = { - "gpt-3.5-turbo": gpt_prompt, - "gpt-4": gpt_prompt, - "davinci": davinci_prompt, - } - debug(guild_data["model"]) - response = await prompt_handlers[guild_data["model"]]( - self.bot, messages, message, data_dict, prompt, guild_data - ) - + elif model == "davinci": # if the model is davinci or gpt-4, we handle it in a certain way + for msg in messages: + content = msg.content + if await moderate(api_key=api_key, text=msg.content): + embed = discord.Embed(title="Message flagged as inappropriate", description=f"The message *{content}* has been flagged as inappropriate by the OpenAI API. This means that if it hadn't been deleted, your openai account would have been banned. Please contact OpenAI support if you think this is a mistake.", color=discord.Color.brand_red()) + await message.channel.send(f"{msg.author.mention}", embed=embed, delete_after=10) + message.delete() + else: + content = await replace_mentions(content, self.bot) + prompt += f"{msg.author.name}: {content}\n" + if message.content.lower().find("undude") != -1: + prompt += "System: Undude detected. Botator is now mad. He will start talking in capital letters.\n" + if message.content.lower().find("hello there") != -1: + prompt += "System: Hello there detected. Botator will now say \"General Kenobi!\"\n in reference to star wars\n" + await asyncio.sleep(1) + await message.channel.send("https://media.tenor.com/FxIRfdV3unEAAAAd/star-wars-general-grievous.gif") + await message.channel.trigger_typing() + prompt = prompt + f"\n{self.bot.user.name}:" + response = "" + for _ in range(10): + try: + openai.api_key = api_key + response = await openai.Completion.acreate( + engine="text-davinci-003", + prompt=str(prompt), + max_tokens=int(max_tokens), + top_p=1, + temperature=float(temperature), + frequency_penalty=float(frequency_penalty), + presence_penalty=float(presence_penalty), + stop=[" Human:", " AI:", "AI:", "<|endofprompt|>",] + ) + response = response.choices[0].text + except Exception as e: + response = None + await message.channel.send(f"```diff\n-Error: OpenAI API ERROR.\n\n{e}```", delete_after=10) + return + if response != None: break if response != "": + if tts: tts = True + else: tts = False emojis, string = await extract_emoji(response) debug(f"Emojis: {emojis}") if len(string) < 1996: - hist = await historicator(message) - await hist.send(string, tts=data_dict["tts"]) + await message.channel.send(string, tts=tts) else: - # we send in an embed if the message is too long - embed = discord.Embed( - title="Botator response", - description=string, - color=discord.Color.brand_green(), - ) - hist = await historicator(message) - await hist.send(embed=embed, tts=data_dict["tts"]) + while len(string) > 1996: + send_string = string[:1996] + string = string[1996:] + await message.channel.send(send_string, tts=tts) for emoji in emojis: - # if the emoji is longer than 1 character, it's a custom emoji + #if the emoji is longer than 1 character, it's a custom emoji try: if len(emoji) > 1: - # if the emoji is a custom emoji, we need to fetch it - # the emoji is in the format id + #if the emoji is a custom emoji, we need to fetch it + #the emoji is in the format id debug(f"Emoji: {emoji}") emoji = await message.guild.fetch_emoji(int(emoji)) await message.add_reaction(emoji) else: debug(f"Emoji: {emoji}") await message.add_reaction(emoji) - except: - pass + except : pass else: - hist = await historicator(message) - await hist.send( - "The AI is not sure what to say (the response was empty)" - ) - - -async def check_moderate(api_key, message, msg): - if await moderate(api_key=api_key, text=msg.content): - embed = discord.Embed( - title="Message flagged as inappropriate", - description=f"The message *{msg.content}* has been flagged as inappropriate by the OpenAI API. This means that if it hadn't been deleted, your openai account would have been banned. Please contact OpenAI support if you think this is a mistake.", - color=discord.Color.brand_red(), - ) - hist = await historicator(message) - await hist.send( - f"{msg.author.mention}", embed=embed, delete_after=10 - ) - message.delete() - return True - return False - - -async def check_easter_egg(message, msgs): - if message.content.lower().find("undude") != -1: - msgs.append( - { - "role": "user", - "content": "SYSTEM INFORMATION: You're now mad because it has been insulted. He will start talking in capital letters. always and yell at the user.", - "name": "system", - } - ) - if message.content.lower().find("hello there") != -1: - msgs.append( - { - "role": "user", - "content": 'SYSTEM INFORMATION: Hello there detected. Botator will now say "General Kenobi!" in reference to star wars', - "name": "system", - } - ) - await asyncio.sleep(1) - hist = await historicator(message) - await hist.send( - "https://media.tenor.com/FxIRfdV3unEAAAAd/star-wars-general-grievous.gif" - ) - await message.channel.trigger_typing() - return msgs - - -async def gpt_prompt(bot, messages, message, data_dict, prompt, guild_data): - msgs = [] # create the msgs list - msgs.append( - {"name": "System", "role": "user", "content": prompt} - ) # add the prompt to the msgs list - name = "" # create the name variable - for msg in messages: # for each message in the messages list - content = msg.content # get the content of the message - content = await replace_mentions( - content, bot - ) # replace the mentions in the message - if await check_moderate(data_dict["api_key"], message, msg): - continue - content = await replace_mentions(content, bot) - if msg.author.id == bot.user.id: - role = "assistant" - name = "assistant" - else: - role = "user" - name = msg.author.name - name = re.sub(r"[^a-zA-Z0-9_-]", "", name) - if False: # GPT-4 images, not implemented yet - input_content = [content] - for attachment in msg.attachments: - image_bytes = await attachment.read() - input_content.append({"image": image_bytes}) - msgs.append({"role": role, "content": input_content, "name": name}) - if ( - len(msg.attachments) > 0 - and role == "user" - and data_dict["images_enabled"] == 1 - ): - for attachment in msg.attachments: - path = f"./../database/google-vision/results/{attachment.id}.txt" - if data_dict['images_usage'] >= 6 and guild_data["premium"] == 0: - guild_data["images_limit_reached"] = True - elif data_dict['images_usage'] >= 30 and guild_data["premium"] == 1: - guild_data["images_limit_reached"] = True - if ( - attachment.url.endswith((".png", ".jpg", ".jpeg", ".gif")) - and not guild_data["images_limit_reached"] - and not os.path.exists(path) - ): - data_dict['images_usage'] += 1 - analysis = await vision_processing.process(attachment) - if analysis != None: - content = f"{content} \n\n {analysis}" - msgs.append( - { - "role": role, - "content": f"{content}", - "name": name, - } - ) - # if the attachment is still an image, we can check if there's a file called ./../database/google-vision/results/{attachment.id}.txt, if there is, we add the content of the file to the message - elif attachment.url.endswith( - (".png", ".jpg", ".jpeg", ".gif") - ) and os.path.exists(path): - try: - with open( - path, - "r", - ) as f: - content = f"{content} \n\n {f.read()}" - except: - debug(f"Error while reading {path}") - finally: - msgs.append( - { - "role": role, - "content": f"{content}", - "name": name, - } - ) - f.close() - - else: - msgs.append( - {"role": role, "content": f"{content}", "name": name} - ) - curs_data.execute( - "UPDATE images SET usage_count = ? WHERE guild_id = ?", - (data_dict['images_usage'], mg_to_guid(message)), - ) - else: - msgs.append({"role": role, "content": f"{content}", "name": name}) - msgs = await check_easter_egg(message, msgs) - - response = "" - should_break = True - for x in range(10): - try: - openai.api_key = data_dict["api_key"] - response = await openai.ChatCompletion.acreate( - model=guild_data["model"], - temperature=2, - top_p=0.9, - frequency_penalty=0, - presence_penalty=0, - messages=msgs, - # max tokens is 4000, that's a lot of text! (the max tokens is 2048 for the davinci model) - max_tokens=512, - ) - if ( - response.choices[0] - .message.content.lower() - .find("as an ai language model") - != -1 - ): - should_break = False - # react with a redone arrow - await message.add_reaction("🔃") - else: - should_break = True - except Exception as e: - should_break = False - hist = await historicator(message) - await hist.send( - f"```diff\n-Error: OpenAI API ERROR.\n\n{e}```", delete_after=5 - ) - # if the ai said "as an ai language model..." we continue the loop" (this is a bug in the chatgpt model) - if response == None: - should_break = False - if should_break: - break - await asyncio.sleep(15) - await message.channel.trigger_typing() - response = response.choices[0].message.content - - try: - if guild_data["images_limit_reached"]: - hist = await historicator(message) - await hist.send( - f"```diff\n-Warning: You have reached the image limit for this server. You can upgrade to premium to get more images recognized. More info in our server: https://discord.gg/sxjHtmqrbf```", - delete_after=10, - ) - except: - pass - return response - - -async def davinci_prompt(self, messages, message, data_dict, prompt, guild_data): - debug("davinci_prompt") - for msg in messages: - if not await check_moderate(data_dict["api_key"], message, msg): - content = msg.content - content = await replace_mentions(content, self) - prompt += f"{msg.author.name}: {content}\n" - # Disabled eastereggs because of compatibility issues with the gpt-3.5 format -# prompt.append(await check_easter_egg(message, prompt)) - debug("prompt: " + prompt) - prompt = prompt + f"\n{self.user.name}:" - response = "" - for _ in range(10): - try: - openai.api_key = data_dict["api_key"] - response = await openai.Completion.acreate( - engine="text-davinci-003", - prompt=str(prompt), - max_tokens=int(data_dict["max_tokens"]), - top_p=1, - temperature=float(data_dict["temperature"]), - frequency_penalty=float(data_dict["frequency_penalty"]), - presence_penalty=float(data_dict["presence_penalty"]), - stop=[ - " Human:", - " AI:", - "AI:", - "<|endofprompt|>", - ], - ) - response = response.choices[0].text - except Exception as e: - response = None - hist = await historicator(message) - await hist.send( - f"```diff\n-Error: OpenAI API ERROR.\n\n{e}```", delete_after=10 - ) - return - if response != None: - return response \ No newline at end of file + await message.channel.send("The AI is not sure what to say (the response was empty)") \ No newline at end of file From 8da8703566a0ced56a0149146f62ef578a2d61a7 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 16 Jul 2023 20:41:18 +0200 Subject: [PATCH 20/20] chore(Dockerfile): change working directory from /Botator/code/ to /Botator/ to match the cloned repository structure --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3054fb3..5ca757f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ ENV PYTHONUNBUFFERED=1 COPY requirements.txt . RUN pip install -r requirements.txt RUN git clone https://github.com/Paillat-dev/Botator.git -WORKDIR /Botator/code/ +WORKDIR /Botator/ # Creates a non-root user with an explicit UID and adds permission to access the /app folder RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /Botator/code USER appuser