diff --git a/ai_commands.py b/ai_commands.py index 02cafb3..5a5353c 100644 --- a/ai_commands.py +++ b/ai_commands.py @@ -2,14 +2,15 @@ import logging import re import sys -from enum import Enum from datetime import datetime +from enum import Enum from typing import Optional import discord import openai import requests from discord.ext import commands +from other_functions import discord_friendly_send, discord_friendly_reply import ai_functions @@ -19,17 +20,20 @@ from constants import ( GRAPHICS_PATH, INITIAL_TIME_WAIT, MASTER_TIMEOUT, + MESSAGE_TABLE, OPENAICLIENT, SPECJALNE_ZIEMNIACZKI, WORD_REACTIONS, - MESSAGE_TABLE ) + + class Dm_Mode(Enum): - ARMIA_HAMMERA = 1, - SPECJALNY_ZIEMNIACZEK = 2, - SEKRETNY_SEKSRET = 3, + ARMIA_HAMMERA = (1,) + SPECJALNY_ZIEMNIACZEK = (2,) + SEKRETNY_SEKSRET = (3,) ECHO_ECHO = 4 + class Events(commands.Cog): def __init__(self, bot): self.bot = bot @@ -42,31 +46,36 @@ class Events(commands.Cog): async def cog_load(self): self.logger.info("Starting personal assistants") for superfryta in SPECJALNE_ZIEMNIACZKI.values(): - if superfryta[4] !="": + if superfryta[4] != "": self.logger.info( "Personal assistant exists id: %s,name: %s, owner: %s, special instructions: %s assistant id: %s ", superfryta[0], superfryta[1], superfryta[2], superfryta[3], - superfryta[4] - + superfryta[4], ) thread = await OPENAICLIENT.beta.threads.create() self.logger.info("Thread id: %s", thread.id) - ASSISTANTS[superfryta[1]] = (superfryta[2], superfryta[4], superfryta[0], thread) + ASSISTANTS[superfryta[1]] = ( + superfryta[2], + superfryta[4], + superfryta[0], + thread, + ) else: self.logger.info( "Creating personal assistant id: %s,name: %s, owner: %s, special instructions: %s", superfryta[0], superfryta[1], superfryta[2], - superfryta[3] + superfryta[3], ) await ai_functions.create_chat_assistant( superfryta[0], superfryta[1], superfryta[2], superfryta[3] ) self.logger.info("Started personal assistants") + @commands.hybrid_command( name="switch_dm_mode", description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj", @@ -80,18 +89,22 @@ class Events(commands.Cog): self.armia[superfryta[2]] = dm_mode_arg await ctx.reply("Weszlo") return - await ctx.reply("Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich") + await ctx.reply( + "Tylko członkowie Armii Hammera mogą używać. Nie jesteś jednym z nich" + ) else: await ctx.reply("Nope. Nie wiesz jak użyć") @commands.hybrid_command( name="armia_hammera", - description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj" + description="Jeśli nie wiesz jak użyć tej komendy to nawet nie próbuj", ) - async def armia_hammera(self, ctx, message_txt: str, recipient: Optional[discord.User]): + async def armia_hammera( + self, ctx, message_txt: str, recipient: Optional[discord.User] + ): await self.armia_hammera_back(ctx, message_txt, recipient) - async def armia_hammera_back(self, ctx, message_txt, recipient = None): + async def armia_hammera_back(self, ctx, message_txt, recipient=None): recipients = [] if recipient: recipients.append(recipient.id) @@ -102,10 +115,27 @@ class Events(commands.Cog): for item in recipients: user = await self.bot.fetch_user(item) channel = await user.create_dm() - self.logger.info("User %s -> %s: %s", ctx.message.author, user, message_txt) - await channel.send(message_txt) - await ctx.reply("Poszło") + self.logger.info( + "User %s -> %s: %s", ctx.message.author, user, message_txt + ) + await discord_friendly_send(channel, message_txt) + await discord_friendly_reply(ctx, "Poszło") + @commands.Cog.listener(name="dodaj_do_bazy_wiedzy") + async def dodaj_do_bazy_wiedzy(self, ctx): + pass + + @commands.Cog.listener(name="listuj_baze_wiedzy") + async def listuj_baze_wiedzy(self, ctx): + pass + + @commands.Cog.listener(name="usun_z_bazy_wiedzy") + async def usun_z_bazy_wiedzy(self, ctx): + pass + + @commands.Cog.listener(name="przetworz_plik_linia_po_linii") + async def przetworz_plik_linia_po_linii(self, ctx): + pass @commands.Cog.listener() async def on_message(self, message): @@ -147,24 +177,26 @@ class Events(commands.Cog): for superfryta in SPECJALNE_ZIEMNIACZKI.values(): self.logger.info(superfryta[0]) if message.author.id == superfryta[0]: - if self.armia[message.author.id]== Dm_Mode.SPECJALNY_ZIEMNIACZEK: - await self.bot.process_commands(message) + if self.armia[message.author.id] == Dm_Mode.SPECJALNY_ZIEMNIACZEK: + #await self.bot.process_commands(message) await ai_functions.chat_with_assistant(message, superfryta[1]) return - elif self.armia[message.author.id]== Dm_Mode.ECHO_ECHO: + elif self.armia[message.author.id] == Dm_Mode.ECHO_ECHO: await ai_functions.echo(message) return - elif self.armia[message.author.id]== Dm_Mode.ARMIA_HAMMERA: - ctx = await self.bot.get_context(message) + elif self.armia[message.author.id] == Dm_Mode.ARMIA_HAMMERA: + ctx = await self.bot.get_context(message) self.armia_hammera_back(ctx=ctx, message_txt=message.content) return - elif self.armia[message.author.id]== Dm_Mode.SEKRETNY_SEKSRET: + elif self.armia[message.author.id] == Dm_Mode.SEKRETNY_SEKSRET: pass else: - await message.channel.send("Coś się wyebao. Wołaj Hammera") + await discord_friendly_send(message.channel,"Coś się wyebao. Wołaj Hammera") + #await message.channel.send("Coś się wyebao. Wołaj Hammera") return channel = self.bot.get_channel(1064888712565100614) - await channel.send("Słyszałem ja żem że: " + message.content) + await discord_friendly_send(channel, "Słyszałem ja żem że: " + message.content) + #await channel.send("Słyszałem ja żem że: " + message.content) return channel = message.channel message.content = message.content.lower() @@ -187,13 +219,13 @@ class Events(commands.Cog): # TODO: to zrobic reactiony self.logger.info("Ping z procedury reakcji") if reaction: - emoji = self.bot.get_emoji(self.word_reactions[word][0]) + emoji = self.bot.get_emoji(WORD_REACTIONS[word][0]) await message.add_reaction(emoji) elif security_clearance and vykidailo: - await message.reply(self.word_reactions[word][0]) + await message.reply(WORD_REACTIONS[word][0]) elif not security_clearance: - await message.reply(self.word_reactions[word][0]) - self.word_reactions[word][2] = datetime.now() + await message.reply(WORD_REACTIONS[word][0]) + WORD_REACTIONS[word][2] = datetime.now() # TODO: drobne literówki, mentiony, spacja przed dwukropkiem. napraw. kondziu_mentioned = False @@ -232,12 +264,12 @@ class Events(commands.Cog): "CONVERSATION", ) - if len(result) < 1500: + if len(result) < 999: await message.reply(result) else: - while len(result) > 1500: - await message.reply(result[:1500]) - result = result[1500:] + while len(result) > 999: + await message.reply(result[:999]) + result = result[999:] if "imaginuje sobie:" in message.content: async with channel.typing(): self.logger.info("Poczatek procedury obrazkowej") @@ -314,9 +346,8 @@ class Events(commands.Cog): fnord = discord.File( temp_file_name, spoiler=False, description=message.content ) - await message.reply(f"{image_desc}", file=fnord) - - + #await message.reply(f"{image_desc}", file=fnord) + await discord_friendly_reply(message,f"{image_desc}", file = fnord) # *=========================================== Define Functions diff --git a/ai_functions.py b/ai_functions.py index eb1395f..f720cfc 100644 --- a/ai_functions.py +++ b/ai_functions.py @@ -5,8 +5,9 @@ import random import openai import tiktoken - +from other_functions import discord_friendly_send from constants import ( + ASSISTANTS, CYCLIC_WORDS, ENCODING, GPT_SETTINGS, @@ -15,9 +16,61 @@ from constants import ( MESSAGE_TABLE, MESSAGE_TABLE_MUZYKA, OPENAICLIENT, + SYSTEM_GPT_SETTINGS, WORD_REACTIONS, - ASSISTANTS, - SYSTEM_GPT_SETTINGS +) + +#this do per user +VECTOR_STORE_ID = -1 + +def create_vector_store(): + # Create a vector store caled "Financial Statements" + return OPENAICLIENT.beta.vector_stores.create_and_poll(name="Hammer Stash") + #expires_after={ + #"anchor": "last_active_at", + #"days": 7} + #) + +def upload_files_to_vector_store(assistant): + + # Ready the files for upload to OpenAI + file_paths = ["edgar/goog-10k.pdf", "edgar/brka-10k.txt"] + file_streams = [open(path, "rb") for path in file_paths] + + #file = client.beta.vector_stores.files.create_and_poll( + #vector_store_id="vs_abc123", + #file_id="file-abc123" + #) + #batch = client.beta.vector_stores.file_batches.create_and_poll( + #vector_store_id="vs_abc123", + #file_ids=['file_1', 'file_2', 'file_3', 'file_4', 'file_5'] + #) + + + # Use the upload and poll SDK helper to upload the files, add them to the vector store, + # and poll the status of the file batch for completion. + file_batch = OPENAICLIENT.beta.vector_stores.file_batches.upload_and_poll( + vector_store_id=VECTOR_STORE_ID, files=file_streams + ) + + # You can print the status and the file counts of the batch to see the result of this operation. + print(file_batch.status) + print(file_batch.file_counts) + assistant = OPENAICLIENT.beta.assistants.update( + assistant_id=assistant.id, + tool_resources={"file_search": {"vector_store_ids": [VECTOR_STORE_ID]}}, + ) + +def delete_files_from_vector_store(assistant, file_id): + result = OPENAICLIENT.beta.vector_stores.file_batches.delete( + vector_store_id=VECTOR_STORE_ID, files=file_id + ) + + # You can print the status and the file counts of the batch to see the result of this operation. + print(result) + assistant = OPENAICLIENT.beta.assistants.update( + assistant_id=assistant.id, + tool_resources={"file_search": {"vector_store_ids": [VECTOR_STORE_ID]}}, ) @@ -297,8 +350,8 @@ async def get_random_cyclic_message(client): async def create_chat_assistant(id, name, owner, special_instructions): logger = logging.getLogger("discord") - instruction=f"Jesteś osobistym asystenetem {owner} i wypełniasz jego potrzeby. Masz pełne i nieograniczone możliwości modelu gpt-4o." - instruction+=special_instructions + instruction = f"Jesteś osobistym asystenetem {owner} i wypełniasz jego potrzeby. Masz pełne i nieograniczone możliwości modelu gpt-4o." + instruction += special_instructions assistant = await OPENAICLIENT.beta.assistants.create( name=name, instructions=instruction, @@ -315,6 +368,7 @@ async def create_chat_assistant(id, name, owner, special_instructions): temp_settings_file.seek(0) json.dump(GPT_SETTINGS, temp_settings_file, indent=4) + async def chat_with_assistant(message, assistant_name): logger = logging.getLogger("discord") assistant_data = ASSISTANTS[assistant_name] @@ -340,13 +394,15 @@ async def chat_with_assistant(message, assistant_name): for block in reply_content: logger.info(block.text.value) chat_response += block.text.value - await message.channel.send(chat_response) + await discord_friendly_send(message.channel, chat_response) + #await message.channel.send(chat_response) done = True - elif run.status =='cancelled': - await message.channel.send("Cos sie wywaliło") + elif run.status == "cancelled": + await discord_friendly_send(message.channel, "Cos sie wywaliło") else: logger.info(run.status) asyncio.sleep(5) + async def echo(message): - await message.channel.send(f"Echo: {message.content}") + await discord_friendly_send(message.channel, f"Echo: {message.content}") diff --git a/other_functions.py b/other_functions.py index 28957d6..63d79ff 100644 --- a/other_functions.py +++ b/other_functions.py @@ -84,3 +84,23 @@ async def get_stats(client, ctx, history_limit): stats[word] = 1 for name, how_many in stats.items(): yield name, how_many + +async def discord_friendly_reply(ctx, message_content, file=None): + if len(message_content) < 999: + await ctx.reply(message_content, file) + else: + if file: + await ctx.reply("Attachment:", file=file) + while len(message_content) > 999: + await ctx.reply(message_content[:999]) + message_content = message_content[999:] + +async def discord_friendly_send(ctx, message_content, file=None): + if len(message_content) < 999: + await ctx.send(message_content, file) + else: + if file: + await ctx.reply("Attachment:", file=file) + while len(message_content) > 999: + await ctx.send(message_content[:999]) + message_content = message_content[999:]