Spaces:
Running
Running
| # appv1.py | |
| # A RAG rendszer grafikus felhasználói felülete Streamlit segítségével. | |
| # Végleges verzió, Chat és Admin felülettel. | |
| # Igazítva a backendv1.py-hoz. | |
| # Kiegészítve a legjobb találati pontszám megjelenítésével. | |
| import streamlit as st | |
| import sys | |
| import os | |
| # A backendv1.py importálása, a futtatható könyvtárhoz hozzáadása. | |
| # Feltételezi, hogy a backendv1.py és az appv1.py ugyanabban a mappában van. | |
| sys.path.append(os.path.dirname(__file__)) | |
| # Az összes szükséges függvény importálása a backendből | |
| from backendv1 import ( | |
| initialize_backend, | |
| process_query, | |
| index_feedback, | |
| get_all_feedback, | |
| delete_feedback_by_id, | |
| update_feedback_comment, | |
| CONFIG | |
| ) | |
| # --- 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) --- | |
| def load_backend_components(): | |
| return initialize_backend() | |
| backend = load_backend_components() | |
| # --- Session State Inicializálása --- | |
| 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") | |
| # A 0.1 egy jó alapértelmezett érték, de a pontos tartomány a Cross-Encoder modell kimenetétől függ | |
| 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": | |
| # --- HOZZÁADOTT RÉSZ --- | |
| # A válaszhoz tartozó pontszám megjelenítése, ha létezik. | |
| score_value = message.get("score") | |
| if score_value is not None: | |
| if score_value == 10.0: | |
| score_display = "Kurált válasz (legmagasabb)" | |
| else: | |
| score_display = f"{score_value:.4f}" | |
| st.caption(f"A válasz legjobb score értéke: **{score_display}**") | |
| # --- HOZZÁADOTT RÉSZ VÉGE --- | |
| 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"): | |
| # Hívás a backendv1 függvényre | |
| 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..."): | |
| # Hívás a backendv1 függvényre | |
| 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") | |
| # --- MÓDOSÍTOTT RÉSZ --- | |
| # A válasz üzenethez hozzáadjuk a 'score' kulcsot is, hogy később meg tudjuk jeleníteni. | |
| 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") # Itt adjuk hozzá a pontszámot | |
| }) | |
| # --- MÓDOSÍTOTT RÉSZ VÉGE --- | |
| 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() | |
| def get_cached_feedback(): | |
| # Hívás a backendv1 függvényre | |
| 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"): | |
| # Hívás a backendv1 függvényre | |
| 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"): | |
| # Hívás a backendv1 függvényre | |
| 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')}") |