Recuperação Híbrida (Arquitetura RAG)
Clinical Corvus usa recuperação híbrida para suportar respostas com evidência: combina matching por palavra-chave (BM25) com recuperação semântica (vetorial) e aplica re-ranking para melhorar precisão em perguntas clínicas reais.
Arquitetura do Pipeline
┌─────────────────────────────────────────────────────────────────────┐
│ Document Ingestion │
│ PaddleOCR 3.x │ pdfplumber │ pypdf │
│ (OCR + layout detection → structured blocks with bboxes) │
└──────────────────────────────┬──────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Metadata & Chunking │
│ Unicode NFKC │ Layout heuristics │ Section summaries │
│ ~512-token chunks │ 64-token overlap │ Table extraction │
│ Role annotation (guideline, table_flat, checklist, procedure) │
│ Medical overlays (scores, units, concept tags) │
└──────────────────────────────┬──────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Indexação │
│ BM25 Index (Whoosh) │ Vector Index (Qdrant ou hashing local) │
│ Section vectors │ Chunk vectors │ Document store │
└──────────────────────────────┬──────────────────────────────────────┘
▼ (rehydration no startup)
┌─────────────────────────────────────────────────────────────────────┐
│ Busca Híbrida │
│ Query normalization │ Synonym expansion │ Abbreviation service │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ BM25 │ │ Vetorial │ │ HyDE │ (opcional) │
│ │ (Whoosh) │ │ (Qdrant) │ │ Expansion│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └──────────────┼──────────────┘ │
│ ▼ │
│ Alpha calibration (dinâmico para evitar overweight hashing) │
│ Normalized scoring │ Role weights │ Language boosts │
│ Section gating │ Metadata filtering │
│ ▼ │
│ MMR deduplication (cap per section/source/role) │
│ Cross-encoder reranking (SentenceTransformers, opcional) │
│ ▼ │
│ Result cache (OrderedDict com TTL) │
└──────────────────────────────┬──────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Síntese Citada │
│ Context packaging para LLM │
│ Citation anchors (docID::section::..., page spans) │
│ Deduplicação via CiteSource logic │
│ Evidence ledger (admitted/weak/contradictory/rejected) │
└─────────────────────────────────────────────────────────────────────┘
Pipeline Ponta a Ponta
1. Ingestão de Documentos
Cascade de parsers com fallback:
- PaddleOCR 3.x (padrão): OCR com detecção de layout para PDFs escaneados e imagens (PP-OCRv5)
- pdfplumber: extração estruturada de palavras e bounding boxes para PDFs born-digital
- pypdf: último recurso para extração de texto simples
Gate de segurança: dados estruturados extraídos por OCR entram no sistema como capture_draft (não como fatos confirmados). São persistidos apenas após confirmação explícita do clínico via POST /clipboard/{context_id}/confirm-facts.
2. Metadados e Chunking
- Unicode normalization (NFKC), remoção de NBSP/zero-width
- Layout heuristics para preservar estrutura
- Chunking hierárquico: summaries de seções + chunks de ~512 tokens com 64-token overlap
- Tabelas: raw (
role: table) e flattened (role: table_flat), com guideline_strength, evidence_quality, grade - Medical overlays: nomes de escores, unidades, concept tags
3. Indexação
Dois índices paralelos:
- BM25 (Whoosh): busca exata por palavras-chave
- Vetorial (Qdrant ou hashing local): busca semântica por similaridade
Metadados persistem em rag_indexed_documents registry. Rehydration no startup para sobreviver a restarts.
4. Busca Híbrida
Query Processing
- Normalização Unicode
- Expansão de abreviações médicas
- Sinônimos manuais para termos clínicos
- Opcional: HyDE (Hypothetical Document Embeddings) — gera resposta hipotética para ancorar busca semântica
Fusão de Resultados
- Alpha calibration: peso dinâmico entre BM25 e vetorial (evita overweight de hashing embeddings)
- Role-aware boosting: guideline bullets, tabelas, checklists priorizados sobre texto narrativo
- Evidence-aware boosting: recomendações de diretrizes com maior qualidade/grade recebem boost
- Language boosts: preferência por PT ou EN conforme contexto
Deduplicação e Reranking
- MMR (Maximal Marginal Relevance): diversifica resultados
- Caps: limite por seção, fonte e role
- Cross-encoder reranking: SentenceTransformers (quando disponível)
5. Síntese e Citação
- Context packaging: chunks organizados com metadados de proveniência
- Citation anchors: IDs canônicos (
docID::section::...,docID#p=12) - Deduplicação via CiteSource: normalização de fontes duplicadas
- Evidence ledger: registro de admissão/rejeição de cada evidência
Políticas de Busca por Tier
A pesquisa externa usa política de tiers:
| Tier | Fontes | Custo | Latência | Gatilho |
|---|---|---|---|---|
| 1 | Hybrid RAG local, PubMed, Europe PMC, OpenAlex | $0 | 1-3s | Default |
| 2 | SearXNG (auto-hospedado) | $0 | 2-5s | Tier 1 insuficiente |
| 3 | APIs pagas (Brave, etc.) | Variável | 1-2s | Opt-in explícito |
Cache e Performance
- Result cache:
OrderedDictcom TTL para queries repetidas - Compass cache: cache de loop de raciocínio
- Metrics: expostas via
/api/agents/health
Observabilidade
- Parâmetros de busca logados com hash de query
- Métricas de retrieval (latência, hit rate, cache hit rate)
- Audit trail de todas as decisões de admissão/rejeição de evidência