Divisão em Chunks e Ingestão
A ingestão transforma documentos brutos em chunks pesquisáveis com embeddings. O tamanho do chunk, a sobreposição e os metadados afetam diretamente a qualidade da recuperação RAG.
Receita
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.split_documents(documents)Quando usar isso: indexar PDFs, wikis, repositórios de código ou qualquer corpus de documentos para RAG.
Exemplo de Trabalho
"""chunking_ingestion.py - limpa, divide em chunks, embuti e indexa documentos."""
from __future__ import annotations
import re
import chromadb
from openai import OpenAI
client = OpenAI()
RAW_DOCS = [
{"id": "doc1", "source": "handbook", "text": "# Testes em Python\n\nUse pytest para testes unitários. " * 20},
{"id": "doc2", "source": "handbook", "text": "# FastAPI\n\nConstrua APIs com type hints. " * 20},
]
def clean_text(text: str) -> str:
text = re.sub(r"\s+", " ", text).strip()
return text
def chunk_text(text: str, size: int = 400, overlap: int = 80) -> list[str]:
chunks = []
start = 0
while start < len(text):
chunks.append(text[start:start + size])
start += size - overlap
return chunks
chroma = chromadb.Client()
collection = chroma.get_or_create_collection("handbook")
for doc in RAW_DOCS:
cleaned = clean_text(doc["text"])
for i, chunk in enumerate(chunk_text(cleaned)):
chunk_id = f"{doc['id']}_chunk_{i}"
emb = client.embeddings.create(model="text-embedding-3-small", input=[chunk])
collection.add(
ids=[chunk_id],
documents=[chunk],
embeddings=[emb.data[0].embedding],
metadatas=[{"source": doc["source"], "doc_id": doc["id"], "chunk_index": i}],
)
print(f"indexou {collection.count()} chunks")O que isso demonstra: limpeza de texto, divisão em chunks de tamanho fixo com sobreposição, metadados por chunk e embedding no momento da ingestão.
Mergulho Profundo
Diretrizes de Tamanho de Chunk
| Tipo de Conteúdo | Tamanho do Chunk | Sobreposição |
|---|---|---|
| Prosa técnica | 500-1000 caracteres | 10-20% |
| Código | Nível de função/classe | Mínimo |
| Jurídico/contratos | 200-500 tokens | 20% |
| Logs de chat | Turno completo ou parágrafo | 0-10% |
Armadilhas
- Chunks muito grandes - a recuperação retorna seções irrelevantes. Correção: chunks menores com boa sobreposição.
- Chunks muito pequenos - perdem contexto para geração. Correção: aumentar o tamanho ou adicionar recuperação de documento pai.
- Sem metadados - não é possível filtrar ou citar fontes. Correção: armazene a fonte, página, título com cada chunk.
- HTML sujo - navegação e anúncios poluem os embeddings. Correção: remova boilerplate antes de dividir em chunks.
- Re-embedding de documentos inalterados - desperdiça chamadas de API. Correção: gere hash do conteúdo; pule se inalterado.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Chunks de tamanho fixo | Prosa geral | Documentos estruturados com seções claras |
| Divisor recursivo | Conteúdo misto | Código com limites rígidos |
| Chunking semântico | Comprimentos de seção variáveis | Documentos simples e uniformes |
| Chunks pai-filho | Precisa de precisão e contexto | Corpora pequenos |
FAQs
Qual tamanho de chunk devo usar para começar?
- 500-1000 caracteres para texto geral.
- Avalie o recall da recuperação em 20 consultas de teste.
- Ajuste com base se os chunks contêm contexto suficiente.
Como faço para dividir PDFs?
- Extraia texto com
pymupdfoupdfplumber. - Preserve os números de página nos metadados.
- Lide com layouts de várias colunas com cuidado.
Como faço para dividir código?
- Divida por limites de função/classe usando análise AST.
- Inclua o caminho do arquivo e a linguagem nos metadados.
Devo dividir no momento da ingestão ou da consulta?
- Sempre na ingestão - o tempo de consulta apenas embuti a pergunta.
Como lidar com atualizações de documentos?
- Exclua chunks antigos por doc_id; reingira seções alteradas.
- Rastreie o hash do conteúdo para detectar alterações.
O que é recuperação de documento pai?
- Armazene chunks pequenos para pesquisa; recupere a seção pai para geração.
- O melhor da precisão e do contexto.
Como faço para ingerir markdown?
- Divida em cabeçalhos (
#,##) para seções semânticas. - Preserve a hierarquia de cabeçalhos nos metadados.
Quantos chunks por documento?
- Depende do comprimento do documento.
- Monitore a contagem média de chunks por tipo de fonte.
Devo desduplicar chunks?
- Sim - chunks quase duplicados desperdiçam espaço de índice.
- Gere hash do texto normalizado; pule duplicatas.
Como faço para agrupar embeddings na ingestão?
- Embuta 100-500 chunks por chamada de API.
- OpenAI aceita até 2048 entradas por solicitação.
Quais metadados devo armazenar?
- source, doc_id, title, page, section, created_at, content_hash.
Como testo a qualidade do chunking?
- Revisão manual de 20 chunks aleatórios.
- Verifique o recall da recuperação em pares de consulta-chunk rotulados.
Relacionado
- Noções Básicas de RAG - pipeline de ponta a ponta
- Embeddings e Similaridade - modelos de embedding
- Bancos de Dados Vetoriais - armazenamento
- Recuperação e Re-ranking - qualidade da pesquisa
- LlamaIndex - framework de dados
Versões da Stack: Esta página foi escrita para Python 3.14.0 (3.14 estável, 3.13 em manutenção), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ e uv 0.6+.