Data Pipeline for LLMs
Data curation pipeline at scale: crawler, deduplication, quality filtering, PII scrubbing. Updated April 2026.
Overview
Training data quality is the #1 factor in an LLM's performance. A model trained on 1T well-curated tokens beats a model trained on 5T dirty tokens.
The typical pipeline has 5 stages:
Collection → Deduplication → Filtering → PII Scrubbing → Final FormattingEach stage reduces the volume but dramatically increases quality.
Stage 1: Collection (Crawler)
Data sources
| Type | Sources | Typical volume |
|---|---|---|
| General web | CommonCrawl, WebDataCommons | 100B–500B pages |
| Code | GitHub, GitLab, Bitbucket, StackOverflow | 1B–5B files |
| Academic | ArXiv, PubMed, Semantic Scholar | 5M–50M papers |
| Books | Project Gutenberg, Libgen (legal caution) | 1M–10M books |
| Dialogue | Reddit, Forums, StackExchange | 100M–1B posts |
| Multilingual | Wikipedia, OPUS, Tatoeba | 10M–100M docs |
CommonCrawl
CommonCrawl is the primary source of web data. Every month (~1B pages, ~5PB raw).
Typical pipeline:
WARC files (raw) → WET files (extracted text) → Filtering → Dedup → CleanTools:
- cc_net (Facebook) — complete CC-to-training pipeline
- datatrove (HuggingFace) — modular pipeline in Python
- resiliparse — fast text extraction from HTML (Rust)
- trafilatura — main-content extraction from web pages
For code
| Source | Format | License |
|---|---|---|
| The Stack v2 (BigCode) | 6TB, 350 languages | Permissive (opt-in) |
| GitHub Archive | JSON of events | Public |
| CodeParrot | Python focused | Apache 2.0 |
| StarCoderData | 800B tokens, 100+ languages | OpenRAIL-M |
For Kode: The Stack v2 is the best code source — already filtered, deduplicated, with license metadata.
Stage 2: Deduplication
Deduplication is the most underrated and most important stage. Duplicate data causes:
- Overfitting — the model memorizes instead of generalizing
- Bias — repeated texts weigh more in the gradient
- Inefficiency — compute wasted processing the same information
Deduplication levels
| Level | Scope | Technique | Example |
|---|---|---|---|
| Exact | Same identical string | MD5/SHA256 hash | Remove exact duplicates of web pages |
| Near-dedup (fuzzy) | Almost identical (95%+) | MinHash + LSH | Mirrored pages, machine translations |
| Semantic | Same meaning | Embeddings + cosine similarity | Paraphrases, rewrites |
| Cross-document | Overlap between docs | Jaccard similarity | Articles that copy parts of each other |
| Intra-document | Repetition within the doc | N-gram overlap | Repeated "Lorem ipsum", boilerplate |
MinHash + LSH (Near-Deduplication)
The industry's gold-standard technique (used by RefinedWeb, FineWeb, RedPajama):
1. Shingling: split document into shingles of n-grams (e.g., 5-grams of words)
2. MinHash: apply ~200 hash functions, take the minimum of each → 200-int signature
3. LSH (Locality Sensitive Hashing): group similar signatures into buckets
4. Compare within buckets: Jaccard similarity > 0.8 → duplicatePerformance: Processes 100B documents in ~24 hours with 64 cores.
Tools:
- datasketch (Python) — MinHash + LSH implementation
- text-dedup (HuggingFace) — complete deduplication pipeline
- Fineweb deduplication — reference implementation
Typical results
| Dataset | Before | After dedup | Reduction |
|---|---|---|---|
| Raw CommonCrawl | 5PB | — | — |
| RefinedWeb (Falcon) | 2.8T tokens | 1.8T tokens | 35% removed |
| FineWeb | 15T tokens | 9.5T tokens | 37% removed |
| RedPajama v2 | 30T tokens | 20T tokens | 33% removed |
Rule of thumb: expect to remove 30–40% of the dataset from deduplication alone.
Stage 3: Quality Filtering
After deduplication, filter what remains to remove junk:
Heuristic filters
| Filter | Criterion | Removes |
|---|---|---|
| Length | < 50 chars or > 100K chars | Boilerplate, fragments |
| Token count | < 20 tokens or > 10K tokens | Text too short/long |
| Alphabet | < 80% alphabetic characters | Binary code, logs |
| Repetition | > 30% n-gram repetition | Spam, lorem ipsum |
| Residual HTML | Unremoved HTML tags | Parsing failed |
| Language | Non-target language | French in an English dataset |
| NSFW | Forbidden words | Adult content |
| PII | Emails, phones, CPFs | Personal data (see Stage 4) |
Model-based filters
| Filter | Technique | Trained to detect |
|---|---|---|
| Language ID | fastText lid.176 | Text language |
| Quality classifier | BERT/RoBERTa fine-tuned | High vs low quality text |
| Toxicity | Detoxify / Perspective API | Toxic, offensive content |
| PII detector | spaCy NER / Presidio | Personal data |
| Code quality | Per-language classifier | Functional code vs junk |
RefinedWeb (Falcon) filtering pipeline
Industry reference:
1. URL filter: remove low-quality domains
2. Heuristic filter: length, repetition, boilerplate
3. Language filter: fastText (keep only English, Spanish, etc.)
4. Quality filter: classifier trained on Wikipedia vs spam
5. PII filter: regex + NER
6. Deduplication: MinHash + LSH at the endResult: From 5PB of raw CommonCrawl → 1.8T high-quality tokens.
Stage 4: PII Scrubbing
PII (Personally Identifiable Information) includes:
- Full names
- Email addresses
- Phone numbers
- CPFs, RGs, documents
- Physical addresses
- Credit card numbers
- IPs
Techniques
| Technique | How it works | Pros | Cons |
|---|---|---|---|
| Regex | Known patterns (email, CPF, phone) | Fast, precise | Only detects known formats |
| NER (spaCy, Presidio) | Named Entity Recognition model | Detects names, locations, orgs | False positives on generic names |
| Microsoft Presidio | Complete PII pipeline | Comprehensive, well maintained | Can be slow at scale |
| LLM-based | Ask the LLM to identify PII | Flexible, contextual | Expensive, slow |
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>"For Kode: Use Presidio with custom entities for Brazil (CPF, CNPJ, RG, BR phone).
Quality loss from PII scrubbing
Aggressive scrubbing can remove valuable context. Example:
"rodrigo@koder.dev"→"<EMAIL>"(ok, we lose nothing)"John Smith wrote a paper"→"<PERSON> wrote a paper"(we lose the name, but the sentence still makes sense)
Recommended strategy:
- Redact sensitive PII (emails, CPFs, phones) → replace with placeholder
- For proper names in generic context → keep (it is not PII if it does not identify a specific person)
- Document what was scrubbed for auditing
Stage 5: Final Formatting
Tokenization and packing
Clean texts → Tokenization (BPE/SentencePiece) → Token sequences
↓
Packing
↓
.bin or .parquet filesPacking vs. Padding:
- Packing: Concatenate short documents until the context window is full (no waste)
- Padding: Fill short documents with padding tokens (compute waste)
Packing is preferable — up to 30% more compute-efficient.
Storage formats
| Format | Use | Pros |
|---|---|---|
| JSONL | Development/debug | Readable, simple |
| Parquet | Production | Compact, queryable, schema |
| HDF5 | Direct training | Fast read, mmap |
| Arrow | Intermediate | Zero-copy, Parquet-compatible |
| MDS (Mosaic) | Distributed training | Automatic sharding, streaming |
Tools and Frameworks
datatrove (HuggingFace)
Modular pipeline for data processing at scale:
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(),
]Advantages: Modular, scalable (Spark/Ray), open-source.
cc_net (Facebook)
Complete CommonCrawl → training-dataset pipeline:
- Text extraction from WARC/WET
- Filtering by language, quality, length
- Deduplication
- Tokenization
RedPajama Data Pipeline
Open source of the pipeline that produced RedPajama v2 (30T tokens):
- GitHub:
togethercomputer/RedPajama-Data - Includes crawling, filtering, dedup scripts
Spark + Ray
For massive scale (10T+ tokens):
- Apache Spark — distributed batch processing
- Ray Data — modern pipeline, easier than Spark
Dataset Quality Metrics
| Metric | What it measures | Target value |
|---|---|---|
| Unique n-gram ratio | Fraction of unique n-grams | > 0.85 |
| Reference perplexity | Dataset PPL on GPT-2/Llama | The lower, the "cleaner" |
| Token diversity | Entropy of the token distribution | High = diverse |
| Language purity | % in the target language | > 95% |
| PII rate | % of tokens with PII | < 0.01% |
| Duplication rate | % of near-duplicates | < 1% after dedup |
For Kode
Recommended pipeline
To build Kode's training dataset:
Phase 1: Collection (1–2 weeks)
→ The Stack v2 (code) — already curated
→ CommonCrawl + cc_net (general text)
→ Technical documentation (lib, framework docs)
Phase 2: Deduplication (3–5 days)
→ MinHash + LSH (threshold 0.8)
→ Remove cross-source near-duplicates
Phase 3: Filtering (2–3 days)
→ Heuristics: length, repetition, boilerplate
→ Language ID: keep Portuguese + English
→ Quality classifier: filter spam, junk
Phase 4: PII Scrubbing (1 day)
→ Presidio with custom BR entities
→ Redact emails, CPFs, phones
Phase 5: Tokenization and Packing (2–3 days)
→ Qwen2.5 or Llama 3 tokenizer
→ Packing with 8K–32K context window
→ Format: Parquet for storage, MDS for trainingVolume estimate
| Source | Raw | After pipeline | Estimated tokens |
|---|---|---|---|
| The Stack v2 | 6TB | 4TB | ~600B |
| CommonCrawl (12 months) | 60TB | 8TB | ~1.5T |
| Technical documentation | 500GB | 300GB | ~50B |
| Total | ~67TB | ~12TB | ~2.1T tokens |
Hardware for the pipeline
| Stage | Hardware | Estimated time |
|---|---|---|
| Collection | Dataset download (broadband) | 1–2 weeks |
| Deduplication | 32 cores, 128GB RAM | 3–5 days |
| Filtering | 16 cores, 64GB RAM | 2–3 days |
| PII Scrubbing | 8 cores, 32GB RAM | 1 day |
| Tokenization | 1× GPU (for neural tokenizer) or CPU | 2–3 days |
Total estimated cost: R$ 5–15K (mostly broadband and storage).
Papers and References
| Paper | Authors | 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 |