mirror of
https://github.com/migatu/conjurer.git
synced 2026-07-14 21:38:38 +00:00
upgrade to latest OpenAI API usage and logging improvements
This commit is contained in:
+113
-125
@@ -19,13 +19,26 @@ from constants import (
|
|||||||
OPENAICLIENT,
|
OPENAICLIENT,
|
||||||
SYSTEM_GPT_SETTINGS,
|
SYSTEM_GPT_SETTINGS,
|
||||||
WORD_REACTIONS,
|
WORD_REACTIONS,
|
||||||
|
CHEAP_MODEL,
|
||||||
|
LATEST_MODEL
|
||||||
)
|
)
|
||||||
|
|
||||||
# this do per user
|
# this do per user
|
||||||
VECTOR_STORE_ID = -1
|
VECTOR_STORE_ID = -1
|
||||||
|
def select_model(req_type: str, algo: str) -> str:
|
||||||
|
# Jeżeli jawnie podano algorithm (i nie jest 'auto'/''):
|
||||||
|
if algo and str(algo).strip().lower() not in ("auto",):
|
||||||
|
# wyjątek: MUZYKA ma zawsze być tania — nadpisujemy TYLKO jeśli przyszedł domyślny 'gpt-4o'
|
||||||
|
if req_type == "MUSIC" and algo.strip() in (LATEST_MODEL,):
|
||||||
|
return CHEAP_MODEL
|
||||||
|
return algo
|
||||||
|
# Auto-dobór:
|
||||||
|
if req_type == "MUSIC":
|
||||||
|
return CHEAP_MODEL
|
||||||
|
return LATEST_MODEL
|
||||||
|
|
||||||
|
|
||||||
async def _openai_call(messages, model, temperature=0.2):
|
async def openai_call(messages, model, temperature=0.2):
|
||||||
"""
|
"""
|
||||||
Responses API dla 4o/4.1*, fallback Chat Completions dla gpt-3.5-turbo.
|
Responses API dla 4o/4.1*, fallback Chat Completions dla gpt-3.5-turbo.
|
||||||
Zwraca czysty string odpowiedzi.
|
Zwraca czysty string odpowiedzi.
|
||||||
@@ -144,6 +157,7 @@ async def handle_response(
|
|||||||
request_type,
|
request_type,
|
||||||
algorithm="gpt-4o",
|
algorithm="gpt-4o",
|
||||||
none_request="",
|
none_request="",
|
||||||
|
internal_retry: bool = False
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Handle responses by appending them to a history, use OpenAI to
|
Handle responses by appending them to a history, use OpenAI to
|
||||||
@@ -167,102 +181,82 @@ async def handle_response(
|
|||||||
"""
|
"""
|
||||||
logger = logging.getLogger("discord")
|
logger = logging.getLogger("discord")
|
||||||
logger.info("Wywolanie procedury openai z promptem: %s", prompt)
|
logger.info("Wywolanie procedury openai z promptem: %s", prompt)
|
||||||
temp = {"role": "user", "content": username + ":" + prompt}
|
|
||||||
if vykidailo or bartender:
|
if vykidailo or bartender:
|
||||||
logger.info("Administrator coś chciał")
|
logger.info("Administrator coś chciał")
|
||||||
history.append(temp)
|
model_to_use = select_model(request_type, algorithm)
|
||||||
if request_type == "MUSIC":
|
logger.info("Wybrany model: %s", model_to_use)
|
||||||
with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as file_music_memory:
|
if request_type == "MUSIC" and model_to_use == "gpt-4o-mini":
|
||||||
# First we load existing data into a dict.
|
try:
|
||||||
file_data = json.load(file_music_memory)
|
# nic — normalnie pójdzie Responses API
|
||||||
# Join new_data with file_data inside emp_details
|
pass
|
||||||
file_data.append(temp)
|
except Exception:
|
||||||
file_music_memory.seek(0)
|
model_to_use = "gpt-3.5-turbo"
|
||||||
# convert back to json.
|
# --- 2) Budowa historii (token budget + reguły systemowe) ---
|
||||||
json.dump(file_data, file_music_memory, indent=4)
|
# NOTE: ignorujemy przekazany 'history' jako listę (tak było wcześniej),
|
||||||
elif request_type == "RANDOM":
|
# ale zwracamy aktualną tablicę do nadpisania w miejscach wołania (back-compat).
|
||||||
with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory:
|
base_system = GPT_SETTINGS[0] # zakładamy {"role":"system","content":...}
|
||||||
# First we load existing data into a dict.
|
history_msgs = []
|
||||||
file_data = json.load(file_memory)
|
|
||||||
# Join new_data with file_data inside emp_details
|
|
||||||
file_data.append(temp)
|
|
||||||
file_memory.seek(0)
|
|
||||||
# convert back to json.
|
|
||||||
json.dump(file_data, file_memory, indent=4)
|
|
||||||
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)
|
|
||||||
# Join new_data with file_data inside emp_details
|
|
||||||
file_data.append(temp)
|
|
||||||
file_memory.seek(0)
|
|
||||||
# convert back to json.
|
|
||||||
json.dump(file_data, file_memory, indent=4)
|
|
||||||
history = []
|
|
||||||
if request_type != "NONE":
|
|
||||||
history.append(GPT_SETTINGS[0])
|
|
||||||
chat_gpt_config_request_size = num_tokens_from_string(GPT_SETTINGS[0], "gpt-4")
|
|
||||||
|
|
||||||
|
if request_type != "NONE":
|
||||||
|
history_msgs.append(base_system)
|
||||||
|
chat_gpt_config_request_size = num_tokens_from_string(base_system, "gpt-4")
|
||||||
|
|
||||||
|
# Dynamiczne mikro-reguły (WORD_REACTIONS), jak w Twoim kodzie
|
||||||
for slowo, reakcja in WORD_REACTIONS.items():
|
for slowo, reakcja in WORD_REACTIONS.items():
|
||||||
if not reakcja[3]:
|
if not reakcja[3]:
|
||||||
content = (
|
content = f"Kiedy słyszysz {slowo} to reagujesz lub dzieje się to {reakcja[0]}"
|
||||||
"Kiedy słyszysz "
|
sys_msg = {"role": "system", "content": content}
|
||||||
+ slowo
|
chat_gpt_config_request_size += num_tokens_from_string(sys_msg, "gpt-4")
|
||||||
+ " to reagujesz lub dzieje się to "
|
history_msgs.append(sys_msg)
|
||||||
+ reakcja[0]
|
|
||||||
)
|
|
||||||
temp = {"role": "system", "content": content}
|
|
||||||
chat_gpt_config_request_size += num_tokens_from_string(temp, "gpt-4")
|
|
||||||
history.append(temp)
|
|
||||||
|
|
||||||
final_prompt = username + ":" + prompt
|
# wybór właściwej tablicy pamięci i budżetu
|
||||||
logger.debug(
|
|
||||||
"Rozmiar zapytania przed dodaniem historii %s", chat_gpt_config_request_size
|
|
||||||
)
|
|
||||||
if request_type == "MUSIC":
|
if request_type == "MUSIC":
|
||||||
table = MESSAGE_TABLE_MUZYKA
|
table = MESSAGE_TABLE_MUZYKA
|
||||||
token_amount = 10700
|
token_amount = 10700
|
||||||
elif request_type == "RANDOM":
|
elif request_type in ("RANDOM", "GENERAL"):
|
||||||
table = MESSAGE_TABLE
|
|
||||||
token_amount = 10700
|
|
||||||
elif request_type == "GENERAL":
|
|
||||||
table = MESSAGE_TABLE
|
table = MESSAGE_TABLE
|
||||||
token_amount = 10700
|
token_amount = 10700
|
||||||
else:
|
else:
|
||||||
table = []
|
table = []
|
||||||
token_amount = 10000
|
token_amount = 10000
|
||||||
|
|
||||||
prompt_gpt_request_size = num_tokens_from_string(
|
# doklejanie historii od końca aż do limitu (zachowana kolejność czasowa)
|
||||||
{"role": "user", "content": final_prompt}, "gpt-4"
|
final_prompt = f"{username}:{prompt}"
|
||||||
)
|
prompt_gpt_request_size = num_tokens_from_string({"role": "user", "content": final_prompt}, "gpt-4")
|
||||||
temptable = []
|
|
||||||
for i in reversed(table):
|
acc = []
|
||||||
temp_token = num_tokens_from_string(i, "gpt-4")
|
for msg in reversed(table):
|
||||||
logger.debug(
|
t = num_tokens_from_string(msg, "gpt-4")
|
||||||
"Rozmiar zapytania %s prompt %s temp %s",
|
if chat_gpt_config_request_size + prompt_gpt_request_size + t <= token_amount:
|
||||||
chat_gpt_config_request_size,
|
acc.append(msg)
|
||||||
prompt_gpt_request_size,
|
chat_gpt_config_request_size += t
|
||||||
temp_token,
|
else:
|
||||||
)
|
break
|
||||||
if (
|
# przywróć chronologicznie
|
||||||
chat_gpt_config_request_size
|
history_msgs.extend(reversed(acc))
|
||||||
< token_amount + prompt_gpt_request_size + temp_token
|
|
||||||
):
|
# aktualny prompt
|
||||||
temptable.insert(1, i)
|
history_msgs.append({"role": "user", "content": final_prompt})
|
||||||
chat_gpt_config_request_size += temp_token
|
logger.info("Rozmiar zapytania (tok): %s", prompt_gpt_request_size) # tokeny już policzone wyżej
|
||||||
history.extend(temptable)
|
|
||||||
temp = {"role": "user", "content": final_prompt}
|
|
||||||
history.append(temp)
|
|
||||||
else:
|
else:
|
||||||
history = none_request
|
# --- tryb NONE: nie dotykamy pamięci i pozwalamy przekazać własny 'none_request' ---
|
||||||
logger.info("Rozmiar zapytania po wyslaniu %s", chat_gpt_config_request_size)
|
if isinstance(none_request, list):
|
||||||
|
history_msgs = none_request
|
||||||
|
elif isinstance(none_request, str) and none_request.strip():
|
||||||
|
history_msgs = [{"role": "user", "content": none_request}]
|
||||||
|
else:
|
||||||
|
history_msgs = [{"role": "user", "content": f"{username}:{prompt}"}]
|
||||||
|
|
||||||
|
logger.info("Rozmiar zapytania (tok): %s", "n/a") # tokeny już policzone wyżej
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ...przygotowanie messages/system prompt/itp. jak masz...
|
# ...przygotowanie messages/system prompt/itp. jak masz...
|
||||||
# retry/backoff + deadline (zachowuje Twoją semantykę logowania)
|
# retry/backoff + deadline (zachowuje Twoją semantykę logowania)
|
||||||
timeout_sec = 120
|
timeout_sec = 120
|
||||||
deadline = time.time() + timeout_sec
|
deadline = time.time() + timeout_sec
|
||||||
response = await asyncio.wait_for(
|
response = await asyncio.wait_for(
|
||||||
_openai_call(messages=history, model=algorithm),
|
openai_call(messages=history_msgs, model=model_to_use),
|
||||||
timeout=max(0.1, deadline - time.time()),
|
timeout=max(0.1, deadline - time.time()),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -273,26 +267,33 @@ async def handle_response(
|
|||||||
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai. *Na ekranie pojawia się*: {e}"
|
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Nie mogę się połączyć z Openai. *Na ekranie pojawia się*: {e}"
|
||||||
except openai.BadRequestError as e:
|
except openai.BadRequestError as e:
|
||||||
# Handle invalid request error, e.g. validate parameters or log
|
# Handle invalid request error, e.g. validate parameters or log
|
||||||
resp, _ = await handle_response(
|
if internal_retry:
|
||||||
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie 'prompt'",
|
resp = "Nie umiem tego teraz ładnie wytłumaczyć — OpenAI mnie zastrzeliło."
|
||||||
True,
|
else:
|
||||||
True,
|
resp, _ = await handle_response(
|
||||||
MESSAGE_TABLE,
|
|
||||||
username,
|
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie 'prompt'",
|
||||||
"RANDOM",
|
True,
|
||||||
)
|
True,
|
||||||
response = f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
|
MESSAGE_TABLE,
|
||||||
|
username,
|
||||||
|
"RANDOM",
|
||||||
|
)
|
||||||
|
response = f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
|
||||||
except openai.APIResponseValidationError as e:
|
except openai.APIResponseValidationError as e:
|
||||||
# Handle invalid request error, e.g. validate parameters or log
|
# Handle invalid request error, e.g. validate parameters or log
|
||||||
resp, _ = await handle_response(
|
if internal_retry:
|
||||||
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie 'prompt'",
|
resp = "Nie umiem tego teraz ładnie wytłumaczyć — OpenAI mnie zastrzeliło."
|
||||||
True,
|
else:
|
||||||
True,
|
resp, _ = await handle_response(
|
||||||
MESSAGE_TABLE,
|
f"Wytlumacz jakie sa zasady dotyczące treści które możesz generować używając Dalle. Wytłumacz błąd {e} prostym językiem. Przeproś za nadmierną cenzurę. Wytłumacz co mogło być nie tak w prompcie 'prompt'",
|
||||||
username,
|
True,
|
||||||
"RANDOM",
|
True,
|
||||||
)
|
MESSAGE_TABLE,
|
||||||
response = f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
|
username,
|
||||||
|
"RANDOM",
|
||||||
|
)
|
||||||
|
response = f"Sorki, cenzura: {resp}. Jak chcesz to są kanały na nudle #sexy-foteczky i #kanal-do-fapania *Na ekranie pojawia się: {e}"
|
||||||
except openai.AuthenticationError as e:
|
except openai.AuthenticationError as e:
|
||||||
# Handle authentication error, e.g. check credentials or log
|
# Handle authentication error, e.g. check credentials or log
|
||||||
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Wołaj szefa - coś się z hasłem zjebało. *Na terminalu pojawia się:* {e}"
|
response = f"*Kondziu patrzy na terminal, chwile się zastanawia. Przypierdala w niego pięścią....* Wołaj szefa - coś się z hasłem zjebało. *Na terminalu pojawia się:* {e}"
|
||||||
@@ -308,41 +309,28 @@ async def handle_response(
|
|||||||
response = f"*Kondziu nurkuje za bar, terminal wybucha. Przed tobą ląduje pergamin zapisany pięknym gotykiem a na nim*: {e}"
|
response = f"*Kondziu nurkuje za bar, terminal wybucha. Przed tobą ląduje pergamin zapisany pięknym gotykiem a na nim*: {e}"
|
||||||
|
|
||||||
logger.info("Historia wysłana:")
|
logger.info("Historia wysłana:")
|
||||||
logger.info(history)
|
temp_assistant = {"role": "assistant", "content": response}
|
||||||
await asyncio.sleep(15)
|
logger.info(temp_assistant)
|
||||||
temp = {"role": "assistant", "content": response}
|
|
||||||
history.append(temp)
|
|
||||||
if request_type == "MUSIC":
|
if request_type == "MUSIC":
|
||||||
with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as file_music_memory:
|
# zapis do pliku MUZYKA
|
||||||
# First we load existing data into a dict.
|
with open(MEMORY_FIVE_MUZYKA, "r+", encoding=ENCODING) as fh:
|
||||||
file_data = json.load(file_music_memory)
|
file_data = json.load(fh)
|
||||||
# Join new_data with file_data inside emp_details
|
file_data.append({"role": "user", "content": f"{username}:{prompt}"})
|
||||||
file_data.append(temp)
|
file_data.append(temp_assistant)
|
||||||
file_music_memory.seek(0)
|
fh.seek(0)
|
||||||
# convert back to json.
|
json.dump(file_data, fh, indent=4)
|
||||||
json.dump(file_data, file_music_memory, indent=4)
|
|
||||||
return response, MESSAGE_TABLE_MUZYKA
|
return response, MESSAGE_TABLE_MUZYKA
|
||||||
elif request_type == "RANDOM":
|
|
||||||
with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory:
|
elif request_type in ("RANDOM", "GENERAL"):
|
||||||
# First we load existing data into a dict.
|
with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as fh:
|
||||||
file_data = json.load(file_memory)
|
file_data = json.load(fh)
|
||||||
# Join new_data with file_data inside emp_details
|
file_data.append({"role": "user", "content": f"{username}:{prompt}"})
|
||||||
file_data.append(temp)
|
file_data.append(temp_assistant)
|
||||||
file_memory.seek(0)
|
fh.seek(0)
|
||||||
# convert back to json.
|
json.dump(file_data, fh, indent=4)
|
||||||
json.dump(file_data, file_memory, indent=4)
|
|
||||||
return response, MESSAGE_TABLE
|
return response, MESSAGE_TABLE
|
||||||
elif request_type == "GENERAL":
|
|
||||||
with open(MEMORY_FIVE_SIARA, "r+", encoding=ENCODING) as file_memory:
|
else: # NONE
|
||||||
# First we load existing data into a dict.
|
|
||||||
file_data = json.load(file_memory)
|
|
||||||
# Join new_data with file_data inside emp_details
|
|
||||||
file_data.append(temp)
|
|
||||||
file_memory.seek(0)
|
|
||||||
# convert back to json.
|
|
||||||
json.dump(file_data, file_memory, indent=4)
|
|
||||||
return response, MESSAGE_TABLE
|
|
||||||
else:
|
|
||||||
return response, []
|
return response, []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -150,4 +150,6 @@ LATEX_MAX_ZIP_MB = 25
|
|||||||
OPENAI_MODEL = "gpt-4o-mini"
|
OPENAI_MODEL = "gpt-4o-mini"
|
||||||
|
|
||||||
ALLOWED_ROLES = ["Nocna Zmiana", "Jarl", "Thane", "Bartender"]
|
ALLOWED_ROLES = ["Nocna Zmiana", "Jarl", "Thane", "Bartender"]
|
||||||
GUILD_ID = 664789470779932693
|
GUILD_ID = 664789470779932693
|
||||||
|
LATEST_MODEL = "gpt-4o" # najnowszy/do rozmów (możesz zmienić w jednym miejscu)
|
||||||
|
CHEAP_MODEL = "gpt-4o-mini" # najtańszy (fallback do 3.5 niżej)
|
||||||
|
|||||||
Reference in New Issue
Block a user