Update app.py
Browse files
app.py
CHANGED
@@ -32,7 +32,7 @@ if not API_KEY:
|
|
32 |
# Definisci i percorsi dei file
|
33 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
34 |
RDF_FILE = os.path.join(BASE_DIR, "Ontologia.rdf")
|
35 |
-
HF_MODEL = "
|
36 |
|
37 |
MAX_CLASSES = 30
|
38 |
MAX_PROPERTIES = 30
|
@@ -96,7 +96,7 @@ def extract_ontology(rdf_file: str, output_file: str):
|
|
96 |
# Estrai le proprietà dell'entità
|
97 |
entity_properties = {}
|
98 |
for predicate, obj in g.predicate_objects(entity):
|
99 |
-
if predicate
|
100 |
entity_properties[str(predicate)] = str(obj)
|
101 |
entities.append({
|
102 |
"entity": str(entity),
|
@@ -111,7 +111,7 @@ def extract_ontology(rdf_file: str, output_file: str):
|
|
111 |
"classes": classes[:MAX_CLASSES],
|
112 |
"properties": properties[:MAX_PROPERTIES],
|
113 |
"entities": entities, # Aggiungi le entità
|
114 |
-
"full_ontology": g.serialize(format="xml") # Decodifica rimossa
|
115 |
}
|
116 |
|
117 |
# Salva il documento in JSON
|
@@ -236,11 +236,11 @@ def extract_classes_and_properties(rdf_file: str) -> str:
|
|
236 |
txt_entities = "\n".join([f"- ENTITÀ: {e}" for e in entities_list])
|
237 |
|
238 |
summary = f"""\
|
239 |
-
|
240 |
{txt_classes}
|
241 |
-
|
242 |
{txt_props}
|
243 |
-
|
244 |
{txt_entities}
|
245 |
"""
|
246 |
logger.info("Estrazione di classi, proprietà ed entità completata.")
|
@@ -287,18 +287,15 @@ def create_system_message(ont_text: str, retrieved_docs: str) -> str:
|
|
287 |
Prompt di sistema robusto, con regole su query in una riga e
|
288 |
informazioni recuperate tramite RAG.
|
289 |
"""
|
290 |
-
return f"""
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
### Ontologia ###
|
295 |
{ont_text}
|
296 |
-
|
297 |
-
|
298 |
Ecco alcune informazioni rilevanti recuperate dalla base di conoscenza:
|
299 |
{retrieved_docs}
|
300 |
-
|
301 |
-
|
302 |
1) Se l'utente chiede informazioni su questa ontologia, genera SEMPRE una query SPARQL in UNA SOLA RIGA, con prefix:
|
303 |
PREFIX base: <http://www.semanticweb.org/lucreziamosca/ontologies/progettoMuseo#>
|
304 |
2) La query SPARQL deve essere precisa e cercare esattamente le entità specificate dall'utente. Ad esempio, se l'utente chiede "Chi ha creato l'opera 'Amore e Psiche'?", la query dovrebbe cercare l'opera esattamente con quel nome.
|
@@ -307,20 +304,15 @@ Ecco alcune informazioni rilevanti recuperate dalla base di conoscenza:
|
|
307 |
5) Se trovi risultati, la risposta finale deve essere la query SPARQL (una sola riga).
|
308 |
6) Se non trovi nulla, rispondi con 'Nessuna info.'
|
309 |
7) Non multiline. Esempio: PREFIX base: <...> SELECT ?x WHERE { ... }.
|
310 |
-
|
311 |
-
**Esempi:**
|
312 |
Utente: Chi ha creato l'opera 'Amore e Psiche'?
|
313 |
Risposta: PREFIX base: <http://www.semanticweb.org/lucreziamosca/ontologies/progettoMuseo#> SELECT ?creatore WHERE { ?opera base:hasName "Amore e Psiche" . ?opera base:creatoDa ?creatore . }
|
314 |
-
|
315 |
-
Utente: che ore sono?
|
316 |
-
Risposta: Ciao! Sono un assistente museale e non ho informazioni sulle ore attuali. Ti consiglio di consultare un orologio o un dispositivo mobile per conoscere l'ora esatta.
|
317 |
-
|
318 |
-
### FINE Regole Stringenti ###
|
319 |
"""
|
320 |
|
321 |
def create_explanation_prompt(results_str: str) -> str:
|
322 |
"""Prompt per generare una spiegazione museale dei risultati SPARQL."""
|
323 |
-
return f"""
|
324 |
Ho ottenuto questi risultati SPARQL:
|
325 |
{results_str}
|
326 |
Ora fornisci una breve spiegazione museale (massimo ~10 righe), senza inventare oltre i risultati.
|
@@ -473,7 +465,7 @@ async def generate_response(req: QueryRequest):
|
|
473 |
row_list = []
|
474 |
for row in results:
|
475 |
row_dict = row.asdict()
|
476 |
-
row_str = ", ".join([f"{k}:{v}" for k, v in row_dict.items()])
|
477 |
row_list.append(row_str)
|
478 |
results_str = "\n".join(row_list)
|
479 |
|
@@ -494,4 +486,4 @@ async def generate_response(req: QueryRequest):
|
|
494 |
|
495 |
@app.get("/")
|
496 |
def home():
|
497 |
-
return {"message": "
|
|
|
32 |
# Definisci i percorsi dei file
|
33 |
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
34 |
RDF_FILE = os.path.join(BASE_DIR, "Ontologia.rdf")
|
35 |
+
HF_MODEL = "google/flan-t5-xxl" # Modello ottimizzato per seguire istruzioni
|
36 |
|
37 |
MAX_CLASSES = 30
|
38 |
MAX_PROPERTIES = 30
|
|
|
96 |
# Estrai le proprietà dell'entità
|
97 |
entity_properties = {}
|
98 |
for predicate, obj in g.predicate_objects(entity):
|
99 |
+
if predicate not in [RDFS.label, RDFS.comment]:
|
100 |
entity_properties[str(predicate)] = str(obj)
|
101 |
entities.append({
|
102 |
"entity": str(entity),
|
|
|
111 |
"classes": classes[:MAX_CLASSES],
|
112 |
"properties": properties[:MAX_PROPERTIES],
|
113 |
"entities": entities, # Aggiungi le entità
|
114 |
+
"full_ontology": g.serialize(format="xml").decode('utf-8') if isinstance(g.serialize(format="xml"), bytes) else g.serialize(format="xml") # Decodifica rimossa
|
115 |
}
|
116 |
|
117 |
# Salva il documento in JSON
|
|
|
236 |
txt_entities = "\n".join([f"- ENTITÀ: {e}" for e in entities_list])
|
237 |
|
238 |
summary = f"""\
|
239 |
+
# CLASSI (max {MAX_CLASSES})
|
240 |
{txt_classes}
|
241 |
+
# PROPRIETÀ (max {MAX_PROPERTIES})
|
242 |
{txt_props}
|
243 |
+
# ENTITÀ (max {MAX_CLASSES})
|
244 |
{txt_entities}
|
245 |
"""
|
246 |
logger.info("Estrazione di classi, proprietà ed entità completata.")
|
|
|
287 |
Prompt di sistema robusto, con regole su query in una riga e
|
288 |
informazioni recuperate tramite RAG.
|
289 |
"""
|
290 |
+
return f"""\
|
291 |
+
Sei un assistente museale esperto in ontologie RDF. Utilizza le informazioni fornite per generare query SPARQL precise e pertinenti. Ecco un estratto di CLASSI, PROPRIETÀ ed ENTità dell'ontologia (senza NamedIndividuals):
|
292 |
+
--- ONTOLOGIA ---
|
|
|
|
|
293 |
{ont_text}
|
294 |
+
--- FINE ---
|
|
|
295 |
Ecco alcune informazioni rilevanti recuperate dalla base di conoscenza:
|
296 |
{retrieved_docs}
|
297 |
+
Suggerimento: se l'utente chiede il 'materiale' di un'opera, potresti usare qualcosa come 'base:materialeOpera' o un'altra proprietà simile (se esiste). Non è tassativo: usa la proprietà che ritieni più affine se ci sono riferimenti in ontologia.
|
298 |
+
REGOLE STRINGENTI:
|
299 |
1) Se l'utente chiede informazioni su questa ontologia, genera SEMPRE una query SPARQL in UNA SOLA RIGA, con prefix:
|
300 |
PREFIX base: <http://www.semanticweb.org/lucreziamosca/ontologies/progettoMuseo#>
|
301 |
2) La query SPARQL deve essere precisa e cercare esattamente le entità specificate dall'utente. Ad esempio, se l'utente chiede "Chi ha creato l'opera 'Amore e Psiche'?", la query dovrebbe cercare l'opera esattamente con quel nome.
|
|
|
304 |
5) Se trovi risultati, la risposta finale deve essere la query SPARQL (una sola riga).
|
305 |
6) Se non trovi nulla, rispondi con 'Nessuna info.'
|
306 |
7) Non multiline. Esempio: PREFIX base: <...> SELECT ?x WHERE { ... }.
|
307 |
+
Esempio:
|
|
|
308 |
Utente: Chi ha creato l'opera 'Amore e Psiche'?
|
309 |
Risposta: PREFIX base: <http://www.semanticweb.org/lucreziamosca/ontologies/progettoMuseo#> SELECT ?creatore WHERE { ?opera base:hasName "Amore e Psiche" . ?opera base:creatoDa ?creatore . }
|
310 |
+
FINE REGOLE
|
|
|
|
|
|
|
|
|
311 |
"""
|
312 |
|
313 |
def create_explanation_prompt(results_str: str) -> str:
|
314 |
"""Prompt per generare una spiegazione museale dei risultati SPARQL."""
|
315 |
+
return f"""\
|
316 |
Ho ottenuto questi risultati SPARQL:
|
317 |
{results_str}
|
318 |
Ora fornisci una breve spiegazione museale (massimo ~10 righe), senza inventare oltre i risultati.
|
|
|
465 |
row_list = []
|
466 |
for row in results:
|
467 |
row_dict = row.asdict()
|
468 |
+
row_str = ", ".join([f"{k}: {v}" for k, v in row_dict.items()])
|
469 |
row_list.append(row_str)
|
470 |
results_str = "\n".join(row_list)
|
471 |
|
|
|
486 |
|
487 |
@app.get("/")
|
488 |
def home():
|
489 |
+
return {"message": "Assistente Museale con supporto SPARQL."}
|