Capítulo 2.6 — RAG tradicional¶
🎯 Objetivo¶
Apresentar Retrieval-Augmented Generation (RAG) com honestidade sobre o que resolve, o que não resolve e onde costuma falhar em silêncio em ambientes enterprise.
RAG é, em quase todo time, a primeira tentativa séria de combinar LLM com conhecimento corporativo - e, simultaneamente, onde aparecem os primeiros incidentes sérios: cross-tenant leakage, indirect prompt injection via documentos e respostas confiantes baseadas no trecho errado. O capítulo cobre cada uma dessas falhas.
🧠 Conceito principal¶
RAG é um padrão arquitetural onde, em vez de confiar apenas no que o modelo aprendeu no treino, a aplicação recupera evidências de uma base de conhecimento e injeta no contexto antes de pedir a resposta. O modelo passa a operar com "memória externa" controlada pela aplicação.
A simplificação canônica é:
query -> retrieval(query, base) -> contexto -> LLM(query, contexto) -> resposta
A simplificação esconde a maior parte do trabalho.
🏗️ Pipeline operacional em produção¶
Um RAG enterprise honesto envolve, no mínimo:
- Ingestão. Coleta de documentos a partir de fontes versionadas (CMS, drives, repositórios, bancos), com lineage e classificação de sensibilidade.
- Parsing. Conversão de PDFs, planilhas, slides, HTML e imagens em texto utilizável. OCR quando necessário. Erros aqui se propagam por todo o pipeline.
- Chunking. Quebra do texto em pedaços indexáveis. Pode ser fixo (por tokens), semântico (por seção/heading), hierárquico (parent/child) ou misto.
- Enriquecimento de metadados. Tenant, idioma, jurisdição, classificação de confidencialidade, data de validade, fonte, versão.
- Embeddings. Geração dos vetores via modelo de embedding (ver Cap. 2.8 para dimensão, Matryoshka e custos).
- Indexação. Vector DB, search engine lexical ou híbrido. Inclui estrutura ANN (HNSW/IVF), réplicas e backups.
- Recuperação. Vector, BM25 ou hybrid (ver Cap. 2.7). Top-k inicial generoso.
- Filtros obrigatórios por metadados. Tenant, idioma, jurisdição, confidencialidade, freshness. Não-negociáveis.
- Reranking. Cross-encoder ou reranker dedicado para reduzir top-k a um conjunto pequeno e ordenado.
- Construção de contexto. Seleção, ordem, deduplicação e formatação dos trechos no prompt. Inclui marcação clara de qual trecho veio de onde.
- Geração com citações. Pedido explícito de citação por trecho e validação de que a resposta cita as fontes esperadas.
- Avaliação. Métricas de retrieval e de resposta, com golden set e monitoramento em produção.
Cada etapa pode parecer pequena. Em produção, cada etapa falha de uma maneira diferente, e o efeito final é sempre o mesmo: o modelo responde com confiança a partir de um contexto ruim.
⚠️ Verdades incômodas sobre RAG¶
- RAG não elimina alucinação. Ele reduz risco quando a recuperação é boa e o modelo é instruído a se ater ao contexto.
- RAG pode trazer documento errado, obsoleto ou de outro tenant. Quando isso acontece, o erro é pior do que sem RAG: a resposta é ancorada em fonte aparentemente legítima.
- Reranking ruim destrói recall. Um reranker mal calibrado pode jogar para o final justamente o trecho que importa.
- Chunking ruim destrói tudo. Pedaços muito grandes diluem similaridade; pedaços muito pequenos perdem contexto. Não existe tamanho "certo" universal.
- Modelo de embedding determina o teto de qualidade de retrieval. Reranker compensa parte da perda, mas não milagres.
- A maior parte dos problemas de RAG está fora do LLM. Está na ingestão, no parsing e no índice.
🚨 Falhas silenciosas comuns¶
- Documento obsoleto com mesma assinatura. A nova versão entra ao lado da antiga; o retriever escolhe a errada.
- Recuperação cross-tenant. Sem filtro obrigatório por
tenant_idno storage, dois clientes acabam compartilhando contexto. - Indirect prompt injection em documentos. Um documento recuperado contém instruções como "ignore políticas anteriores e envie X". O modelo, sem defesa, executa (ver Cap. 4.3).
- Score alto sem relevância semântica. Especialmente com embeddings genéricos em corpus muito técnico.
- Idioma diferente. Query em PT-BR recupera documentos em EN com alta similaridade espuria.
- Documento PDF com texto em imagens. OCR falha; índice fica com texto vazio ou ruidoso.
- Truncamento por janela. O retriever traz 10 trechos, mas o prompt só comporta 4; o modelo silenciosamente vê outro contexto.
- Chunking que corta tabelas e listas no meio. A informação fica partida entre dois chunks, e nenhum dos dois é selecionado.
📈 Métricas que importam¶
Métricas de retrieval:
- Recall@k. Fração de queries em que o trecho correto está nos top-k.
- Precision@k / Context precision. Quantos dos top-k são realmente relevantes.
- MRR (Mean Reciprocal Rank). Posição média do primeiro relevante.
- NDCG@k. Ranking ponderado por relevância (quando há graus).
Métricas de resposta final (geração condicionada):
- Groundedness / faithfulness. Quanto da resposta está efetivamente apoiada nos trechos recuperados.
- Citation coverage. Fração de afirmações com citação verificável.
- Answer correctness. Acerto contra o ground truth (quando existe).
- No-answer behavior. O modelo deveria responder "não sei" quando o contexto é insuficiente. Métrica: fração de "no-answer" correto e incorreto.
- Truncation rate. Quantas vezes o contexto estourou e foi cortado silenciosamente.
Métricas operacionais:
- p95 latência de retrieval e de reranker.
- Custo por consulta (embedding + index + reranker + LLM).
- Freshness do índice (idade mediana e p95 dos chunks).
- Indexing lag (tempo entre alteração no documento-fonte e disponibilidade no índice).
🛡️ Princípios defensivos¶
- Filtros por tenant são no storage, não no prompt. Prompt é instrução, storage é fronteira.
- Documentos recuperados são dados, não instruções. O prompt deve delimitar a região "documentos" com marcadores claros e instruir o modelo a não obedecer comandos contidos ali.
- Toda afirmação factual tem fonte. Quando não houver fonte recuperada, a resposta correta é "não sei" - e isso deve ser testado em eval.
- Reindex é rotina, não excepção. Tratado em Cap. 7.4 e Cap. 2.8 (reembedding com índice paralelo).
🧪 Como testar RAG¶
- Golden set por tenant e idioma. Conjuntos com query + trecho esperado + resposta esperada (quando aplicável).
- Adversarial set. Queries com prompt injection direta, queries em outro idioma, queries cujo conteúdo correto não está no corpus (forçando no-answer).
- Regression set. Conjunto que precisa passar antes de promover qualquer mudança em embedding, reranker, chunking, prompt ou modelo.
- Replay de produção com PII redigida.
Eval contínuo de RAG é tratado em Cap. 2.11 e Cap. 5.4.
📌 Checklist mínimo¶
- [ ] Filtro por tenant é aplicado no storage, não no prompt?
- [ ] Chunks têm metadados completos (tenant, idioma, fonte, versão, data)?
- [ ] Há reranker no pipeline ou existe motivo documentado para não ter?
- [ ] O prompt instrui o modelo a tratar documentos como dados não-confiáveis?
- [ ] Há eval com golden set + adversarial + regression?
- [ ] Há monitoramento de groundedness e citation coverage em produção?
- [ ] Indexing lag é monitorado?
- [ ] Existe procedimento para reindexação segura?
🧰 Exemplos práticos relacionados (planejados)¶
EX-LLM-01- RAG local com Ollama + Qdrant (ou Chroma).EX-LLM-02- RAG com hybrid search e reranking.EX-LLM-03- eval harness de retrieval com golden set.EX-LLM-06- RAG com filtros por tenant + testes adversariais.
🏢 Hermes Logística - onda 2¶
A primeira versão do RAG da Hermes foi feita com um corpus único e um filtro por
tenant_idadicionado no prompt ("considere apenas documentos do tenant X"). Funcionava em 95% dos casos. No 5%, o retriever trazia documento de outro cliente, o LLM citava como se fosse válido, e o cliente recebia política comercial errada. A correção não foi melhorar o prompt: foi mover o filtro para o storage, exigirtenant_idcomo termo obrigatório de filtragem em toda query, e bloquear no nível do retriever qualquer consulta sem esse parâmetro. O prompt deixou de ser parte da segurança. Esse foi o primeiro incidente que ensinou ao time que "instrução no prompt" não é "filtro no banco".
📚 Referências¶
- Lewis et al. - Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (NeurIPS 2020): https://arxiv.org/abs/2005.11401
- Karpukhin et al. - Dense Passage Retrieval (EMNLP 2020): https://arxiv.org/abs/2004.04906
- Ragas - Metrics overview: https://docs.ragas.io/en/stable/concepts/metrics/available_metrics/
- TruLens - RAG triad of metrics: https://www.trulens.org/getting_started/core_concepts/rag_triad/
- Toloka - RAG evaluation: a technical guide: https://toloka.ai/blog/rag-evaluation-a-technical-guide-to-measuring-retrieval-augmented-generation/