From 207df295f01b4ff08803fae848dc486dcb766601 Mon Sep 17 00:00:00 2001 From: Rene Teigen Date: Sun, 15 Jan 2023 17:39:13 +0000 Subject: [PATCH] Even more --- cogs/commands.py | 4 +-- cogs/moderations_service_cog.py | 2 +- cogs/prompt_optimizer_cog.py | 2 ++ gpt3discord.py | 50 ++++++++++++++++--------------- models/autocomplete_model.py | 2 +- models/check_model.py | 13 ++++---- models/openai_model.py | 2 +- models/user_model.py | 20 ++++++------- services/deletion_service.py | 3 +- services/environment_service.py | 28 ++++++++--------- services/message_queue_service.py | 2 +- services/moderations_service.py | 15 ++++------ services/pinecone_service.py | 27 ++++++++--------- services/text_service.py | 29 +++++++++--------- services/usage_service.py | 5 ++-- 15 files changed, 101 insertions(+), 103 deletions(-) diff --git a/cogs/commands.py b/cogs/commands.py index aa0a292..e43d66d 100644 --- a/cogs/commands.py +++ b/cogs/commands.py @@ -374,13 +374,13 @@ class Commands(discord.Cog, name="Commands"): self, ctx: discord.ApplicationContext, instruction: str, - input: str, + text: str, temperature: float, top_p: float, codex: bool, ): await self.converser_cog.edit_command( - ctx, instruction, input, temperature, top_p, codex + ctx, instruction, text, temperature, top_p, codex ) @add_to_group("gpt") diff --git a/cogs/moderations_service_cog.py b/cogs/moderations_service_cog.py index a7c9ed4..1754ec9 100644 --- a/cogs/moderations_service_cog.py +++ b/cogs/moderations_service_cog.py @@ -193,7 +193,7 @@ class ModerationsService(discord.Cog, name="ModerationsService"): async def restart_moderations_service(self, ctx): '''restarts the moderation of the guild it's run in''' if not self.check_guild_moderated(ctx.guild_id): - await ctx.respond("Moderations are not enabled, can't restart") + await ctx.respond("Moderations are not enabled, can't restart", ephemeral=True, delete_after=30) return await ctx.respond( diff --git a/cogs/prompt_optimizer_cog.py b/cogs/prompt_optimizer_cog.py index e85203a..6adf6ae 100644 --- a/cogs/prompt_optimizer_cog.py +++ b/cogs/prompt_optimizer_cog.py @@ -18,6 +18,7 @@ if USER_INPUT_API_KEYS: class ImgPromptOptimizer(discord.Cog, name="ImgPromptOptimizer"): + '''cog containing the optimizer command''' _OPTIMIZER_PRETEXT = "Optimize the following text for DALL-E image generation to have the most detailed and realistic image possible. Prompt:" def __init__( @@ -54,6 +55,7 @@ class ImgPromptOptimizer(discord.Cog, name="ImgPromptOptimizer"): self.OPTIMIZER_PRETEXT = self._OPTIMIZER_PRETEXT async def optimize_command(self, ctx: discord.ApplicationContext, prompt: str): + '''Command handler. Given a string it generates an output that's fitting for image generation''' user_api_key = None if USER_INPUT_API_KEYS: user_api_key = await TextService.get_user_api_key(ctx.user.id, ctx, USER_KEY_DB) diff --git a/gpt3discord.py b/gpt3discord.py index 7a4c7ef..0c0b33f 100644 --- a/gpt3discord.py +++ b/gpt3discord.py @@ -1,3 +1,4 @@ +import os import asyncio import sys import traceback @@ -6,36 +7,37 @@ from pathlib import Path import discord import pinecone from pycord.multicog import apply_multicog -import os - -from cogs.moderations_service_cog import ModerationsService -from services.pinecone_service import PineconeService - -if sys.platform == "win32": - separator = "\\" -else: - separator = "/" -from cogs.image_service_cog import DrawDallEService from cogs.text_service_cog import GPT3ComCon +from cogs.image_service_cog import DrawDallEService from cogs.prompt_optimizer_cog import ImgPromptOptimizer +from cogs.moderations_service_cog import ModerationsService from cogs.commands import Commands + +from services.pinecone_service import PineconeService from services.deletion_service import Deletion from services.message_queue_service import Message -from models.openai_model import Model from services.usage_service import UsageService from services.environment_service import EnvService +from models.openai_model import Model + __version__ = "7.0" -""" -The pinecone service is used to store and retrieve conversation embeddings. -""" +if sys.platform == "win32": + separator = "\\" +else: + separator = "/" + +# +# The pinecone service is used to store and retrieve conversation embeddings. +# + try: PINECONE_TOKEN = os.getenv("PINECONE_TOKEN") -except: +except Exception: PINECONE_TOKEN = None pinecone_service = None @@ -55,18 +57,18 @@ if PINECONE_TOKEN: print("Got the pinecone service") -""" -Message queueing for the debug service, defer debug messages to be sent later so we don't hit rate limits. -""" +# +# Message queueing for the debug service, defer debug messages to be sent later so we don't hit rate limits. +# message_queue = asyncio.Queue() deletion_queue = asyncio.Queue() asyncio.ensure_future(Message.process_message_queue(message_queue, 1.5, 5)) asyncio.ensure_future(Deletion.process_deletion_queue(deletion_queue, 1, 1)) -""" -Settings for the bot -""" +# +#Settings for the bot +# activity = discord.Activity( type=discord.ActivityType.watching, name="for /help /gpt, and more!" ) @@ -75,9 +77,9 @@ usage_service = UsageService(Path(os.environ.get("DATA_DIR", os.getcwd()))) model = Model(usage_service) -""" -An encapsulating wrapper for the discord.py client. This uses the old re-write without cogs, but it gets the job done! -""" +# +# An encapsulating wrapper for the discord.py client. This uses the old re-write without cogs, but it gets the job done! +# @bot.event # Using self gives u diff --git a/models/autocomplete_model.py b/models/autocomplete_model.py index f390263..51f06b9 100644 --- a/models/autocomplete_model.py +++ b/models/autocomplete_model.py @@ -66,5 +66,5 @@ class File_autocompleter: ][ :25 ] # returns the 25 first files from your current input - except: + except Exception: return ["No 'openers' folder"] diff --git a/models/check_model.py b/models/check_model.py index caf0777..c717ebf 100644 --- a/models/check_model.py +++ b/models/check_model.py @@ -10,7 +10,8 @@ ALLOWED_GUILDS = EnvService.get_allowed_guilds() class Check: - def check_admin_roles(self) -> Callable: + @staticmethod + def check_admin_roles() -> Callable: async def inner(ctx: discord.ApplicationContext): if ADMIN_ROLES == [None]: return True @@ -27,14 +28,15 @@ class Check: return inner - def check_dalle_roles(self) -> Callable: + @staticmethod + def check_dalle_roles() -> Callable: async def inner(ctx: discord.ApplicationContext): if DALLE_ROLES == [None]: return True if not any(role.name.lower() in DALLE_ROLES for role in ctx.user.roles): await ctx.defer(ephemeral=True) await ctx.respond( - "You don't have permission, list of roles is {DALLE_ROLES}", + f"You don't have permission, list of roles is {DALLE_ROLES}", ephemeral=True, delete_after=10, ) @@ -43,14 +45,15 @@ class Check: return inner - def check_gpt_roles(self) -> Callable: + @staticmethod + def check_gpt_roles() -> Callable: async def inner(ctx: discord.ApplicationContext): if GPT_ROLES == [None]: return True if not any(role.name.lower() in GPT_ROLES for role in ctx.user.roles): await ctx.defer(ephemeral=True) await ctx.respond( - "You don't have permission, list of roles is {GPT_ROLES}", + f"You don't have permission, list of roles is {GPT_ROLES}", ephemeral=True, delete_after=10, ) diff --git a/models/openai_model.py b/models/openai_model.py index f83825b..ff03035 100644 --- a/models/openai_model.py +++ b/models/openai_model.py @@ -669,7 +669,7 @@ class Model: images = await asyncio.get_running_loop().run_in_executor( None, lambda: [ - Image.open(requests.get(url, stream=True).raw) for url in image_urls + Image.open(requests.get(url, stream=True, timeout=10).raw) for url in image_urls ], ) diff --git a/models/user_model.py b/models/user_model.py index 761531f..f8221a5 100644 --- a/models/user_model.py +++ b/models/user_model.py @@ -34,8 +34,8 @@ class RedoUser: class User: - def __init__(self, id): - self.id = id + def __init__(self, user_id): + self.user_id = user_id self.history = [] self.count = 0 @@ -43,21 +43,21 @@ class User: # objects in a list, and we did `if 1203910293001 in user_list`, it would return True # if the user with that ID was in the list def __eq__(self, other): - return self.id == other.id + return self.user_id == other.id def __hash__(self): - return hash(self.id) + return hash(self.user_id) def __repr__(self): - return f"User(id={self.id}, history={self.history})" + return f"User(id={self.user_id}, history={self.history})" def __str__(self): return self.__repr__() class Thread: - def __init__(self, id): - self.id = id + def __init__(self, thread_id): + self.thread_id = thread_id self.history = [] self.count = 0 self.model = None @@ -90,13 +90,13 @@ class Thread: # objects in a list, and we did `if 1203910293001 in user_list`, it would return True # if the user with that ID was in the list def __eq__(self, other): - return self.id == other.id + return self.thread_id == other.id def __hash__(self): - return hash(self.id) + return hash(self.thread_id) def __repr__(self): - return f"Thread(id={self.id}, history={self.history})" + return f"Thread(id={self.thread_id}, history={self.history})" def __str__(self): return self.__repr__() diff --git a/services/deletion_service.py b/services/deletion_service.py index d1a5710..6ddcc44 100644 --- a/services/deletion_service.py +++ b/services/deletion_service.py @@ -39,6 +39,5 @@ class Deletion: # Sleep for a short time before processing the next message # This will prevent the bot from spamming messages too quickly await asyncio.sleep(PROCESS_WAIT_TIME) - except: + except Exception: traceback.print_exc() - pass diff --git a/services/environment_service.py b/services/environment_service.py index c6f10e7..701b587 100644 --- a/services/environment_service.py +++ b/services/environment_service.py @@ -31,9 +31,9 @@ class EnvService: @staticmethod def environment_path_with_fallback(env_name, relative_fallback=None): - dir = os.getenv(env_name) - if dir != None: - return Path(dir).resolve() + directory = os.getenv(env_name) + if directory is not None: + return Path(directory).resolve() if relative_fallback: app_relative = (app_root_path() / relative_fallback).resolve() @@ -70,7 +70,7 @@ class EnvService: # Read these allowed guilds and return as a list of ints try: allowed_guilds = os.getenv("ALLOWED_GUILDS") - except: + except Exception: allowed_guilds = None if allowed_guilds is None: @@ -93,7 +93,7 @@ class EnvService: # Read these allowed roles and return as a list of strings try: admin_roles = os.getenv("ADMIN_ROLES") - except: + except Exception: admin_roles = None if admin_roles is None: @@ -119,7 +119,7 @@ class EnvService: # Read these allowed roles and return as a list of strings try: dalle_roles = os.getenv("DALLE_ROLES") - except: + except Exception: dalle_roles = None if dalle_roles is None: @@ -145,7 +145,7 @@ class EnvService: # Read these allowed roles and return as a list of strings try: gpt_roles = os.getenv("GPT_ROLES") - except: + except Exception: gpt_roles = None if gpt_roles is None: @@ -171,7 +171,7 @@ class EnvService: # The string is DMd to the new server member as part of an embed. try: welcome_message = os.getenv("WELCOME_MESSAGE") - except: + except Exception: welcome_message = "Hi there! Welcome to our Discord server!" return welcome_message @@ -181,7 +181,7 @@ class EnvService: # The string can be blank but this is not advised. If a string cannot be found in the .env file, the below string is used. try: moderations_alert_channel = os.getenv("MODERATIONS_ALERT_CHANNEL") - except: + except Exception: moderations_alert_channel = None return moderations_alert_channel @@ -191,9 +191,8 @@ class EnvService: user_input_api_keys = os.getenv("USER_INPUT_API_KEYS") if user_input_api_keys.lower().strip() == "true": return True - else: - return False - except: + return False + except Exception: return False @staticmethod @@ -202,7 +201,6 @@ class EnvService: user_key_db_path = os.getenv("USER_KEY_DB_PATH") if user_key_db_path is None: return None - else: - return Path(user_key_db_path) - except: + return Path(user_key_db_path) + except Exception: return None diff --git a/services/message_queue_service.py b/services/message_queue_service.py index 3221661..c382528 100644 --- a/services/message_queue_service.py +++ b/services/message_queue_service.py @@ -22,7 +22,7 @@ class Message: # Send the message try: await message.channel.send(message.content) - except: + except Exception: pass # Sleep for a short time before processing the next message diff --git a/services/moderations_service.py b/services/moderations_service.py index 5698a38..83061da 100644 --- a/services/moderations_service.py +++ b/services/moderations_service.py @@ -155,10 +155,9 @@ class Moderation: if delete_result: return ModerationResult.DELETE - elif warn_result: + if warn_result: return ModerationResult.WARN - else: - return ModerationResult.NONE + return ModerationResult.NONE # This function will be called by the bot to process the message queue @staticmethod @@ -238,9 +237,8 @@ class Moderation: # Sleep for a short time before processing the next message # This will prevent the bot from spamming messages too quickly await asyncio.sleep(PROCESS_WAIT_TIME) - except: + except Exception: traceback.print_exc() - pass class ModerationAdminView(discord.ui.View): @@ -352,7 +350,7 @@ class KickUserButton(discord.ui.Button["ModerationAdminView"]): await self.message.author.kick( reason="You broke the server rules. Please rejoin and review the rules." ) - except: + except Exception: pass await interaction.response.send_message( "This user was attempted to be kicked", ephemeral=True, delete_after=10 @@ -392,7 +390,7 @@ class TimeoutUserButton(discord.ui.Button["ModerationAdminView"]): # Get the user id try: await self.message.delete() - except: + except Exception: pass try: @@ -400,9 +398,8 @@ class TimeoutUserButton(discord.ui.Button["ModerationAdminView"]): until=discord.utils.utcnow() + timedelta(hours=self.hours), reason="Breaking the server chat rules", ) - except Exception as e: + except Exception: traceback.print_exc() - pass await interaction.response.send_message( f"This user was timed out for {self.hours} hour(s)", diff --git a/services/pinecone_service.py b/services/pinecone_service.py index d57c029..2334f21 100644 --- a/services/pinecone_service.py +++ b/services/pinecone_service.py @@ -37,20 +37,19 @@ class PineconeService: }, ) return first_embedding - else: - embedding = await model.send_embedding_request( - text, custom_api_key=custom_api_key - ) - self.index.upsert( - [ - ( - text, - embedding, - {"conversation_id": conversation_id, "timestamp": timestamp}, - ) - ] - ) - return embedding + embedding = await model.send_embedding_request( + text, custom_api_key=custom_api_key + ) + self.index.upsert( + [ + ( + text, + embedding, + {"conversation_id": conversation_id, "timestamp": timestamp}, + ) + ] + ) + return embedding def get_n_similar(self, conversation_id: int, embedding, n=10): response = self.index.query( diff --git a/services/text_service.py b/services/text_service.py index efca958..cd116cc 100644 --- a/services/text_service.py +++ b/services/text_service.py @@ -470,9 +470,11 @@ class TextService: except Exception: message = "Something went wrong, please try again later. This may be due to upstream issues on the API, or rate limiting." - await ctx.send_followup(message) if from_context else await ctx.reply( - message - ) + if not from_context: + await ctx.send_followup(message) + else: + await ctx.reply(message) + converser_cog.remove_awaiting( ctx.author.id, ctx.channel.id, from_ask_command, from_edit_command ) @@ -480,7 +482,7 @@ class TextService: try: await converser_cog.end_conversation(ctx) - except: + except Exception: pass return @@ -675,9 +677,9 @@ class TextService: converser_cog.redo_users[after.author.id].prompt = edited_content -""" -Conversation interaction buttons -""" +# +#Conversation interaction buttons +# class ConversationView(discord.ui.View): @@ -753,7 +755,6 @@ class EndConvoButton(discord.ui.Button["ConversationView"]): await interaction.response.send_message( e, ephemeral=True, delete_after=30 ) - pass else: await interaction.response.send_message( "This is not your conversation to end!", ephemeral=True, delete_after=10 @@ -789,7 +790,7 @@ class RedoButton(discord.ui.Button["ConversationView"]): response_message = self.converser_cog.redo_users[user_id].response codex = self.converser_cog.redo_users[user_id].codex - msg = await interaction.response.send_message( + await interaction.response.send_message( "Retrying your original request...", ephemeral=True, delete_after=15 ) @@ -815,9 +816,9 @@ class RedoButton(discord.ui.Button["ConversationView"]): ) -""" -The setup modal when using user input API keys -""" +# +#The setup modal when using user input API keys +# class SetupModal(discord.ui.Modal): @@ -880,7 +881,7 @@ class SetupModal(discord.ui.Modal): ephemeral=True, delete_after=10, ) - except Exception as e: + except Exception: traceback.print_exc() await interaction.followup.send( "There was an error saving your API key.", @@ -888,5 +889,3 @@ class SetupModal(discord.ui.Modal): delete_after=30, ) return - - pass diff --git a/services/usage_service.py b/services/usage_service.py index 4bf7e4e..dd13927 100644 --- a/services/usage_service.py +++ b/services/usage_service.py @@ -1,4 +1,3 @@ -import os from pathlib import Path import aiofiles @@ -36,8 +35,8 @@ class UsageService: await f.close() return usage - def count_tokens(self, input): - res = self.tokenizer(input)["input_ids"] + def count_tokens(self, text): + res = self.tokenizer(text)["input_ids"] return len(res) async def update_usage_image(self, image_size):