upd docker prepare script

This commit is contained in:
oleh 2025-04-05 23:39:54 +02:00
parent 5b6d7728ce
commit 0d681ea2ba
5 changed files with 238 additions and 16 deletions

122
Backend/arch.py Normal file
View File

@ -0,0 +1,122 @@
from pptx import Presentation
from pptx.util import Inches
from pptx.enum.shapes import MSO_AUTO_SHAPE_TYPE, MSO_CONNECTOR
# Vytvorenie novej prezentácie
prs = Presentation()
slide_layout = prs.slide_layouts[5] # Prázdny slide
slide = prs.slides.add_slide(slide_layout)
# Definícia základných rozmerov a pozícií
left_margin = Inches(0.5)
top_margin = Inches(0.5)
block_width = Inches(3)
block_height = Inches(0.7)
vertical_gap = Inches(0.3)
horizontal_gap = Inches(0.5)
# Blok 1: Používateľský dotaz & Chat history
box1 = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_margin, top_margin, block_width, block_height)
box1.text = "Používateľský dotaz\n& Chat history"
# Blok 2: ConversationalAgent (pod box1)
box2_top = top_margin + block_height + vertical_gap
box2 = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_margin, box2_top, block_width, block_height)
box2.text = "ConversationalAgent"
# Blok 3: Klasifikácia dotazu (pod box2)
box3_top = box2_top + block_height + vertical_gap
box3 = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_margin, box3_top, block_width, block_height)
box3.text = "Klasifikácia dotazu"
# Vetvenie: Pozície pre dve vetvy
branch_top = box3_top + block_height + vertical_gap
# Ľavá vetva ("Vyhladavanie")
left_branch_left = left_margin - Inches(0.2)
box4A = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_branch_left, branch_top, block_width, block_height)
box4A.text = "ElasticsearchStore\nvyhľadávanie"
box5A_top = branch_top + block_height + vertical_gap
box5A = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_branch_left, box5A_top, block_width, block_height)
box5A.text = "Generovanie\ndynamického promptu"
box6A_top = box5A_top + block_height + vertical_gap
box6A = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_branch_left, box6A_top, block_width, block_height)
box6A.text = "Generovanie\nodpovede"
box7A_top = box6A_top + block_height + vertical_gap
box7A = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_branch_left, box7A_top, block_width, block_height)
box7A.text = "Finalizácia\nodpovede"
# Pravá vetva ("Upresnenie")
right_branch_left = left_margin + block_width + horizontal_gap
box4B = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, right_branch_left, branch_top, block_width, block_height)
box4B.text = "Kombinovanie\ndotazov"
box5B_top = branch_top + block_height + vertical_gap
box5B = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, right_branch_left, box5B_top, block_width, block_height)
box5B.text = "ElasticsearchStore\nvyhľadávanie"
box6B_top = box5B_top + block_height + vertical_gap
box6B = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, right_branch_left, box6B_top, block_width, block_height)
box6B.text = "Generovanie\ndynamického promptu"
box7B_top = box6B_top + block_height + vertical_gap
box7B = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, right_branch_left, box7B_top, block_width, block_height)
box7B.text = "Generovanie\nodpovedí (2 modely)"
box8B_top = box7B_top + block_height + vertical_gap
box8B = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, right_branch_left, box8B_top, block_width, block_height)
box8B.text = "Validácia a\nhodnotenie odpovedí"
box9B_top = box8B_top + block_height + vertical_gap
box9B = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, right_branch_left, box9B_top, block_width, block_height)
box9B.text = "Finalizácia\nodpovede"
# Finálny blok: Výstup (zlúčenie vetiev)
final_box_top = max(box7A_top, box9B_top) + block_height + vertical_gap
final_box = slide.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.RECTANGLE, left_margin, final_box_top, block_width, block_height)
final_box.text = "Výstup"
# Funkcia na pridanie šípok medzi blokmi
def add_connector(slide, start_shape, end_shape):
start_x = start_shape.left + start_shape.width / 2
start_y = start_shape.top + start_shape.height
end_x = end_shape.left + end_shape.width / 2
end_y = end_shape.top
connector = slide.shapes.add_connector(MSO_CONNECTOR.STRAIGHT, start_x, start_y, end_x, end_y)
# Aktuálna verzia python-pptx nepodporuje nastavenie šípky, preto tento riadok odstraňte alebo zakomentujte:
# connector.line.end_arrowhead.style = 1
return connector
# Prepojenie blokov
add_connector(slide, box1, box2)
add_connector(slide, box2, box3)
# Vetvenie z Box3 do oboch vetiev
mid_point = box3.left + box3.width / 2
branch_mid_y = box3.top + box3.height + vertical_gap/2
# Do ľavej vetvy:
connector_left = slide.shapes.add_connector(MSO_CONNECTOR.STRAIGHT, mid_point, box3.top + box3.height, left_branch_left + block_width/2, branch_mid_y)
# Do pravej vetvy:
connector_right = slide.shapes.add_connector(MSO_CONNECTOR.STRAIGHT, mid_point, box3.top + box3.height, right_branch_left + block_width/2, branch_mid_y)
# Prepojenie blokov v ľavej vetve
add_connector(slide, box4A, box5A)
add_connector(slide, box5A, box6A)
add_connector(slide, box6A, box7A)
# Prepojenie blokov v pravej vetve
add_connector(slide, box4B, box5B)
add_connector(slide, box5B, box6B)
add_connector(slide, box6B, box7B)
add_connector(slide, box7B, box8B)
add_connector(slide, box8B, box9B)
# Spojenie oboch vetiev s finálnym blokom "Výstup"
add_connector(slide, box7A, final_box)
add_connector(slide, box9B, final_box)
# Uloženie prezentácie
prs.save("architecture_diagram.pptx")

View File

@ -14,7 +14,6 @@ from psycopg2.extras import RealDictCursor
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
config_file_path = "config.json"
with open(config_file_path, 'r') as config_file:
config = json.load(config_file)
@ -23,15 +22,18 @@ mistral_api_key = "hXDC4RBJk1qy5pOlrgr01GtOlmyCBaNs"
if not mistral_api_key:
raise ValueError("Mistral API key not found in configuration.")
###############################################################################
# Simple functions for translation (stub)
###############################################################################
def translate_to_slovak(text: str) -> str:
return text
def translate_preserving_medicine_names(text: str) -> str:
return text
###############################################################################
# Function for evaluating the completeness of the answer
###############################################################################
@ -53,6 +55,7 @@ def evaluate_complete_answer(query: str, answer: str) -> dict:
score = 0.0
return {"rating": round(score, 2), "explanation": "Evaluation based on required criteria."}
###############################################################################
# Function for validating the response logic
###############################################################################
@ -73,6 +76,7 @@ def validate_answer_logic(query: str, answer: str) -> str:
logger.error(f"Error during answer validation: {e}")
return answer
###############################################################################
# Function for creating a dynamic prompt with information from documents
###############################################################################
@ -91,6 +95,7 @@ def build_dynamic_prompt(query: str, documents: list) -> str:
)
return prompt
###############################################################################
# Function to get user data from the database via endpoint /api/get_user_data
###############################################################################
@ -106,6 +111,7 @@ def get_user_data_from_db(chat_id: str) -> str:
logger.error(f"Error retrieving user_data from DB: {e}", exc_info=True)
return ""
###############################################################################
# Class for calling Mistral LLM
###############################################################################
@ -147,6 +153,21 @@ class CustomMistralLLM:
raise ex
raise Exception("Reached maximum number of retries for API request")
###############################################################################
# Function for generating a detailed evaluation description
###############################################################################
# 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
###############################################################################
@ -188,6 +209,7 @@ llm_large = CustomMistralLLM(
model_name="mistral-large-latest"
)
###############################################################################
# Request classification function: vyhladavanie vs. upresnenie
###############################################################################
@ -213,6 +235,7 @@ def classify_query(query: str, chat_history: str = "") -> str:
return "upresnenie"
return "vyhladavanie"
###############################################################################
# Template for upresnenie dopytu
###############################################################################
@ -237,6 +260,7 @@ Upresňujúca otázka od používateľa:
"""
return prompt
###############################################################################
# Function for retrieving the last vyhladavacieho dopytu z histórie
###############################################################################
@ -249,6 +273,7 @@ def extract_last_vyhladavacie_query(chat_history: str) -> str:
break
return last_query
###############################################################################
# Agent class for data storage: vek, anamneza, predpis, user_data, search_query
###############################################################################
@ -308,15 +333,16 @@ class ConversationalAgent:
def ask_follow_up(self, missing_info: dict) -> str:
return " ".join(missing_info.values())
###############################################################################
# Main function process_query_with_mistral with updated logic
###############################################################################
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):
logger.info("Processing query started.")
chat_history = ""
if chat_context:
chat_history = chat_context
@ -337,23 +363,18 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
except Exception as e:
logger.error(f"Chyba pri načítaní histórie: {e}")
agent = ConversationalAgent()
if chat_history:
agent.load_memory_from_history(chat_history)
existing_user_data = ""
if chat_id:
existing_user_data = get_user_data_from_db(chat_id)
agent.parse_user_info(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}
@ -388,19 +409,16 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
"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":
original_search = agent.long_term_memory.get("search_query")
if not original_search:
@ -442,7 +460,8 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
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é."
"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)
@ -454,8 +473,32 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
{"summary": val_small, "eval": eval_small, "model": "Mistral Small"},
{"summary": val_large, "eval": eval_large, "model": "Mistral Large"},
]
#
# for candidate in candidates:
# 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"])
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"])
memory_json = json.dumps(agent.long_term_memory)
memory_block = f"[MEMORY]{memory_json}[/MEMORY]"
@ -467,7 +510,6 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
"explanation": best["eval"]["explanation"]
}
vector_results = vectorstore.similarity_search(query, k=k)
max_docs = 5
max_len = 1000
@ -484,7 +526,8 @@ def process_query_with_mistral(query: str, chat_id: str, chat_context: str, k=10
f"Otázka: {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é."
"Vygeneruj odporúčanie liekov alebo vysvetlenie, ak je to relevantné.\n"
"Prosím, odpovedaj stručne a dostatočne, bez nadmernej dĺžky."
)
answer = llm_small.generate_text(final_prompt, max_tokens=1200, temperature=0.7)
memory_json = json.dumps(agent.long_term_memory)

56
Backend/tablepresent.py Normal file
View File

@ -0,0 +1,56 @@
from pptx import Presentation
from pptx.util import Inches
# Создание новой презентации
prs = Presentation()
# Добавляем пустой слайд (layout с индексом 5 обычно является пустым)
slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(slide_layout)
# Определяем позицию и размер таблицы
left = Inches(0.5)
top = Inches(1.5)
width = Inches(9)
height = Inches(3)
# Количество строк: 1 заголовок + 2 строки с данными
rows = 3
cols = 4
# Добавляем таблицу на слайд
table = slide.shapes.add_table(rows, cols, left, top, width, height).table
# Устанавливаем ширину столбцов (при необходимости можно настроить отдельно)
table.columns[0].width = Inches(1.5) # Модель
table.columns[1].width = Inches(1) # Оценка
table.columns[2].width = Inches(4) # Текст
table.columns[3].width = Inches(2.5) # Описание
# Заполняем заголовки
table.cell(0, 0).text = "Модель"
table.cell(0, 1).text = "Оценка"
table.cell(0, 2).text = "Текст"
table.cell(0, 3).text = "Описание"
# Данные для первого кандидата
table.cell(1, 0).text = "Mistral Small"
table.cell(1, 1).text = "9.0"
table.cell(1, 2).text = (
"Nevolnosť môže byť spôsobená rôznymi príčinami, ako sú napríklad gastrointestinálne problémy, infekcie, alebo vedľajšie účinky liekov. "
"Pre ľudí, ktorí hľadajú voľnopredajný liek na nevolnosť, sú dostupné niekoľko možností: 1. Dimedrol (Dramin) Antihistaminikum; "
"2. Bismut subsalicylát (Pepto-Bismol); 3. Ginger (Zázvor); 4. Meclizin (Bonine). Pred použitím lieku je dôležité konzultovať s lekárom."
)
table.cell(1, 3).text = "Evaluation based on required criteria."
# Данные для второго кандидата
table.cell(2, 0).text = "Mistral Large"
table.cell(2, 1).text = "8.0"
table.cell(2, 2).text = (
"Pre nevolnosť sa dajú použiť niektoré voľne predávané lieky, ale dôležité je poradiť sa s lekárom, najmä ak má pacient 20 rokov. "
"Medzi bežné voľne predávané lieky patria: 1. Dimenhydrinát; 2. Meclozín. Tieto lieky môžu spôsobiť spánkovosť a dávkovanie je nutné konzultovať."
)
table.cell(2, 3).text = "Evaluation based on required criteria."
# Сохраняем презентацию в файл
prs.save("evaluation_table.pptx")

View File

@ -1,4 +1,5 @@
#!/bin/bash
echo "Подготовка окружения: сборка Docker образов..."
docker-compose build
echo "Подготовка завершена."
echo "Prepearing Docker images..."
docker-compose up --build
echo "Preparation ended."