diff --git a/ai_commands.py b/ai_commands.py index 353746e..baa3bc1 100644 --- a/ai_commands.py +++ b/ai_commands.py @@ -294,7 +294,7 @@ class Events(commands.Cog): bartender, MESSAGE_TABLE, username, - "CONVERSATION", + "GENERAL", ) await discord_friendly_reply(message, result) @@ -332,7 +332,7 @@ class Events(commands.Cog): True, MESSAGE_TABLE, username, - "RANDOM", + "GENERAL", ) await discord_friendly_reply( message, f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}" diff --git a/ai_functions.py b/ai_functions.py index d02b148..3034dd1 100644 --- a/ai_functions.py +++ b/ai_functions.py @@ -5,6 +5,7 @@ import random import openai import tiktoken +import time from other_functions import discord_friendly_send from constants import ( ASSISTANTS, @@ -23,6 +24,36 @@ from constants import ( #this do per user VECTOR_STORE_ID = -1 + +async def _openai_call(messages, model, temperature=0.2): + """ + Responses API dla 4o/4.1*, fallback Chat Completions dla gpt-3.5-turbo. + Zwraca czysty string odpowiedzi. + """ + + if model.startswith("gpt-3.5"): + # legacy path – bez zmian w Twoim kodzie wyżej/niżej + def _sync_call(): + resp = OPENAICLIENT.chat.completions.create( + model=model, + messages=messages, + temperature=temperature, + ) + return resp.choices[0].message.content.strip() + return await asyncio.to_thread(_sync_call) + + # Responses API (zalecane dla 4o/4.1*) + def _sync_resp(): + resp = OPENAICLIENT.responses.create( + model=model, + temperature=temperature, + input=messages, + ) + # SDK zapewnia output_text dla zwykłych odpowiedzi + return (getattr(resp, "output_text", None) or "").strip() or str(resp) + return await asyncio.to_thread(_sync_resp) + + def create_vector_store(): # Create a vector store caled "Financial Statements" return OPENAICLIENT.beta.vector_stores.create_and_poll(name="Hammer Stash") @@ -99,7 +130,7 @@ def num_tokens_from_string(message, model): async def handle_response( - prompt, vykidailo, bartender, history, username, request_type + prompt, vykidailo, bartender, history, username, request_type, algorithm="gpt-4o" ): """ Handle responses by appending them to a history, use OpenAI to @@ -115,6 +146,10 @@ async def handle_response( :param music: The "music" parameter is a boolean value that indicates whether the conversation is related to music or not. If it is True, the conversation history will be stored in a different file and the response will be generated using a different model + :param request_type: The type of request being made, which can be "MUSIC", "RANDOM", "NONE" or "GENERAL" + GENERAL is for regular conversations, MUSIC is for music-related requests, + RANDOM is for random requests, and NONE is to not store the request in memory + :param algorithm: The algorithm to be used for generating the response, default is "gpt-4o" :return: The function `handle_response` returns a tuple containing the `result` and `MESSAGE_TABLE`. """ logger = logging.getLogger("discord") @@ -141,7 +176,7 @@ async def handle_response( file_memory.seek(0) # convert back to json. json.dump(file_data, file_memory, indent=4) - else: + elif request_type == "GENERAL": with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory: # First we load existing data into a dict. file_data = json.load(file_memory) @@ -171,17 +206,18 @@ async def handle_response( "Rozmiar zapytania przed dodaniem historii %s", chat_gpt_config_request_size ) if request_type == "MUSIC": - algorithm = "gpt-4o" table = MESSAGE_TABLE_MUZYKA token_amount = 10700 elif request_type == "RANDOM": - algorithm = "gpt-4o" + table = MESSAGE_TABLE + token_amount = 10700 + elif request_type == "GENERAL": table = MESSAGE_TABLE token_amount = 10700 else: - table = MESSAGE_TABLE - algorithm = "gpt-4o" - token_amount = 10700 + table = [] + token_amount = 10000 + prompt_gpt_request_size = num_tokens_from_string( {"role": "user", "content": final_prompt}, "gpt-4" @@ -206,9 +242,19 @@ async def handle_response( history.append(temp) logger.info("Rozmiar zapytania po wyslaniu %s", chat_gpt_config_request_size) try: - response = await OPENAICLIENT.chat.completions.create( - model=algorithm, messages=history - ) + # ...przygotowanie messages/system prompt/itp. jak masz... + # retry/backoff + deadline (zachowuje Twoją semantykę logowania) + timeout_sec = 120 + max_retries = 3 + deadline = time.time() + timeout_sec + for _ in range(max_retries): + if time.time() > deadline: + break + response = await asyncio.wait_for( + _openai_call(messages=history, model=algorithm), + timeout=max(0.1, deadline - time.time()) + ) + except openai.APITimeoutError as e: # Handle timeout error, e.g. retry or log result = f"*Kondziu patrzy na terminal, czeka, czeka, czeka,.... Jeszcze chwile czeka Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai spróbuj od nowa. *Na ekranie pojawia się*: {e}" @@ -272,6 +318,7 @@ async def handle_response( file_music_memory.seek(0) # convert back to json. json.dump(file_data, file_music_memory, indent=4) + return result, MESSAGE_TABLE_MUZYKA elif request_type == "RANDOM": with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory: # First we load existing data into a dict. @@ -281,7 +328,8 @@ async def handle_response( file_memory.seek(0) # convert back to json. json.dump(file_data, file_memory, indent=4) - else: + return result, MESSAGE_TABLE + elif request_type == "GENERAL": with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory: # First we load existing data into a dict. file_data = json.load(file_memory) @@ -290,8 +338,9 @@ async def handle_response( file_memory.seek(0) # convert back to json. json.dump(file_data, file_memory, indent=4) - return result, MESSAGE_TABLE - + return result, MESSAGE_TABLE + else: + return result, [] async def get_random_cyclic_message(client): """ diff --git a/latex_commands.py b/latex_commands.py new file mode 100644 index 0000000..e69de29 diff --git a/librarian_commands.py b/librarian_commands.py index ed858f6..0fe8d7f 100644 --- a/librarian_commands.py +++ b/librarian_commands.py @@ -222,7 +222,7 @@ class DataModule(commands.Cog): global MESSAGE_TABLE # pylint: disable=global-statement result, MESSAGE_TABLE = await handle_response( - prompt, vykidailo, bartender, MESSAGE_TABLE, username, "CONVERSATION" + prompt, vykidailo, bartender, MESSAGE_TABLE, username, "GENERAL" ) if len(result) < 1500: await ctx.send(result)