Data Pipeline para LLMs
Pipeline de curadoria de dados em escala: crawler, deduplicação, filtragem de qualidade, PII scrubbing. Atualizado em abril de 2026.
Visão Geral
A qualidade dos dados de treino é o fator #1 de performance de um LLM. Um modelo treinado em 1T de tokens bem curados supera um modelo treinado em 5T de tokens sujos.
O pipeline típico tem 5 etapas:
Coleta → Deduplicação → Filtragem → PII Scrubbing → Formatação FinalCada etapa reduz o volume mas aumenta drasticamente a qualidade.
Etapa 1: Coleta (Crawler)
Fontes de dados
| Tipo | Fontes | Volume típico |
|---|---|---|
| Web geral | CommonCrawl, WebDataCommons | 100B–500B páginas |
| Código | GitHub, GitLab, Bitbucket, StackOverflow | 1B–5B de arquivos |
| Academic | ArXiv, PubMed, Semantic Scholar | 5M–50M papers |
| Livros | Project Gutenberg, Libgen (cuidado legal) | 1M–10M livros |
| Diálogos | Reddit, Forums, StackExchange | 100M–1B posts |
| Multilingual | Wikipedia, OPUS, Tatoeba | 10M–100M docs |
CommonCrawl
O CommonCrawl é a fonte primária de dados web.每个月 (~1B páginas, ~5PB raw).
Pipeline típico:
WARC files (raw) → WET files (texto extraído) → Filtragem → Dedup → LimpoFerramentas:
- cc_net (Facebook) — pipeline completo de CC para treino
- datatrove (HuggingFace) — pipeline modular em Python
- resiliparse — extração de texto de HTML rápido (Rust)
- trafilatura — extração de conteúdo principal de páginas web
Para código
| Fonte | Formato | Licença |
|---|---|---|
| The Stack v2 (BigCode) | 6TB, 350 linguagens | Permissiva (opt-in) |
| GitHub Archive | JSON de events | Pública |
| CodeParrot | Python focado | Apache 2.0 |
| StarCoderData | 800B tokens, 100+ linguagens | OpenRAIL-M |
Para o Kode: The Stack v2 é a melhor fonte de código — já filtrado, deduplicado, com metadados de licença.
Etapa 2: Deduplicação
Deduplicação é a etapa mais subestimada e mais importante. Dados duplicados causam:
- Overfitting — o modelo memoriza em vez de generalizar
- Viés — textos repetidos pesam mais no gradiente
- Ineficiência — compute gasto processando a mesma informação
Níveis de deduplicação
| Nível | Escopo | Técnica | Exemplo |
|---|---|---|---|
| Exata | Mesma string idêntica | Hash MD5/SHA256 | Remover duplicatas exatas de páginas web |
| Near-dedup (fuzzy) | Quase idêntico (95%+) | MinHash + LSH | Páginas espelhadas, traduções automáticas |
| Semântica | Mesmo significado | Embeddings + cosine similarity | Paráfrases, reescritas |
| Cross-document | Sobreposição entre docs | Jaccard similarity | Artigos que copiam partes um do outro |
| Intra-document | Repetição dentro do doc | N-gram overlap | "Lorem ipsum" repetido, boilerplate |
MinHash + LSH (Near-Deduplicação)
A técnica padrão-ouro da indústria (usada por RefinedWeb, FineWeb, RedPajama):
1. Shingling: dividir documento em shingles de n-grams (ex: 5-grams de palavras)
2. MinHash: aplicar ~200 hash functions, pegar o mínimo de cada → assinatura de 200 ints
3. LSH (Locality Sensitive Hashing): agrupar assinaturas similares em buckets
4. Comparar dentro de buckets: Jaccard similarity > 0.8 → duplicataPerformance: Processa 100B de documentos em ~24 horas com 64 cores.
Ferramentas:
- datasketch (Python) — implementação de MinHash + LSH
- text-dedup (HuggingFace) — pipeline completo de deduplicação
- Fineweb deduplication — referência de implementação
Resultados típicos
| Dataset | Antes | Depois da dedup | Redução |
|---|---|---|---|
| CommonCrawl bruto | 5PB | — | — |
| RefinedWeb (Falcon) | 2.8T tokens | 1.8T tokens | 35% removido |
| FineWeb | 15T tokens | 9.5T tokens | 37% removido |
| RedPajama v2 | 30T tokens | 20T tokens | 33% removido |
Regra prática: espere remover 30–40% do dataset apenas com deduplicação.
Etapa 3: Filtragem de Qualidade
Após deduplicação, filtrar o que sobra para remover lixo:
Filtros heurísticos
| Filtro | Critério | Remove |
|---|---|---|
| Comprimento | < 50 chars ou > 100K chars | Boilerplate, fragmentos |
| Token count | < 20 tokens ou > 10K tokens | Texto muito curto/longo |
| Alfabeto | < 80% caracteres alfabéticos | Código binário, logs |
| Repetição | > 30% n-gram repetition | Spam, lorem ipsum |
| HTML residual | Tags HTML não removidas | Parsing falhou |
| Idioma | Non-target language | Francês num dataset em inglês |
| NSFW | Palavras proibidas | Conteúdo adulto |
| PII | Emails, telefones, CPFs | Dados pessoais (ver Etapa 4) |
Filtros baseados em modelo
| Filtro | Técnica | Treinado para detectar |
|---|---|---|
| Language ID | fastText lid.176 | Idioma do texto |
| Quality classifier | BERT/RoBERTa fine-tuned | Texto de alta vs baixa qualidade |
| Toxicity | Detoxify / Perspective API | Conteúdo tóxico, ofensivo |
| PII detector | spaCy NER / Presidio | Dados pessoais |
| Code quality | Classificador por linguagem | Código funcional vs lixo |
Pipeline de filtragem do RefinedWeb (Falcon)
Referência da indústria:
1. Filtro por URL: remover domains de baixa qualidade
2. Filtro heurístico: comprimento, repetição, boilerplate
3. Filtro de idioma: fastText (manter apenas inglês, espanhol, etc.)
4. Filtro de qualidade: classifier treinado em Wikipedia vs spam
5. Filtro de PII: regex + NER
6. Deduplicação: MinHash + LSH no finalResultado: De 5PB de CommonCrawl bruto → 1.8T tokens de alta qualidade.
Etapa 4: PII Scrubbing
PII (Personally Identifiable Information) inclui:
- Nomes completos
- Endereços de email
- Números de telefone
- CPFs, RGs, documentos
- Endereços físicos
- Números de cartão de crédito
- IPs
Técnicas
| Técnica | Como funciona | Prós | Contras |
|---|---|---|---|
| Regex | Padrões conhecidos (email, CPF, telefone) | Rápido, preciso | Só detecta formatos conhecidos |
| NER (spaCy, Presidio) | Modelo de Named Entity Recognition | Detecta nomes, locais, orgs | Falso positivo em nomes genéricos |
| Microsoft Presidio | Pipeline completo de PII | Abrangente, bem mantido | Pode ser lento em escala |
| LLM-based | Pedir ao LLM para identificar PII | Flexível, contextual | Caro, lento |
Microsoft Presidio
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine
analyzer = AnalyzerEngine()
anonymizer = AnonymizerEngine()
text = "Meu email é rodrigo@koder.dev e meu CPF é 123.456.789-00"
results = analyzer.analyze(text=text, entities=["EMAIL_ADDRESS", "BR_CPF"], language='pt')
anonymized = anonymizer.anonymize(text=text, analyzer_results=results)
# "Meu email é <EMAIL_ADDRESS> e meu CPF é <BR_CPF>"Para o Kode: Usar Presidio com entidades customizadas para o Brasil (CPF, CNPJ, RG, telefone BR).
Redução de qualidade por PII scrubbing
Scrubbing agressivo pode remover contexto valioso. Exemplo:
"rodrigo@koder.dev"→"<EMAIL>"(ok, não perdemos nada)"John Smith wrote a paper"→"<PERSON> wrote a paper"(perdemos o nome, mas a frase ainda faz sentido)
Estratégia recomendada:
- Redact PII sensível (emails, CPFs, telefones) → substituir por placeholder
- Para nomes próprios em contexto genérico → manter (não é PII se não identificar alguém específico)
- Documentar o que foi scrubbed para auditoria
Etapa 5: Formatação Final
Tokenização e empacotamento
Textos limpos → Tokenização (BPE/SentencePiece) → Sequências de tokens
↓
Empacotamento (packing)
↓
Arquivos .bin ou .parquetPacking vs. Padding:
- Packing: Concatenar documentos curtos até填满 o context window (sem waste)
- Padding: Preencher documentos curtos com tokens de padding (waste de compute)
Packing é preferível — até 30% mais eficiente em compute.
Formatos de armazenamento
| Formato | Uso | Prós |
|---|---|---|
| JSONL | Desenvolvimento/debug | Legível, simples |
| Parquet | Produção | Compacto, queryable, schema |
| HDF5 | Treino direto | Leitura rápida, mmap |
| Arrow | Intermediário | Zero-copy, compatível com Parquet |
| MDS (Mosaic) | Treino distribuído | Sharding automático, streaming |
Ferramentas e Frameworks
datatrove (HuggingFace)
Pipeline modular para processamento de dados em escala:
from datatrove.pipeline import (
DocumentTokenizer,
MinhashDedupSignature,
MinhashDedupCluster,
QualityFilter,
PIIExtraction,
)
pipeline = [
DocumentTokenizer(),
MinhashDedupSignature(num_permutations=200),
MinhashDedupCluster(threshold=0.8),
QualityFilter(min_length=50, max_length=100000),
PIIExtraction(),
]Vantagens: Modular, escalável (Spark/Ray), open-source.
cc_net (Facebook)
Pipeline completo de CommonCrawl → dataset de treino:
- Extração de texto de WARC/WET
- Filtragem por idioma, qualidade, comprimento
- Deduplicação
- Tokenização
RedPajama Data Pipeline
Código aberto do pipeline que gerou o RedPajama v2 (30T tokens):
- GitHub:
togethercomputer/RedPajama-Data - Inclui scripts de crawling, filtragem, dedup
Spark + Ray
Para escala massiva (10T+ tokens):
- Apache Spark — processamento distribuído batch
- Ray Data — pipeline moderno, mais fácil que Spark
Métricas de Qualidade do Dataset
| Métrica | O que mede | Valor alvo |
|---|---|---|
| Unique n-gram ratio | Fração de n-grams únicos | > 0.85 |
| Perplexity de referência | PPL do dataset em GPT-2/Llama | Quanto menor, mais "limpo" |
| Token diversity | Entropia da distribuição de tokens | Alta = diversificado |
| Language purity | % no idioma alvo | > 95% |
| PII rate | % de tokens com PII | < 0.01% |
| Duplication rate | % de near-duplicatas | < 1% após dedup |
Para o Kode
Pipeline recomendado
Para construir o dataset de treino do Kode:
Fase 1: Coleta (1–2 semanas)
→ The Stack v2 (código) — já curado
→ CommonCrawl + cc_net (texto geral)
→ Documentação técnica (docs de libs, frameworks)
Fase 2: Deduplicação (3–5 dias)
→ MinHash + LSH (threshold 0.8)
→ Remover near-duplicatas cross-fonte
Fase 3: Filtragem (2–3 dias)
→ Heurísticas: comprimento, repetição, boilerplate
→ Language ID: manter Português + Inglês
→ Quality classifier: filtrar spam, lixo
Fase 4: PII Scrubbing (1 dia)
→ Presidio com entidades BR customizadas
→ Redact emails, CPFs, telefones
Fase 5: Tokenização e Packing (2–3 dias)
→ Tokenizer do Qwen2.5 ou Llama 3
→ Packing com context window de 8K–32K
→ Formato: Parquet para storage, MDS para treinoEstimativa de volume
| Fonte | Bruto | Após pipeline | Tokens estimados |
|---|---|---|---|
| The Stack v2 | 6TB | 4TB | ~600B |
| CommonCrawl (12 meses) | 60TB | 8TB | ~1.5T |
| Documentação técnica | 500GB | 300GB | ~50B |
| Total | ~67TB | ~12TB | ~2.1T tokens |
Hardware para o pipeline
| Etapa | Hardware | Tempo estimado |
|---|---|---|
| Coleta | Download de datasets (banda larga) | 1–2 semanas |
| Deduplicação | 32 cores, 128GB RAM | 3–5 dias |
| Filtragem | 16 cores, 64GB RAM | 2–3 dias |
| PII Scrubbing | 8 cores, 32GB RAM | 1 dia |
| Tokenização | 1× GPU (para tokenizer neural) ou CPU | 2–3 dias |
Custo total estimado: R$ 5–15K (principalmente banda larga e storage).
Papers e Referências
| Paper | Autores | Venue | arXiv |
|---|---|---|---|
| RefinedWeb | Penedo et al. (Falcon) | 2023 | arXiv:2306.01116 |
| FineWeb | Penedo et al. | 2024 | arXiv:2406.17557 |
| RedPajama v2 | Weber et al. | 2023 | — |
| DataComp | Dodge et al. | NeurIPS 2023 | arXiv:2306.10200 |
| The Stack | Kocetkov et al. | 2022 | arXiv:2211.15533 |
| cc_net | Wenzek et al. | ACL 2020 | arXiv:1911.00359 |
| SemDeDup | Abbas et al. | 2023 | arXiv:2303.09540 |