caucus.Documentazione
GitHubApri l'app
PanoramicaSelf-hostingCorpusTrust layerGuida ai moduliAPIBenchmarkFAQ
PanoramicaSelf-hostingCorpusTrust layerGuida ai moduliAPIBenchmarkFAQ

Self-hosting

Caucus è progettato per girare per intero sulla tua macchina o nel tuo studio: database, vector store, reranker e, volendo, anche i modelli di linguaggio. Questa pagina porta da zero a uno stack funzionante. Tempo stimato: 10–15 minuti con il pacchetto corpus, qualche ora se ricostruisci il corpus da zero.

Prerequisiti

  • Docker (con Docker Compose) per Postgres, Qdrant e Redis;
  • uv (gestore Python) e Python 3.12;
  • Node.js ≥ 20 e pnpm;
  • una chiave OpenAI per la generazione delle risposte (default; backend alternativi: Ollama e modelli locali, vedi Backend LLM). Con il pacchetto corpus non servono chiamate di embedding: paghi solo la generazione, centesimi per centinaia di domande.
  • Disco: ~8 GB liberi per il corpus completo (Postgres + Qdrant); 4 GB di RAM per i container sono sufficienti.

1. Clona e configura

git clone https://github.com/gral-digital/caucus && cd caucus
cp .env.example .env
# apri .env e imposta OPENAI_API_KEY=sk-...

Tutte le opzioni sono variabili d'ambiente documentate in .env.example: backend LLM ed embedding, device del reranker, rate limiting, autenticazione. I default vanno bene per un primo avvio locale.

2. Dipendenze e infrastruttura

make install     # dipendenze Python (uv) + Node (pnpm)
make up          # Postgres :55432, Qdrant :6333, Redis
make migrate     # schema del database (Alembic)

3. Il corpus: importa il pacchetto (consigliato)

La via rapida è importare il pacchetto corpus pubblicato con le release: contiene le tabelle Postgres già popolate e gli embedding Qdrant già calcolati. Un solo comando, nessuna chiamata API, nessun costo:

make corpus-import SRC=https://github.com/gral-digital/caucus/releases/download/corpus-20260801

Lo script scarica i file (con ripresa automatica se la connessione cade), verifica i checksum SHA-256, controlla che lo schema del database sia alla revisione giusta e ripristina tabelle e collection. Le tabelle utente non vengono toccate. Dettagli su contenuto e licenze del pacchetto: Corpus.

L'alternativa è ricostruire tutto dalle fonti pubbliche (Normattiva, EUR-Lex, SentenzeWeb):

make seed-all             # 50 fonti normative + 14 atti UE (~ centesimi di embedding)
make harvest-cassazione   # giurisprudenza, incrementale e resumabile (ore)

4. Avvia

make dev    # API su :8000, web su :3000

Apri http://localhost:3000/app. Al primo avvio il reranker locale (bge-reranker-v2-m3) scarica i pesi e si scalda in qualche secondo; le richieste successive non pagano questo costo.

Backend LLM ed embedding

Il backend di default è OpenAI (gpt-4o per la generazione, gpt-4.1-mini per l'espansione query, text-embedding-3-small per gli embedding). Sono intercambiabili via env:

  • LLM_BACKEND=ollama: modelli locali via Ollama, per un deployment senza alcuna dipendenza cloud;
  • EMBEDDING_BACKEND=local: embedding self-hosted (BGE-M3); nota che gli embedding del pacchetto corpus sono text-embedding-3-small: cambiando modello di embedding va rifatta l'indicizzazione vettoriale;
  • RERANKER_BACKEND=local (default) con RERANKER_DEVICE=mps|cuda|cpu; in assenza delle dipendenze il sistema degrada a un reranker keyword e lo segnala nei log: le prestazioni misurate valgono solo con il cross-encoder attivo.

La qualità dichiarata nel benchmark è misurata sulla configurazione di riferimento: se cambi modelli, rimisura con make eval prima di fidarti dei numeri.

Autenticazione e multiutenza

In self-hosting l'app è aperta di default (nessuna registrazione: i dati non lasciano la tua macchina). Per esporre l'istanza a più utenti puoi attivare gli account con ACCOUNTS_ENABLED=true: registrazione e login con password (Argon2id), sessioni con token salvato solo come hash, documenti caricati legati all'utente. Per API machine-to-machine c'è il token statico API_AUTH_TOKEN (obbligatorio fuori da APP_ENV=local: il server non parte senza).

Deploy del frontend su Vercel

Il frontend è un'app Next.js standard e si deploya su Vercel così com'è; l'API (FastAPI + Postgres + Qdrant + reranker) gira invece su un server tuo (VPS, Fly.io, Railway…). Configurazione:

  • Root Directory: apps/web (il repo è un monorepo pnpm; Vercel rileva Next e pnpm da solo);
  • Variabile d'ambiente: NEXT_PUBLIC_API_URL = URL pubblico della tua API (es. https://api.tuodominio.it). Le rewrite di Next proxano /api/v1/* verso quell'URL, quindi il browser parla solo col dominio del frontend;
  • lo streaming SSE attraversa il proxy senza buffering: la config Next disattiva già la compressione sulla rotta della chat. Se davanti all'API metti nginx, mantieni le esclusioni descritte sotto in Problemi comuni;
  • CORS: passando dal proxy Next non serve aprire l'API ad altre origini; se invece esponi l'API direttamente, configura CORS_ALLOW_ORIGINS con il dominio Vercel.

Problemi comuni

  • Porte occupate: Postgres è mappato su :55432 proprio per non collidere con un Postgres locale; Qdrant usa :6333.
  • «reranker_local_deps_missing_fallback_keyword» nei log: manca sentence-transformers nel venv; rilancia make install. Con il fallback keyword la qualità del retrieval cala sensibilmente.
  • Streaming che arriva «a blocchi»: se metti un reverse proxy davanti all'API, disattiva compressione e buffering su /api/v1/chat (l'API imposta già X-Accel-Buffering: no e Cache-Control: no-transform).
  • Import corpus rifiutato: il pacchetto dichiara la revisione di schema per cui è stato prodotto: esegui make migrate (o aggiorna il codice) e riprova.