File size: 4,558 Bytes
ee1f7e6
034a1e6
ee1f7e6
034a1e6
 
 
ee1f7e6
4c52594
 
 
 
 
1575481
034a1e6
 
 
 
 
21119e3
034a1e6
3031ece
 
034a1e6
4c52594
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3031ece
 
 
4c52594
034a1e6
 
a1f8fd1
034a1e6
 
a1f8fd1
3031ece
034a1e6
8c772f5
4c52594
034a1e6
 
 
1575481
 
034a1e6
 
 
4d4b9ae
034a1e6
 
 
 
 
3031ece
 
034a1e6
3031ece
 
 
 
034a1e6
 
3b0ec68
034a1e6
4c52594
 
baa2201
3b0ec68
 
 
 
baa2201
034a1e6
baa2201
034a1e6
3b0ec68
 
 
 
ee1f7e6
034a1e6
4c52594
baa2201
034a1e6
4c52594
034a1e6
aa07e9d
034a1e6
 
 
3b0ec68
4c52594
 
4d4b9ae
 
 
 
 
034a1e6
a1f8fd1
4d4b9ae
 
 
 
8e527d0
4d4b9ae
034a1e6
3031ece
1575481
034a1e6
ee1f7e6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import json
import os
from pathlib import Path
from huggingface_hub import InferenceClient
from rdflib import Graph
from pydantic import BaseModel
from fastapi import FastAPI, HTTPException
import logging

# Configurazione logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)

# Configurazione API Hugging Face
API_KEY = os.getenv("HF_API_KEY")
client = InferenceClient(api_key=API_KEY)

# File RDF
RDF_FILE = "Ontologia.rdf"

# Carica un riassunto del file RDF
def load_rdf_summary():
    if os.path.exists(RDF_FILE):
        try:
            g = Graph()
            g.parse(RDF_FILE, format="xml")

            classes = set()
            properties = set()

            for s, _, o in g.triples((None, None, None)):
                if "Class" in str(o) or "rdfs:Class" in str(o):
                    classes.add(s)
                if "Property" in str(o):
                    properties.add(s)

            classes_summary = "\n".join([f"- Classe: {cls}" for cls in classes])
            properties_summary = "\n".join([f"- Proprietà: {prop}" for prop in properties])
            return f"Classi:\n{classes_summary}\n\nProprietà:\n{properties_summary}"
        except Exception as e:
            logger.error(f"Errore durante il parsing del file RDF: {e}")
            return "Errore nel caricamento del file RDF."
    return "Nessun dato RDF trovato."

rdf_context = load_rdf_summary()
logger.info("RDF Summary: %s", rdf_context)

# Valida le query SPARQL
def validate_sparql_query(query, rdf_file_path):
    try:
        g = Graph()
        g.parse(rdf_file_path, format="xml")
        g.query(query)  # Prova ad eseguire la query
        return True
    except Exception as e:
        logger.error(f"Errore durante la validazione della query SPARQL: {e}")
        return False

# FastAPI app
app = FastAPI()

# Modello di input per richieste POST
class QueryRequest(BaseModel):
    message: str
    max_tokens: int = 2048
    temperature: float = 0.7

# Messaggio di sistema con RDF incluso
def create_system_message(rdf_context):
    return f"""
Sei un assistente esperto nella generazione di query SPARQL basate su ontologie RDF.
Ecco un riassunto dell'ontologia su cui devi lavorare:
{rdf_context}
Il tuo compito:
- Genera esclusivamente query SPARQL valide in UNA SOLA RIGA.
- Rispondi solo se la domanda è pertinente alle classi e proprietà fornite.
- Se non puoi rispondere, di': "Non posso generare una query SPARQL per questa richiesta."
"""

async def generate_response(message, max_tokens, temperature):
    system_message = create_system_message(rdf_context)
    logger.debug("System Message: %s", system_message)
    logger.info("User Message: %s", message)

    messages = [
        {"role": "system", "content": system_message},
        {"role": "user", "content": message}
    ]

    try:
        response = client.chat.completions.create(
            model="Qwen/Qwen2.5-72B-Instruct",
            messages=messages,
            temperature=temperature,
            max_tokens=max_tokens,
            top_p=0.7,
            stream=False
        )
        logger.info("Raw Response: %s", response)
        return response['choices'][0]['message']['content'].replace("\n", " ").strip()
    except Exception as e:
        logger.error(f"Errore nell'elaborazione: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Errore nell'elaborazione: {str(e)}")

# Endpoint per generare query SPARQL
@app.post("/generate-query/")
async def generate_query(request: QueryRequest):
    response = await generate_response(request.message, request.max_tokens, request.temperature)
    logger.info("Risposta generata dal modello: %s", response)

    if not (response.startswith("SELECT") or response.startswith("ASK")):
        return {
            "query": None,
            "explanation": "Non posso generare una query SPARQL per questa richiesta. Assicurati che la domanda sia coerente con i dati RDF forniti."
        }

    if not validate_sparql_query(response, RDF_FILE):
        return {
            "query": None,
            "explanation": "La query generata non è valida rispetto alla base di conoscenza RDF. Assicurati di chiedere informazioni che siano presenti nell'ontologia."
        }

    return {"query": response, "explanation": "Ecco la query generata correttamente in una riga pronta per GraphDB."}

# Endpoint di test
@app.get("/")
async def root():
    return {"message": "Il server è attivo e pronto a generare query SPARQL!"}