upd model.py
This commit is contained in:
parent
703ef0fcc6
commit
972e475233
302
Backend/model.py
302
Backend/model.py
@ -14,17 +14,19 @@ from psycopg2.extras import RealDictCursor
|
|||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Získanie konfiguračného súboru
|
||||||
config_file_path = "config.json"
|
config_file_path = "config.json"
|
||||||
with open(config_file_path, 'r') as config_file:
|
with open(config_file_path, 'r') as config_file:
|
||||||
config = json.load(config_file)
|
config = json.load(config_file)
|
||||||
|
|
||||||
|
# Získanie Mistral API kľúča
|
||||||
mistral_api_key = "hXDC4RBJk1qy5pOlrgr01GtOlmyCBaNs"
|
mistral_api_key = "hXDC4RBJk1qy5pOlrgr01GtOlmyCBaNs"
|
||||||
if not mistral_api_key:
|
if not mistral_api_key:
|
||||||
raise ValueError("Mistral API key not found in configuration.")
|
raise ValueError("Mistral API key not found in configuration.")
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Simple functions for translation (stub)
|
# Funkcie pre preklad (stub verzie)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def translate_to_slovak(text: str) -> str:
|
def translate_to_slovak(text: str) -> str:
|
||||||
return text
|
return text
|
||||||
@ -35,7 +37,23 @@ def translate_preserving_medicine_names(text: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Function for evaluating the completeness of the answer
|
# Funkcia na generovanie podrobného opisu hodnotenia cez Mistral
|
||||||
|
###############################################################################
|
||||||
|
def generate_detailed_description(query: str, answer: str, rating: float) -> str:
|
||||||
|
prompt = (
|
||||||
|
f"Podrobne opíš, prečo odpoveď: '{answer}' na otázku: '{query}' dosiahla hodnotenie {rating} zo 10. "
|
||||||
|
"Uveď relevantné aspekty, ktoré ovplyvnili toto hodnotenie, vrátane úplnosti, presnosti a kvality vysvetlenia."
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
description = llm_small.generate_text(prompt=prompt, max_tokens=150, temperature=0.5)
|
||||||
|
return description.strip()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error generating detailed description: {e}")
|
||||||
|
return "Nie je dostupný podrobný popis."
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Funkcia na hodnotenie úplnosti odpovede
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def evaluate_complete_answer(query: str, answer: str) -> dict:
|
def evaluate_complete_answer(query: str, answer: str) -> dict:
|
||||||
evaluation_prompt = (
|
evaluation_prompt = (
|
||||||
@ -57,28 +75,53 @@ def evaluate_complete_answer(query: str, answer: str) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Function for validating the response logic
|
# Funkcia pre validáciu logiky odpovede (aktualizovaná verzia)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def validate_answer_logic(query: str, answer: str) -> str:
|
def validate_answer_logic(query: str, answer: str) -> str:
|
||||||
validation_prompt = (
|
validation_prompt = (
|
||||||
f"Otázka: '{query}'\n"
|
f"Otázka: '{query}'\n"
|
||||||
f"Odpoveď: '{answer}'\n\n"
|
f"Odpoveď: '{answer}'\n\n"
|
||||||
"Analyzuj prosím túto odpoveď. Ak odpoveď neobsahuje všetky dodatočné informácie, na ktoré sa pýtal používateľ, "
|
"Vyhodnoť, či odpoveď jednoznačne reaguje na uvedenú otázku a obsahuje všetky dôležité informácie. "
|
||||||
"alebo ak odporúčania liekov nie sú úplné (napr. chýba dávkovanie alebo čas užívania, ak boli takéto požiadavky v otázke), "
|
"Ak odpoveď nereaguje presne na otázku, vytvor novú odpoveď, ktorá jasne a logicky reaguje na tento dotaz. "
|
||||||
"vytvor opravenú odpoveď, ktorá je logicky konzistentná s otázkou. "
|
"Ak je odpoveď správna, začni svoju odpoveď textom 'OK:'; následne uveď potvrdenú odpoveď. "
|
||||||
"Odpovedz v slovenčine a iba čistou, konečnou odpoveďou bez ďalších komentárov."
|
"Odpovedz len finálnou odpoveďou bez ďalších komentárov."
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
validated_answer = llm_small.generate_text(prompt=validation_prompt, max_tokens=800, temperature=0.5)
|
validated_answer = llm_small.generate_text(prompt=validation_prompt, max_tokens=800, temperature=0.5)
|
||||||
logger.info(f"Validated answer: {validated_answer}")
|
logger.info(f"Validated answer (first 200 chars): {validated_answer[:200]}")
|
||||||
return validated_answer
|
if validated_answer.strip().lower().startswith("ok:"):
|
||||||
|
return validated_answer.split("OK:", 1)[1].strip()
|
||||||
|
else:
|
||||||
|
return validated_answer.strip()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error during answer validation: {e}")
|
logger.error(f"Error during answer validation: {e}")
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Function for creating a dynamic prompt with information from documents
|
# Funkcia pre logovanie hodnotení do súboru
|
||||||
|
###############################################################################
|
||||||
|
def log_evaluation_to_file(model: str, search_type: str, rating: float, detailed_desc: str, answer: str):
|
||||||
|
safe_model = model.replace(" ", "_")
|
||||||
|
file_name = f"{safe_model}_{search_type}.txt"
|
||||||
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
|
log_entry = (
|
||||||
|
f"Timestamp: {timestamp}\n"
|
||||||
|
f"Rating: {rating}/10\n"
|
||||||
|
f"Detailed description:\n{detailed_desc}\n"
|
||||||
|
f"Answer:\n{answer}\n"
|
||||||
|
+ "=" * 80 + "\n\n"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
with open(file_name, "a", encoding="utf-8") as f:
|
||||||
|
f.write(log_entry)
|
||||||
|
logger.info(f"Hodnotenie bolo zapísané do súboru {file_name}.")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error writing evaluation to file {file_name}: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Funkcia pre vytvorenie dynamického prompt-u z informácií o dokumentoch
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def build_dynamic_prompt(query: str, documents: list) -> str:
|
def build_dynamic_prompt(query: str, documents: list) -> str:
|
||||||
documents_str = "\n".join(documents)
|
documents_str = "\n".join(documents)
|
||||||
@ -90,14 +133,13 @@ def build_dynamic_prompt(query: str, documents: list) -> str:
|
|||||||
"Ak áno, v odpovedi najprv uveď odporúčané lieky – pre každý liek uveď jeho názov, stručné vysvetlenie a, ak je to relevantné, "
|
"Ak áno, v odpovedi najprv uveď odporúčané lieky – pre každý liek uveď jeho názov, stručné vysvetlenie a, ak je to relevantné, "
|
||||||
"odporúčané dávkovanie alebo čas užívania, a potom v ďalšej časti poskytn ú odpoveď na dodatočné požiadavky. "
|
"odporúčané dávkovanie alebo čas užívania, a potom v ďalšej časti poskytn ú odpoveď na dodatočné požiadavky. "
|
||||||
"Odpovedaj priamo a ľudským, priateľským tónom v číslovanom zozname, bez zbytočných úvodných fráz. "
|
"Odpovedaj priamo a ľudským, priateľským tónom v číslovanom zozname, bez zbytočných úvodných fráz. "
|
||||||
"Odpoveď musí byť v slovenčine. "
|
"Odpovedz výlučne po slovensky."
|
||||||
"Prosím, odpovedaj v priateľskom, zdvorilom a profesionálnom tóne, bez akýchkoľvek agresívnych či drzých výrazov."
|
|
||||||
)
|
)
|
||||||
return prompt
|
return prompt
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Function to get user data from the database via endpoint /api/get_user_data
|
# Funkcia pre získavanie user_data z databázy cez endpoint /api/get_user_data
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def get_user_data_from_db(chat_id: str) -> str:
|
def get_user_data_from_db(chat_id: str) -> str:
|
||||||
try:
|
try:
|
||||||
@ -113,7 +155,7 @@ def get_user_data_from_db(chat_id: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Class for calling Mistral LLM
|
# Trieda pre prácu s Mistral LLM cez API
|
||||||
###############################################################################
|
###############################################################################
|
||||||
class CustomMistralLLM:
|
class CustomMistralLLM:
|
||||||
def __init__(self, api_key: str, endpoint_url: str, model_name: str):
|
def __init__(self, api_key: str, endpoint_url: str, model_name: str):
|
||||||
@ -122,6 +164,10 @@ class CustomMistralLLM:
|
|||||||
self.model_name = model_name
|
self.model_name = model_name
|
||||||
|
|
||||||
def generate_text(self, prompt: str, max_tokens=812, temperature=0.7, retries=3, delay=2):
|
def generate_text(self, prompt: str, max_tokens=812, temperature=0.7, retries=3, delay=2):
|
||||||
|
# Pre mistral-large, ak je prompt príliš dlhý, skracujeme ho (napr. na 4000 znakov)
|
||||||
|
if self.model_name == "mistral-large-latest" and len(prompt) > 4000:
|
||||||
|
logger.warning(f"Prompt dlhší ako 4000 znakov, skracujem ho.")
|
||||||
|
prompt = prompt[:4000]
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {self.api_key}",
|
"Authorization": f"Bearer {self.api_key}",
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
@ -155,21 +201,7 @@ class CustomMistralLLM:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Function for generating a detailed evaluation description
|
# Inicializácia embeddingov a Elasticsearch
|
||||||
###############################################################################
|
|
||||||
# def detailed_evaluation_description(query: str, answer: str, rating: float) -> str:
|
|
||||||
# prompt = (
|
|
||||||
# f"Podrobne opíš, prečo odpoveď: '{answer}' na otázku: '{query}' dosiahla hodnotenie {rating} zo 10. "
|
|
||||||
# "Uveď relevantné aspekty, ktoré ovplyvnili toto hodnotenie, vrátane úplnosti, presnosti a kvality vysvetlenia."
|
|
||||||
# )
|
|
||||||
# description = llm_small.generate_text(prompt=prompt, max_tokens=150, temperature=0.5)
|
|
||||||
# return description.strip()
|
|
||||||
#
|
|
||||||
# Ak chcete vidieť podrobné hodnotenie, odkomentujte funkciu detailed_evaluation_description a príslušné časti kódu.
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Initialisation of Embeddings and Elasticsearch
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
logger.info("Loading HuggingFaceEmbeddings model...")
|
logger.info("Loading HuggingFaceEmbeddings model...")
|
||||||
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
|
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
|
||||||
@ -188,7 +220,7 @@ if config.get("useCloud", False):
|
|||||||
else:
|
else:
|
||||||
logger.info("Using local Elasticsearch.")
|
logger.info("Using local Elasticsearch.")
|
||||||
vectorstore = ElasticsearchStore(
|
vectorstore = ElasticsearchStore(
|
||||||
es_url="http://elasticsearch:9200",
|
es_url="http://localhost:9200",
|
||||||
index_name=index_name,
|
index_name=index_name,
|
||||||
embedding=embeddings,
|
embedding=embeddings,
|
||||||
)
|
)
|
||||||
@ -196,7 +228,7 @@ else:
|
|||||||
logger.info("Connected to Elasticsearch.")
|
logger.info("Connected to Elasticsearch.")
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Initialisation of LLM small & large
|
# Inicializácia LLM small & large
|
||||||
###############################################################################
|
###############################################################################
|
||||||
llm_small = CustomMistralLLM(
|
llm_small = CustomMistralLLM(
|
||||||
api_key=mistral_api_key,
|
api_key=mistral_api_key,
|
||||||
@ -211,9 +243,13 @@ llm_large = CustomMistralLLM(
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Request classification function: vyhladavanie vs. upresnenie
|
# Funkcia na klasifikáciu dopytu: vyhladavanie vs. upresnenie alebo update informácií
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def classify_query(query: str, chat_history: str = "") -> str:
|
def classify_query(query: str, chat_history: str = "") -> str:
|
||||||
|
# Ak v histórii sa nachádza výzva na zadanie údajov a query obsahuje číslice (napr. vek),
|
||||||
|
# považujeme to za odpoveď na doplnenie informácií.
|
||||||
|
if "Prosím, uveďte vek pacienta" in chat_history and re.search(r"\d+\s*(rok(ov|y)?|years?)", query.lower()):
|
||||||
|
return "update"
|
||||||
if not chat_history.strip():
|
if not chat_history.strip():
|
||||||
return "vyhladavanie"
|
return "vyhladavanie"
|
||||||
prompt = (
|
prompt = (
|
||||||
@ -222,8 +258,8 @@ def classify_query(query: str, chat_history: str = "") -> str:
|
|||||||
"o upresnenie/doplnenie už poskytnutej odpovede.\n"
|
"o upresnenie/doplnenie už poskytnutej odpovede.\n"
|
||||||
"Ak dopyt obsahuje výrazy ako 'čo pit', 'aké lieky', 'odporuč liek', 'hľadám liek', "
|
"Ak dopyt obsahuje výrazy ako 'čo pit', 'aké lieky', 'odporuč liek', 'hľadám liek', "
|
||||||
"odpovedaj slovom 'vyhľadávanie'.\n"
|
"odpovedaj slovom 'vyhľadávanie'.\n"
|
||||||
"Ak dopyt slúži na upresnenie, napríklad obsahuje výrazy ako 'a nie na predpis', "
|
"Ak dopyt slúži na upresnenie, napríklad obsahuje výrazy ako 'a nie na predpis', 'upresni', 'este raz', "
|
||||||
"'upresni', 'este raz', odpovedaj slovom 'upresnenie'.\n"
|
"odpovedaj slovom 'upresnenie'.\n"
|
||||||
f"Dopyt: \"{query}\""
|
f"Dopyt: \"{query}\""
|
||||||
)
|
)
|
||||||
classification = llm_small.generate_text(prompt=prompt, max_tokens=20, temperature=0.3)
|
classification = llm_small.generate_text(prompt=prompt, max_tokens=20, temperature=0.3)
|
||||||
@ -237,7 +273,7 @@ def classify_query(query: str, chat_history: str = "") -> str:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Template for upresnenie dopytu
|
# Šablóna prompt-u pre upresnenie (bez histórie)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def build_upresnenie_prompt_no_history(chat_history: str, user_query: str) -> str:
|
def build_upresnenie_prompt_no_history(chat_history: str, user_query: str) -> str:
|
||||||
prompt = f"""
|
prompt = f"""
|
||||||
@ -262,7 +298,7 @@ Upresňujúca otázka od používateľa:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Function for retrieving the last vyhladavacieho dopytu z histórie
|
# Funkcia pre extrakciu posledného vyhľadávacieho dopytu z histórie
|
||||||
###############################################################################
|
###############################################################################
|
||||||
def extract_last_vyhladavacie_query(chat_history: str) -> str:
|
def extract_last_vyhladavacie_query(chat_history: str) -> str:
|
||||||
lines = chat_history.splitlines()
|
lines = chat_history.splitlines()
|
||||||
@ -275,7 +311,7 @@ def extract_last_vyhladavacie_query(chat_history: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Agent class for data storage: vek, anamneza, predpis, user_data, search_query
|
# Trieda agenta pre ukladanie údajov: vek, anamneza, predpis, user_data, search_query
|
||||||
###############################################################################
|
###############################################################################
|
||||||
class ConversationalAgent:
|
class ConversationalAgent:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -325,7 +361,7 @@ class ConversationalAgent:
|
|||||||
if not self.get_memory("vek"):
|
if not self.get_memory("vek"):
|
||||||
missing_info["vek"] = "Prosím, uveďte vek pacienta."
|
missing_info["vek"] = "Prosím, uveďte vek pacienta."
|
||||||
if not self.get_memory("anamneza"):
|
if not self.get_memory("anamneza"):
|
||||||
missing_info["anamnéza"] = "Má pacient nejaké chronické ochorenia alebo alergie?"
|
missing_info["anamneza"] = "Má pacient nejaké chronické ochorenia alebo alergie?"
|
||||||
if not self.get_memory("predpis"):
|
if not self.get_memory("predpis"):
|
||||||
missing_info["predpis"] = "Ide o liek na predpis alebo voľnopredajný liek?"
|
missing_info["predpis"] = "Ide o liek na predpis alebo voľnopredajný liek?"
|
||||||
return missing_info
|
return missing_info
|
||||||
@ -335,7 +371,7 @@ class ConversationalAgent:
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Main function process_query_with_mistral with updated logic
|
# Hlavná funkcia process_query_with_mistral, ktorá vykonáva obidva druhy vyhľadávania
|
||||||
###############################################################################
|
###############################################################################
|
||||||
CHAT_HISTORY_ENDPOINT = "http://localhost:5000/api/chat_history_detail"
|
CHAT_HISTORY_ENDPOINT = "http://localhost:5000/api/chat_history_detail"
|
||||||
|
|
||||||
@ -343,6 +379,7 @@ CHAT_HISTORY_ENDPOINT = "http://localhost:5000/api/chat_history_detail"
|
|||||||
def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10):
|
def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10):
|
||||||
logger.info("Processing query started.")
|
logger.info("Processing query started.")
|
||||||
|
|
||||||
|
# Načítame históriu chatu
|
||||||
chat_history = ""
|
chat_history = ""
|
||||||
if chat_context:
|
if chat_context:
|
||||||
chat_history = chat_context
|
chat_history = chat_context
|
||||||
@ -371,36 +408,29 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
|
|||||||
if chat_id:
|
if chat_id:
|
||||||
existing_user_data = get_user_data_from_db(chat_id)
|
existing_user_data = get_user_data_from_db(chat_id)
|
||||||
|
|
||||||
|
if not chat_history.strip():
|
||||||
|
agent.update_memory("search_query", query)
|
||||||
|
|
||||||
|
qtype = classify_query(query, chat_history)
|
||||||
|
logger.info(f"Typ dopytu: {qtype}")
|
||||||
|
logger.info(f"Chat context (snippet): {chat_history[:200]}...")
|
||||||
|
|
||||||
|
if qtype == "update":
|
||||||
|
original_search = agent.long_term_memory.get("search_query")
|
||||||
|
if not original_search:
|
||||||
|
original_search = extract_last_vyhladavacie_query(chat_history)
|
||||||
|
query_to_use = original_search
|
||||||
|
else:
|
||||||
|
query_to_use = query
|
||||||
|
|
||||||
|
if qtype == "vyhladavanie":
|
||||||
|
agent.parse_user_info(chat_history)
|
||||||
agent.parse_user_info(query)
|
agent.parse_user_info(query)
|
||||||
missing_info = agent.analyze_input(query)
|
missing_info = agent.analyze_input(query)
|
||||||
|
|
||||||
if not existing_user_data:
|
|
||||||
if "Prosím, uveďte vek pacienta" in chat_history:
|
|
||||||
if chat_id:
|
|
||||||
update_payload = {"chatId": chat_id, "userData": query}
|
|
||||||
try:
|
|
||||||
update_response = requests.post("http://localhost:5000/api/save_user_data", json=update_payload)
|
|
||||||
if update_response.status_code == 200:
|
|
||||||
logger.info("User data was successfully updated via endpoint /api/save_user_data (data question flag).")
|
|
||||||
else:
|
|
||||||
logger.warning(f"Failed to update data (data question flag): {update_response.text}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error when updating user_data via endpoint (data question flag): {e}")
|
|
||||||
|
|
||||||
if missing_info:
|
if missing_info:
|
||||||
logger.info(f"Chýbajúce informácie: {missing_info}")
|
logger.info(f"Chýbajúce informácie: {missing_info}")
|
||||||
combined_missing_text = " ".join(missing_info.values())
|
combined_missing_text = " ".join(missing_info.values())
|
||||||
if query.strip() not in combined_missing_text:
|
|
||||||
if chat_id:
|
|
||||||
update_payload = {"chatId": chat_id, "userData": query}
|
|
||||||
try:
|
|
||||||
update_response = requests.post("http://localhost:5000/api/save_user_data", json=update_payload)
|
|
||||||
if update_response.status_code == 200:
|
|
||||||
logger.info("User data was successfully updated via endpoint /api/save_user_data.")
|
|
||||||
else:
|
|
||||||
logger.warning(f"Failed to update the data: {update_response.text}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error when updating user_data via endpoint: {e}")
|
|
||||||
return {
|
return {
|
||||||
"best_answer": combined_missing_text,
|
"best_answer": combined_missing_text,
|
||||||
"model": "FollowUp (new chat)",
|
"model": "FollowUp (new chat)",
|
||||||
@ -409,111 +439,69 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
|
|||||||
"patient_data": query
|
"patient_data": query
|
||||||
}
|
}
|
||||||
|
|
||||||
qtype = classify_query(query, chat_history)
|
|
||||||
logger.info(f"Typ dopytu: {qtype}")
|
|
||||||
logger.info(f"Chat context (snippet): {chat_history[:200]}...")
|
|
||||||
|
|
||||||
if qtype == "vyhladavanie":
|
|
||||||
user_data_db = get_user_data_from_db(chat_id)
|
|
||||||
if user_data_db:
|
|
||||||
query = query + " Udaje cloveka: " + user_data_db
|
|
||||||
agent.long_term_memory["search_query"] = query
|
|
||||||
|
|
||||||
if qtype == "upresnenie":
|
if qtype == "upresnenie":
|
||||||
original_search = agent.long_term_memory.get("search_query")
|
original_search = agent.long_term_memory.get("search_query")
|
||||||
if not original_search:
|
if not original_search:
|
||||||
original_search = extract_last_vyhladavacie_query(chat_history)
|
original_search = extract_last_vyhladavacie_query(chat_history)
|
||||||
if original_search is None:
|
if original_search is None:
|
||||||
original_search = ""
|
original_search = ""
|
||||||
combined_query = (original_search + " " + query).strip()
|
combined_query = (original_search + " " + query_to_use).strip()
|
||||||
user_data_db = get_user_data_from_db(chat_id)
|
user_data_db = get_user_data_from_db(chat_id)
|
||||||
if user_data_db:
|
if user_data_db:
|
||||||
combined_query += " Udaje cloveka: " + user_data_db
|
combined_query += " Udaje cloveka: " + user_data_db
|
||||||
logger.info(f"Combined query for search: {combined_query}")
|
logger.info(f"Použitý dopyt pre upresnenie: '{combined_query}'")
|
||||||
|
|
||||||
upres_prompt = build_upresnenie_prompt_no_history(chat_history, combined_query)
|
upres_prompt = build_upresnenie_prompt_no_history(chat_history, combined_query)
|
||||||
response_str = llm_small.generate_text(upres_prompt, max_tokens=1200, temperature=0.5)
|
response_str = llm_small.generate_text(upres_prompt, max_tokens=1200, temperature=0.5)
|
||||||
normalized = response_str.strip()
|
normalized = response_str.strip()
|
||||||
logger.info(f"Upresnenie prompt response: {normalized}")
|
logger.info(f"Upresnenie prompt response: {normalized}")
|
||||||
|
|
||||||
if re.match(r"(?i)^found_in_history:\s*", normalized):
|
# Vektorové a textové vyhľadávanie
|
||||||
logger.info("Zistený FOUND_IN_HISTORY – vykonávame vyhľadávanie s kombinovaným dopytom.")
|
|
||||||
elif re.match(r"(?i)^no_answer_in_history:\s*", normalized):
|
|
||||||
parts = re.split(r"(?i)^no_answer_in_history:\s*", normalized, maxsplit=1)
|
|
||||||
if len(parts) >= 2:
|
|
||||||
combined_query = parts[1].strip()
|
|
||||||
logger.info(f"Upravený vyhľadávací dopyт z NO_ANSWER_IN_HISTORY: {combined_query}")
|
|
||||||
|
|
||||||
vector_results = vectorstore.similarity_search(combined_query, k=k)
|
vector_results = vectorstore.similarity_search(combined_query, k=k)
|
||||||
max_docs = 5
|
text_results = vectorstore.client.search(
|
||||||
max_len = 1000
|
index=index_name,
|
||||||
vector_docs = [hit.metadata.get("text", "")[:max_len] for hit in vector_results[:max_docs]]
|
body={"size": k, "query": {"match": {"text": combined_query}}}
|
||||||
if not vector_docs:
|
|
||||||
return {
|
|
||||||
"best_answer": "Ľutujem, nenašli sa žiadne relevantné informácie.",
|
|
||||||
"model": "Upresnenie-NoResults",
|
|
||||||
"rating": 0,
|
|
||||||
"explanation": "No results from search."
|
|
||||||
}
|
|
||||||
joined_docs = "\n".join(vector_docs)
|
|
||||||
final_prompt = (
|
|
||||||
f"Otázka: {combined_query}\n\n"
|
|
||||||
"Na základe týchto informácií:\n"
|
|
||||||
f"{joined_docs}\n\n"
|
|
||||||
"Vygeneruj odporúčanie liekov alebo vysvetlenie, ak je to relevantné.\n"
|
|
||||||
"Prosím, odpovedaj stručne a dostatočne, bez nadmernej dĺžky."
|
|
||||||
)
|
)
|
||||||
|
vector_docs = [getattr(hit, 'page_content', None) or hit.metadata.get('text', '') for hit in vector_results[:5]]
|
||||||
|
text_docs = [hit['_source'].get('text', '') for hit in text_results['hits']['hits']]
|
||||||
|
all_docs = vector_docs + text_docs
|
||||||
|
final_prompt = build_dynamic_prompt(combined_query, all_docs)
|
||||||
|
if len(final_prompt) > 4000:
|
||||||
|
final_prompt = final_prompt[:4000]
|
||||||
|
|
||||||
ans_small = llm_small.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
ans_small = llm_small.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
||||||
ans_large = llm_large.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
ans_large = llm_large.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
||||||
|
|
||||||
val_small = validate_answer_logic(combined_query, ans_small)
|
val_small = validate_answer_logic(combined_query, ans_small)
|
||||||
val_large = validate_answer_logic(combined_query, ans_large)
|
val_large = validate_answer_logic(combined_query, ans_large)
|
||||||
eval_small = evaluate_complete_answer(combined_query, val_small)
|
eval_small = evaluate_complete_answer(combined_query, val_small)
|
||||||
eval_large = evaluate_complete_answer(combined_query, val_large)
|
eval_large = evaluate_complete_answer(combined_query, val_large)
|
||||||
|
|
||||||
candidates = [
|
candidates = [
|
||||||
{"summary": val_small, "eval": eval_small, "model": "Mistral Small"},
|
{"model": "Mistral Small Vector", "summary": val_small, "eval": eval_small},
|
||||||
{"summary": val_large, "eval": eval_large, "model": "Mistral Large"},
|
{"model": "Mistral Large Vector", "summary": val_large, "eval": eval_large},
|
||||||
]
|
]
|
||||||
|
for c in candidates:
|
||||||
#
|
desc = generate_detailed_description(combined_query, c["summary"], c["eval"]["rating"])
|
||||||
# for candidate in candidates:
|
log_evaluation_to_file(c["model"], "vector", c["eval"]["rating"], desc, c["summary"])
|
||||||
# detailed_desc = detailed_evaluation_description(combined_query, candidate["summary"], candidate["eval"]["rating"])
|
|
||||||
# candidate["eval"]["detailed_description"] = detailed_desc
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
best = max(candidates, key=lambda x: x["eval"]["rating"])
|
best = max(candidates, key=lambda x: x["eval"]["rating"])
|
||||||
logger.info(f"Odpoveď od modelu {best['model']} má rating: {best['eval']['rating']}/10")
|
|
||||||
|
|
||||||
|
|
||||||
evaluation_table = "=== Výsledky hodnotenia odpovedí ===\n"
|
|
||||||
evaluation_table += "{:<15} | {:<6} | {:<60}\n".format("Model", "Rating", "Evaluated Text")
|
|
||||||
evaluation_table += "-" * 100 + "\n"
|
|
||||||
for candidate in candidates:
|
|
||||||
model_name = candidate["model"]
|
|
||||||
rating = candidate["eval"]["rating"]
|
|
||||||
evaluated_text = candidate["summary"].replace("\n", " ")
|
|
||||||
evaluation_table += "{:<15} | {:<6} | {:<60}\n".format(model_name, rating, evaluated_text)
|
|
||||||
evaluation_table += "=" * 100 + "\n"
|
|
||||||
|
|
||||||
# with open("evaluation.txt", "w", encoding="utf-8") as f:
|
|
||||||
# f.write(evaluation_table)
|
|
||||||
# logger.info("Evaluation table записана в evaluation.txt")
|
|
||||||
|
|
||||||
final_answer = translate_preserving_medicine_names(best["summary"])
|
final_answer = translate_preserving_medicine_names(best["summary"])
|
||||||
memory_json = json.dumps(agent.long_term_memory)
|
memory_block = f"[MEMORY]{json.dumps(agent.long_term_memory)}[/MEMORY]"
|
||||||
memory_block = f"[MEMORY]{memory_json}[/MEMORY]"
|
|
||||||
final_answer_with_memory = final_answer + "\n\n"
|
|
||||||
return {
|
return {
|
||||||
"best_answer": final_answer_with_memory,
|
"best_answer": final_answer,
|
||||||
"model": best["model"],
|
"model": best["model"],
|
||||||
"rating": best["eval"]["rating"],
|
"rating": best["eval"]["rating"],
|
||||||
"explanation": best["eval"]["explanation"]
|
"explanation": best["eval"]["explanation"]
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_results = vectorstore.similarity_search(query, k=k)
|
# Vetva pre vyhladavanie
|
||||||
max_docs = 5
|
vector_results = vectorstore.similarity_search(query_to_use, k=k)
|
||||||
max_len = 1000
|
text_results = vectorstore.client.search(
|
||||||
vector_docs = [hit.metadata.get("text", "")[:max_len] for hit in vector_results[:max_docs]]
|
index=index_name,
|
||||||
|
body={"size": k, "query": {"match": {"text": query_to_use}}}
|
||||||
|
)
|
||||||
|
vector_docs = [getattr(hit, 'page_content', None) or hit.metadata.get('text', '') for hit in vector_results[:5]]
|
||||||
if not vector_docs:
|
if not vector_docs:
|
||||||
return {
|
return {
|
||||||
"best_answer": "Ľutujem, nenašli sa žiadne relevantné informácie.",
|
"best_answer": "Ľutujem, nenašli sa žiadne relevantné informácie.",
|
||||||
@ -521,21 +509,35 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
|
|||||||
"rating": 0,
|
"rating": 0,
|
||||||
"explanation": "No results"
|
"explanation": "No results"
|
||||||
}
|
}
|
||||||
joined_docs = "\n".join(vector_docs)
|
text_docs = [hit['_source'].get('text', '') for hit in text_results['hits']['hits']]
|
||||||
final_prompt = (
|
all_docs = vector_docs + text_docs
|
||||||
f"Otázka: {query}\n\n"
|
final_prompt = build_dynamic_prompt(query_to_use, all_docs)
|
||||||
"Na základe týchto informácií:\n"
|
if len(final_prompt) > 4000:
|
||||||
f"{joined_docs}\n\n"
|
final_prompt = final_prompt[:4000]
|
||||||
"Vygeneruj odporúčanie liekov alebo vysvetlenie, ak je to relevantné.\n"
|
|
||||||
"Prosím, odpovedaj stručne a dostatočne, bez nadmernej dĺžky."
|
ans_small = llm_small.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
||||||
)
|
ans_large = llm_large.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
||||||
answer = llm_small.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
|
|
||||||
memory_json = json.dumps(agent.long_term_memory)
|
val_small = validate_answer_logic(query_to_use, ans_small)
|
||||||
memory_block = f"[MEMORY]{memory_json}[/MEMORY]"
|
val_large = validate_answer_logic(query_to_use, ans_large)
|
||||||
answer_with_memory = answer + "\n\n"
|
eval_small = evaluate_complete_answer(query_to_use, val_small)
|
||||||
|
eval_large = evaluate_complete_answer(query_to_use, val_large)
|
||||||
|
|
||||||
|
candidates = [
|
||||||
|
{"model": "Mistral Small Text", "summary": val_small, "eval": eval_small},
|
||||||
|
{"model": "Mistral Large Text", "summary": val_large, "eval": eval_large},
|
||||||
|
]
|
||||||
|
for c in candidates:
|
||||||
|
desc = generate_detailed_description(query_to_use, c["summary"], c["eval"]["rating"])
|
||||||
|
log_evaluation_to_file(c["model"], "text", c["eval"]["rating"], desc, c["summary"])
|
||||||
|
|
||||||
|
best = max(candidates, key=lambda x: x["eval"]["rating"])
|
||||||
|
final_answer = translate_preserving_medicine_names(best["summary"])
|
||||||
|
memory_block = f"[MEMORY]{json.dumps(agent.long_term_memory)}[/MEMORY]"
|
||||||
return {
|
return {
|
||||||
"best_answer": answer_with_memory,
|
"best_answer": final_answer,
|
||||||
"model": "Vyhladavanie-Final",
|
"model": best["model"],
|
||||||
"rating": 9,
|
"rating": best["eval"]["rating"],
|
||||||
"explanation": "Vyhľadávacia cesta"
|
"explanation": best["eval"]["explanation"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user