Update app.py
Browse files
app.py
CHANGED
|
@@ -94,25 +94,46 @@ def run_query(driver, query, params=None):
|
|
| 94 |
# --- UI: SIDEBAR ---
|
| 95 |
st.sidebar.title("⚙️ Configurazione")
|
| 96 |
|
|
|
|
|
|
|
| 97 |
env_uri = os.getenv("NEO4J_URI", "")
|
| 98 |
env_user = os.getenv("NEO4J_USER", "neo4j")
|
| 99 |
env_password = os.getenv("NEO4J_PASSWORD", "")
|
| 100 |
env_hf_token = os.getenv("HF_TOKEN", "")
|
| 101 |
|
| 102 |
st.sidebar.subheader("Backend AI")
|
| 103 |
-
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
|
| 106 |
st.sidebar.subheader("Knowledge Graph")
|
|
|
|
| 107 |
uri = st.sidebar.text_input("URI", value=env_uri)
|
| 108 |
user = st.sidebar.text_input("User", value=env_user)
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
driver = None
|
| 112 |
if uri and password:
|
| 113 |
driver = get_driver(uri, user, password)
|
| 114 |
if driver:
|
| 115 |
st.sidebar.success("🟢 Connesso a Neo4j")
|
|
|
|
| 116 |
os.environ["NEO4J_URI"] = uri
|
| 117 |
os.environ["NEO4J_USER"] = user
|
| 118 |
os.environ["NEO4J_PASSWORD"] = password
|
|
@@ -221,8 +242,8 @@ with tab_gen:
|
|
| 221 |
is_step_b_unlocked = st.session_state.pipeline_stage >= 1
|
| 222 |
|
| 223 |
with st.container():
|
| 224 |
-
# Header grigio se bloccato,
|
| 225 |
-
color = "
|
| 226 |
icon = "✅" if st.session_state.pipeline_stage >= 2 else ("2️⃣" if is_step_b_unlocked else "🔒")
|
| 227 |
st.markdown(f"<h3 style='color:{color}'>{icon} Fase B: Information Extraction</h3>", unsafe_allow_html=True)
|
| 228 |
|
|
@@ -275,7 +296,7 @@ with tab_gen:
|
|
| 275 |
is_step_c_unlocked = st.session_state.pipeline_stage >= 2
|
| 276 |
|
| 277 |
with st.container():
|
| 278 |
-
color = "
|
| 279 |
icon = "✅" if st.session_state.pipeline_stage >= 3 else ("3️⃣" if is_step_c_unlocked else "🔒")
|
| 280 |
st.markdown(f"<h3 style='color:{color}'>{icon} Fase C: Graph Construction</h3>", unsafe_allow_html=True)
|
| 281 |
|
|
@@ -289,6 +310,7 @@ with tab_gen:
|
|
| 289 |
Puoi esplorarli nei tab "Validazione" e "Visualizzazione".
|
| 290 |
</div>
|
| 291 |
""", unsafe_allow_html=True)
|
|
|
|
| 292 |
if st.button("Riavvia con nuovo file"):
|
| 293 |
reset_pipeline()
|
| 294 |
st.rerun()
|
|
@@ -355,32 +377,39 @@ with tab_val:
|
|
| 355 |
with tab_vis:
|
| 356 |
st.header("Esplorazione Topologica")
|
| 357 |
if driver:
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
os.makedirs("data/processed", exist_ok=True)
|
| 380 |
-
net.save_graph(path)
|
| 381 |
-
|
| 382 |
-
with open(path, 'r', encoding='utf-8') as f:
|
| 383 |
-
html_string = f.read()
|
| 384 |
-
components.html(html_string, height=600, scrolling=True)
|
| 385 |
else:
|
| 386 |
-
st.warning("Database non connesso.")
|
|
|
|
| 94 |
# --- UI: SIDEBAR ---
|
| 95 |
st.sidebar.title("⚙️ Configurazione")
|
| 96 |
|
| 97 |
+
# Recuperiamo le variabili d'ambiente (Server Side)
|
| 98 |
+
# NOTA: Queste variabili contengono i veri segreti ma NON vengono passate al frontend
|
| 99 |
env_uri = os.getenv("NEO4J_URI", "")
|
| 100 |
env_user = os.getenv("NEO4J_USER", "neo4j")
|
| 101 |
env_password = os.getenv("NEO4J_PASSWORD", "")
|
| 102 |
env_hf_token = os.getenv("HF_TOKEN", "")
|
| 103 |
|
| 104 |
st.sidebar.subheader("Backend AI")
|
| 105 |
+
# LOGICA SICURA: Se il token esiste nei secrets, mostriamo solo un badge verde.
|
| 106 |
+
# Non mostriamo mai il token nel campo input (value=...).
|
| 107 |
+
if env_hf_token:
|
| 108 |
+
st.sidebar.success("✅ HF Token: Configurato da Secrets")
|
| 109 |
+
# Se l'utente vuole sovrascriverlo, può usare questo campo opzionale
|
| 110 |
+
hf_token_input = st.sidebar.text_input("Sovrascrivi Token (Opzionale)", type="password", key="hf_token_override")
|
| 111 |
+
if hf_token_input:
|
| 112 |
+
os.environ["HF_TOKEN"] = hf_token_input
|
| 113 |
+
else:
|
| 114 |
+
hf_token_input = st.sidebar.text_input("Inserisci HF Token", type="password")
|
| 115 |
+
if hf_token_input:
|
| 116 |
+
os.environ["HF_TOKEN"] = hf_token_input
|
| 117 |
|
| 118 |
st.sidebar.subheader("Knowledge Graph")
|
| 119 |
+
# URI e User non sono segreti critici, possiamo mostrarli pre-compilati
|
| 120 |
uri = st.sidebar.text_input("URI", value=env_uri)
|
| 121 |
user = st.sidebar.text_input("User", value=env_user)
|
| 122 |
+
|
| 123 |
+
# LOGICA SICURA: Gestione Password
|
| 124 |
+
# Non usiamo 'value=env_password' per evitare che finisca nell'HTML.
|
| 125 |
+
pwd_placeholder = "✅ Configurato da Secrets (Lascia vuoto)" if env_password else "Inserisci Password"
|
| 126 |
+
password_input = st.sidebar.text_input("Password", type="password", placeholder=pwd_placeholder)
|
| 127 |
+
|
| 128 |
+
# Determiniamo quale password usare (Input Utente > Secret Env)
|
| 129 |
+
password = password_input if password_input else env_password
|
| 130 |
|
| 131 |
driver = None
|
| 132 |
if uri and password:
|
| 133 |
driver = get_driver(uri, user, password)
|
| 134 |
if driver:
|
| 135 |
st.sidebar.success("🟢 Connesso a Neo4j")
|
| 136 |
+
# Aggiorniamo l'ambiente per i moduli backend che usano os.getenv
|
| 137 |
os.environ["NEO4J_URI"] = uri
|
| 138 |
os.environ["NEO4J_USER"] = user
|
| 139 |
os.environ["NEO4J_PASSWORD"] = password
|
|
|
|
| 242 |
is_step_b_unlocked = st.session_state.pipeline_stage >= 1
|
| 243 |
|
| 244 |
with st.container():
|
| 245 |
+
# Header grigio se bloccato, bianco (per dark mode) se attivo
|
| 246 |
+
color = "white" if is_step_b_unlocked else "gray"
|
| 247 |
icon = "✅" if st.session_state.pipeline_stage >= 2 else ("2️⃣" if is_step_b_unlocked else "🔒")
|
| 248 |
st.markdown(f"<h3 style='color:{color}'>{icon} Fase B: Information Extraction</h3>", unsafe_allow_html=True)
|
| 249 |
|
|
|
|
| 296 |
is_step_c_unlocked = st.session_state.pipeline_stage >= 2
|
| 297 |
|
| 298 |
with st.container():
|
| 299 |
+
color = "white" if is_step_c_unlocked else "gray"
|
| 300 |
icon = "✅" if st.session_state.pipeline_stage >= 3 else ("3️⃣" if is_step_c_unlocked else "🔒")
|
| 301 |
st.markdown(f"<h3 style='color:{color}'>{icon} Fase C: Graph Construction</h3>", unsafe_allow_html=True)
|
| 302 |
|
|
|
|
| 310 |
Puoi esplorarli nei tab "Validazione" e "Visualizzazione".
|
| 311 |
</div>
|
| 312 |
""", unsafe_allow_html=True)
|
| 313 |
+
st.balloons()
|
| 314 |
if st.button("Riavvia con nuovo file"):
|
| 315 |
reset_pipeline()
|
| 316 |
st.rerun()
|
|
|
|
| 377 |
with tab_vis:
|
| 378 |
st.header("Esplorazione Topologica")
|
| 379 |
if driver:
|
| 380 |
+
col_ctrl, col_info = st.columns([1, 4])
|
| 381 |
+
with col_ctrl:
|
| 382 |
+
physics = st.checkbox("Abilita Fisica (Gravità)", value=True)
|
| 383 |
+
if st.button("🔄 Ricarica Dati"):
|
| 384 |
+
st.rerun()
|
| 385 |
+
|
| 386 |
+
# Logica di visualizzazione automatica (non dipendente da un bottone)
|
| 387 |
+
cypher_vis = """
|
| 388 |
+
MATCH (s)-[r]->(o)
|
| 389 |
+
RETURN COALESCE(s.label, s.name, head(labels(s))) as src,
|
| 390 |
+
type(r) as rel,
|
| 391 |
+
COALESCE(o.label, o.name, head(labels(o))) as dst
|
| 392 |
+
LIMIT 100
|
| 393 |
+
"""
|
| 394 |
+
graph_data = run_query(driver, cypher_vis)
|
| 395 |
+
|
| 396 |
+
if graph_data:
|
| 397 |
+
net = Network(height="600px", width="100%", bgcolor="#222222", font_color="white", notebook=False)
|
| 398 |
+
for item in graph_data:
|
| 399 |
+
src, dst, rel = str(item['src']), str(item['dst']), str(item['rel'])
|
| 400 |
+
net.add_node(src, label=src, color="#4facfe", title=src)
|
| 401 |
+
net.add_node(dst, label=dst, color="#00f2fe", title=dst)
|
| 402 |
+
net.add_edge(src, dst, title=rel, label=rel)
|
| 403 |
|
| 404 |
+
net.toggle_physics(physics)
|
| 405 |
+
path = "data/processed/graph_viz.html"
|
| 406 |
+
os.makedirs("data/processed", exist_ok=True)
|
| 407 |
+
net.save_graph(path)
|
| 408 |
+
|
| 409 |
+
with open(path, 'r', encoding='utf-8') as f:
|
| 410 |
+
html_string = f.read()
|
| 411 |
+
components.html(html_string, height=600, scrolling=True)
|
| 412 |
+
else:
|
| 413 |
+
st.info("Il grafo è attualmente vuoto o non raggiungibile.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 414 |
else:
|
| 415 |
+
st.warning("Database non connesso. Configura le credenziali nella sidebar.")
|