Chunking: semântico, hierárquico e por estrutura
Chunking é a decisão mais subestimada em projetos RAG. A maioria dos tutoriais usa "divida em chunks de 500 tokens com 50 de overlap" e segue em frente. Mas é aqui que 80% dos problemas de qualidade têm origem. Um chunk ruim gera um embedding ruim, que recupera o trecho errado, que leva o LLM a uma resposta errada ou vazia — e o culpado parece ser o modelo, não a estratégia de chunking.
Por que chunking ingênuo arruína o RAG
Chunking (ou fragmentação) é o processo de dividir documentos em pedaços menores antes de gerar embeddings e indexar no vector store. O objetivo é criar unidades de texto que sejam:
- Semanticamente coesas: cada chunk deve tratar de um único tópico ou responder a um tipo de pergunta.
- Completas o suficiente: devem conter contexto suficiente para que a resposta faça sentido isoladamente.
- Pequenas o suficiente: para não diluir o embedding com múltiplos tópicos não relacionados.
O chunking por tamanho fixo viola os três critérios com frequência. Considere um manual de procedimentos:
# Texto original (simplificado):
"...concluída a verificação de segurança (etapa 2.3), prossiga para a etapa 3.
3. PROCEDIMENTO DE REINICIALIZAÇÃO
3.1 Desligue o equipamento pressionando o botão vermelho por 5 segundos.
3.2 Aguarde 30 segundos antes de religar.
3.3 Ao religar, verifique o painel de status — indicadores verdes confirmam..."
# Chunking fixo de 100 tokens pode cortar assim:
Chunk A: "...concluída a verificação de segurança (etapa 2.3), prossiga para
a etapa 3. 3. PROCEDIMENTO DE REINICIALIZAÇÃO 3.1 Desligue o equipamento
pressionando o botão vermelho por 5 segundos. 3.2 Aguarde 30 segundos"
Chunk B: "antes de religar. 3.3 Ao religar, verifique o painel de status
— indicadores verdes confirmam..."
# Resultado: a pergunta "como verificar se o equipamento reiniciou com sucesso?"
# pode recuperar apenas o Chunk B, que não tem contexto sobre o que veio antes.
As 5 estratégias de chunking: comparação completa
| Estratégia | Tamanho típico | Overlap recomendado | Quando usar | Limitações |
|---|---|---|---|---|
| Fixo (por tokens/caracteres) | 256–512 tokens | 10–15% do chunk (25–75 tokens) | Corpus homogêneo, prototipagem rápida, documentos sem estrutura clara | Corta frases e cláusulas ao meio; desconsidera estrutura semântica; ruim para documentos heterogêneos |
| Por sentença | 1–5 sentenças (~100–300 tokens) | 1–2 sentenças de overlap | Textos narrativos, FAQs simples, artigos de blog, textos corridos sem estrutura hierárquica | Sentenças longas ou muito curtas criam chunks desequilibrados; problemas com listas e tabelas |
| Semântico | Variável (~200–800 tokens) | Baseado em similaridade, não tamanho fixo | Documentos com mudanças de tópico internas; textos de múltiplos assuntos; corpus misto | Custo computacional maior (requer modelo de embedding na etapa de chunking); chunks de tamanho muito variável complica indexação uniforme |
| Hierárquico (parent-child) | Pai: 512–2048 tokens / Filho: 128–256 tokens | Overlap no nível filho; pai usa fronteiras naturais (seção) | Manuais, contratos, documentos técnicos com estrutura de capítulos/seções; quando precisão de busca E contexto rico são necessários | Dobra o volume de chunks indexados; mais complexidade no pipeline de retrieval; requer metadado de parentesco |
| Por estrutura de documento | Variável (por unidade lógica: cláusula, seção, item de lista) | Contexto do título pai adicionado como prefixo | Documentos com estrutura formal definida (contratos, normas, especificações técnicas, documentação de API); Markdown; HTML estruturado | Requer parsing específico por tipo de documento; documentos sem estrutura explícita falham; mais trabalho de pré-processamento |
Chunking semântico: como funciona na prática
O chunking semântico detecta mudanças de tópico no texto usando embeddings, em vez de cortar por tamanho fixo. O algoritmo básico:
- Dividir o texto em sentenças.
- Gerar embedding para cada sentença (ou grupo de 3 sentenças — "janela deslizante").
- Calcular similaridade coseno entre sentenças adjacentes.
- Identificar "pontos de corte" onde a similaridade cai abaixo de um threshold (mudança de tópico).
- Criar chunks agrupando sentenças entre os pontos de corte.
# Exemplo conceitual com LangChain SemanticChunker
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai.embeddings import OpenAIEmbeddings
splitter = SemanticChunker(
embeddings=OpenAIEmbeddings(),
breakpoint_threshold_type="percentile", # ou "standard_deviation"
breakpoint_threshold_amount=95 # percentil 95 de dissimilaridade
)
chunks = splitter.create_documents([texto_completo])
# Resultado: chunks de tamanho variável, cada um tratando de um tópico coeso
O custo extra: gerar embeddings na etapa de chunking (não apenas na ingestão) aumenta o tempo e custo de processamento em ~30%. Para um corpus de 10.000 documentos, isso é geralmente aceitável.
Parent-child chunking: o melhor de dois mundos
O dilema clássico do chunk size: chunks pequenos têm embeddings mais precisos e são melhores para retrieval; chunks grandes fornecem mais contexto ao LLM para gerar respostas completas. Parent-child resolve isso usando ambos:
# Estrutura de parent-child
Documento: "Manual de Segurança — Capítulo 3: Procedimentos de Emergência"
CHUNK PAI (para contexto no LLM, ~1000 tokens):
"3. Procedimentos de Emergência
3.1 Em caso de incêndio, acione o alarme...
3.2 Evacue pelo corredor principal...
3.3 Ponto de encontro: estacionamento...
3.4 Nunca use elevadores durante a evacuação..."
CHUNKS FILHOS (para busca, ~100-150 tokens cada):
Filho 3.1: "Em caso de incêndio, acione o alarme vermelho no corredor..."
Filho 3.2: "Evacue pelo corredor principal em direção à saída norte..."
Filho 3.3: "O ponto de encontro para evacuação é o estacionamento..."
Filho 3.4: "Durante evacuação de emergência, nunca utilize os elevadores..."
# Na query: "onde fica o ponto de encontro de evacuação?"
# → Busca encontra: Filho 3.3 (alta similaridade)
# → Sistema envia ao LLM: CHUNK PAI (contexto completo)
# → LLM responde com contexto rico, não apenas a frase do filho
Metadata-aware chunking: o contexto que o chunk carrega
Além do texto, cada chunk pode carregar metadados contextuais que melhoram tanto o retrieval quanto a geração. Uma técnica poderosa é o "contextual retrieval" (popularizado pela Anthropic): adicionar ao início de cada chunk um resumo de onde ele está no documento.
# Chunk ingênuo:
"O prazo de pagamento é de 30 dias corridos após a emissão da nota fiscal."
# Chunk com prefixo contextual:
"[Contexto: Contrato de Fornecimento n.º 2024-0891, Cláusula 6 — Condições de Pagamento]
O prazo de pagamento é de 30 dias corridos após a emissão da nota fiscal."
O prefixo contextual custa tokens extras (20–50 tokens por chunk), mas melhora significativamente a qualidade do embedding e a precisão do retrieval — especialmente para perguntas que se referem ao documento ou seção pelo nome. Benchmarks da Anthropic mostram melhoria de 49% na taxa de recuperação de chunks relevantes com contextual retrieval.
Chunk size vs. qualidade do retrieval: o trade-off em números
Não existe resposta universal, mas existe uma framework de decisão:
- Chunks muito pequenos (< 100 tokens): embeddings de alta precisão, mas sem contexto suficiente para resposta. Úteis apenas como filhos em estratégia hierárquica.
- Chunks de 128–256 tokens: boa precisão de retrieval, respostas possíveis para perguntas simples. Problema: perguntas complexas precisam de múltiplos chunks para compor a resposta.
- Chunks de 512–1024 tokens: equilíbrio para a maioria dos casos. O modelo de embedding ainda captura o tema principal; o LLM tem contexto suficiente.
- Chunks de 2048+ tokens: embeddings menos precisos (o vetor "médio" perde especificidade); custo de contexto maior; usar apenas como chunks-pai em estratégia hierárquica.
Uma forma prática de calibrar: pegue 20 perguntas típicas do seu domínio, gere a resposta esperada e meça a quantidade de tokens necessária. O chunk size deve ser pelo menos 1,5× essa quantidade para garantir que a resposta esteja completa no chunk.
Chunking por estrutura de documento: o mais poderoso para conteúdo formal
Para documentos com estrutura explícita (contratos, normas, manuais estruturados, Markdown, HTML), o chunking por estrutura usa as fronteiras naturais do documento — títulos, cláusulas, itens de lista — em vez de critérios artificiais de tamanho ou similaridade.
# Para Markdown com estrutura de headers:
from langchain.text_splitter import MarkdownHeaderTextSplitter
headers_para_dividir = [
("#", "titulo"),
("##", "secao"),
("###", "subsecao"),
]
splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_para_dividir)
chunks = splitter.split_text(texto_markdown)
# Cada chunk contém automaticamente os metadados de hierarquia:
# chunk.metadata = {"titulo": "3. Procedimentos", "secao": "3.2 Evacuação"}
# Para contratos em texto plano, regex por cláusula:
import re
clausulas = re.split(r'\n(?=\d+\.\s+[A-Z])', texto_contrato)
# Divide em cada novo número de cláusula seguido de texto em maiúsculas
Qual estratégia escolher: guia de decisão
Use este fluxo de decisão:
- O documento tem estrutura formal (headers, cláusulas, seções numeradas)? → Chunking por estrutura de documento. Se sim e os chunks resultantes são grandes, adicione hierarquia (parent-child).
- O corpus é heterogêneo (documentos de tipos muito diferentes misturados)? → Chunking semântico, com estratégia específica por tipo se possível.
- As perguntas são simples e o corpus é homogêneo (ex.: FAQ, base de conhecimento)? → Chunking por sentença ou fixo com overlap adequado. Simples e eficiente.
- Você precisa de alta precisão de retrieval E respostas detalhadas? → Parent-child obrigatório.
- Está prototipando ou em POC? → Fixo com 512 tokens e 10% de overlap. Ajuste depois com métricas reais.
Independente da estratégia, valide com métricas objetivas. Veja como avaliar RAG com faithfulness e context recall para saber se sua estratégia de chunking está funcionando. E entenda como o retrieval usa os chunks em busca híbrida e reranking no RAG.
Para uma visão completa do que é RAG e como o chunking se encaixa no pipeline, veja o guia prático de RAG para empresas.