From 6dc58ea02585e5520d8ea2b3fdb36f2a656acf17 Mon Sep 17 00:00:00 2001 From: Kaveen Kumarasinghe Date: Sun, 19 Mar 2023 22:34:41 -0400 Subject: [PATCH 1/7] temp fix for gpt4 conversations, some safeguards for channel chats --- cogs/text_service_cog.py | 20 +++++++++++++++++++ conversation_starter_pretext.txt | 2 +- detailed_guides/OTHER-MINOR-FEATURES.md | 2 ++ gpt3discord.py | 2 +- models/openai_model.py | 9 +++------ services/environment_service.py | 26 +++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/cogs/text_service_cog.py b/cogs/text_service_cog.py index 5ea0432..3737e0a 100644 --- a/cogs/text_service_cog.py +++ b/cogs/text_service_cog.py @@ -43,6 +43,7 @@ CHAT_BYPASS_ROLES = EnvService.get_bypass_roles() PRE_MODERATE = EnvService.get_premoderate() FORCE_ENGLISH = EnvService.get_force_english() BOT_TAGGABLE = EnvService.get_bot_is_taggable() +CHANNEL_CHAT_ROLES = EnvService.get_channel_chat_roles() # # Obtain the Moderation table and the General table, these are two SQLite tables that contain @@ -1073,6 +1074,25 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): await ctx.respond("Conversation started.") target = thread else: + # Check if this current channel is already in a conversation + if ctx.channel.id in self.conversation_threads: + await ctx.respond( + "There is already a conversation in this channel. Please finish that conversation before starting a new one." + ) + return + + # Check if the user is permitted to start a conversation in full channels + # check if any of the user role names match CHANNEL_CHAT_ROLES + if CHANNEL_CHAT_ROLES and CHANNEL_CHAT_ROLES != [None]: + if not any( + role.name in CHANNEL_CHAT_ROLES for role in ctx.user.roles + ): + await ctx.respond( + "You are not permitted to start a conversation in this channel." + ) + return + + target = ctx.channel if private: embed_title = f"{user.name}'s private conversation with GPT" diff --git a/conversation_starter_pretext.txt b/conversation_starter_pretext.txt index d564bdf..8ac06a9 100644 --- a/conversation_starter_pretext.txt +++ b/conversation_starter_pretext.txt @@ -33,4 +33,4 @@ Human: I'm making a discord bot <|endofstatement|> There can be an arbitrary amount of newlines between chat entries. can be any name, pay attention to who's talking. The text "<|endofstatement|>" is used to separate chat entries and make it easier for you to understand the context. -You speak in a fun, casual, and friendly tone, not worrying about capitalizations and using slang like "lol", "lmao", and etc, like you're talking to a friend. \ No newline at end of file +You speak in a fun, casual, and friendly tone, not worrying about capitalizations and using slang like "lol", "lmao", and etc, like you're talking to a friend, you are not overly verbose. \ No newline at end of file diff --git a/detailed_guides/OTHER-MINOR-FEATURES.md b/detailed_guides/OTHER-MINOR-FEATURES.md index 568161c..a6905c8 100644 --- a/detailed_guides/OTHER-MINOR-FEATURES.md +++ b/detailed_guides/OTHER-MINOR-FEATURES.md @@ -1,4 +1,6 @@ ## Other Features +### Full-channel chat +This bot supports designating an entire discord text channel as a GPT conversation. Use /gpt converse and set the use_threads option to false. You can designate who is allowed to turn full channels into chat by setting the `CHANNEL_CHAT_ROLES` variable in your `.env` file to be a list of role names separated by commas that should be able to use this functionality. ### Health Check Service The bot has the ability to launch a HTTP endpoint at `:8181/` that will return a json response of the bot's status and uptime. This is especially useful if you want to run this bot on cloud application containers, like Azure App Service. diff --git a/gpt3discord.py b/gpt3discord.py index cd8b45b..d7b0f1d 100644 --- a/gpt3discord.py +++ b/gpt3discord.py @@ -33,7 +33,7 @@ from services.environment_service import EnvService from models.openai_model import Model -__version__ = "11.1.1" +__version__ = "11.1.2" PID_FILE = Path("bot.pid") diff --git a/models/openai_model.py b/models/openai_model.py index f31a11b..77a3a17 100644 --- a/models/openai_model.py +++ b/models/openai_model.py @@ -874,7 +874,6 @@ class Model: messages.append( { "role": "system", - "name": "Instructor", "content": message.text, } ) @@ -884,29 +883,27 @@ class Model: text = message.text.replace(bot_name, "") text = text.replace("<|endofstatement|>", "") messages.append( - {"role": "assistant", "name": bot_name_clean, "content": text} + {"role": "assistant", "content": text} # TODO add back the assistant's name when the API is fixed.. ) else: try: - print("In first block The message text is ->" + message.text) if ( message.text.strip() .lower() .startswith("this conversation has some context from earlier") ): - print("Hit the exception clause") raise Exception("This is a context message") username = re.search(r"(?<=\n)(.*?)(?=:)", message.text).group() username_clean = self.cleanse_username(username) text = message.text.replace(f"{username}:", "") + # Strip whitespace just from the right side of the string + text = text.rstrip() text = text.replace("<|endofstatement|>", "") messages.append( {"role": "user", "name": username_clean, "content": text} ) - print("Got to here") except Exception: - print("In second block The message text is ->" + message.text) text = message.text.replace("<|endofstatement|>", "") messages.append({"role": "system", "content": text}) diff --git a/services/environment_service.py b/services/environment_service.py index 94d55e8..711e7ff 100644 --- a/services/environment_service.py +++ b/services/environment_service.py @@ -250,6 +250,32 @@ class EnvService: ) return index_roles + @staticmethod + def get_channel_chat_roles(): + # GPT_ROLES is a comma separated list of string roles + # It can also just be one role + # Read these allowed roles and return as a list of strings + try: + cc_roles = os.getenv("CHANNEL_CHAT_ROLES") + except Exception: + cc_roles = None + + if cc_roles is None: + print( + "INDEX_ROLES is not defined properly in the environment file!" + "Please copy your server's role and put it into INDEX_ROLES in the .env file." + 'For example a line should look like: `INDEX_ROLES="Gpt"`' + ) + print("Defaulting to allowing all users to use Index commands...") + return [None] + + cc_roles = ( + cc_roles.lower().strip().split(",") + if "," in cc_roles + else [cc_roles.lower()] + ) + return cc_roles + @staticmethod def get_welcome_message(): # WELCOME_MESSAGE is a default string used to welcome new members to the server if GPT3 is not available. From 07b6882a95fd3096e12314dfaf676901b5f875b1 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 20 Mar 2023 02:35:03 +0000 Subject: [PATCH 2/7] Format Python code with psf/black push --- cogs/text_service_cog.py | 5 +---- models/openai_model.py | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cogs/text_service_cog.py b/cogs/text_service_cog.py index 3737e0a..2a43eb6 100644 --- a/cogs/text_service_cog.py +++ b/cogs/text_service_cog.py @@ -1084,15 +1084,12 @@ class GPT3ComCon(discord.Cog, name="GPT3ComCon"): # Check if the user is permitted to start a conversation in full channels # check if any of the user role names match CHANNEL_CHAT_ROLES if CHANNEL_CHAT_ROLES and CHANNEL_CHAT_ROLES != [None]: - if not any( - role.name in CHANNEL_CHAT_ROLES for role in ctx.user.roles - ): + if not any(role.name in CHANNEL_CHAT_ROLES for role in ctx.user.roles): await ctx.respond( "You are not permitted to start a conversation in this channel." ) return - target = ctx.channel if private: embed_title = f"{user.name}'s private conversation with GPT" diff --git a/models/openai_model.py b/models/openai_model.py index 77a3a17..6137e0a 100644 --- a/models/openai_model.py +++ b/models/openai_model.py @@ -883,7 +883,10 @@ class Model: text = message.text.replace(bot_name, "") text = text.replace("<|endofstatement|>", "") messages.append( - {"role": "assistant", "content": text} # TODO add back the assistant's name when the API is fixed.. + { + "role": "assistant", + "content": text, + } # TODO add back the assistant's name when the API is fixed.. ) else: try: From 17e82a30ca320f7fcd327937cee1676420b6b7ae Mon Sep 17 00:00:00 2001 From: Kaveen Kumarasinghe Date: Mon, 20 Mar 2023 01:17:30 -0400 Subject: [PATCH 3/7] bugfixes for 3.5 model --- conversation_starter_pretext.txt | 2 +- gpt3discord.py | 2 +- models/autocomplete_model.py | 9 --------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/conversation_starter_pretext.txt b/conversation_starter_pretext.txt index 8ac06a9..6d1442d 100644 --- a/conversation_starter_pretext.txt +++ b/conversation_starter_pretext.txt @@ -33,4 +33,4 @@ Human: I'm making a discord bot <|endofstatement|> There can be an arbitrary amount of newlines between chat entries. can be any name, pay attention to who's talking. The text "<|endofstatement|>" is used to separate chat entries and make it easier for you to understand the context. -You speak in a fun, casual, and friendly tone, not worrying about capitalizations and using slang like "lol", "lmao", and etc, like you're talking to a friend, you are not overly verbose. \ No newline at end of file +You speak in a fun, casual, and friendly tone, not worrying about capitalizations and using slang like "lol", "lmao", and etc, like you're talking to a friend, you are not overly verbose. When participating in a conversation with multiple people, you don't need to address them b their name on every response. \ No newline at end of file diff --git a/gpt3discord.py b/gpt3discord.py index d7b0f1d..29d8283 100644 --- a/gpt3discord.py +++ b/gpt3discord.py @@ -33,7 +33,7 @@ from services.environment_service import EnvService from models.openai_model import Model -__version__ = "11.1.2" +__version__ = "11.1.3" PID_FILE = Path("bot.pid") diff --git a/models/autocomplete_model.py b/models/autocomplete_model.py index cd3c092..b98da4f 100644 --- a/models/autocomplete_model.py +++ b/models/autocomplete_model.py @@ -102,15 +102,6 @@ class Settings_autocompleter: models = [ value for value in Models.TEXT_MODELS if value.startswith(ctx.value.lower()) ] - models.append("chatgpt") - - # We won't let the user directly use these models but we will decide which one to use based on the status. - attempt_removes = ["gpt-3.5-turbo", "gpt-3.5-turbo-0301"] - - for attempt_remove in attempt_removes: - if attempt_remove in models: - models.remove(attempt_remove) - return models async def get_value_moderations( From 5424710f4f1f2b0f5da11a4bc923e2487d3a2fc7 Mon Sep 17 00:00:00 2001 From: Kaveen Kumarasinghe Date: Mon, 20 Mar 2023 03:48:29 -0400 Subject: [PATCH 4/7] Update prompt_optimizer_cog.py Signed-off-by: Kaveen Kumarasinghe --- cogs/prompt_optimizer_cog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/prompt_optimizer_cog.py b/cogs/prompt_optimizer_cog.py index efd6f2c..715db69 100644 --- a/cogs/prompt_optimizer_cog.py +++ b/cogs/prompt_optimizer_cog.py @@ -96,7 +96,7 @@ class ImgPromptOptimizer(discord.Cog, name="ImgPromptOptimizer"): best_of_override=1, max_tokens_override=60, custom_api_key=user_api_key, - is_chatgpt_request="turbo" in str(self.model.model), + is_chatgpt_request="turbo" in str(self.model.model) or "gpt-4" in str(self.model.model), ) # THIS USES MORE TOKENS THAN A NORMAL REQUEST! This will use roughly 4000 tokens, and will repeat the query @@ -105,7 +105,7 @@ class ImgPromptOptimizer(discord.Cog, name="ImgPromptOptimizer"): response_text = ( str(response["choices"][0]["text"]) - if not self.model.model in Models.CHATGPT_MODELS + if not (self.model.model in Models.CHATGPT_MODELS or self.model.model in Models.GPT4_MODELS) else response["choices"][0]["message"]["content"] ) From 877c49b380e580f8eadec31d79196ae177932f07 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 20 Mar 2023 07:50:16 +0000 Subject: [PATCH 5/7] Format Python code with psf/black push --- cogs/prompt_optimizer_cog.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cogs/prompt_optimizer_cog.py b/cogs/prompt_optimizer_cog.py index 715db69..62abdd4 100644 --- a/cogs/prompt_optimizer_cog.py +++ b/cogs/prompt_optimizer_cog.py @@ -96,7 +96,8 @@ class ImgPromptOptimizer(discord.Cog, name="ImgPromptOptimizer"): best_of_override=1, max_tokens_override=60, custom_api_key=user_api_key, - is_chatgpt_request="turbo" in str(self.model.model) or "gpt-4" in str(self.model.model), + is_chatgpt_request="turbo" in str(self.model.model) + or "gpt-4" in str(self.model.model), ) # THIS USES MORE TOKENS THAN A NORMAL REQUEST! This will use roughly 4000 tokens, and will repeat the query @@ -105,7 +106,10 @@ class ImgPromptOptimizer(discord.Cog, name="ImgPromptOptimizer"): response_text = ( str(response["choices"][0]["text"]) - if not (self.model.model in Models.CHATGPT_MODELS or self.model.model in Models.GPT4_MODELS) + if not ( + self.model.model in Models.CHATGPT_MODELS + or self.model.model in Models.GPT4_MODELS + ) else response["choices"][0]["message"]["content"] ) From 82b3331b267687626431fa6a0d4d3a2bda390507 Mon Sep 17 00:00:00 2001 From: Kaveen Kumarasinghe Date: Mon, 20 Mar 2023 03:54:32 -0400 Subject: [PATCH 6/7] Update gpt3discord.py Signed-off-by: Kaveen Kumarasinghe --- gpt3discord.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpt3discord.py b/gpt3discord.py index 29d8283..066800e 100644 --- a/gpt3discord.py +++ b/gpt3discord.py @@ -33,7 +33,7 @@ from services.environment_service import EnvService from models.openai_model import Model -__version__ = "11.1.3" +__version__ = "11.1.4" PID_FILE = Path("bot.pid")