- TD#8 hybrid.ts: rerank_strategy {always|when_top_k_gt|never} + threshold
(default skips rerank for top_k ≤ 15; chat tool uses threshold 10)
- O11 vision.ts + tools.ts: analyze_image_region tool — sharp-crops the
bbox, claude CLI reads the temp PNG via Read tool, Sonnet vision answers
- TD#12 /graph: SigmaGraph replaces ForceGraphCanvas; react-force-graph-2d
uninstalled (-37 transitive deps); force-graph-canvas.tsx deleted
- TD#27 messages/route.ts gatherContext slice sizes via CTX_* env vars
- TD#22 tests/rag/: golden.yaml (15 queries) + run.py (Recall@k + MRR +
negative-pass rate) + baseline.json + CI job in .forgejo/workflows/ci.yml
- docs/adrs/: ADR-001..005 published from systems-atelier deliverables
Verified live on disclosure.top: top_k=5 path skips rerank (6.7s embed-only,
was 12-15s with rerank); rerank=always still available on demand.
First RAG baseline: Recall@5 = 0.2083, MRR = 0.25, Negative pass = 1.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
56 lines
2.6 KiB
Markdown
56 lines
2.6 KiB
Markdown
---
|
|
adr: ADR-001
|
|
title: Embedding e reranker stack — manter BGE-M3 self-hosted CPU; tornar reranker opt-in; reavaliar GPU em 6 meses
|
|
status: accepted
|
|
date: 2026-05-23
|
|
deciders: sa-principal, sa-architecture-lead, sa-platform-lead
|
|
project: disclosure-bureau
|
|
---
|
|
|
|
## Context
|
|
|
|
A retrieval pipeline atual (BGE-M3 dense + BM25 + RRF + BGE-Reranker-v2-M3 cross-encoder) entrega `Recall@5` aceitavel para 20.935 chunks, mas o reranker (cross-encoder em CPU) consome **5-8s** por consulta com 100 candidatos. Esse e o **gargalo dominante de UX** no chat sincrono.
|
|
|
|
Alternativas conhecidas:
|
|
|
|
1. **Manter status quo**: CPU rerank sempre on.
|
|
2. **Skip rerank**: confiar so em RRF do RPC `hybrid_search_chunks`. Mais rapido, perde precisao em queries ambiguas.
|
|
3. **Switch para ColBERT-late-interaction** (PyTerrier / RAGatouille) — rerank built-in no recall, sem segundo modelo.
|
|
4. **GPU para reranker**: VPS com GPU pequena (Hetzner GPU-1: ~$20/mes). BGE-Reranker em GPU caem de 5-8s para <1s.
|
|
5. **External managed (Voyage, Cohere)**: viola politica "self-hosted by default".
|
|
|
|
## Decision
|
|
|
|
1. **Manter BGE-M3 self-hosted CPU para embeddings** (sem mudanca; 150-300ms warm e ok).
|
|
2. **Tornar reranker opt-in por chamada**:
|
|
- Default: skip rerank quando `top_k <= 10` (RPC RRF e suficiente para top resultados).
|
|
- Aplicar rerank quando `top_k > 10` OU explicit `rerank=1` no API.
|
|
3. **Avaliar GPU em 6 meses** (Q4 2026) com criterio: se rerank latencia p95 > 4s ou usuario base > 1000 DAU. Se ambos, provisionar GPU 1.
|
|
4. **ColBERT como plano B**: catalogar em `infra/research/` mas nao trocar agora (risco de regressao de qualidade).
|
|
5. **Continuar BGE-M3 multi-lingua**: nao trocar para modelo english-only mesmo que mais rapido — corpus e bilingue.
|
|
|
|
## Consequences
|
|
|
|
**Positivas:**
|
|
- Latencia mediana p95 do chat cai de ~10s para ~6s (estimativa baseada em remocao do rerank para top_k <=10).
|
|
- Custo continua $0/mes alem do VPS (sem GPU upgrade).
|
|
- Reranker continua disponivel para queries complexas (`top_k=20+`).
|
|
|
|
**Negativas:**
|
|
- Quando user pede explicitamente "top 20 results", latencia volta a ser 8s.
|
|
- Recall@5 pode cair marginalmente em queries muito ambiguas. Ver eval harness W2.
|
|
|
|
**Trade-off aceito:** UX media melhora; UX pior caso mantem. Eval harness do W2 vai pegar regressao real.
|
|
|
|
## Verification
|
|
|
|
- `tests/rag/golden.yaml` mede Recall@5 antes/depois.
|
|
- Sentry timing histogram `chat_query_latency_ms` p95 antes/depois.
|
|
- Manual smoke test: 5 queries cobrindo cada `top_k` bucket.
|
|
|
|
## References
|
|
|
|
- `infra/RETRIEVAL.md` (performance budget).
|
|
- `web/lib/retrieval/hybrid.ts` (codigo).
|
|
- BGE-M3 paper: arxiv:2402.03216.
|
|
- ColBERT-late-interaction: arxiv:2004.12832.
|