RAG do começo ao fim: Input, Retriever e Generator explicados
Um overview denso sobre RAG (Retrieval-Augmented Generation): o que é, por que importa, o significado de Retrieval, Augmented e Generation, o pipeline de ingestão offline, o fluxo de consulta online, embeddings, similaridade por cosseno, HNSW e chunking.

🧪 Versão interativa: este post tem animações em Canvas embutidas — fluxo RAG, chunking, similaridade por cosseno e HNSW. Brinca com elas no meio do texto. Ou abra o lab em tela cheia.
LLMs escrevem bem. Mas quando você pergunta sobre o seu PDF interno, a política de reembolso da sua loja ou algo que aconteceu depois do período em que o modelo foi treinado, eles fazem uma de duas coisas:
- dizem que não sabem;
- inventam uma resposta convincente, com cara de verdade — alucinação.
O RAG (Retrieval-Augmented Generation) existe pra resolver isso. Não substitui o LLM, complementa: adiciona uma etapa de busca antes da geração, pra que o modelo responda consultando evidência real em vez de só "lembrar" do treino.
Esse post é um overview denso do RAG do começo ao fim — o que é, por que importa, o que significa cada letra do nome, a arquitetura mínima, o pipeline de ingestão offline, o fluxo de consulta online, e os conceitos que sustentam tudo (embeddings, similaridade por cosseno, HNSW, chunking).
A frase de uma linha
RAG = recuperar trechos de evidência relevantes de um corpus + entregá-los ao LLM como contexto pra ele escrever a resposta.
Tudo o que vem a seguir é detalhe técnico em cima dessa frase.
O que significam o R, o A e o G
O nome é literal: cada letra corresponde a uma responsabilidade do fluxo.
Busca os trechos de evidência mais relevantes em uma base externa: documentos, páginas, tickets, PDFs, base interna.
Anexa esses trechos ao prompt para que o modelo tenha evidência disponível antes de responder.
O LLM escreve a resposta final usando a pergunta do usuário mais o contexto recuperado.
Sem o R, o modelo responde só com o que já estava no treino ou no prompt. Sem o A, a busca não vira contexto útil para o LLM. Sem o G, você tem documentos relevantes, mas ainda não tem uma resposta sintetizada.
Por que RAG existe — o problema que cada metade não resolve sozinha
LLM puro tem dois limites duros:
- Sabe só o que viu no treino. Não tem acesso a documentos privados, dados recentes ou base interna da sua empresa. O que veio depois do treinamento fica fora da memória do modelo.
- Preenche lacunas quando falta contexto. Se a resposta depende de uma informação que não está no prompt nem foi vista no treino, o modelo ainda tenta produzir uma resposta coerente. O problema é que coerente não significa verdadeiro.
Sistema de retrieval puro (tipo busca clássica) tem o limite oposto:
- Acha trechos relevantes, mas não escreve uma resposta coerente em linguagem natural. Devolve a lista de documentos e deixa o usuário interpretar.
RAG junta os dois:
- + escreve texto fluido
- - preenche lacunas
- - não vê dados privados
- + encontra conteúdo
- - não sintetiza
- - devolve lista crua
busca evidência primeiro, depois gera uma resposta contextualizada
A arquitetura mínima: 3 componentes
Em sua forma mais simples, RAG tem três peças:
- Input Query — a pergunta do usuário.
- Retriever — o mecanismo que busca os chunks de evidência mais relevantes pra essa pergunta.
- Generator — o LLM que recebe pergunta + chunks recuperados e escreve a resposta final.
Esse modelo mental cabe num post-it. O resto do artigo é zoom em cada peça.
O fluxo real tem dois pipelines
Na prática RAG não é um pipeline só, são dois:
- Ingestão (offline) — roda uma vez (ou sempre que a base de conhecimento muda). Transforma documentos brutos em vetores indexados.
- Consulta (online) — roda a cada pergunta. Pega a query, busca no índice, monta o prompt, chama o LLM.
Antes de mergulhar nas etapas em detalhe, brinca com o pipeline ao vivo: clica em Disparar pergunta e segue as partículas. Depois avance pelas abas na ordem do fluxo: Chunking mostra a preparação do texto; Similaridade 2D mostra como a busca mede proximidade; HNSW mostra como o vector DB encontra vizinhos rápido.
Em cima (magenta) o pipeline offline que prepara o Qdrant. Embaixo (ciano) o pipeline online que roda a cada pergunta. O Qdrant no meio é compartilhado.
Daqui pra frente, cada etapa em detalhe.
Passo a passo do fluxo RAG
Ingestão (offline · feita uma vez)
1. Text Loader · carrega os documentos
Cada fonte vira texto puro antes de qualquer coisa. O loader certo depende do formato:
| Fonte | Como vira texto |
|---|---|
| Extração de texto + estrutura (loaders como Docling) | |
| HTML | Stripping de tags, scripts e nav |
| Word / Excel | Parser específico (mantém tabelas e estilos) |
| Vídeo | Áudio → transcrição via Whisper |
| Imagem | OCR ou modelo visão→descrição |
- Input: arquivos brutos.
- Output: string de texto unificada (idealmente em Markdown estruturado).
- Por que importa: é a porta de entrada. Loader ruim contamina tudo. Tabela vira sopa de letras, imagem dentro do PDF é ignorada, cabeçalho some, ordem de leitura inverte. O resto do pipeline herda esse ruído.
Posts irmãos: Markdown como lingua franca dos LLMs explica por que exportar pra Markdown bem feito tem efeito mensurável em compreensão e em retrieval.
2. Splitter · quebra o texto em chunks
Documento inteiro não serve pra busca por dois motivos:
- Embedding de documento inteiro vira uma média que não representa nada bem. Um PDF de 100 páginas tem 30 tópicos; o vetor médio é ruído.
- Janela de contexto do LLM é finita. Não dá pra enfiar 300 páginas no prompt.
O splitter divide o texto em pedaços menores — chunks — e anexa metadados (título, página, autor, capítulo, data).
Três estratégias principais
| Estratégia | Como funciona | Quando usa |
|---|---|---|
| Fixed-size | Corta a cada N caracteres/tokens. Rápido e burro. Quebra parágrafos no meio. | Prototipagem, corpus já meio normalizado. |
| Recursive | Tenta separadores naturais — primeiro \n\n, depois \n, depois . — até caber no limite. | Default sensato. É o que LangChain usa por padrão. |
| Hybrid / Structure-aware | Respeita estrutura do documento (headers Markdown, listas, tabelas) + limite máximo de tokens. | Conteúdo bem estruturado. É o ideal pra RAG sério. |
A qualidade do chunking aparece nas bordas:
- Corte limpo: termina no fim de uma frase ou seção. O chunk vira uma unidade semântica coerente.
- Corte ruim: parte uma frase ao meio, separa título do conteúdo, divide a tabela. O embedding fica incoerente, a busca volta lixo.
Overlap (sobreposição)
Chunks costumam ser criados com overlap (ex.: 50 tokens compartilhados entre vizinhos). Isso evita perder contexto quando uma ideia atravessa a fronteira: se um conceito começa no fim do chunk A e termina no início do B, com overlap os dois carregam a informação ponte.
- Input: texto longo.
- Output: lista de chunks (~300–1000 tokens cada) + metadados por chunk.
3. Embedding Model · transforma cada chunk em vetor
Cada chunk passa por um modelo de embeddings. O modelo tokeniza o texto, processa, e devolve um vetor — uma lista fixa de números — que captura o significado semântico do chunk.
“Thiago Marinho é Senior AI Engineer.”
Modelos comuns
| Modelo | Dimensões | Observações |
|---|---|---|
text-embedding-3-small (OpenAI) | 1536 | Barato, bom default. |
text-embedding-3-large (OpenAI) | 3072 | Mais preciso, mais caro. |
all-MiniLM-L6-v2 (open-source) | 384 | Roda local, leve, surpreendentemente bom. |
BAAI/bge-m3 | 1024 | Forte em multilíngue / PT-BR. |
A intuição central
Embedding transforma texto num ponto num espaço matemático. Textos com significado parecido caem perto, mesmo sem compartilhar letras:
- "carro" e "automóvel" ficam próximos;
- "gato" e "felino" ficam próximos;
- "carro" e "presidente" ficam longe.
É isso que viabiliza busca semântica (encontrar por significado) em vez de só busca por keyword (casar palavra exata).
Pegadinha crucial
Modelos diferentes vivem em espaços vetoriais diferentes. Um embedding gerado pelo OpenAI text-embedding-3-small não é comparável com um gerado pelo MiniLM. Se você trocar o modelo de embeddings, precisa reindexar todo o corpus. Não tem atalho.
4. Vector Database · indexa os vetores
Os vetores entram numa collection de um vector database — Qdrant, Pinecone, Weaviate, pgvector, Milvus — junto com o texto original e os metadados:
{
id: "chunk_42",
vetor: [0.12, -0.34, ..., 0.05], // 1536 dims
texto_original: "Thiago Marinho é ...",
metadados: { titulo, página, autor, data }
}O problema que o vector DB resolve
Comparar uma query contra 1 milhão de vetores com um for linear levaria segundos por busca. Inviável.
A solução é busca aproximada (ANN — Approximate Nearest Neighbors). O algoritmo mais usado é o HNSW (Hierarchical Navigable Small World).
HNSW em uma frase
HNSW replica o espaço de vetores em várias camadas: a do topo tem poucos nós (saltos longos), a base tem todos. Você desce camada a camada fazendo greedy descent até cair no vizinho mais próximo.
Layer 0 (topo · esparso)
● ● ●
\ /
\ /
Layer 1
● ● ● ● ● ● ●
\ / \ /
\ / \/
Layer 2
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
↑
query
Layer 3 (base · denso, contém todos)
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●Por que é rápido: a camada esparsa cobre grandes distâncias em poucos saltos. Só na camada densa existe muito vizinho — e aí você já está perto do alvo. Resultado: tempo sub-linear em vez de linear.
Fim do pipeline de ingestão. O sistema agora é stateful — pode responder offline sem reprocessar nada.
Consulta (online · a cada pergunta)
A cada pergunta, sete passos.
A. Usuário faz uma pergunta
Ponto de entrada. Pode vir de chat, API, formulário, voz transcrita por Whisper. Não importa: tudo a seguir é orientado a respondê-la.
B. A pergunta vira texto
String literal da query — exatamente o que o usuário escreveu, já sem ruído de interface. Nenhuma transformação semântica aconteceu ainda.
"Quem é Thiago Marinho?"No RAG mínimo, essa query segue quase literal para o embedding. Em sistemas mais avançados, essa etapa pode aplicar query rewriting, HyDE (gerar uma resposta hipotética antes de embeddar) ou multi-query (gerar variações da pergunta e buscar com todas).
C. Embedding da pergunta
A query passa pelo mesmo modelo de embeddings usado na ingestão. Isso é crítico:
Regra de ouro: query e chunks precisam viver no mesmo espaço vetorial pra serem comparáveis. Mesmo modelo na ingestão e na consulta. Sem exceção.
"Quem é Thiago Marinho?" ──▶ Embedding Model ──▶ [0.27, -0.06, 0.27, ...]
(mesmo da ingestão) vetor de 1536 dimsD. Similarity Search no Vector DB
O vector DB compara o vetor da query com os vetores indexados via similaridade por cosseno (ou produto interno, ou distância euclidiana) e devolve os top-K chunks com maior score.
Similaridade por cosseno — fórmula e intuição
A · B
cos(θ) = ────────────────────
||A|| · ||B||
cos(θ) ∈ [-1, 1]
1 → mesmo sentido (significado idêntico)
0 → ortogonal (sem relação)
-1 → sentido opostoA medida é o ângulo entre os vetores, não a distância. Magnitude não importa — só direção.
Visualização 2D simplificada (em embeddings reais, são 384–3072 dimensões; o princípio é o mesmo):
A "gato"
↗
/
/ θ ← ângulo pequeno = significado próximo
/ ↘
/ B "felino"
/↗
/
●─────────────────────────▶
origem
cos(θ) ≈ 0.97 → muito similarTop-K — quantos chunks pegar
- Top-K típico: 3 a 10.
- K muito alto: polui o contexto, "lost in the middle", custo de token alto.
- K muito baixo: pode perder evidência crítica.
Variações importantes
| Técnica | O que faz |
|---|---|
| Busca híbrida | Combina similaridade vetorial (semântica) com BM25 (keyword). Cobre os pontos cegos de cada um. |
| Filtros por metadados | WHERE autor = "Thiago" AND ano >= 2024. Reduz o espaço de busca antes da busca por similaridade. |
| Reranking | Recupera top-50 por similaridade (barato), passa por um cross-encoder (caro, mais preciso), fica com top-3. |
O top-K é o teto da resposta. Recall ruim aqui = resposta ruim, e o LLM não compensa. Se o chunk certo não veio, o modelo não tem como inventar a verdade.
E. Prompt montado
O prompt final junta três coisas:
System: Você é um chatbot. Responda à pergunta a seguir
utilizando APENAS as informações do contexto.
Se a resposta não estiver no contexto, diga que
não sabe. Cite o chunk usado.
Pergunta: Quem é Thiago Marinho?
Contexto:
[Chunk 1] Thiago Marinho é Senior AI Engineer...
[Chunk 2] ...atua criando produtos e sistemas com IA...
[Chunk 3] ...escreve sobre agentes de IA, RAG e engenharia de produto...Três decisões que importam
- Instrução "use apenas o contexto" — força ancoragem nos chunks, reduz alucinação. Sem isso, o LLM mistura memória do treino com contexto recuperado e você perde controle sobre a fonte.
- Ordem dos chunks — LLMs prestam mais atenção no início e no fim do contexto (fenômeno lost in the middle). Coloque o chunk com maior score em um desses extremos.
- Peça citação —
[Chunk 1],[Chunk 2]. Resposta com citação é resposta auditável.
F. LLM gera a resposta
O modelo de geração (GPT-4, Claude, Llama 3, Mistral, …) recebe o prompt completo e produz a resposta — agora ancorada nos chunks reais, não em memória implícita.
Configuração comum
temperature = 0— em RAG quase sempre. Resposta determinística, fiel ao contexto. Temperatura alta vira "criatividade", que é o oposto do que se quer num sistema de Q&A factual.max_tokens— limite generoso o suficiente pra resposta completa, baixo o suficiente pra não inflar a conta.
O ganho aqui não é o LLM ficar "mais inteligente" — é ele ter evidência concreta na mão. Em vez de responder de memória, responde consultando o livro.
G. Resposta entregue ao usuário
A saída do LLM volta pra interface — idealmente com citações dos chunks usados. Isso permite que o usuário:
- verifique a fonte;
- confira se a resposta é fiel ao texto recuperado;
- abra o documento original e leia mais contexto.
Resposta sem fonte é só "outro chatbot". Resposta com link pra trecho exato é um sistema auditável.
Por que esse fluxo reduz alucinação
Sem RAG:
- o modelo responde com base no treino;
- se a pergunta sai do que ele "lembra", ele completa com o que parece plausível;
- não há fonte; não há como auditar.
Com RAG:
- a pergunta dispara uma busca na base de conhecimento;
- os trechos recuperados entram no prompt como evidência;
- a instrução do system prompt obriga ancoragem nessa evidência;
- a resposta deixa de ser "memória implícita" e vira "leitura guiada".
O LLM continua escrevendo. Só que agora com o livro aberto na mesa.
SEM RAG:
pergunta ──▶ LLM ──▶ resposta (memória do treino)
⚠ pode alucinar
COM RAG:
pergunta ──▶ retriever ──▶ chunks ──▶ LLM ──▶ resposta
(evidência ancorada)
✓ rastreável até a fonteQuando NÃO usar RAG
RAG não é a resposta pra tudo. Quatro cenários onde ele é overkill ou errado:
| Cenário | Solução melhor |
|---|---|
| Conteúdo cabe inteiro no contexto do LLM | Joga tudo no prompt direto. |
| Pergunta exige raciocínio sobre todo o corpus | RAG vê pedaços, não o todo. Use map-reduce ou agentes. |
| Conhecimento muito estruturado e tipado | SQL + function calling > RAG. |
| Resposta precisa ser determinística e auditável 100% | Lookup tabular puro > LLM. |
E mesmo onde RAG faz sentido, ele vem em camadas: o "RAG simples" deste post é o começo. Em produção você acaba adicionando reranking, busca híbrida, filtros por metadados, query rewriting, self-query, agentes que iteram buscas. Cada camada custa latência e complexidade — só adicione quando a métrica pedir.
Recap — o mapa em uma página
INGESTÃO (offline · 1 vez)
─────────────────────────────────────────────────────
1. Text Loader fontes brutas → texto limpo
2. Splitter texto longo → chunks + meta
3. Embedding cada chunk → vetor [1536]
4. Vector DB vetores + meta → índice HNSW
CONSULTA (online · cada pergunta)
─────────────────────────────────────────────────────
A. Pergunta chat/API/voz → string
B. Query texto "Quem é X?" → string literal
C. Embedding mesmo modelo da ingestão → vetor query
D. Similarity similaridade no HNSW → top-K chunks
E. Prompt system + query + chunks → prompt final
F. LLM prompt → resposta gerada
G. Entrega resposta + citações → usuárioEsse é o RAG mínimo viável. Tudo o que se discute em RAG avançado — chunking semântico, multi-query, HyDE, reranking, agentes — é refinamento de uma dessas onze etapas, não substituição do esqueleto.
O que vem depois
Esse post é overview. Em posts seguintes do mesmo módulo de estudos vou aprofundar separadamente:
- Chunking — fixed vs. recursive vs. hybrid, overlap, header-aware, e como medir;
- Embeddings — escolha de modelo, dimensionalidade, multilíngue, custo vs. precisão;
- Vector DBs e HNSW — parâmetros (
M,ef_construction,ef_search), trade-offs latência × recall; - Retriever avançado — busca híbrida, reranking, filtros por metadados;
- Prompt do generator — system prompt, ordem de contexto, citação, anti-alucinação.
A intuição central, no entanto, já está aqui: RAG não substitui o LLM. Dá um livro pro modelo consultar antes de responder. É a diferença entre "respondi de cabeça" e "respondi com a fonte na mão". E em sistemas de informação, isso é tudo.
22 de maio de 2026 · Brazil