From fbdc03b8ddcf81903f30349bd05a4c72bcafc3a0 Mon Sep 17 00:00:00 2001 From: Rene Teigen Date: Wed, 11 Jan 2023 18:37:13 +0000 Subject: [PATCH] Enable json openers with overrides --- README.md | 2 + cogs/gpt_3_commands_and_converser.py | 86 ++++++++++++++++++---------- models/user_model.py | 18 ++++++ openers/english_translator.json | 8 +++ 4 files changed, 85 insertions(+), 29 deletions(-) create mode 100644 openers/english_translator.json diff --git a/README.md b/README.md index d65116c..18a358e 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,8 @@ These commands are grouped, so each group has a prefix but you can easily tab co - Custom openers need to be placed as a .txt file in the `openers` directory, in the same directory as `gpt3discord.py` +- Can use files in the `{"text": your prompt, "temp":0, "top_p":0,"frequency_penalty":0,"presence_penalty":0}` format to include permanent overrides + `/gpt converse minimal:yes` - Start a conversation with the bot, like ChatGPT, with minimal context (saves tokens) - Note that the above options for `/gpt converse` can be combined (you can combine minimal, private, and opener!) diff --git a/cogs/gpt_3_commands_and_converser.py b/cogs/gpt_3_commands_and_converser.py index cd12ecf..afd051c 100644 --- a/cogs/gpt_3_commands_and_converser.py +++ b/cogs/gpt_3_commands_and_converser.py @@ -8,6 +8,7 @@ from pathlib import Path import aiofiles +import json import discord from pycord.multicog import add_to_group @@ -636,11 +637,17 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): ) self.conversation_threads[after.channel.id].count += 1 + overrides = self.conversation_threads[after.channel.id].get_overrides() + await self.encapsulated_send( id=after.channel.id, prompt=edited_content, ctx=ctx, response_message=response_message, + temp_override=overrides["temperature"], + top_p_override=overrides["top_p"], + frequency_penalty_override=overrides["frequency_penalty"], + presence_penalty_override=overrides["presence_penalty"], ) self.redo_users[after.author.id].prompt = after.content @@ -774,10 +781,17 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): self.conversation_threads[message.channel.id].history ) + #set conversation overrides + overrides = self.conversation_threads[message.channel.id].get_overrides() + await self.encapsulated_send( message.channel.id, primary_prompt, message, + temp_override=overrides["temperature"], + top_p_override=overrides["top_p"], + frequency_penalty_override=overrides["frequency_penalty"], + presence_penalty_override=overrides["presence_penalty"], custom_api_key=user_api_key, ) @@ -1236,30 +1250,6 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): ) return - if not opener and not opener_file: - user_id_normalized = user.id - else: - user_id_normalized = ctx.author.id - if ( - opener_file - ): # only load in files if it's included in the command, if not pass on as normal - if opener_file.endswith(".txt"): - # Load the file and read it into opener - opener_file = EnvService.find_shared_file( - f"openers{separator}{opener_file}" - ) - opener_file = await self.load_file(opener_file, ctx) - if ( - not opener - ): # if we only use opener_file then only pass on opener_file for the opening prompt - opener = opener_file - else: - opener = opener_file + opener - if not opener_file: - return - else: - pass - if private: await ctx.respond(user.name + "'s private conversation with GPT3") thread = await ctx.channel.create_thread( @@ -1287,10 +1277,46 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): self.CONVERSATION_STARTER_TEXT ) + if not opener and not opener_file: + user_id_normalized = user.id + else: + user_id_normalized = ctx.author.id + if not opener_file: + pass + else: + if opener_file.endswith((".txt", ".json")): + # Load the file and read it into opener + opener_file = EnvService.find_shared_file( + f"openers{separator}{opener_file}" + ) + opener_file = await self.load_file(opener_file, ctx) + try: + opener_file = json.loads(opener_file) # Try opening as json, if it fails it'll do it as a str + temperature=None if not opener_file["temperature"] else opener_file["temperature"] + top_p=None if not opener_file["top_p"] else opener_file["top_p"] + frequency_penalty=None if not opener_file["frequency_penalty"] else opener_file["frequency_penalty"] + presence_penalty=None if not opener_file["presence_penalty"] else opener_file["presence_penalty"] + self.conversation_threads[thread.id].set_overrides(temperature, top_p, frequency_penalty, presence_penalty) # set overrides + if not opener: # if we only use opener_file then only pass on opener_file for the opening prompt + opener = opener_file["text"] + else: + opener = opener_file["text"] + opener + except: + if not opener: # if we only use opener_file then only pass on opener_file for the opening prompt + opener = opener_file + else: + opener = opener_file + opener + + # Set user as owner before sending anything that can error and leave the thread unowned + self.conversation_thread_owners[user_id_normalized] = thread.id + overrides = self.conversation_threads[thread.id].get_overrides() + await thread.send( - "<@" - + str(user_id_normalized) - + "> You are now conversing with GPT3. *Say hi to start!*\n End the conversation by saying `end`.\n\n If you want GPT3 to ignore your messages, start your messages with `~`\n\nYour conversation will remain active even if you leave this thread and talk in other GPT supported channels, unless you end the conversation!" + f"<@{str(user_id_normalized)}> You are now conversing with GPT3. *Say hi to start!*\n" + f"Overrides for this thread is **temp={overrides['temperature']}**, **top_p={overrides['top_p']}**, **frequency penalty={overrides['frequency_penalty']}**, **presence penalty={overrides['presence_penalty']}**\n" + f"End the conversation by saying `end`.\n\n" + f"If you want GPT3 to ignore your messages, start your messages with `~`\n\n" + f"Your conversation will remain active even if you leave this thread and talk in other GPT supported channels, unless you end the conversation!" ) # send opening @@ -1313,14 +1339,16 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): if thread.id not in self.conversation_threads or self.pinecone_service else "".join(self.conversation_threads[thread.id].history), thread_message, + temp_override=overrides["temperature"], + top_p_override=overrides["top_p"], + frequency_penalty_override=overrides["frequency_penalty"], + presence_penalty_override=overrides["presence_penalty"], custom_api_key=user_api_key, ) self.awaiting_responses.remove(user_id_normalized) if thread.id in self.awaiting_thread_responses: self.awaiting_thread_responses.remove(thread.id) - self.conversation_thread_owners[user_id_normalized] = thread.id - @add_to_group("system") @discord.slash_command( name="moderations-test", diff --git a/models/user_model.py b/models/user_model.py index 358ed43..adcd1fa 100644 --- a/models/user_model.py +++ b/models/user_model.py @@ -57,6 +57,24 @@ class Thread: self.id = id self.history = [] self.count = 0 + self.temperature = None + self.top_p = None + self.frequency_penalty = None + self.presence_penalty = None + + def set_overrides(self, temperature=None,top_p=None,frequency_penalty=None,presence_penalty=None): + self.temperature = temperature + self.top_p = top_p + self.frequency_penalty = frequency_penalty + self.presence_penalty = presence_penalty + + def get_overrides(self): + return { + "temperature": self.temperature, + "top_p": self.temperature, + "frequency_penalty": self.frequency_penalty, + "presence_penalty": self.presence_penalty, + } # These user objects should be accessible by ID, for example if we had a bunch of user # objects in a list, and we did `if 1203910293001 in user_list`, it would return True diff --git a/openers/english_translator.json b/openers/english_translator.json new file mode 100644 index 0000000..c2dbf3f --- /dev/null +++ b/openers/english_translator.json @@ -0,0 +1,8 @@ +{ + "text":"I want you to act as an English translator, spelling corrector and improver. I will speak to you in any language and you will detect the language, translate it and answer in the corrected and improved version of my text, in English. I want you to replace my simplified A0-level words and sentences with more beautiful and elegant, upper level English words and sentences. Keep the meaning same, but make them more literary. I want you to only reply the correction, the improvements and nothing else, do not write explanations. ", + "temperature":0.77, + "top_p":0.9, + "frequency_penalty":0.95, + "presence_penalty":0.95 +} +