diff --git a/.streamlit/secrets.toml b/.streamlit/secrets.toml new file mode 100644 index 0000000..ab109a1 --- /dev/null +++ b/.streamlit/secrets.toml @@ -0,0 +1 @@ +[default] diff --git a/src/app_dashboard.py b/src/app_dashboard.py index 98b7b96..5977a7c 100644 --- a/src/app_dashboard.py +++ b/src/app_dashboard.py @@ -5,6 +5,7 @@ Seiten: Übersicht, Engramme, Suche, Graph, Heal-Log, Neural Scorer. import json import sys +import os from pathlib import Path import streamlit as st @@ -25,33 +26,22 @@ _DEFAULT_DB = _root / "data" / "brain.sqlite" @st.cache_resource -class _LazyDB: - """Lazy-Initialisierung damit st.secrets erst bei Bedarf gelesen wird.""" - _store = None - _chroma = None - - @staticmethod - def store(): - if _LazyDB._store is None: - db = str(_DEFAULT_DB) - try: - db = st.secrets.get("db_path", str(_DEFAULT_DB)) - except Exception: - pass - _LazyDB._store = EngramStore(db) - return _LazyDB._store - - @staticmethod - def chroma(): - if _LazyDB._chroma is None: - p = Path(str(_DEFAULT_DB)).parent / "chroma" - _LazyDB._chroma = ChromaStore(str(p)) - return _LazyDB._chroma +def _store(): + return EngramStore(str(_DEFAULT_DB)) @st.cache_resource +def _chroma(): + p = Path(str(_DEFAULT_DB)).parent / "chroma" + return ChromaStore(str(p)) + + +_retriever_cache = None def _retriever(): - return Retriever(_LazyDB.store(), _LazyDB.chroma()) + global _retriever_cache + if _retriever_cache is None: + _retriever_cache = Retriever(_store(), _chroma()) + return _retriever_cache @st.cache_resource @@ -61,18 +51,18 @@ def _scorer(): @st.cache_resource def _healer(): - return ErrorHealer(_LazyDB.store()) + return ErrorHealer(_store()) st.set_page_config(page_title="Second Brain Dashboard", layout="wide") -st.title("🧠 2.Brain v0.3.0") +st.title("🧠 2.Brain v0.3.1") page = st.sidebar.radio("Seite", ["Übersicht", "Engramme", "Suche", "Graph", "Heal-Log", "Neural Scorer"]) if page == "Übersicht": - store = _LazyDB.store() - engrams = store.get_all(limit=1000) + store = _store() + engrams = store.get_all(limit=10000) confirmed = sum(1 for e in engrams if e.correctness.confirmed) unconfirmed = len(engrams) - confirmed avg_conf = sum(e.compute_confidence() for e in engrams) / max(1, len(engrams)) @@ -100,12 +90,12 @@ if page == "Übersicht": if st.button("Auto-Fix", key=f"af_{eg.id}"): eg.auto_fix_grounding() store.save(eg) - st.success("Fixed!") + st.experimental_rerun() elif page == "Engramme": - store = _LazyDB.store() - st.subheader("Alle Engramme") + store = _store() + st.subheader("Alle Engramme (max 1000)") tag_filter = st.text_input("Filter tags") source_filter = st.selectbox("Source", ["alle", "user", "agent", "web", "file", "system"]) for eg in store.get_all(limit=1000): @@ -135,34 +125,37 @@ elif page == "Engramme": elif page == "Suche": st.subheader("Hybrid Search (Semantic + Keyword)") - query = st.text_input("Query") + query = st.text_input("Query", placeholder="Suchbegriff eingeben...") mode = st.radio("Modus", ["Hybrid", "Keyword", "Semantic"], horizontal=True) if st.button("Suchen") and query: ret = _retriever() results = ret.hybrid_retrieve(query, limit=10) if mode == "Hybrid" else \ ret.semantic_retrieve(query, limit=10) if mode == "Semantic" else \ ret.retrieve(query, limit=10) + if not results: + st.info("Keine Ergebnisse gefunden.") for r in results: eg = r["engram"] with st.container(): st.markdown(f"**{eg.content[:200]}...**") - st.write(f"Score: {r['score']:.3f} | Match: {r['match_type']} | Conf: {eg.compute_confidence():.2f}") + st.write(f"Score: `{r['score']:.3f}` | Match: `{r['match_type']}` | Conf: `{eg.compute_confidence():.2f}`") c1, c2 = st.columns(2) if c1.button("✅ Confirm", key=f"sc_{eg.id}"): eg.correctness.confirm("user") - _LazyDB.store().save(eg) - c1.success("Confirmed") + _store().save(eg) + st.success("Confirmed") if c2.button("❌ Reject", key=f"sr_{eg.id}"): eg.correctness.reject("user") - _LazyDB.store().save(eg) - c2.warning("Rejected") + _store().save(eg) + st.warning("Rejected") elif page == "Graph": st.subheader("Graph-Visualisierung") graph_html_path = Path(str(_DEFAULT_DB)).parent / "graph_view.html" if st.button("Graph neu generieren"): - path = generate_graph_html(_LazyDB.store(), str(graph_html_path)) + with st.spinner("Generiere Graph..."): + path = generate_graph_html(_store(), str(graph_html_path)) st.success(f"Graph generiert: {path}") if graph_html_path.exists(): with open(graph_html_path, "r", encoding="utf-8") as f: @@ -199,7 +192,7 @@ elif page == "Heal-Log": elif page == "Neural Scorer": st.subheader("Neural Scorer Training") scorer = _scorer() - store = _LazyDB.store() + store = _store() engrams = store.get_all(limit=10000) labeled = [e for e in engrams if e.correctness.confirmed or e.correctness.rejections > 0] st.write(f"Labelled Engramme: **{len(labeled)}**") @@ -207,7 +200,7 @@ elif page == "Neural Scorer": if len(labeled) < 2: st.error("Mindestens 2 labelierte Engramme nötig (confirm + reject).") else: - with st.spinner("Training..."): + with st.spinner("Training läuft..."): result = scorer.train(labeled, epochs=30) st.json(result) st.success("Training abgeschlossen!")