|
import os |
|
from fastapi import FastAPI, HTTPException |
|
from huggingface_hub import InferenceClient |
|
from rdflib import Graph |
|
from pydantic import BaseModel |
|
|
|
|
|
API_KEY = os.getenv("HF_API_KEY") |
|
client = InferenceClient(api_key=API_KEY) |
|
|
|
|
|
RDF_FILE = "Progetto.rdf" |
|
|
|
|
|
def load_rdf(): |
|
if os.path.exists(RDF_FILE): |
|
with open(RDF_FILE, "r") as f: |
|
return f.read() |
|
return "" |
|
|
|
rdf_context = load_rdf() |
|
print(rdf_context) |
|
|
|
def validate_sparql_query(query, rdf_data): |
|
try: |
|
g = Graph() |
|
g.parse(data=rdf_data, format="xml") |
|
|
|
g.query(query) |
|
return True |
|
except Exception as e: |
|
print(f"Errore durante la validazione della query SPARQL: {e}") |
|
return False |
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
class QueryRequest(BaseModel): |
|
message: str |
|
max_tokens: int = 2048 |
|
temperature: float = 0.7 |
|
|
|
|
|
def create_system_message(rdf_context): |
|
return f""" |
|
Sei un assistente specializzato nella generazione di query SPARQL basate su dati RDF. |
|
La base di conoscenza RDF è la seguente: |
|
{rdf_context} |
|
Il tuo compito è: |
|
1. Generare una query SPARQL valida e **scritta in una sola riga** senza formattazioni aggiuntive. |
|
2. Rispondere **solo** a domande che possono essere soddisfatte con i dati RDF forniti. |
|
3. Se la domanda non può essere soddisfatta, rispondi con: "Non posso generare una query SPARQL per questa richiesta.". |
|
Regole: |
|
- Non generare spiegazioni o commenti extra nella risposta. |
|
- Non soddisfare richieste fuori dal contesto RDF fornito. |
|
- Restituisci esclusivamente una query SPARQL in **una sola riga**. |
|
""" |
|
|
|
|
|
async def generate_response(message, max_tokens, temperature): |
|
system_message = create_system_message(rdf_context) |
|
messages = [ |
|
{"role": "system", "content": system_message}, |
|
{"role": "user", "content": message} |
|
] |
|
|
|
try: |
|
|
|
stream = client.chat.completions.create( |
|
model="Qwen/Qwen2.5-72B-Instruct", |
|
messages=messages, |
|
temperature=temperature, |
|
max_tokens=max_tokens, |
|
top_p=0.7, |
|
stream=True |
|
) |
|
|
|
response = "" |
|
for chunk in stream: |
|
if "choices" in chunk and len(chunk["choices"]) > 0: |
|
response += chunk["choices"][0]["delta"]["content"] |
|
|
|
|
|
response = response.replace("\n", " ").strip() |
|
return response |
|
except Exception as e: |
|
raise HTTPException(status_code=500, detail=f"Errore nell'elaborazione: {str(e)}") |
|
|
|
|
|
@app.post("/generate-query/") |
|
async def generate_query(request: QueryRequest): |
|
|
|
response = await generate_response(request.message, request.max_tokens, request.temperature) |
|
print("Risposta generata dal modello:", 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_context): |
|
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."} |
|
|
|
|
|
@app.get("/") |
|
async def root(): |
|
return {"message": "Il server è attivo e pronto a generare query SPARQL!"} |
|
|