Pretraining data: curation, dedup & quality
A model is what it eats. The internet is mostly junk, so the gap between a mediocre LLM and a frontier one is as much about the data pipeline — extraction, quality filtering, deduplication, decontamination — as the architecture. How trillions of raw tokens become a clean training set.
Written and reviewed by Shreyash Prashu Last reviewed
What you'll learn
- Where pretraining data comes from and why raw web text is unusable as-is
- The curation funnel — extract, language-ID, quality-filter, dedup, decontaminate
- Why deduplication is one of the highest-ROI steps (and how near-dup detection works)
- Why the data mixture, not just the size, determines what the model can do
Before you start
A language model is, almost literally, what it eats. Everything it knows and every habit it has comes from the text it was trained on — so the quality of that text is a first-class lever, right next to the architecture. And the raw material is grim: a web crawl is mostly spam, boilerplate, navigation menus, near-duplicate reposts, and machine-generated filler. Pour that in unfiltered and you get a fluent model with no taste.
The unglamorous pipeline that turns petabytes of raw crawl into a clean, deduplicated training set is a big part of why two models with the same architecture and parameter count can be worlds apart. This lesson walks that pipeline.
Where the tokens come from
Frontier pretraining sets are assembled from a few broad sources:
- Web crawl — the bulk, usually from Common Crawl (petabytes of raw HTML scraped over years). Enormous, and mostly low quality.
- Code — GitHub and similar. Punches above its weight: code teaches structure, reasoning, and long-range consistency, and it helps even on non-code tasks.
- Books and long-form — high-quality, coherent, long-context prose.
- Reference — Wikipedia, papers, curated Q&A.
- Synthetic — increasingly, text generated by other models (more on this below).
The web is where the volume is and where the cleaning problem lives. Everything that follows is mostly about making the web crawl usable.
The curation funnel
Curation is a funnel: each stage throws away more than it keeps, and what survives is a small, dense fraction of the input.
Extraction and language ID. Strip HTML to text, drop the nav/ads/boilerplate, and keep only the languages you are training on. Already most of the raw bytes are gone.
Quality filtering. Decide whether a document reads like something worth learning from. Two styles, usually combined: cheap heuristics (reject pages that are too short, mostly symbols, keyword-stuffed, or missing normal stopword patterns) and a learned classifier that scores how much a page resembles known-good reference text. FineWeb-Edu, for instance, trained a classifier to keep “educational” web pages and saw downstream gains from that filter alone.
Deduplication — the quiet high-ROI step
The single highest-leverage cleaning step is usually deduplication, because the web is staggeringly repetitive: the same article is reposted across hundreds of sites, each wrapped in different navigation and ads. Removing duplicates buys three things at once:
- Less memorization / better privacy — text seen many times is more likely to be regurgitated verbatim, including any personal data in it.
- No train-test contamination — duplicates of benchmark questions hiding in the crawl would otherwise inflate eval scores (see decontamination below).
- Cheaper, better training — you do not pay FLOPs to read the same paragraph a thousand times, and heavy duplication can actively hurt quality.
Exact-match dedup is easy (hash each document). The hard, important case is near-duplicates — same content, different boilerplate. The standard tool is MinHash + LSH: represent each document as a set of overlapping word shingles and measure the Jaccard similarity (shared shingles over total). High overlap = near-duplicate. (Semantic dedup, e.g. SemDedup, goes further and clusters by embedding similarity to catch paraphrases.)
def shingles(text, k=4): # overlapping k-word sequences
t = text.lower().split()
return set(tuple(t[i:i+k]) for i in range(len(t) - k + 1))
def jaccard(a, b):
A, B = shingles(a), shingles(b)
return len(A & B) / len(A | B) # shared / total
article = "the central bank raised interest rates by half a point on tuesday citing inflation"
copy_a = article + " all rights reserved subscribe now" # same article, site A
copy_b = "home about contact " + article + " cookie policy" # same article, site B
other = "researchers trained a new vision model on a billion labeled images"
print("same article, different boilerplate:", round(jaccard(copy_a, copy_b), 3))
print("article vs unrelated doc :", round(jaccard(article, other), 3))
print("flag as duplicate at threshold 0.5:", jaccard(copy_a, copy_b) >= 0.5,
"/", jaccard(article, other) >= 0.5)
same article, different boilerplate: 0.524
article vs unrelated doc : 0.0
flag as duplicate at threshold 0.5: True / False
The two reposts share most of their shingles (0.52) and get flagged as the same content despite different wrappers, while the unrelated document scores 0. Run this across billions of documents with MinHash signatures (so you never compute the full pairwise comparison) and the duplicate reposts collapse to one copy.
Decontamination and safety
Decontamination removes any copies of evaluation benchmarks’ test questions from the training data. Skip it and your model may “ace” a benchmark simply because it memorised the answers during pretraining — a measurement artifact, not a capability. Safety/PII filtering strips or down-weights toxic content and personal data so the model is less likely to emit it.
The mixture is the model
Two sets of the same size can produce very different models, because what you mix in determines what the model can do. Recipes deliberately up-weight high-value sources — code, books, reference text — above their natural web proportion, because each disproportionately improves reasoning and coherence. The mixture is a tuned recipe, not an accident.
In one breath
- A model is what it eats; raw web crawl is mostly junk, so curation is a first-class lever next to the architecture.
- Pretraining data comes from web crawl (the bulk, e.g. Common Crawl), code, books, reference, and increasingly synthetic text.
- The curation funnel — extract + language-ID, quality-filter (heuristics + classifier), deduplicate, decontaminate + safety — keeps only ~10–15% of the raw input.
- Dedup is the quiet high-ROI step: it cuts memorization, prevents train-test contamination, and saves compute; near-dups are caught with MinHash/LSH on shingle Jaccard similarity (0.52 for two reposts of one article vs 0 for unrelated text).
- The mixture decides capability — up-weighting code/books/reference — and the modern consensus is quality over quantity (Chinchilla, the phi “textbooks” result), with synthetic data the answer to the looming data wall.
Quick check
Quick check
Next
You have seen how the training data is built; pretraining covers the objective that turns it into weights, and scaling laws explain how data and parameters should grow together. For shaping behaviour after pretraining, head to alignment.
Practice this in an interview
All questionsPretraining teaches a model general language structure by predicting tokens across a massive corpus; fine-tuning adapts the pretrained weights to a narrower task or domain using supervised data; instruction-tuning is supervised fine-tuning specifically on (instruction, response) pairs so the model follows directives; RLHF further aligns the model to human preferences by training a reward model on ranked responses and using it as a signal for policy optimisation with PPO or a similar algorithm.
Full retraining trains a fresh model from scratch on the latest data window, giving the cleanest result but at the highest cost and slowest cadence. Incremental or warm-start training continues from existing weights on new data, which is cheaper and faster but can accumulate drift and forgetting. Continual online learning updates the model continuously from a live stream for maximum freshness, at the cost of stability, harder evaluation, and vulnerability to bad or poisoned data.
Work top-down: start at the model layer with quantization, distillation, or routing cheaper models for easy requests, since model choices drive every downstream cost. Then optimize the runtime with batching, caching, and techniques like prompt caching for LLMs, and finally match infrastructure to the load using autoscaling on queue depth and spot or batch capacity. Track cost per token or per prediction alongside latency percentiles and accuracy so optimizations never silently degrade quality.
Evaluation splits into retrieval quality (did we fetch the right chunks?) and generation quality (did the model use them correctly?). Key metrics are context precision/recall for retrieval and faithfulness plus answer relevance for generation. Frameworks like RAGAS automate LLM-as-judge scoring; human annotation anchors the ground truth.