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
This commit is contained in:
1 parent
f3fe13c60e
commit
76bc667adf
20 files changed
+3385
-245
No files matched your search
@@ -1,101 +1,241 @@
|
||||
# 🔮 Sibilla
|
||||
# 🔮 Sibilla — L'Oracolo AI
|
||||
|
||||
> *L'oracolo AI che cerca nel web e risponde alle tue domande.*
|
||||
> Self-hosted Perplexity-like search engine.
|
||||
> *Self-hosted Perplexity-like AI search engine.*
|
||||
> *Chiedi, cerca, sintetizza — con fonti verificabili.*
|
||||
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://flask.palletsprojects.com/)
|
||||
[](https://ai.google.dev/)
|
||||
[](https://github.com/tuo-user/sibilla)
|
||||
[](LICENSE)
|
||||
[](https://modelcontextprotocol.io/)
|
||||
|
||||
---
|
||||
|
||||
**Sibilla** è un motore di ricerca AI self-hosted che combina:
|
||||
|
||||
- 🧠 **Google Gemini** — LLM per sintesi e query expansion
|
||||
- 🔍 **Degoog** — metasearch engine self-hosted (primary) con MCP nativo
|
||||
- 🔄 **SearXNG + DuckDuckGo** — fallback a cascata se Degoog non risponde
|
||||
- 🧠 **Google Gemini** — LLM per sintesi con citazioni inline [1], [2], ...
|
||||
- 🔍 **Degoog** — metasearch engine self-hosted (primary) con API nativa
|
||||
- 🔄 **SearXNG + DuckDuckGo** — fallback a cascata se il primary non risponde
|
||||
- 🌐 **Interfaccia web** — UI responsive, dark theme, mobile-first
|
||||
- 📡 **API REST** — endpoint per consumo programmatico e skill vocali (Alexa, Google Home)
|
||||
- 🔧 **MCP (Model Context Protocol)** — server stdio per agent AI esterni
|
||||
- 🖥️ **Flask web app** — interfaccia pulita e reattiva
|
||||
- 🗣️ **TTS-ready** — campo `speakable_text` ottimizzato per sintesi vocale
|
||||
|
||||
```
|
||||
Tu chiedi → Query expansion → Degoog search → Fetch pagine → Gemini sintesi → Risposta con fonti
|
||||
Tu chiedi → Query expansion → Ricerca multi-engine → Fetch pagine → Gemini sintesi → Risposta con fonti
|
||||
```
|
||||
|
||||
## Architettura
|
||||
---
|
||||
|
||||
```
|
||||
sibilla/
|
||||
├── src/sibilla/
|
||||
│ ├── app.py # Flask app factory + pipeline /api/ask
|
||||
│ ├── cli.py # Entry point server web
|
||||
│ ├── search.py # DegoogClient, SearXNGClient, DuckDuckGoClient, PageFetcher
|
||||
│ ├── ai.py # GeminiClient (sintesi + query rewriting)
|
||||
│ ├── mcp.py # MCP server su stdio (per agent AI esterni)
|
||||
│ └── prompts.py # System prompt stile Perplexity
|
||||
├── templates/
|
||||
│ └── index.html # Interfaccia di ricerca
|
||||
├── static/
|
||||
│ ├── style.css # Stili dark theme
|
||||
│ └── app.js # Logica frontend
|
||||
└── tests/
|
||||
```
|
||||
## 📚 Documentazione
|
||||
|
||||
## Pipeline di ricerca
|
||||
| Documento | Descrizione |
|
||||
|-----------|-------------|
|
||||
| [Architettura](docs/ARCHITECTURE.md) | 🏗️ Visione d'insieme, stack tecnologico, componenti, modello dati |
|
||||
| [Diagramma di Flusso](docs/FLOW.md) | 🔄 Pipeline di ricerca, flusso richieste, macchina a stati (Mermaid) |
|
||||
| [API REST](docs/API.md) | 📡 Documentazione completa degli endpoint `/api/ask` e `/api/v1/query` |
|
||||
| [Wiki](docs/WIKI.md) | 📚 FAQ, glossario, confronto con Perplexity, roadmap |
|
||||
| [Deployment](docs/DEPLOYMENT.md) | 🚀 Guida al deployment in produzione (Gunicorn, Nginx, Docker, systemd) |
|
||||
| [Contributing](docs/CONTRIBUTING.md) | 🤝 Guida per contribuire, convenzioni, test, struttura branch |
|
||||
|
||||
```
|
||||
POST /api/ask {query: "..."}
|
||||
│
|
||||
├─ 1. Gemini riscrive la query in 3 varianti (query expansion)
|
||||
├─ 2. Multi-query search: Degoog → SearXNG → DuckDuckGo (cascading)
|
||||
├─ 3. PageFetcher scarica il contenuto completo delle top pagine
|
||||
├─ 4. Prompt assembly con fonti numerate
|
||||
├─ 5. Gemini sintesi con citazioni [1], [2], ...
|
||||
└─ 6. JSON {answer, sources[], model, search_engine, tokens_used}
|
||||
```
|
||||
---
|
||||
|
||||
## Setup
|
||||
## 🚀 Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Clona e installa
|
||||
git clone https://github.com/tuo-user/sibilla.git
|
||||
cd sibilla
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# 2. Avvia Degoog (motore di ricerca primary, opzionale ma consigliato)
|
||||
docker run -d --name degoog -p 4444:4444 ghcr.io/degoog-org/degoog:latest
|
||||
|
||||
# 3. Configura
|
||||
# Crea un file .env con la tua Google API Key:
|
||||
# GOOGLE_API_KEY=la-tua-api-key
|
||||
|
||||
# 4. Avvia
|
||||
sibilla
|
||||
# → http://127.0.0.1:5000
|
||||
```
|
||||
|
||||
### Prerequisiti
|
||||
### Prerequisiti minimi
|
||||
|
||||
1. **Google API Key** — [https://aistudio.google.com/apikey](https://aistudio.google.com/apikey)
|
||||
2. **Degoog** (consigliato) — motore di ricerca primary:
|
||||
```bash
|
||||
docker run -d --name degoog -p 4444:4444 ghcr.io/degoog-org/degoog:latest
|
||||
```
|
||||
3. **SearXNG** (opzionale, fallback) — se vuoi un secondo motore di backup:
|
||||
```bash
|
||||
docker run -d -p 8080:8080 searxng/searxng
|
||||
```
|
||||
- **Python 3.10+**
|
||||
- **Google API Key** — [ottienila gratis](https://aistudio.google.com/apikey)
|
||||
- Almeno un motore di ricerca (Degoog, SearXNG, o DuckDuckGo automatico)
|
||||
|
||||
---
|
||||
|
||||
## 🔌 API
|
||||
|
||||
### Ricerca via API (per skill Alexa, bot, app)
|
||||
|
||||
```bash
|
||||
# GET — il più semplice
|
||||
curl "http://localhost:5000/api/v1/query?q=ultimo+film+sull%27Odissea"
|
||||
|
||||
# POST — per query lunghe
|
||||
curl -X POST http://localhost:5000/api/v1/query \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "quali sono i migliori ristoranti a Roma?"}'
|
||||
|
||||
# Estrai solo il testo 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'])"
|
||||
```
|
||||
|
||||
**Risposta:**
|
||||
```json
|
||||
{
|
||||
"query": "ultimo film sull'Odissea",
|
||||
"answer": "L'ultimo adattamento è **The Return** (2024)...",
|
||||
"speakable_text": "L'ultimo adattamento è The Return del 2024...",
|
||||
"sources": [{"index": 1, "title": "...", "url": "..."}],
|
||||
"model": "gemini-2.5-flash",
|
||||
"search_engine": "degoog",
|
||||
"tokens_used": 1847
|
||||
}
|
||||
```
|
||||
|
||||
> **Documentazione completa:** [`docs/API.md`](docs/API.md)
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architettura
|
||||
|
||||
```
|
||||
sibilla/
|
||||
├── docs/ # 📚 Documentazione
|
||||
│ ├── ARCHITECTURE.md # Architettura di sistema
|
||||
│ ├── FLOW.md # Diagramma di flusso (Mermaid)
|
||||
│ ├── API.md # Documentazione API REST
|
||||
│ ├── WIKI.md # Wiki + FAQ
|
||||
│ ├── DEPLOYMENT.md # Guida al deployment
|
||||
│ └── CONTRIBUTING.md # Guida alla contribuzione
|
||||
│
|
||||
├── src/sibilla/ # 📦 Codice sorgente
|
||||
│ ├── app.py # Flask app factory + pipeline condivisa
|
||||
│ ├── search.py # Degoog, SearXNG, DuckDuckGo, PageFetcher
|
||||
│ ├── ai.py # GeminiClient (sintesi + query rewriting)
|
||||
│ ├── markdown.py # Markdown → HTML + strip per TTS
|
||||
│ ├── prompts.py # System prompt stile Perplexity
|
||||
│ ├── mcp.py # MCP server stdio (per agent AI)
|
||||
│ └── cli.py # Entry point server
|
||||
│
|
||||
├── templates/index.html # Interfaccia web
|
||||
├── static/ # CSS, JS, favicon
|
||||
├── tests/ # Test (pytest, 109 test)
|
||||
└── pyproject.toml # Configurazione progetto
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Pipeline di Ricerca
|
||||
|
||||
```
|
||||
POST /api/ask {query: "..."}
|
||||
│
|
||||
├─ 1. 🔮 Gemini riscrive la query in 3 varianti (query expansion)
|
||||
├─ 2. 🔍 Multi-engine search: Degoog → SearXNG → DuckDuckGo (cascading)
|
||||
├─ 3. 📥 PageFetcher scarica il contenuto completo delle top pagine
|
||||
├─ 4. 📝 Prompt assembly con fonti numerate + data odierna
|
||||
├─ 5. 🧠 Gemini sintesi con citazioni inline [1], [2], ...
|
||||
└─ 6. ✅ JSON {answer, html_answer, speakable_text, sources[], metadata}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 MCP Server
|
||||
|
||||
Sibilla espone le sue capacità di ricerca come tool MCP (Model Context Protocol) su stdio:
|
||||
|
||||
```bash
|
||||
sibilla-mcp
|
||||
```
|
||||
|
||||
**Tool disponibili:**
|
||||
- `web_search(query, num_results)` — ricerca web con fallback Degoog → SearXNG → DuckDuckGo
|
||||
- `fetch_page(url)` — estrai contenuto testuale da una pagina web
|
||||
|
||||
Compatibile con client MCP come Claude Desktop, Gemini Desktop e altri agent AI.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Sviluppo
|
||||
|
||||
```bash
|
||||
# Installa dipendenze dev
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# Lint
|
||||
ruff check src tests
|
||||
|
||||
# Test
|
||||
pytest tests/ -v
|
||||
|
||||
# Coverage
|
||||
pip install pytest-cov
|
||||
pytest tests/ --cov=src/sibilla --cov-report=html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment
|
||||
|
||||
Per il deployment in produzione:
|
||||
|
||||
```bash
|
||||
# Con Gunicorn
|
||||
pip install gunicorn
|
||||
gunicorn -w 4 -b 0.0.0.0:5000 "sibilla.app:create_app()"
|
||||
|
||||
# Con Docker Compose (Sibilla + Degoog + SearXNG)
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
> **Guida completa:** [`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md)
|
||||
|
||||
---
|
||||
|
||||
## 📋 Configurazione
|
||||
|
||||
Crea un file `.env`:
|
||||
|
||||
```env
|
||||
GOOGLE_API_KEY=la-tua-api-key
|
||||
SECRET_KEY=una-chiave-segreta-lunga-e-casuale
|
||||
SIBILLA_HOST=127.0.0.1
|
||||
SIBILLA_PORT=5000
|
||||
SIBILLA_DEBUG=1
|
||||
DEGOOG_URL=http://localhost:4444
|
||||
SEARXNG_URL=http://localhost:8080
|
||||
SIBILLA_DDG_FALLBACK=1
|
||||
```
|
||||
|
||||
Senza Degoog, Sibilla userà automaticamente SearXNG e DuckDuckGo come fallback.
|
||||
---
|
||||
|
||||
## Uso
|
||||
## 🤝 Contribuire
|
||||
|
||||
```bash
|
||||
# Avvia la web app
|
||||
sibilla
|
||||
# → http://127.0.0.1:5000
|
||||
Contributi benvenuti! Vedi [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) per:
|
||||
|
||||
# Avvia il server MCP (per agent AI esterni)
|
||||
sibilla-mcp
|
||||
```
|
||||
- Setup dell'ambiente di sviluppo
|
||||
- Convenzioni di codice e commit
|
||||
- Come aggiungere search engine, endpoint, o tool MCP
|
||||
- Struttura dei test
|
||||
|
||||
## Sviluppo
|
||||
---
|
||||
|
||||
```bash
|
||||
pip install -e ".[dev,mcp]"
|
||||
ruff check src tests
|
||||
pytest
|
||||
```
|
||||
## 📄 Licenza
|
||||
|
||||
## Licenza
|
||||
MIT — vedi il file [LICENSE](LICENSE) per i dettagli.
|
||||
|
||||
MIT
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<sub>Fatto con 🔮 da Sibilla Team · <a href="docs/ARCHITECTURE.md">Architettura</a> · <a href="docs/API.md">API</a> · <a href="docs/DEPLOYMENT.md">Deployment</a></sub>
|
||||
</p>
|
||||
Reference in new issue
Block a user