Király Zoltán
Fix: Clean up requirements.txt to resolve build conflicts
138e4b0
# appv1.py
# A RAG rendszer grafikus felhasználói felülete Streamlit segítségével.
# JAVÍTOTT VERZIÓ: A modern, cloud-kompatibilis backendv1.py-hoz igazítva.
import streamlit as st
import sys
import os
# --- Backend Importálása ---
# A backendv1.py-nak ebben a mappában kell lennie.
try:
from backendv1 import (
initialize_backend,
process_query,
index_feedback,
get_all_feedback,
delete_feedback_by_id,
update_feedback_comment,
CONFIG
)
except ImportError:
st.error("Hiba: A 'backendv1.py' fájl nem található. Győződj meg róla, hogy ugyanabban a mappában van, mint ez a script.")
st.stop()
# --- Oldal Konfiguráció ---
st.set_page_config(page_title="Dunaelektronika AI", layout="wide")
st.title("🤖 Dunaelektronika AI Asszisztens")
# --- Backend Betöltése (gyorsítótárazva, hogy ne töltődjön be minden interakciónál újra) ---
@st.cache_resource
def load_backend_components():
"""
Betölti a backendet (AI modellek, DB kapcsolat).
A @st.cache_resource biztosítja, hogy ez a lassú folyamat csak egyszer fusson le.
"""
print("Backend komponensek inicializálása...")
backend_data = initialize_backend()
if backend_data:
print("Backend sikeresen betöltve.")
else:
print("Hiba a backend betöltésekor.")
return backend_data
# Backend betöltése és hibakezelés
backend = load_backend_components()
if not backend:
st.error(
"A háttérrendszer (AI modellek vagy adatbázis kapcsolat) nem tudott elindulni. "
"Ellenőrizd a konzol logját a hiba okáért, és hogy a környezeti változók (pl. .env fájl) helyesen vannak-e beállítva."
)
st.stop()
# --- Session State Inicializálása (az adatok tárolására a böngészőben) ---
if "messages" not in st.session_state:
st.session_state.messages = []
if "last_confidence_score" not in st.session_state:
st.session_state.last_confidence_score = "N/A"
if "page" not in st.session_state:
st.session_state.page = "Chat"
# --- Navigáció az Oldalsávon ---
with st.sidebar:
st.header("Menü")
if st.button("💬 Chat", use_container_width=True, type="primary" if st.session_state.page == "Chat" else "secondary"):
st.session_state.page = "Chat"
st.rerun()
if st.button("⚙️ Feedback Adminisztráció", use_container_width=True, type="primary" if st.session_state.page == "Admin" else "secondary"):
st.session_state.page = "Admin"
st.rerun()
st.write("---")
# ==============================================================================
# = CHAT OLDAL LOGIKÁJA =
# ==============================================================================
if st.session_state.page == "Chat":
with st.sidebar:
st.header("Beállítások")
confidence_threshold = st.slider("Minimális pontossági küszöb", min_value=-5.0, max_value=5.0, value=0.1, step=0.1)
fallback_message = st.text_area("Válasz alacsony pontosságnál", "A rendelkezésre álló információk alapján sajnos nem tudok egyértelmű választ adni a kérdésre.", height=100)
CONFIG["GENERATION_TEMPERATURE"] = st.slider("Kreativitás (Temperature)", 0.0, 1.0, 0.6, 0.05)
st.write("---")
st.subheader("Utolsó Válasz Elemzése")
score = st.session_state.last_confidence_score
if score == "N/A":
level, help_text = "N/A", "Tegyen fel egy kérdést a megbízhatóság méréséhez."
elif score is None:
level, help_text = "Alap Rangsor (RRF)", "A Cross-Encoder bizonytalan volt."
elif score == 10.0:
level, help_text = "Kurált Válasz", "Ez egy korábban megadott, pontosított válasz."
else:
help_text = f"Nyers pontszám: {score:.4f}"
if score > 1.0: level = "Magas"
elif score >= -1.5: level = "Közepes"
else: level = "Alacsony"
st.metric(label="Keresési Magabiztosság", value=level, help=help_text)
# Chat Előzmények Megjelenítése
for i, message in enumerate(st.session_state.messages):
with st.chat_message(message["role"]):
st.markdown(message["content"].replace('$', '\\$'))
if message["role"] == "assistant":
score_value = message.get("score")
if score_value is not None:
score_display = "Kurált válasz (legmagasabb)" if score_value == 10.0 else f"{score_value:.4f}"
st.caption(f"A válasz legjobb score értéke: **{score_display}**")
if message.get("sources"):
with st.expander("Felhasznált források"):
for source in message["sources"]:
st.caption(f"Forrás: {source.get('url', 'N/A')}")
st.markdown(f"> {source.get('content', '')[:250]}...")
feedback_key_prefix = f"feedback_{i}"
if not message.get("rated"):
st.write("---")
cols = st.columns(7)
if cols[0].button("👍 Jó", key=f"{feedback_key_prefix}_good"):
message["rated"] = "good"; st.toast("Köszönjük a visszajelzést!"); st.rerun()
if cols[1].button("👎 Rossz", key=f"{feedback_key_prefix}_bad"):
message["rated"] = "bad"; st.rerun()
if message.get("rated") == "bad":
with st.form(key=f"{feedback_key_prefix}_form"):
correction_text = st.text_area("Javítás:", key=f"{feedback_key_prefix}_text", value=message.get("correction", ""))
if st.form_submit_button("Javítás elküldése"):
index_feedback(backend["es_client"], backend["embedding_model"], message["original_question"], correction_text)
st.success("Javításodat rögzítettük!"); message["rated"] = "corrected"; st.rerun()
# Felhasználói Kérdés Feldolgozása
if prompt := st.chat_input("Kérdezz valamit a Dunaelektronikáról..."):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.spinner("Keresek és gondolkodom..."):
response_data = process_query(prompt, st.session_state.messages, backend, confidence_threshold, fallback_message)
st.session_state.last_confidence_score = response_data.get("confidence_score")
st.session_state.messages.append({
"role": "assistant",
"content": response_data.get("answer", "Hiba történt."),
"sources": response_data.get("sources", []),
"original_question": prompt,
"rated": False,
"score": response_data.get("confidence_score")
})
st.rerun()
# ==============================================================================
# = ADMIN OLDAL LOGIKÁJA =
# ==============================================================================
elif st.session_state.page == "Admin":
st.header("Rögzített Visszajelzések Kezelése")
if st.button("Lista frissítése"):
st.cache_data.clear()
@st.cache_data(ttl=60)
def get_cached_feedback():
return get_all_feedback(backend["es_client"], CONFIG["FEEDBACK_INDEX_NAME"])
feedback_list = get_cached_feedback()
if not feedback_list:
st.warning("Nincsenek rögzített visszajelzések.")
else:
st.info(f"Összesen {len(feedback_list)} visszajelzés található.")
for item in feedback_list:
doc_id = item["_id"]
source = item["_source"]
with st.container(border=True):
st.markdown(f"**Kérdés:** `{source.get('question_text', 'N/A')}`")
with st.form(key=f"edit_form_{doc_id}"):
new_comment = st.text_area("Javítás/Megjegyzés:", value=source.get('correction_text', ''), key=f"text_{doc_id}", label_visibility="collapsed")
col1, col2 = st.columns([4, 1])
with col1:
if st.form_submit_button("💾 Mentés"):
if update_feedback_comment(backend["es_client"], CONFIG["FEEDBACK_INDEX_NAME"], doc_id, new_comment):
st.success("Sikeresen frissítve!"); st.cache_data.clear(); st.rerun()
else: st.error("Hiba történt a frissítés során.")
with col2:
if st.form_submit_button("🗑️ Törlés"):
if delete_feedback_by_id(backend["es_client"], CONFIG["FEEDBACK_INDEX_NAME"], doc_id):
st.success(f"Sikeresen törölve!"); st.cache_data.clear(); st.rerun()
else: st.error("Hiba történt a törlés során.")
st.caption(f"Elasticsearch ID: {doc_id} | Időbélyeg: {source.get('timestamp', 'N/A')}")