RAG — Retrieval-Augmented Generation
Combinar busca semântica com geração de LLM para responder perguntas sobre sua própria base de dados.
Definição
RAG (Retrieval-Augmented Generation) resolve o problema de LLMs não saberem sobre dados privados ou recentes. Pipeline: 1) Ingest: dividir documentos em chunks, gerar embeddings, armazenar em vector DB. 2) Query: gerar embedding da pergunta, buscar chunks mais similares (cosine similarity), 3) Augment: inserir chunks no contexto do LLM junto com a pergunta. 4) Generate: LLM responde usando apenas o contexto fornecido.
Problema → Solução
Problema
LLM não sabe sobre sua documentação interna, base de conhecimento da empresa, ou dados após sua data de corte. Fine-tuning é caro e difícil. Passar todos os documentos no contexto é inviável (custo, limite de tokens).Solução
RAG: buscar apenas os N chunks mais relevantes para cada pergunta. Custo por query em vez de fine-tuning caro. Documentos atualizáveis sem retreinar. Citações rastreáveis (você sabe qual chunk gerou a resposta). Stack típico: LangChain/LlamaIndex + OpenAI embeddings + Pinecone/pgvector.Dica de entrevista
Tip
A qualidade do RAG depende 80% do chunking e do retrieval, não do LLM. Chunks muito grandes perdem precisão. Chunks muito pequenos perdem contexto. Testar diferentes estratégias: fixed-size, semantic, hierarchical. Hybrid search (vetorial + BM25 keyword) quase sempre supera só vetorial.Código
// RAG pipeline com LangChain + OpenAI + pgvector
import { OpenAIEmbeddings } from '@langchain/openai'
import { PGVectorStore } from '@langchain/community/vectorstores/pgvector'
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter'
// 1. INGEST — processar documentos
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000, // chars por chunk
chunkOverlap: 200, // overlap para não perder contexto
})
const chunks = await splitter.createDocuments([documentText])
const vectorStore = await PGVectorStore.fromDocuments(
chunks,
new OpenAIEmbeddings({ model: 'text-embedding-3-small' }),
{ postgresConnectionOptions: { connectionString: process.env.DB_URL } }
)
// 2. QUERY — buscar chunks relevantes
const retriever = vectorStore.asRetriever({ k: 5 }) // top 5 chunks
const relevantDocs = await retriever.invoke(userQuestion)
// 3. AUGMENT + GENERATE — LLM com contexto
const context = relevantDocs.map(d => d.pageContent).join('\n\n')
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'Responda APENAS com base no contexto fornecido. Se não souber, diga que não encontrou.' },
{ role: 'user', content: `Contexto:\n${context}\n\nPergunta: ${userQuestion}` }
]
})Perguntas de entrevista
Q.O que são embeddings e como funcionam no RAG?▾
A.Embeddings são representações vetoriais de texto em espaço de alta dimensão (1536 dims no ada-002). Textos semanticamente similares ficam próximos no espaço vetorial. A busca RAG encontra os K vetores mais próximos ao vetor da query (cosine similarity ou dot product). Modelo de embedding diferente do modelo de geração — pode usar text-embedding-3-small e GPT-4o juntos.
Q.Qual a diferença entre RAG e fine-tuning?▾
A.RAG: dados ficam fora do modelo, atualizáveis, rastreáveis, sem treinamento. Bom para: base de conhecimento dinâmica, documentos privados, citações. Fine-tuning: modifica os pesos do modelo com seus dados. Bom para: estilo de escrita, formato de resposta, domínio muito específico. Na prática: RAG para conhecimento, fine-tuning para comportamento/estilo.
Q.Como avaliar a qualidade de um RAG?▾
A.Métricas: Faithfulness (resposta é suportada pelos chunks recuperados?), Answer Relevancy (resposta responde a pergunta?), Context Recall (os chunks certos foram recuperados?). Tools: RAGAS, TruLens. O problema mais comum é retrieval falho — o LLM pode responder corretamente SE tiver o contexto certo, mas o retrieval buscou os chunks errados.
86/122← →