Files
Sibilla 76bc667adf feat: v0.2.0 — API REST, TTS support, documentazione completa e UI mobile-first
✨ Nuove funzionalità:
- Nuovo endpoint API REST /api/v1/query (GET+POST) per consumo programmatico
- Campo speakable_text ottimizzato per sintesi vocale (Alexa, Google Home)
- Funzione strip_markdown() per conversione Markdown → plain text TTS
- Supporto CORS per accesso cross-origin
- UI responsive mobile-first con micro-interazioni e stati
- Nuovo pulsante 'Nuova ricerca' e metadata bar

📚 Documentazione completa:
- docs/ARCHITECTURE.md — architettura di sistema, stack, componenti
- docs/FLOW.md — diagrammi Mermaid della pipeline e flussi
- docs/API.md — documentazione endpoint REST con esempi curl
- docs/WIKI.md — FAQ, glossario, roadmap
- docs/DEPLOYMENT.md — guida deployment (Gunicorn, Nginx, Docker, systemd)
- docs/CONTRIBUTING.md — guida alla contribuzione

🔧 Migliorie tecniche:
- Pipeline di ricerca condivisa in _run_search_pipeline()
- Gestione errori Gemini migliorata con _clean_error()
- Sanitizzazione HTML con allowlist per prevenzione XSS
- .env.example completo con commenti

🧪 Test: 109/109 passati
2026-07-18 10:05:46 +00:00

8.8 KiB
Raw Permalink Blame History

📡 Sibilla — Documentazione API REST

Versione: 0.2.0
Ultimo aggiornamento: 18 Luglio 2026


Indice

  1. Panoramica
  2. Health Check
  3. API Ask (Web)
  4. API v1 Query (Programmatica)
  5. Codici di errore
  6. Esempi curl
  7. Integrazione Alexa Skill

Panoramica

Tutti gli endpoint sono accessibili su http://localhost:5000 (o l'host/porta configurati).

Metodo Endpoint Descrizione Formato
GET / Interfaccia web HTML text/html
GET /api/health Health check application/json
POST /api/ask Ricerca + sintesi (web UI) application/json
GET /api/v1/query Ricerca + sintesi (API, query string) application/json
POST /api/v1/query Ricerca + sintesi (API, JSON body) application/json

CORS: Tutti gli endpoint includono header CORS permissivi (Access-Control-Allow-Origin: *).


Health Check

GET /api/health

Verifica lo stato del server e la configurazione.

Request:

curl http://localhost:5000/api/health

Response 200 OK:

{
    "status": "ok",
    "version": "0.2.0",
    "gemini_configured": true,
    "degoog_url": "http://localhost:4444",
    "searxng_url": "http://localhost:8080"
}
Campo Tipo Descrizione
status string Sempre "ok" se il server risponde
version string Versione di Sibilla
gemini_configured boolean true se GOOGLE_API_KEY è configurata
degoog_url string URL dell'istanza Degoog
searxng_url string URL dell'istanza SearXNG

API Ask

POST /api/ask

Endpoint principale per la ricerca con sintesi AI. Utilizzato dall'interfaccia web.

Request:

{
    "query": "Qual è stato l'ultimo film sull'Odissea?",
    "num_sources": 5
}
Parametro Tipo Default Range Descrizione
query string richiesto — La domanda da cercare
num_sources integer 5 1–10 Numero massimo di fonti da usare

Response 200 OK:

{
    "answer": "L'ultimo adattamento cinematografico dell'**Odissea** è *The Return* (2024)...",
    "html_answer": "<p>L'ultimo adattamento cinematografico dell'<strong>Odissea</strong> è <em>The Return</em> (2024)...</p>",
    "speakable_text": "L'ultimo adattamento cinematografico dell'Odissea è The Return del 2024...",
    "sources": [
        {
            "index": 1,
            "title": "The Return - Wikipedia",
            "url": "https://it.wikipedia.org/wiki/The_Return_(film_2024)",
            "snippet": "The Return è un film del 2024 diretto da Uberto Pasolini..."
        }
    ],
    "model": "gemini-2.5-flash",
    "search_engine": "degoog",
    "tokens_used": 1847,
    "error": null
}
Campo Tipo Descrizione
answer string Risposta in formato Markdown
html_answer string Risposta in HTML sicuro (sanitizzato)
speakable_text string Risposta in plain text, ottimizzata per TTS
sources array Lista delle fonti utilizzate
sources[].index integer Numero della fonte (1-based)
sources[].title string Titolo della pagina
sources[].url string URL della fonte
sources[].snippet string Estratto della pagina (max 200 caratteri)
model string Modello LLM utilizzato
search_engine string Motore di ricerca usato (degoog, searxng, duckduckgo, none)
tokens_used integer Token totali consumati
error string or null Eventuale messaggio di errore

Response 400 Bad Request:

{
    "error": "La query non può essere vuota."
}

Response 502 Bad Gateway:

{
    "error": "Ricerca web fallita: Connection refused",
    "answer": "",
    "sources": []
}

API v1 Query

GET /api/v1/query

Endpoint semplificato per consumo programmatico. Accetta la query via query string.

Request:

curl "http://localhost:5000/api/v1/query?q=ultimo+film+sull%27Odissea"

POST /api/v1/query

Stesso endpoint, con query nel body JSON.

Request:

{
    "query": "Qual è stato l'ultimo film sull'Odissea?"
}
Parametro Tipo Default Descrizione
q (GET) string richiesto La query di ricerca (URL-encoded)
query (POST) string richiesto La query di ricerca

Response 200 OK:

{
    "query": "Qual è stato l'ultimo film sull'Odissea?",
    "answer": "L'ultimo adattamento è **The Return** (2024), diretto da Uberto Pasolini...",
    "speakable_text": "L'ultimo adattamento è The Return del 2024, diretto da Uberto Pasolini...",
    "sources": [
        {
            "index": 1,
            "title": "The Return - Wikipedia",
            "url": "https://it.wikipedia.org/wiki/The_Return_(film_2024)"
        }
    ],
    "model": "gemini-2.5-flash",
    "search_engine": "degoog",
    "tokens_used": 1847
}
Campo Tipo Descrizione
query string Echo della query originale
answer string Risposta in formato Markdown
speakable_text string Plain text ottimizzato per sintesi vocale (TTS)
sources array Fonti semplificate (solo index, title, url)
model string Modello LLM utilizzato
search_engine string Motore di ricerca usato
tokens_used integer Token totali consumati

Nota: Il formato è più compatto di /api/ask — pensato per API consumer come skill Alexa, Lambda function, o mobile app.

Response 400 Bad Request:

{
    "error": "Missing query parameter 'q'."
}

Response 502 Bad Gateway:

{
    "error": "Ricerca web fallita: Connection refused",
    "answer": "",
    "speakable_text": ""
}

Codici di errore

HTTP Status Significato Quando
200 OK Richiesta completata con successo
400 Bad Request Query mancante o vuota
502 Bad Gateway Tutti i motori di ricerca sono down

Errori interni gestiti:

  • Se tutti i motori falliscono ma Gemini è disponibile → fallback a risposta solo LLM (200 OK)
  • Se Gemini non è configurato → answer vuoto con error nel JSON
  • Se Gemini restituisce errore → messaggio di errore inline in answer

Esempi curl

Health check

curl -s http://localhost:5000/api/health | python -m json.tool

Ricerca via API v1 (GET)

curl -s "http://localhost:5000/api/v1/query?q=cosa+sono+i+raggi+cosmici" | python -m json.tool

Ricerca via API v1 (POST)

curl -s -X POST http://localhost:5000/api/v1/query \
  -H "Content-Type: application/json" \
  -d '{"query": "cosa sono i raggi cosmici"}' | python -m json.tool

Estrai solo la risposta speakable (per TTS)

curl -s "http://localhost:5000/api/v1/query?q=raggi+cosmici" | python -c "import sys,json; print(json.load(sys.stdin)['speakable_text'])"

Ricerca via web UI (POST /api/ask)

curl -s -X POST http://localhost:5000/api/ask \
  -H "Content-Type: application/json" \
  -d '{"query": "raggi cosmici", "num_sources": 3}' | python -m json.tool

Verifica errori

# Query vuota → 400
curl -i "http://localhost:5000/api/v1/query?q="

# Motori down → 502 (se tutti falliscono)
curl -i "http://localhost:5000/api/v1/query?q=test"

Integrazione Alexa Skill

Ecco un esempio di come usare l'endpoint /api/v1/query da una Lambda Python per una skill Alexa:

import json
import urllib.request

SIBILLA_URL = "https://tuo-server.com/api/v1/query"

def call_sibilla(query: str) -> dict:
    """Chiama Sibilla e restituisce la risposta parlata."""
    params = urllib.parse.urlencode({"q": query})
    url = f"{SIBILLA_URL}?{params}"

    with urllib.request.urlopen(url, timeout=30) as resp:
        data = json.loads(resp.read().decode())

    return {
        "answer": data["answer"],
        "speakable_text": data["speakable_text"],
        "sources": data["sources"],
    }

# In un handler Alexa:
def lambda_handler(event, context):
    query = event["request"]["intent"]["slots"]["query"]["value"]
    result = call_sibilla(query)

    return {
        "version": "1.0",
        "response": {
            "outputSpeech": {
                "type": "SSML",
                "ssml": f"<speak>{result['speakable_text']}</speak>"
            },
            "shouldEndSession": True
        }
    }

Nota: Il campo speakable_text è già pulito da markup Markdown, URL, grassetti e codice — pronto per essere letto da un motore TTS.