Ingestão e Segmentação (Chunking)
Visão geral
“Ingestão (ingestion) e fragmentação (chunking)” é a primeira metade da maioria dos sistemas de recuperação (retrieval): transformar documentos brutos (PDFs, páginas HTML, tickets, e-mails, páginas wiki, código, imagens) em unidades pesquisáveis com o texto, a estrutura e os metadados (metadata) corretos. Em sistemas de Geração Aumentada por Recuperação (RAG), essas unidades normalmente são convertidas em vetores de incorporação (embeddings) e armazenadas em um índice vetorial (vector index), às vezes junto com um índice esparso (sparse index) (por exemplo, BM25) para Busca Híbrida (Esparsa + Densa) (Hybrid Search (Sparse + Dense)).
Um pipeline de recuperação (retrieval pipeline) de alto desempenho geralmente depende mais da qualidade de ingestão do que de qualquer escolha individual de modelo. Se o parsing de documentos (document parsing) for frágil, se os limites dos fragmentos forem ruins, ou se faltarem metadados, etapas posteriores como Reranqueamento (Reranking) e a síntese de respostas terão menos material para trabalhar — levando a alucinações (hallucinations), citações ausentes ou falha ao recuperar as evidências certas.
Este artigo aborda:
- Parsing de documentos e extração de texto (text extraction) (incluindo layout e reconhecimento óptico de caracteres (OCR))
- Estratégias de fragmentação e seus trade-offs
- Design de metadados para filtragem, citações e controle de acesso
- Pipelines de indexação (indexing), versionamento (versioning) e melhores práticas operacionais
Por que ingestão e fragmentação importam (a teoria)
A recuperação funciona com *unidades*, não com documentos
A maioria dos sistemas de recuperação não recupera “um PDF”; ela recupera fragmentos — trechos menores de texto que podem ser transformados em vetores de incorporação, indexados e retornados de forma eficiente. A fragmentação cria a granularidade de recuperação (retrieval granularity).
- Grande demais: as incorporações vetoriais borram vários tópicos; a recuperação retorna contexto ruidoso; modelos atingem limites da janela de contexto (context window).
- Pequeno demais: os fragmentos perdem contexto; a revocação (recall) cai; a síntese de respostas precisa costurar muitos fragmentos.
A fragmentação é, portanto, um problema de otimização entre:
- Coerência semântica (cada fragmento deve tratar de uma coisa)
- Revocação/precisão de recuperação (recall/precision) (a evidência certa aparece no top-k)
- Eficiência da janela de contexto (empacotar tokens úteis, evitar desperdício)
- Latência/custo (latency/cost) (volume de incorporação vetorial e indexação)
Vetores de incorporação e limites dos fragmentos
Vetores de incorporação densos (dense embeddings) (veja Busca Vetorial e Vetores de Incorporação (Vector Search & Embeddings)) comprimem um fragmento em um vetor. Se o fragmento contiver vários tópicos não relacionados, o vetor vira um “compromisso” que pode ficar distante de consultas sobre qualquer um dos tópicos. Esse é um grande motivo pelo qual a fragmentação sensível à estrutura (structure-aware) frequentemente supera a simples divisão de tamanho fixo.
Fragmentação também é uma decisão de *prompts*
Em RAG, os fragmentos recuperados viram entrada do modelo. A fragmentação determina:
- O que é citado (veja Fundamentação e Citações (Grounding & Citations))
- Se definições-chave aparecem junto com suas ressalvas
- Se tabelas, listas e procedimentos passo a passo permanecem intactos
Pipeline de ingestão: etapas e responsabilidades
Um pipeline típico de ingestão se parece com isto:
- Descoberta e coleta de fontes
- Fazer crawl de URLs, sincronizar armazenamentos de arquivos, exportar tickets, puxar de bancos de dados
- Parsing e extração
- Converter para texto + estrutura; extrair imagens/tabelas se necessário
- Normalização e limpeza
- Corrigir codificação, remover boilerplate, normalizar espaços em branco, deduplicar
- Segmentação e fragmentação
- Dividir em unidades de recuperação; atribuir IDs de fragmento
- Enriquecimento de metadados
- Adicionar fonte, timestamps, títulos/seções, controle de acesso, tags, idioma
- Incorporação vetorial e indexação
- Calcular vetores de incorporação; fazer inserção/atualização (upsert) no banco de dados vetorial; opcionalmente construir índice esparso
- Validação e monitoramento
- Checagens de qualidade, amostragem, detecção de deriva (drift), políticas de reingestão (reingestion)
Em sistemas agênticos (agentic systems) (veja RAG Agêntico (Agentic RAG)), decisões de ingestão também afetam o comportamento das ferramentas — por exemplo, se um agente consegue buscar de forma confiável “a seção exata da política” versus parágrafos vagos.
Parsing e extração de documentos
O parsing costuma ser a parte de maior variância do pipeline. PDFs, em particular, são formatos de apresentação, não formatos semânticos.
Entradas comuns e o que pode dar errado
HTML / Markdown / Documentos com estrutura
- Normalmente contêm títulos, listas e links que mapeiam bem para a estrutura de fragmentos.
- Armadilhas: boilerplate de navegação, cabeçalhos/rodapés repetidos, banners de cookies, texto oculto.
PDFs (digitais)
- O texto existe, mas a ordem de leitura é ambígua.
- Falha comum: layouts com múltiplas colunas viram frases intercaladas.
PDFs (escaneados) e imagens
- Exigem OCR; a qualidade depende da resolução do scan e do idioma.
- É preciso preservar números de página e regiões para citações.
Planilhas e tabelas
- Tabelas são difíceis para fragmentação em texto puro:
- Relações de linha/coluna podem se perder.
- Tabelas “achatadas” podem ficar ilegíveis.
Repositórios de código
- Código deve ser fragmentado por funções/classes e incluir caminhos de arquivo e símbolos.
- Comentários/docstrings podem ser mais úteis do que detalhes de implementação para muitas consultas.
Objetivos do parsing: texto *e* estrutura
Um parser robusto deve produzir:
- Texto limpo (legível para humanos, mínimo de lixo)
- Estrutura do documento
- títulos e hierarquia
- números de página / offsets
- tipos de bloco (parágrafo, lista, tabela, bloco de código)
- Âncoras para citações
- identificadores estáveis como
doc_id + page + bboxoudoc_id + heading path
- identificadores estáveis como
Essa estrutura permite uma fragmentação melhor e citações melhores.
Considerações de OCR (quando necessário)
Se você fizer OCR:
- Armazene a confiança do OCR por página/região (útil para filtrar texto de baixa qualidade).
- Mantenha imagens de página ou caixas delimitadoras (bounding boxes) se você quiser citações precisas na interface.
- Detecção de idioma pode melhorar a precisão do OCR (e, mais tarde, a seleção do modelo de incorporação).
Passos práticos de limpeza
Limpezas típicas que melhoram a qualidade de recuperação:
- Remover cabeçalhos/rodapés repetidos e menus de navegação
- Remover banners e boilerplate de “política de cookies”
- Normalizar espaços em branco e hifenização (quebras de linha de PDFs)
- Corrigir codificação (aspas inteligentes, Unicode quebrado)
- Canonicalizar URLs e IDs de documentos
A deduplicação também importa: conteúdo duplicado pode “lotar” os resultados relevantes no top-k.
Estratégias de fragmentação (e quando usá-las)
Fragmentação é escolher limites e tamanhos que se alinham a como usuários fazem perguntas.
1) Fragmentação de tamanho fixo (baseline)
Abordagem: dividir o texto a cada N caracteres ou tokens, muitas vezes com sobreposição.
- Prós: simples, rápida, previsível.
- Contras: quebra frases/seções; mistura tópicos; ruim para tabelas e código.
Quando é aceitável: conteúdo homogêneo como entradas curtas de FAQ ou texto bem estruturado onde limites importam menos.
2) Fragmentação recursiva / baseada em delimitadores (padrão comum)
Abordagem: dividir por separadores do documento em ordem de prioridade, por exemplo:
- parágrafos
\n\n - linhas
\n - limites de sentença
- fallback baseado em tokens
Isso mantém limites naturais quando possível.
- Prós: preserva parágrafos e listas; robusta em diferentes formatos.
- Contras: ainda é cega a mudanças semânticas dentro de parágrafos longos; depende de bom parsing.
3) Fragmentação sensível à estrutura (títulos e seções)
Abordagem: usar títulos (H1/H2/H3, cabeçalhos markdown, sumário/outline de PDF) para definir fragmentos por seção/subseção. Opcionalmente, manter um “caminho de títulos (heading path)” como metadado.
- Prós: alinha com a organização humana do documento; melhora citações (“Seção 3.2”).
- Contras: exige extração confiável de estrutura.
Melhor para: políticas, documentação técnica, wikis, referências de API.
4) Fragmentação semântica (ciente de incorporações vetoriais)
Abordagem: dividir onde a similaridade semântica cai — frequentemente pontuando a coerência de sentença a sentença usando vetores de incorporação ou algoritmos de segmentação de tópicos.
- Prós: pode superar divisão heurística para textos narrativos longos.
- Contras: mais cara; pode ser instável entre versões de modelos; mais difícil de depurar.
5) Janela deslizante com sobreposição (para contextos longos)
Abordagem: janelas de tamanho fixo com sobreposição (por exemplo, 300 tokens, sobreposição de 60 tokens).
A sobreposição ajuda quando respostas cruzam limites de fragmentos, mas sobreposição demais aumenta o tamanho do índice e a recuperação redundante.
Um bom modelo mental:
- A sobreposição deve preservar a cola contextual (definições, nomes de variáveis, antecedentes).
- A sobreposição não deve duplicar parágrafos inteiros, a menos que você precise de forte continuidade.
6) Fragmentação pai–filho (hierárquica)
Abordagem: indexar fragmentos “filhos” pequenos para recuperação, mas manter referências a um trecho “pai” maior para o contexto final.
- Recuperar: filhos (alta precisão)
- Ler/responder: pais (melhor contexto)
Isso frequentemente melhora a qualidade das respostas sem sacrificar a precisão da recuperação.
7) Fragmentação específica por modalidade
Em RAG Multimodal (Multimodal RAG):
- Imagens: fragmentar por figura; armazenar legenda + texto ao redor; opcionalmente armazenar vetores de incorporação de imagem (image embeddings).
- Tabelas: fragmentar por tabela, além de fragmentos curtos por grupo de linhas se as tabelas forem grandes.
- Código: fragmentar por símbolo (função/classe), incluir assinatura e docstring.
Escolhendo o tamanho do fragmento: orientação prática
Não existe um tamanho universalmente ideal, mas faixas comuns para RAG de texto:
- 200–500 tokens por fragmento para muitas tarefas de perguntas e respostas
- 500–1000 tokens para conteúdo técnico denso em que o contexto é essencial
Ajuste com base em:
- Tipo médio de consulta (busca de fato vs. explicação)
- Estilo dos documentos (manuais densos vs. notas curtas)
- Janela de contexto do modelo e orçamento de prompt
- Se você usa reranqueamento (veja Reranqueamento)
Metadados: a diferença entre “encontrei algo” e “encontrei a coisa certa”
Metadados permitem filtragem, ranqueamento, citações, controle de acesso e analytics.
Campos principais de metadados (recomendado)
No mínimo, armazene:
doc_id: identificador estável do documento-fontechunk_id: identificador estável do fragmentosource: URL/caminho/repo + título legívelcreated_at,updated_at,ingested_atchunk_index: ordem dentro do documentotext: o conteúdo do fragmento (ou um ponteiro)heading_path: por exemplo,["Políticas de RH", "Licenças", "Licença Parental"]page_rangeouchar_range: para citaçõescontent_type: pdf/html/wiki/code/tablelanguage: útil para sistemas multilíngues
Controle de acesso (crítico em empresas)
Se seu sistema for multiusuário, armazene metadados de lista de controle de acesso (ACL):
tenant_idallowed_user_idse/ouallowed_group_idsvisibility: public/internal/confidential
A filtragem por ACL deve ser aplicada no momento da consulta antes de os resultados serem retornados.
Metadados para qualidade e operações
Campos adicionais úteis:
parser_version,chunker_version,embedding_modelocr_confidencehash: hash de conteúdo para deduplicação e reingestão idempotentetags: área de produto, time, categoria do documento
Isso torna a reindexação mais segura e a depuração mais fácil.
Metadados e citações
Para suportar Fundamentação e Citações, armazene informação suficiente para reconstruir de onde veio o fragmento:
- URL com âncora (
#section-...) para HTML - Número de página para PDF
- Caminho do arquivo + intervalo de linhas para código
- ID da tabela + intervalo de linhas para planilhas
Pipelines de indexação: denso, esparso e híbrido
Indexação vetorial densa
Recuperação densa (dense retrieval) usa vetores de incorporação + vizinhos mais próximos aproximados (approximate nearest neighbors, ANN). Decisões-chave:
- Escolha do modelo de incorporação e versionamento
- Dimensão do vetor e métrica de distância (cosseno vs produto escalar)
- Tipo de índice (HNSW, IVF, PQ, etc.)
- Estratégia de inserção/atualização e semântica de deleção
Recuperação densa é ótima para paráfrase e correspondência conceitual, mas pode falhar em palavras-chave exatas, IDs e termos raros.
Indexação esparsa e híbrida
Busca esparsa (sparse search) (estilo BM25) se destaca em correspondência exata e tokens raros. Muitos sistemas em produção combinam as duas (veja Busca Híbrida (Esparsa + Densa)):
- Recuperar candidatos dos índices denso e esparso
- Mesclar pontuações (ponderadas) ou fazer união e depois reranquear
Busca híbrida é particularmente útil para:
- códigos de erro, IDs de ticket, SKUs
- nomes próprios e siglas
- nomes de símbolos de código
Interação entre reranqueamento e fragmentação
Um reranqueador pode compensar algumas imperfeições de fragmentação ao selecionar os melhores fragmentos entre os candidatos. Mas reranqueadores não fazem milagres:
- Se a evidência certa nunca aparecer no top-N de candidatos (porque parsing/fragmentação falhou), o reranqueamento não consegue recuperá-la.
- Limites melhores de fragmentos frequentemente reduzem o pool de candidatos necessário, melhorando latência e custo.
Exemplo prático: um fluxo mínimo de ingestão + fragmentação + indexação
A seguir, um exemplo simplificado em estilo Python ilustrando o formato de um pipeline. (As bibliotecas exatas vão variar: você pode usar um parser de HTML, um extrator de PDF e um cliente de banco de dados vetorial.)
import hashlib
from datetime import datetime
def stable_hash(text: str) -> str:
return hashlib.sha256(text.encode("utf-8")).hexdigest()
def chunk_recursive(text: str, max_tokens=400, overlap_tokens=60):
"""
Placeholder: in practice, use a tokenizer and split by paragraphs/sentences first.
Returns a list of chunk strings.
"""
words = text.split()
chunks = []
i = 0
while i < len(words):
chunk_words = words[i:i+max_tokens]
chunks.append(" ".join(chunk_words))
i += max_tokens - overlap_tokens
return chunks
def ingest_document(doc_id: str, title: str, source_url: str, raw_text: str, headings=None):
headings = headings or []
cleaned = normalize_text(raw_text) # remove boilerplate, fix whitespace, etc.
# idempotency: if content unchanged, skip
content_hash = stable_hash(cleaned)
chunks = chunk_recursive(cleaned, max_tokens=400, overlap_tokens=60)
records = []
for idx, chunk in enumerate(chunks):
chunk_id = f"{doc_id}:{idx}"
record = {
"doc_id": doc_id,
"chunk_id": chunk_id,
"title": title,
"source": source_url,
"heading_path": headings,
"chunk_index": idx,
"text": chunk,
"content_hash": content_hash,
"ingested_at": datetime.utcnow().isoformat(),
"chunker_version": "v1-recursive-400-60",
"embedding_model": "text-embedding-3-large" # example label
}
records.append(record)
# Embed + upsert
vectors = embed([r["text"] for r in records]) # returns list of float vectors
upsert_to_vector_db(vectors=vectors, metadata=records)
return len(records)
def normalize_text(text: str) -> str:
# extremely simplified normalization
text = text.replace("\r\n", "\n")
text = "\n".join(line.strip() for line in text.split("\n"))
return text.strip()
Em um pipeline de produção, normalmente você:
- Faz parsing específico por fonte (PDF vs HTML vs código)
- Usa divisão baseada em tokens com um tokenizador real
- Adiciona metadados de controle de acesso
- Armazena intervalos de páginas / offsets para citações
- Acompanha
parser_version,embedding_modele hashes de conteúdo para reindexação
Padrões avançados e melhores práticas
Mantenha IDs de fragmento estáveis entre reingestões
Se os IDs de fragmento mudarem a cada execução, você não consegue atualizar ou deletar fragmentos de forma confiável. Prefira IDs determinísticos derivados de:
doc_id + section_id + chunk_index, oudoc_id + char_range, oudoc_id + hash(chunk_text)(cuidado: pequenas edições causam churn)
IDs estáveis reduzem a “rotatividade do índice (index churn)” e tornam o cache mais efetivo (veja Cache (Caching)).
Trate atualizações com uma estratégia clara
Abordagens comuns:
- Reconstrução completa (full rebuild): mais simples; cara; boa para corpora pequenos
- Reingestão incremental (incremental reingestion):
- detectar mudanças via timestamps de última modificação + hashes de conteúdo
- deletar fragmentos de documentos atualizados e então inserir/atualizar os novos
- Indexação versionada (versioned indexing):
- escrever em uma nova versão do índice e então alternar leitores atomicamente
Versionamento ajuda ao mudar a lógica de fragmentação ou modelos de incorporação.
Avalie fragmentação como um problema de IR
Meça a qualidade de recuperação com um conjunto de teste de consultas e fontes relevantes conhecidas:
- Recall@k: o fragmento correto aparece no top-k?
- MRR / nDCG: os fragmentos mais relevantes ficam bem ranqueados?
- Fidelidade da resposta: as respostas geradas são suportadas pelos fragmentos recuperados? (se conecta a Fundamentação e Citações)
Faça teste A/B de tamanhos de fragmento, sobreposição e segmentação sensível à estrutura. Muitas vezes, pequenas mudanças na fragmentação superam a troca de modelos de incorporação.
Observe modos comuns de falha na ingestão
- Domínio de boilerplate: texto de navegação aparece em muitos documentos e “lota” a recuperação
- Ordem de leitura quebrada: colunas de PDF se intercalam
- Colapso de tabela: relações de coluna são perdidas
- Duplicatas com sobreposição: sobreposição demais + conteúdo repetido infla o índice
- Tópicos misturados por fragmento: “um fragmento contém três seções”
- ACL vazando: metadados ausentes/incorretos permitem recuperação não autorizada
Combine fragmentação com ferramentas downstream
Decisões de fragmentação devem combinar com como o sistema vai usar os fragmentos:
- Se você gera respostas em JSON com citações, garanta que os metadados do fragmento consigam suportar citações precisas (Saídas Estruturadas (Structured Outputs)).
- Se um agente chamar ferramentas para buscar “a seção completa”, armazene ponteiros para o pai (pai–filho) e habilite um fetch de acompanhamento (Chamada de Funções / Uso de Ferramentas (Function Calling / Tool Use)).
- Se você planeja aumento via grafo (graph augmentation), mantenha metadados ricos em entidades e IDs estáveis que possam mapear para um armazenamento de grafos (graph store) (RAG com Grafo de Conhecimento (Híbridos) (Knowledge Graph RAG (Hybrids))).
Juntando tudo: uma arquitetura de referência para ingestão
Um pipeline prático “maduro” frequentemente inclui:
- Conectores: crawler web, sincronização Google Drive/SharePoint, sincronização Git, exportador de tickets
- Serviço de parsing: parsers por formato, OCR, extração de layout
- Serviço de fragmentação: sensível à estrutura + fallbacks, suporte a pai–filho
- Enriquecimento: detecção de idioma, tags, ACL, extração de entidades (opcional)
- Escritores de índice:
- índice vetorial denso
- índice esparso/BM25 opcional para recuperação híbrida
- Observabilidade (observability):
- logs de ingestão por documento
- painéis para falhas, throughput, tamanho do índice
- interface de amostragem para “ver texto parseado + fragmentos”
Essa base torna muito mais fácil iterar depois em estratégias de recuperação como recuperação híbrida, reranqueamento e consulta agêntica multi-salto (multi-hop querying).
Resumo
Ingestão e fragmentação são as camadas de engenharia que transformam documentos confusos do mundo real em unidades de recuperação de alta qualidade. Sistemas fortes:
- Fazem parsing de documentos em texto limpo com estrutura
- Fragmentam ao longo de limites significativos (frequentemente títulos/seções), não tamanhos arbitrários
- Anexam metadados ricos para filtragem, ACL e citações
- Indexam de forma consistente com IDs estáveis, versionamento e iteração guiada por avaliação
Quando essas peças são bem-feitas, componentes downstream — recuperação densa, recuperação híbrida, reranqueamento e geração fundamentada (grounded generation) — tornam-se marcadamente mais confiáveis e mais fáceis de operar em escala.