GaetanoParente commited on
Commit
9cbbfac
·
1 Parent(s): 9acef2c

rimossi import inutili e blindato utilizzo utente

Browse files
app.py CHANGED
@@ -10,6 +10,7 @@ from pyvis.network import Network
10
  from dotenv import load_dotenv
11
  import warnings
12
  import logging
 
13
 
14
  # --- IMPORT MODULI SPECIFICI ---
15
  from src.ingestion.semantic_splitter import ActivaSemanticSplitter
@@ -40,6 +41,8 @@ def local_css(file_name):
40
  local_css("assets/style.css")
41
 
42
  # --- SESSION STATE MANAGEMENT ---
 
 
43
  if 'pipeline_stage' not in st.session_state:
44
  st.session_state.pipeline_stage = 0
45
  if 'document_text' not in st.session_state:
@@ -95,6 +98,21 @@ def get_node_color(labels):
95
  label = specific_labels[0]
96
  return COLOR_PALETTE.get(label, COLOR_PALETTE["DEFAULT"])
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  # Pre-load dei modelli in memoria
99
  _ = get_splitter()
100
  _ = get_extractor()
@@ -121,14 +139,31 @@ st.sidebar.title("⚙️ Configurazione")
121
  env_uri = os.getenv("NEO4J_URI", "")
122
  env_user = os.getenv("NEO4J_USER", "neo4j")
123
  env_password = os.getenv("NEO4J_PASSWORD", "")
124
- env_google_key = os.getenv("GOOGLE_API_KEY", "")
125
 
126
  st.sidebar.subheader("Backend AI (TDDT)")
127
- if env_google_key:
128
- st.sidebar.success("✅ Google API Key: Configurata")
 
 
 
 
 
 
 
129
  else:
130
- google_key_input = st.sidebar.text_input("Inserisci GOOGLE_API_KEY", type="password")
131
- if google_key_input: os.environ["GOOGLE_API_KEY"] = google_key_input
 
 
 
 
 
 
 
 
 
 
132
 
133
  st.sidebar.subheader("Knowledge Graph")
134
  uri = st.sidebar.text_input("URI Neo4j", value=env_uri)
@@ -193,13 +228,15 @@ with tab_gen:
193
  with st.expander("ℹ️ Cosa fa questa fase?"):
194
  st.write("Segmenta il testo in frammenti coerenti analizzando la similarità semantica vettoriale tra le frasi.")
195
 
 
 
196
  if st.session_state.pipeline_stage >= 1:
197
  chunks = st.session_state.chunks
198
  st.success(f"Chunking completato! Generati {len(chunks)} frammenti semantici.")
199
  with st.expander("Vedi dettagli frammenti"):
200
  st.json(chunks)
201
  else:
202
- if st.button("Avvia Semantic Splitter", type="primary"):
203
  with st.spinner("Creazione chunks in corso..."):
204
  try:
205
  splitter = get_splitter()
@@ -235,9 +272,10 @@ with tab_gen:
235
  if data['triples']:
236
  st.dataframe(pd.DataFrame([t.model_dump() for t in data['triples']]), hide_index=True)
237
  else:
238
- if st.button("Avvia Estrazione TDDT", type="primary"):
239
- if not os.getenv("GOOGLE_API_KEY"):
240
- st.error("⚠️ GOOGLE_API_KEY mancante. Inseriscila nella sidebar.")
 
241
  else:
242
  with st.spinner("Classificazione ed estrazione gerarchica in corso..."):
243
  try:
 
10
  from dotenv import load_dotenv
11
  import warnings
12
  import logging
13
+ import requests
14
 
15
  # --- IMPORT MODULI SPECIFICI ---
16
  from src.ingestion.semantic_splitter import ActivaSemanticSplitter
 
41
  local_css("assets/style.css")
42
 
43
  # --- SESSION STATE MANAGEMENT ---
44
+ if 'groq_valid' not in st.session_state:
45
+ st.session_state.groq_valid = False
46
  if 'pipeline_stage' not in st.session_state:
47
  st.session_state.pipeline_stage = 0
48
  if 'document_text' not in st.session_state:
 
98
  label = specific_labels[0]
99
  return COLOR_PALETTE.get(label, COLOR_PALETTE["DEFAULT"])
100
 
101
+ def validate_groq_key(api_key):
102
+ """Effettua un ping leggero all'API di Groq per verificare la validità della chiave."""
103
+ if not api_key:
104
+ return False
105
+
106
+ headers = {
107
+ "Authorization": f"Bearer {api_key}",
108
+ "Content-Type": "application/json"
109
+ }
110
+ try:
111
+ response = requests.get("https://api.groq.com/openai/v1/models", headers=headers, timeout=5)
112
+ return response.status_code == 200
113
+ except:
114
+ return False
115
+
116
  # Pre-load dei modelli in memoria
117
  _ = get_splitter()
118
  _ = get_extractor()
 
139
  env_uri = os.getenv("NEO4J_URI", "")
140
  env_user = os.getenv("NEO4J_USER", "neo4j")
141
  env_password = os.getenv("NEO4J_PASSWORD", "")
142
+ env_groq_key = ""
143
 
144
  st.sidebar.subheader("Backend AI (TDDT)")
145
+ if env_groq_key and not st.session_state.groq_valid:
146
+ if validate_groq_key(env_groq_key):
147
+ st.session_state.groq_valid = True
148
+ else:
149
+ os.environ["GROQ_API_KEY"] = ""
150
+ env_groq_key = ""
151
+
152
+ if st.session_state.groq_valid:
153
+ st.sidebar.success("✅ Groq API Key: Valida e Attiva")
154
  else:
155
+ groq_key_input = st.sidebar.text_input("Inserisci GROQ_API_KEY", type="password")
156
+
157
+ if st.sidebar.button("Verifica Chiave"):
158
+ with st.spinner("Verifica in corso..."):
159
+ if validate_groq_key(groq_key_input):
160
+ os.environ["GROQ_API_KEY"] = groq_key_input
161
+ st.session_state.groq_valid = True
162
+ st.sidebar.success("✅ Chiave valida!")
163
+ time.sleep(1)
164
+ st.rerun()
165
+ else:
166
+ st.sidebar.error("❌ Chiave non valida o non autorizzata.")
167
 
168
  st.sidebar.subheader("Knowledge Graph")
169
  uri = st.sidebar.text_input("URI Neo4j", value=env_uri)
 
228
  with st.expander("ℹ️ Cosa fa questa fase?"):
229
  st.write("Segmenta il testo in frammenti coerenti analizzando la similarità semantica vettoriale tra le frasi.")
230
 
231
+ is_groq_ready = bool(env_groq_key)
232
+
233
  if st.session_state.pipeline_stage >= 1:
234
  chunks = st.session_state.chunks
235
  st.success(f"Chunking completato! Generati {len(chunks)} frammenti semantici.")
236
  with st.expander("Vedi dettagli frammenti"):
237
  st.json(chunks)
238
  else:
239
+ if st.button("Avvia Semantic Splitter", type="primary", disabled=not is_groq_ready):
240
  with st.spinner("Creazione chunks in corso..."):
241
  try:
242
  splitter = get_splitter()
 
272
  if data['triples']:
273
  st.dataframe(pd.DataFrame([t.model_dump() for t in data['triples']]), hide_index=True)
274
  else:
275
+ is_extraction_ready = st.session_state.groq_valid
276
+ if st.button("Avvia Estrazione TDDT", type="primary", disabled=not is_extraction_ready):
277
+ if not st.session_state.groq_valid:
278
+ st.warning("⚠️ Per avviare l'estrazione devi prima inserire e verificare una GROQ_API_KEY valida nella sidebar.")
279
  else:
280
  with st.spinner("Classificazione ed estrazione gerarchica in corso..."):
281
  try:
src/extraction/extractor.py CHANGED
@@ -2,10 +2,8 @@ import os
2
  import json
3
  import time
4
  from typing import List, Optional, Dict, Any
5
- from pydantic import BaseModel, Field, ValidationError
6
- from langchain_core.prompts import ChatPromptTemplate
7
- from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
8
- from langchain_google_genai import ChatGoogleGenerativeAI
9
  from langchain_groq import ChatGroq
10
  from dotenv import load_dotenv
11
 
 
2
  import json
3
  import time
4
  from typing import List, Optional, Dict, Any
5
+ from pydantic import BaseModel, Field
6
+ from langchain_core.messages import SystemMessage, HumanMessage
 
 
7
  from langchain_groq import ChatGroq
8
  from dotenv import load_dotenv
9
 
src/ingestion/semantic_splitter.py CHANGED
@@ -1,4 +1,3 @@
1
- import os
2
  import re
3
  import numpy as np
4
  import nltk
 
 
1
  import re
2
  import numpy as np
3
  import nltk
src/utils/build_schema.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import json
3
  from pathlib import Path
4
  from collections import defaultdict
5
- from rdflib import Graph, URIRef, BNode, RDF, RDFS, OWL, Namespace
6
 
7
  # --- MAPPA DEI NAMESPACE--
8
  ARCO_NAMESPACES = {
 
2
  import json
3
  from pathlib import Path
4
  from collections import defaultdict
5
+ from rdflib import Graph, URIRef, BNode, RDF, RDFS, OWL
6
 
7
  # --- MAPPA DEI NAMESPACE--
8
  ARCO_NAMESPACES = {
src/validation/shapes/schema_constraints.ttl DELETED
@@ -1,44 +0,0 @@
1
- @prefix sh: <http://www.w3.org/ns/shacl#> .
2
- @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
3
- @prefix ex: <http://activadigital.it/ontology/> .
4
- @prefix arco: <https://w3id.org/arco/ontology/arco/> .
5
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
6
-
7
- # --- REGOLA 1: Anti-nodi fantasma ---
8
- # Il DB a grafo non deve riempirsi di nodi vuoti o corrotti. Se l'LLM decide di estrarre
9
- # un'entità (soggetto o oggetto che sia), mi deve garantire che abbia una label di testo associata.
10
- ex:NodeLabelShape
11
- a sh:NodeShape ;
12
- sh:targetSubjectsOf skos:prefLabel ;
13
- sh:property [
14
- sh:path skos:prefLabel ;
15
- sh:minCount 1 ;
16
- sh:nodeKind sh:Literal ;
17
- sh:message "Errore Topologico: Il nodo estratto non ha un nome testuale. Impossibile creare l'entità in Neo4j."
18
- ] .
19
-
20
- # --- REGOLA 2: Protezione Relazioni (No Datatype properties) ---
21
- # Un classico limite degli LLM in ambito knowledge graph: confondono i nodi con le stringhe.
22
- # Spesso tentano di fare (Soggetto) -[relazione]-> "Stringa di testo".
23
- # Qui blindo la cosa: le relazioni semantiche devono SEMPRE puntare a un altro nodo fisico (IRI).
24
- ex:ObjectPropertyShape
25
- a sh:NodeShape ;
26
- sh:targetSubjectsOf skos:prefLabel ;
27
- sh:property [
28
- sh:path skos:related ;
29
- sh:nodeKind sh:IRI ;
30
- sh:message "Errore Semantico: La relazione punta a un testo libero (Literal) invece che a un nodo (IRI)."
31
- ] .
32
-
33
- # --- REGOLA 3: Tipizzazione rigorosa ---
34
- # Se LLM prova a classificare un'entità usando rdf:type, l'oggetto DEVE essere
35
- # un URI valido pescato dall'ontologia (es. arco:HistoricOrArtisticProperty).
36
- # È severamente vietato inventarsi classi testuali tipo rdf:type -> "Monumento Antico".
37
- ex:TypeShape
38
- a sh:NodeShape ;
39
- sh:targetSubjectsOf rdf:type ;
40
- sh:property [
41
- sh:path rdf:type ;
42
- sh:nodeKind sh:IRI ;
43
- sh:message "Errore Ontologico: L'LLM ha usato una stringa per rdf:type invece di un URI ufficiale di ArCo."
44
- ] .
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/validation/validator.py CHANGED
@@ -1,8 +1,8 @@
1
  import os
2
  import re
3
  from pathlib import Path
4
- from rdflib import Graph, Literal, RDF, URIRef, Namespace
5
- from rdflib.namespace import SKOS, OWL
6
  from pyshacl import validate
7
 
8
  class SemanticValidator:
 
1
  import os
2
  import re
3
  from pathlib import Path
4
+ from rdflib import Graph, Literal, RDF, Namespace
5
+ from rdflib.namespace import SKOS
6
  from pyshacl import validate
7
 
8
  class SemanticValidator: