Update app.py
Browse files
app.py
CHANGED
@@ -48,6 +48,7 @@ def create_data_directory():
|
|
48 |
"""Crea la directory 'data/' se non esiste."""
|
49 |
os.makedirs(os.path.join(BASE_DIR, "data"), exist_ok=True)
|
50 |
logger.info("Directory 'data/' creata o già esistente.")
|
|
|
51 |
def extract_ontology(rdf_file: str, output_file: str):
|
52 |
"""
|
53 |
Estrae classi, proprietà ed entità dall'ontologia RDF e le salva in un file JSON come un unico documento.
|
@@ -125,7 +126,6 @@ def extract_ontology(rdf_file: str, output_file: str):
|
|
125 |
logger.error(f"Errore nel salvataggio di {output_file}: {e}")
|
126 |
raise e
|
127 |
|
128 |
-
|
129 |
def create_faiss_index(documents_file: str, index_file: str, embedding_model: str = 'all-MiniLM-L6-v2'):
|
130 |
"""
|
131 |
Crea un indice FAISS a partire dal documento estratto.
|
@@ -284,7 +284,7 @@ def retrieve_relevant_documents(query: str, top_k: int = 5):
|
|
284 |
except Exception as e:
|
285 |
logger.error(f"Errore nel recupero dei documenti rilevanti: {e}")
|
286 |
raise e
|
287 |
-
|
288 |
def create_system_message(ont_text: str, retrieved_docs: str) -> str:
|
289 |
"""
|
290 |
Prompt di sistema robusto, con regole su query in una riga e
|
@@ -323,23 +323,25 @@ Ho ottenuto questi risultati SPARQL:
|
|
323 |
{results_str}
|
324 |
Ora fornisci una breve spiegazione museale (massimo ~10 righe), senza inventare oltre i risultati.
|
325 |
"""
|
326 |
-
|
327 |
-
async def call_hf_model(
|
328 |
"""Chiama il modello Hugging Face e gestisce la risposta."""
|
329 |
-
logger.debug("Chiamo HF con
|
330 |
-
|
331 |
-
|
332 |
-
logger.debug(f"ROLE={m['role']} => {content_preview}")
|
333 |
try:
|
334 |
-
resp = client.
|
335 |
model=HF_MODEL,
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
|
|
|
|
340 |
)
|
341 |
-
|
342 |
-
|
|
|
343 |
single_line = " ".join(raw.splitlines())
|
344 |
logger.debug(f"Risposta HF single-line: {single_line}")
|
345 |
return single_line.strip()
|
@@ -373,14 +375,11 @@ async def generate_response(req: QueryRequest):
|
|
373 |
return {"type": "ERROR", "response": f"Errore nel recupero dei documenti: {e}"}
|
374 |
|
375 |
sys_msg = create_system_message(knowledge_text, retrieved_docs)
|
376 |
-
|
377 |
-
{"role": "system", "content": sys_msg},
|
378 |
-
{"role": "user", "content": user_input}
|
379 |
-
]
|
380 |
|
381 |
# Primo tentativo
|
382 |
try:
|
383 |
-
r1 = await call_hf_model(
|
384 |
logger.info(f"PRIMA RISPOSTA:\n{r1}")
|
385 |
except Exception as e:
|
386 |
logger.error(f"Errore nella chiamata al modello Hugging Face: {e}")
|
@@ -389,13 +388,9 @@ async def generate_response(req: QueryRequest):
|
|
389 |
# Se non parte con "PREFIX base:"
|
390 |
if not r1.startswith("PREFIX base:"):
|
391 |
sc = f"Non hai risposto con query SPARQL su una sola riga. Riprova. Domanda: {user_input}"
|
392 |
-
|
393 |
-
{"role": "system", "content": sys_msg},
|
394 |
-
{"role": "assistant", "content": r1},
|
395 |
-
{"role": "user", "content": sc}
|
396 |
-
]
|
397 |
try:
|
398 |
-
r2 = await call_hf_model(
|
399 |
logger.info(f"SECONDA RISPOSTA:\n{r2}")
|
400 |
if r2.startswith("PREFIX base:"):
|
401 |
sparql_query = r2
|
@@ -421,13 +416,9 @@ async def generate_response(req: QueryRequest):
|
|
421 |
logger.info(f"Query SPARQL eseguita con successo. Risultati: {len(results)}")
|
422 |
except Exception as e:
|
423 |
fallback = f"La query SPARQL ha fallito. Riprova. Domanda: {user_input}"
|
424 |
-
|
425 |
-
{"role": "system", "content": sys_msg},
|
426 |
-
{"role": "assistant", "content": sparql_query},
|
427 |
-
{"role": "user", "content": fallback}
|
428 |
-
]
|
429 |
try:
|
430 |
-
r3 = await call_hf_model(
|
431 |
logger.info(f"TERZA RISPOSTA (fallback):\n{r3}")
|
432 |
if r3.startswith("PREFIX base:"):
|
433 |
sparql_query = r3
|
@@ -456,12 +447,8 @@ async def generate_response(req: QueryRequest):
|
|
456 |
|
457 |
# Spiegazione
|
458 |
exp_prompt = create_explanation_prompt(results_str)
|
459 |
-
msgs4 = [
|
460 |
-
{"role": "system", "content": exp_prompt},
|
461 |
-
{"role": "user", "content": ""}
|
462 |
-
]
|
463 |
try:
|
464 |
-
explanation = await call_hf_model(
|
465 |
except Exception as e:
|
466 |
logger.error(f"Errore nella generazione della spiegazione: {e}")
|
467 |
return {"type": "ERROR", "response": f"Errore nella generazione della spiegazione: {e}"}
|
|
|
48 |
"""Crea la directory 'data/' se non esiste."""
|
49 |
os.makedirs(os.path.join(BASE_DIR, "data"), exist_ok=True)
|
50 |
logger.info("Directory 'data/' creata o già esistente.")
|
51 |
+
|
52 |
def extract_ontology(rdf_file: str, output_file: str):
|
53 |
"""
|
54 |
Estrae classi, proprietà ed entità dall'ontologia RDF e le salva in un file JSON come un unico documento.
|
|
|
126 |
logger.error(f"Errore nel salvataggio di {output_file}: {e}")
|
127 |
raise e
|
128 |
|
|
|
129 |
def create_faiss_index(documents_file: str, index_file: str, embedding_model: str = 'all-MiniLM-L6-v2'):
|
130 |
"""
|
131 |
Crea un indice FAISS a partire dal documento estratto.
|
|
|
284 |
except Exception as e:
|
285 |
logger.error(f"Errore nel recupero dei documenti rilevanti: {e}")
|
286 |
raise e
|
287 |
+
|
288 |
def create_system_message(ont_text: str, retrieved_docs: str) -> str:
|
289 |
"""
|
290 |
Prompt di sistema robusto, con regole su query in una riga e
|
|
|
323 |
{results_str}
|
324 |
Ora fornisci una breve spiegazione museale (massimo ~10 righe), senza inventare oltre i risultati.
|
325 |
"""
|
326 |
+
|
327 |
+
async def call_hf_model(prompt: str, temperature=0.5, max_tokens=1024) -> str:
|
328 |
"""Chiama il modello Hugging Face e gestisce la risposta."""
|
329 |
+
logger.debug("Chiamo HF con il seguente prompt:")
|
330 |
+
content_preview = (prompt[:300] + '...') if len(prompt) > 300 else prompt
|
331 |
+
logger.debug(f"PROMPT => {content_preview}")
|
|
|
332 |
try:
|
333 |
+
resp = client.text_generation(
|
334 |
model=HF_MODEL,
|
335 |
+
inputs=prompt,
|
336 |
+
parameters={
|
337 |
+
"temperature": temperature,
|
338 |
+
"max_new_tokens": max_tokens,
|
339 |
+
"top_p": 0.9
|
340 |
+
}
|
341 |
)
|
342 |
+
# La struttura della risposta dipende dall'API; verifica se "generated_text" è il campo corretto
|
343 |
+
raw = resp["generated_text"]
|
344 |
+
# Forza la risposta su una singola linea se multilinea
|
345 |
single_line = " ".join(raw.splitlines())
|
346 |
logger.debug(f"Risposta HF single-line: {single_line}")
|
347 |
return single_line.strip()
|
|
|
375 |
return {"type": "ERROR", "response": f"Errore nel recupero dei documenti: {e}"}
|
376 |
|
377 |
sys_msg = create_system_message(knowledge_text, retrieved_docs)
|
378 |
+
prompt = f"{sys_msg}\nUtente: {user_input}\nAssistente:"
|
|
|
|
|
|
|
379 |
|
380 |
# Primo tentativo
|
381 |
try:
|
382 |
+
r1 = await call_hf_model(prompt, req.temperature, req.max_tokens)
|
383 |
logger.info(f"PRIMA RISPOSTA:\n{r1}")
|
384 |
except Exception as e:
|
385 |
logger.error(f"Errore nella chiamata al modello Hugging Face: {e}")
|
|
|
388 |
# Se non parte con "PREFIX base:"
|
389 |
if not r1.startswith("PREFIX base:"):
|
390 |
sc = f"Non hai risposto con query SPARQL su una sola riga. Riprova. Domanda: {user_input}"
|
391 |
+
fallback_prompt = f"{sys_msg}\nAssistente: {r1}\nUtente: {sc}\nAssistente:"
|
|
|
|
|
|
|
|
|
392 |
try:
|
393 |
+
r2 = await call_hf_model(fallback_prompt, req.temperature, req.max_tokens)
|
394 |
logger.info(f"SECONDA RISPOSTA:\n{r2}")
|
395 |
if r2.startswith("PREFIX base:"):
|
396 |
sparql_query = r2
|
|
|
416 |
logger.info(f"Query SPARQL eseguita con successo. Risultati: {len(results)}")
|
417 |
except Exception as e:
|
418 |
fallback = f"La query SPARQL ha fallito. Riprova. Domanda: {user_input}"
|
419 |
+
fallback_prompt = f"{sys_msg}\nAssistente: {sparql_query}\nUtente: {fallback}\nAssistente:"
|
|
|
|
|
|
|
|
|
420 |
try:
|
421 |
+
r3 = await call_hf_model(fallback_prompt, req.temperature, req.max_tokens)
|
422 |
logger.info(f"TERZA RISPOSTA (fallback):\n{r3}")
|
423 |
if r3.startswith("PREFIX base:"):
|
424 |
sparql_query = r3
|
|
|
447 |
|
448 |
# Spiegazione
|
449 |
exp_prompt = create_explanation_prompt(results_str)
|
|
|
|
|
|
|
|
|
450 |
try:
|
451 |
+
explanation = await call_hf_model(exp_prompt, req.temperature, req.max_tokens)
|
452 |
except Exception as e:
|
453 |
logger.error(f"Errore nella generazione della spiegazione: {e}")
|
454 |
return {"type": "ERROR", "response": f"Errore nella generazione della spiegazione: {e}"}
|