# 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')}")