AshenClock
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -16,7 +16,7 @@ logging.basicConfig(
|
|
16 |
handlers=[logging.FileHandler("app.log"), logging.StreamHandler()]
|
17 |
)
|
18 |
logger = logging.getLogger(__name__)
|
19 |
-
|
20 |
# ---------------------------------------------------------------------------
|
21 |
# COSTANTI / CHIAVI / MODELLI
|
22 |
# ---------------------------------------------------------------------------
|
@@ -214,27 +214,22 @@ def classify_and_translate(question_text: str, model_answer_text: str):
|
|
214 |
try:
|
215 |
question_lang_result = lang_detect_client.text_classification(text=question_text)
|
216 |
question_lang = question_lang_result[0]['label']
|
217 |
-
explanation_dict['language_detection'] = f"Domanda in: {question_lang}."
|
218 |
logger.info(f"[LangDetect] Lingua della domanda: {question_lang}")
|
219 |
except Exception as e:
|
220 |
logger.error(f"Errore nel rilevamento della lingua della domanda: {e}")
|
221 |
question_lang = "en" # Fallback se non riusciamo a rilevare la lingua
|
222 |
-
explanation_dict['language_detection'] = "Lingua domanda non rilevata, impostata a 'en'."
|
223 |
# Rileva la lingua della risposta
|
224 |
try:
|
225 |
answer_lang_result = lang_detect_client.text_classification(text=model_answer_text)
|
226 |
answer_lang = answer_lang_result[0]['label']
|
227 |
-
explanation_dict['language_detection'] += f" Risposta in: {answer_lang}."
|
228 |
logger.info(f"[LangDetect] Lingua della risposta: {answer_lang}")
|
229 |
except Exception as e:
|
230 |
logger.error(f"Errore nel rilevamento della lingua della risposta: {e}")
|
231 |
answer_lang = "it" # Fallback se non riusciamo a rilevare la lingua
|
232 |
-
explanation_dict['language_detection'] += " Lingua risposta non rilevata, impostata a 'it'."
|
233 |
|
234 |
# Se domanda e risposta sono nella stessa lingua, non traduciamo
|
235 |
if question_lang == answer_lang:
|
236 |
logger.info("[Translate] Nessuna traduzione necessaria: stessa lingua.")
|
237 |
-
explanation_dict['translation'] = "Nessuna traduzione necessaria."
|
238 |
return model_answer_text
|
239 |
|
240 |
# Altrimenti, costruiamo "al volo" il modello di traduzione appropriato
|
@@ -244,17 +239,13 @@ def classify_and_translate(question_text: str, model_answer_text: str):
|
|
244 |
token=HF_API_KEY,
|
245 |
model=translator_model
|
246 |
)
|
247 |
-
explanation_dict['translation'] = f"Usato modello: {translator_model}."
|
248 |
# Traduzione della risposta
|
249 |
try:
|
250 |
translation_result = translator_client.translation(text=model_answer_text)
|
251 |
translated_answer = translation_result["translation_text"]
|
252 |
-
explanation_dict['translation'] += " Traduzione riuscita."
|
253 |
except Exception as e:
|
254 |
logger.error(f"Errore nella traduzione {answer_lang} -> {question_lang}: {e}")
|
255 |
-
explanation_dict['translation'] += " Traduzione fallita, risposta originale usata."
|
256 |
# Se fallisce, restituiamo la risposta originale come fallback
|
257 |
-
explanation_dict['translation'] = "Errore inizializzazione traduttore."
|
258 |
translated_answer = model_answer_text
|
259 |
|
260 |
return translated_answer
|
@@ -357,7 +348,6 @@ def is_sparql_query_valid(query: str) -> bool:
|
|
357 |
# ---------------------------------------------------------------------------
|
358 |
@app.post("/assistant")
|
359 |
def assistant_endpoint(req: AssistantRequest):
|
360 |
-
explanation_dict = {}
|
361 |
"""
|
362 |
Endpoint che gestisce l'intera pipeline:
|
363 |
1) Genera una query SPARQL dal messaggio dell'utente (prompt dedicato).
|
@@ -391,19 +381,15 @@ def assistant_endpoint(req: AssistantRequest):
|
|
391 |
# Serializziamo l'ontologia in XML per fornirla al prompt (anche se si chiama 'turtle' va bene così).
|
392 |
ontology_turtle = ontology_graph.serialize(format="xml")
|
393 |
logger.debug("Ontologia serializzata con successo (XML).")
|
394 |
-
explanation_dict['ontology'] = "Ontologia serializzata."
|
395 |
except Exception as e:
|
396 |
logger.warning(f"Impossibile serializzare l'ontologia in formato XML: {e}")
|
397 |
-
explanation_dict['ontology'] = f"Errore serializzazione: {e}."
|
398 |
ontology_turtle = ""
|
399 |
|
400 |
# Creiamo il prompt di sistema per la generazione SPARQL
|
401 |
system_prompt_sparql = create_system_prompt_for_sparql(ontology_turtle)
|
402 |
-
explanation_dict['sparql_prompt'] = "Prompt SPARQL creato."
|
403 |
# Chiamata al modello per generare la query SPARQL
|
404 |
try:
|
405 |
logger.debug("[assistant_endpoint] Chiamata HF per generare la query SPARQL...")
|
406 |
-
explanation_dict['sparql_generation'] = "Generazione query SPARQL iniziata."
|
407 |
gen_sparql_output = hf_generation_client.chat.completions.create(
|
408 |
messages=[
|
409 |
{"role": "system", "content": system_prompt_sparql},
|
@@ -414,10 +400,8 @@ def assistant_endpoint(req: AssistantRequest):
|
|
414 |
)
|
415 |
possible_query = gen_sparql_output["choices"][0]["message"]["content"].strip()
|
416 |
logger.info(f"[assistant_endpoint] Query generata dal modello: {possible_query}")
|
417 |
-
explanation_dict['sparql_generation'] += f" Query: {possible_query}."
|
418 |
except Exception as ex:
|
419 |
logger.error(f"Errore nella generazione della query SPARQL: {ex}")
|
420 |
-
explanation_dict['sparql_generation'] = f"Errore generazione SPARQL: {ex}."
|
421 |
# Se fallisce la generazione, consideriamo la query come "NO_SPARQL"
|
422 |
possible_query = "NO_SPARQL"
|
423 |
|
@@ -428,15 +412,12 @@ def assistant_endpoint(req: AssistantRequest):
|
|
428 |
else:
|
429 |
# Applichiamo la correzione avanzata
|
430 |
advanced_corrected = correct_sparql_syntax_advanced(possible_query)
|
431 |
-
explanation_dict['sparql_correction'] = "Sintassi SPARQL corretta."
|
432 |
# Verifichiamo la validità della query
|
433 |
if is_sparql_query_valid(advanced_corrected):
|
434 |
generated_query = advanced_corrected
|
435 |
logger.debug(f"[assistant_endpoint] Query SPARQL valida dopo correzione avanzata: {generated_query}")
|
436 |
-
explanation_dict['sparql_validation'] = "Query SPARQL valida."
|
437 |
else:
|
438 |
logger.debug("[assistant_endpoint] Query SPARQL non valida. Verrà ignorata.")
|
439 |
-
explanation_dict['sparql_validation'] = "Query SPARQL non valida."
|
440 |
generated_query = None
|
441 |
|
442 |
# -----------------------------------------------------------------------
|
@@ -446,23 +427,17 @@ def assistant_endpoint(req: AssistantRequest):
|
|
446 |
point = "" # variabile per contenere il punto (inizialmente nessuno)
|
447 |
if generated_query:
|
448 |
logger.debug(f"[assistant_endpoint] Esecuzione della query SPARQL:\n{generated_query}")
|
449 |
-
explanation_dict['sparql_execution'] = "Esecuzione query SPARQL."
|
450 |
try:
|
451 |
query_result = ontology_graph.query(generated_query)
|
452 |
results = list(query_result)
|
453 |
logger.info(f"[assistant_endpoint] Query eseguita con successo. Numero risultati = {len(results)}")
|
454 |
-
explanation_dict['sparql_execution'] += f" Risultati: {len(results)}."
|
455 |
except Exception as ex:
|
456 |
logger.error(f"[assistant_endpoint] Errore nell'esecuzione della query: {ex}")
|
457 |
-
explanation_dict['sparql_execution'] = f"Errore esecuzione: {ex}."
|
458 |
results = []
|
459 |
-
else:
|
460 |
-
explanation_dict['sparql_execution'] = "Nessuna query eseguita."
|
461 |
# -----------------------------------------------------------------------
|
462 |
# STEP 3: Generazione della risposta finale stile "guida museale"
|
463 |
# -----------------------------------------------------------------------
|
464 |
system_prompt_guide = create_system_prompt_for_guide()
|
465 |
-
explanation_dict['guide_prompt'] = "Prompt guida museale creato."
|
466 |
if generated_query and results:
|
467 |
# Caso: query generata + risultati SPARQL
|
468 |
# Convertiamo i risultati in una stringa più leggibile
|
@@ -488,7 +463,6 @@ def assistant_endpoint(req: AssistantRequest):
|
|
488 |
"Rispondi in modo breve (max ~50 parole)."
|
489 |
)
|
490 |
logger.debug("[assistant_endpoint] Prompt di risposta con risultati SPARQL.")
|
491 |
-
explanation_dict['guide_prompt'] += " Inclusi risultati SPARQL."
|
492 |
elif generated_query and not results:
|
493 |
# Caso: query valida ma 0 risultati
|
494 |
second_prompt = (
|
@@ -498,7 +472,6 @@ def assistant_endpoint(req: AssistantRequest):
|
|
498 |
"Nessun risultato dalla query. Prova comunque a rispondere con le tue conoscenze."
|
499 |
)
|
500 |
logger.debug("[assistant_endpoint] Prompt di risposta: query valida ma senza risultati.")
|
501 |
-
explanation_dict['guide_prompt'] += " Query valida senza risultati."
|
502 |
else:
|
503 |
# Caso: nessuna query generata
|
504 |
second_prompt = (
|
@@ -507,11 +480,9 @@ def assistant_endpoint(req: AssistantRequest):
|
|
507 |
"Nessuna query SPARQL generata. Rispondi come puoi, riarrangiando le tue conoscenze."
|
508 |
)
|
509 |
logger.debug("[assistant_endpoint] Prompt di risposta: nessuna query generata.")
|
510 |
-
explanation_dict['guide_prompt'] += " Nessuna query generata."
|
511 |
# Chiamata finale al modello per la risposta "guida museale"
|
512 |
try:
|
513 |
logger.debug("[assistant_endpoint] Chiamata HF per generare la risposta finale...")
|
514 |
-
explanation_dict['response_generation'] = "Generazione risposta finale iniziata."
|
515 |
final_output = hf_generation_client.chat.completions.create(
|
516 |
messages=[
|
517 |
{"role": "system", "content": second_prompt},
|
@@ -522,10 +493,8 @@ def assistant_endpoint(req: AssistantRequest):
|
|
522 |
)
|
523 |
final_answer = final_output["choices"][0]["message"]["content"].strip()
|
524 |
logger.info(f"[assistant_endpoint] Risposta finale generata: {final_answer}")
|
525 |
-
explanation_dict['response_generation'] += " Risposta generata."
|
526 |
except Exception as ex:
|
527 |
logger.error(f"Errore nella generazione della risposta finale: {ex}")
|
528 |
-
explanation_dict['response_generation'] = f"Errore generazione risposta finale: {ex}."
|
529 |
raise HTTPException(status_code=500, detail="Errore nella generazione della risposta in linguaggio naturale.")
|
530 |
|
531 |
# -----------------------------------------------------------------------
|
@@ -533,7 +502,6 @@ def assistant_endpoint(req: AssistantRequest):
|
|
533 |
# -----------------------------------------------------------------------
|
534 |
final_ans = classify_and_translate(user_message, final_answer)
|
535 |
final_ans = final_ans.replace('\\"', "").replace('\"', "")
|
536 |
-
explanation_dict['translation_completion'] = "Traduzione completata."
|
537 |
# -----------------------------------------------------------------------
|
538 |
# Restituzione in formato JSON
|
539 |
# -----------------------------------------------------------------------
|
@@ -541,7 +509,6 @@ def assistant_endpoint(req: AssistantRequest):
|
|
541 |
return {
|
542 |
"query": generated_query,
|
543 |
"response": final_ans,
|
544 |
-
"explanation": explanation_dict,
|
545 |
"point": point
|
546 |
}
|
547 |
# ---------------------------------------------------------------------------
|
|
|
16 |
handlers=[logging.FileHandler("app.log"), logging.StreamHandler()]
|
17 |
)
|
18 |
logger = logging.getLogger(__name__)
|
19 |
+
|
20 |
# ---------------------------------------------------------------------------
|
21 |
# COSTANTI / CHIAVI / MODELLI
|
22 |
# ---------------------------------------------------------------------------
|
|
|
214 |
try:
|
215 |
question_lang_result = lang_detect_client.text_classification(text=question_text)
|
216 |
question_lang = question_lang_result[0]['label']
|
|
|
217 |
logger.info(f"[LangDetect] Lingua della domanda: {question_lang}")
|
218 |
except Exception as e:
|
219 |
logger.error(f"Errore nel rilevamento della lingua della domanda: {e}")
|
220 |
question_lang = "en" # Fallback se non riusciamo a rilevare la lingua
|
|
|
221 |
# Rileva la lingua della risposta
|
222 |
try:
|
223 |
answer_lang_result = lang_detect_client.text_classification(text=model_answer_text)
|
224 |
answer_lang = answer_lang_result[0]['label']
|
|
|
225 |
logger.info(f"[LangDetect] Lingua della risposta: {answer_lang}")
|
226 |
except Exception as e:
|
227 |
logger.error(f"Errore nel rilevamento della lingua della risposta: {e}")
|
228 |
answer_lang = "it" # Fallback se non riusciamo a rilevare la lingua
|
|
|
229 |
|
230 |
# Se domanda e risposta sono nella stessa lingua, non traduciamo
|
231 |
if question_lang == answer_lang:
|
232 |
logger.info("[Translate] Nessuna traduzione necessaria: stessa lingua.")
|
|
|
233 |
return model_answer_text
|
234 |
|
235 |
# Altrimenti, costruiamo "al volo" il modello di traduzione appropriato
|
|
|
239 |
token=HF_API_KEY,
|
240 |
model=translator_model
|
241 |
)
|
|
|
242 |
# Traduzione della risposta
|
243 |
try:
|
244 |
translation_result = translator_client.translation(text=model_answer_text)
|
245 |
translated_answer = translation_result["translation_text"]
|
|
|
246 |
except Exception as e:
|
247 |
logger.error(f"Errore nella traduzione {answer_lang} -> {question_lang}: {e}")
|
|
|
248 |
# Se fallisce, restituiamo la risposta originale come fallback
|
|
|
249 |
translated_answer = model_answer_text
|
250 |
|
251 |
return translated_answer
|
|
|
348 |
# ---------------------------------------------------------------------------
|
349 |
@app.post("/assistant")
|
350 |
def assistant_endpoint(req: AssistantRequest):
|
|
|
351 |
"""
|
352 |
Endpoint che gestisce l'intera pipeline:
|
353 |
1) Genera una query SPARQL dal messaggio dell'utente (prompt dedicato).
|
|
|
381 |
# Serializziamo l'ontologia in XML per fornirla al prompt (anche se si chiama 'turtle' va bene così).
|
382 |
ontology_turtle = ontology_graph.serialize(format="xml")
|
383 |
logger.debug("Ontologia serializzata con successo (XML).")
|
|
|
384 |
except Exception as e:
|
385 |
logger.warning(f"Impossibile serializzare l'ontologia in formato XML: {e}")
|
|
|
386 |
ontology_turtle = ""
|
387 |
|
388 |
# Creiamo il prompt di sistema per la generazione SPARQL
|
389 |
system_prompt_sparql = create_system_prompt_for_sparql(ontology_turtle)
|
|
|
390 |
# Chiamata al modello per generare la query SPARQL
|
391 |
try:
|
392 |
logger.debug("[assistant_endpoint] Chiamata HF per generare la query SPARQL...")
|
|
|
393 |
gen_sparql_output = hf_generation_client.chat.completions.create(
|
394 |
messages=[
|
395 |
{"role": "system", "content": system_prompt_sparql},
|
|
|
400 |
)
|
401 |
possible_query = gen_sparql_output["choices"][0]["message"]["content"].strip()
|
402 |
logger.info(f"[assistant_endpoint] Query generata dal modello: {possible_query}")
|
|
|
403 |
except Exception as ex:
|
404 |
logger.error(f"Errore nella generazione della query SPARQL: {ex}")
|
|
|
405 |
# Se fallisce la generazione, consideriamo la query come "NO_SPARQL"
|
406 |
possible_query = "NO_SPARQL"
|
407 |
|
|
|
412 |
else:
|
413 |
# Applichiamo la correzione avanzata
|
414 |
advanced_corrected = correct_sparql_syntax_advanced(possible_query)
|
|
|
415 |
# Verifichiamo la validità della query
|
416 |
if is_sparql_query_valid(advanced_corrected):
|
417 |
generated_query = advanced_corrected
|
418 |
logger.debug(f"[assistant_endpoint] Query SPARQL valida dopo correzione avanzata: {generated_query}")
|
|
|
419 |
else:
|
420 |
logger.debug("[assistant_endpoint] Query SPARQL non valida. Verrà ignorata.")
|
|
|
421 |
generated_query = None
|
422 |
|
423 |
# -----------------------------------------------------------------------
|
|
|
427 |
point = "" # variabile per contenere il punto (inizialmente nessuno)
|
428 |
if generated_query:
|
429 |
logger.debug(f"[assistant_endpoint] Esecuzione della query SPARQL:\n{generated_query}")
|
|
|
430 |
try:
|
431 |
query_result = ontology_graph.query(generated_query)
|
432 |
results = list(query_result)
|
433 |
logger.info(f"[assistant_endpoint] Query eseguita con successo. Numero risultati = {len(results)}")
|
|
|
434 |
except Exception as ex:
|
435 |
logger.error(f"[assistant_endpoint] Errore nell'esecuzione della query: {ex}")
|
|
|
436 |
results = []
|
|
|
|
|
437 |
# -----------------------------------------------------------------------
|
438 |
# STEP 3: Generazione della risposta finale stile "guida museale"
|
439 |
# -----------------------------------------------------------------------
|
440 |
system_prompt_guide = create_system_prompt_for_guide()
|
|
|
441 |
if generated_query and results:
|
442 |
# Caso: query generata + risultati SPARQL
|
443 |
# Convertiamo i risultati in una stringa più leggibile
|
|
|
463 |
"Rispondi in modo breve (max ~50 parole)."
|
464 |
)
|
465 |
logger.debug("[assistant_endpoint] Prompt di risposta con risultati SPARQL.")
|
|
|
466 |
elif generated_query and not results:
|
467 |
# Caso: query valida ma 0 risultati
|
468 |
second_prompt = (
|
|
|
472 |
"Nessun risultato dalla query. Prova comunque a rispondere con le tue conoscenze."
|
473 |
)
|
474 |
logger.debug("[assistant_endpoint] Prompt di risposta: query valida ma senza risultati.")
|
|
|
475 |
else:
|
476 |
# Caso: nessuna query generata
|
477 |
second_prompt = (
|
|
|
480 |
"Nessuna query SPARQL generata. Rispondi come puoi, riarrangiando le tue conoscenze."
|
481 |
)
|
482 |
logger.debug("[assistant_endpoint] Prompt di risposta: nessuna query generata.")
|
|
|
483 |
# Chiamata finale al modello per la risposta "guida museale"
|
484 |
try:
|
485 |
logger.debug("[assistant_endpoint] Chiamata HF per generare la risposta finale...")
|
|
|
486 |
final_output = hf_generation_client.chat.completions.create(
|
487 |
messages=[
|
488 |
{"role": "system", "content": second_prompt},
|
|
|
493 |
)
|
494 |
final_answer = final_output["choices"][0]["message"]["content"].strip()
|
495 |
logger.info(f"[assistant_endpoint] Risposta finale generata: {final_answer}")
|
|
|
496 |
except Exception as ex:
|
497 |
logger.error(f"Errore nella generazione della risposta finale: {ex}")
|
|
|
498 |
raise HTTPException(status_code=500, detail="Errore nella generazione della risposta in linguaggio naturale.")
|
499 |
|
500 |
# -----------------------------------------------------------------------
|
|
|
502 |
# -----------------------------------------------------------------------
|
503 |
final_ans = classify_and_translate(user_message, final_answer)
|
504 |
final_ans = final_ans.replace('\\"', "").replace('\"', "")
|
|
|
505 |
# -----------------------------------------------------------------------
|
506 |
# Restituzione in formato JSON
|
507 |
# -----------------------------------------------------------------------
|
|
|
509 |
return {
|
510 |
"query": generated_query,
|
511 |
"response": final_ans,
|
|
|
512 |
"point": point
|
513 |
}
|
514 |
# ---------------------------------------------------------------------------
|