← All posts

Model development

Post 2 of 26

Building a pre-training corpus: from a web crawl to training text

Posts in this series · 26

In the previous post we followed one training update, starting from a batch of tokens that simply arrived. Now we go upstream and ask where those tokens come from. For most open language models the answer is the public web: navigation menus, cookie banners, keyword-stuffed shop pages, the same story mirrored on a thousand sites, pages in hundreds of languages, and somewhere in between, the articles, explanations and conversations we actually want a model to learn from.

A pre-training corpus is what remains after a sequence of decisions about that mess. We will walk through them in the order a real pipeline makes them, using FineWeb as the running example because its authors published both the pipeline and the experiments behind each choice. Two ideas run through the whole post:

What a pipeline does to the training distribution

The training objective from the previous post averages the loss over tokens drawn from the corpus, so the corpus is the objective: whatever is common in it, the model is pushed hardest to predict. A typical pipeline:

  1. Extract the readable text from each crawled page.
  2. Identify the language and keep the ones you want.
  3. Filter out low-quality documents with simple rules.
  4. Remove duplicates, exact and near.
  5. Optionally, score quality with a model and keep the best.
  6. Remove benchmark items you will evaluate on, and personal data.

At FineWeb’s scale, the text from 96 Common Crawl snapshots came to roughly 36 trillion tokens after the first filters, 20 trillion after deduplication, and 15 trillion after the remaining filters (FineWeb, §§3.3–3.7). Less than half of what passed the first filters survived.

Keep, for every stage, the counts in and out, and the removed documents with the reason they were removed. A stage you cannot inspect is a stage you cannot fix. Keep provenance too: each FineWeb record carries its URL, snapshot, crawl date and source file, which is what lets you trace a document back, honour a removal request or rebuild one snapshot. Whether a page could be crawled, whether the compiled dataset may be shared and what may be done with its content are separate questions; FineWeb is released under ODC-By 1.0 and notes that its use is also subject to Common Crawl’s terms (Appendix B).

Extracting the text

A crawled news page might contain:

Home | News | Sport | Contact
We use cookies to improve your experience. Accept
The cat sat on the mat for most of the afternoon.
Neighbours said it was the warmest day of the year.
© 2024 Example News. Terms of use

Only the middle two lines are content. A naive conversion keeps all five, and the model spends capacity predicting menus and footers that appear, almost identically, on millions of pages. An extractor uses the HTML structure to keep the main content and drop the boilerplate.

Common Crawl ships a plain-text version of every page (WET files), but FineWeb found it “retained too much boilerplate and menu text” and extracted from the raw HTML (WARC files) with trafilatura instead; models trained on the custom extraction did clearly better (§3.2, Fig. 1). DCLM measured the same effect independently: 24.1 and 24.5 on its core score for two custom extractors, against 20.7 for WET text (DCLM, §4.2, Table 3). Extraction is also the most expensive stage to redo, so it is worth getting right first.

Keeping one language

A classifier then guesses each document’s language. FineWeb keeps a document if a fastText classifier’s top label is English with probability at least 0.65 (§3.3). Running that same filter (in datatrove 0.10.1) on three short pages shows what the threshold decides:

PageTop labelScoreIn an English corpus
An English sentence about Angkor WatEnglish0.998kept
The same facts, half Khmer and half EnglishKhmer0.852removed
The same facts in KhmerKhmer0.998removed

The mixed page goes, English half included. That is correct for an English-only corpus, but it shows that coverage of code-switched text, transliteration and languages the classifier knows poorly all hangs on one score. A multilingual corpus needs per-language thresholds and checks that its smaller languages survive.

Heuristic quality filters

Many extracted documents are still not prose: product listings, keyword lists, link farms. Heuristic filters compute simple statistics and remove documents whose values fall where junk is common. Take this page:

Cheap flights Paris
Cheap flights Rome
Cheap flights Berlin
Book now and save on every route this summer!
Cheap flights Madrid

Two of FineWeb’s own rules (§3.6):

datatrove’s FineWebQualityFilter removes it for exactly that reason, short_line_ratio.

FineWeb chose thresholds from data rather than intuition: it compared the distributions of over 50 statistics between a higher- and a lower-quality version of one old snapshot, set thresholds where the lower-quality version dominated, and then trained models to see which filters actually helped (§3.6). The trade-off is explicit: C4’s rule that drops every line without terminal punctuation removes about 30% of tokens, while FineWeb’s looser punctuation rule removes about 10% (§§3.5–3.6).

Everyday picture: a heuristic filter is a dress code at the door. It is fast and catches the obvious cases, but it also turns away good guests who dress differently. Poetry, instructions and code fail “most lines end in punctuation” for reasons unrelated to quality; FineWeb’s datasheet warns that code is probably rare in the result (Appendix A).

Removing duplicates

The web repeats itself: mirrors, aggregators, syndicated news, templates. A document that appears a thousand times is trained on a thousand times, so it carries a thousand times the weight in the loss, and repeated text is more likely to be memorized. Deduplication has been associated with better models and less memorization (FineWeb, §3.4).

Exact duplicates are easy: normalize the text, hash it, keep one per hash. Near-duplicates, pages that differ by a date, an ad or a few words, need a similarity measure. The usual one describes each document by its set of overlapping word sequences (shingles) and measures overlap with the Jaccard similarity, shared shingles divided by distinct shingles:

Comparing every pair of billions of documents is impossible, so pipelines use MinHash: each document gets a short signature (112 numbers in FineWeb) computed from its shingles, designed so that the fraction of positions where two signatures agree estimates their Jaccard similarity. Grouping the signature into buckets then finds candidate pairs by looking for identical buckets, without comparing all pairs. The settings decide what counts as a duplicate: FineWeb’s 14 buckets of 8 numbers catch a pair at similarity 0.75 about 77% of the time and at 0.85 about 99% of the time, and rarely catch pairs below 0.5 (Appendix E.1). More hash functions give a sharper cut-off at more compute and storage. Matching pairs are joined into groups and one document per group is kept. (For the derivation, see the further reading at the end.)

How widely to deduplicate

Deduplication changes the mixture, not just the size, and FineWeb’s most instructive experiment shows how much that matters. It first deduplicated across all 96 snapshots, newest first. Old snapshots lost up to 90% of their data, and a model trained on the result was barely better than one trained without deduplication (§3.4, Fig. 3). In the 2013 snapshot, the 10% that survived trained a worse model than the 90% that was removed, and inspection found the survivors had more ads, keyword lists and badly formatted text (§3.4, Fig. 4). Deduplicating each snapshot separately worked better and matched the strong RefinedWeb dataset (Fig. 5).

The figure shows the mechanism in a deliberately simple toy where, as in FineWeb’s 2013 snapshot, the pages repeated across crawls happen to be good ones.

Three crawls of ten pages deduplicated globally, newest first, and then each crawl on its own
Figure 1. Deduplication changes the mixture. In this toy the pages repeated across crawls are good, so removing their copies from older crawls leaves those crawls mostly spam. Whether that happens on real data depends on what is repeated: FineWeb found it in an old Common Crawl snapshot, but repeated text can just as well be boilerplate or templated spam.

The toy is not a law. Repetition is a property of what gets copied, and plenty of copied text is junk: CS336’s data lecture shows a single product description repeated 61,036 times in C4. FineWeb’s own explanation, offered as a hypothesis, is that most of the benefit comes from removing the very large clusters of copies that every crawl contains, while removing small clusters of fewer than about 100 copies can hurt (§3.4). The general lesson is to judge deduplication by what remains, and by training on it.

Model-based quality filters

Heuristics catch the obviously broken. To prefer the genuinely useful, many recent pipelines train a classifier to score documents: a strong model or people label a sample, a cheap classifier learns to predict the labels, and documents above a threshold are kept.

FineWeb-Edu had Llama-3-70B-Instruct score 460,000 pages for educational value on a 0–5 scale, trained a small regression model on those scores, and kept documents scoring at least 3: 1.3 trillion of FineWeb’s 15 trillion tokens, about 9% (§4). DCLM trained a fastText classifier to distinguish instruction-style text from random web text and kept the top 10% (DCLM, §4.4). Both improved knowledge and reasoning benchmarks; FineWeb-Edu raised MMLU from 33% to 37% and ARC from 46% to 57% in FineWeb’s experiments (§4).

A classifier encodes the preferences of whoever labelled its training data, and the filter shifts the topic mixture. FineWeb-Edu has more education and history and less business, entertainment and travel than FineWeb (§4.1), and models trained on it predict Wikipedia and academic text better but broad web and social-media text worse (§4.2). That can be exactly what you want, or a coverage loss you did not intend.

Is a stage worth what it removes?

Statistics about the data cannot tell you whether a stage helped. FineWeb’s method is to train small models that differ only in their data, with the same architecture, the same number of training tokens and two seeds per variant, and compare them on benchmarks chosen to give a stable signal at that scale (§3.1). The comparison is always at a fixed training budget, and the right answer depends on that budget.

Try it: predict token exposure. You will train for 100 billion tokens. After basic filtering you have 300 billion. A quality classifier offers two thresholds: keep the top 30% (90 billion tokens) or the top 10% (30 billion). How many times will the model see each kept document? Now change the budget to 1 trillion tokens.

Answer. At 100 billion tokens, the 30% threshold gives 100 / 90 ≈ 1.1 passes over the data and the 10% threshold 100 / 30 ≈ 3.3. At 1 trillion tokens the same thresholds give about 11 and 33 passes, and even the unfiltered 300 billion would be seen about 3.3 times. The budget changes the trade completely: a strict filter costs nothing in repetition at 100 billion tokens and a great deal at 1 trillion.

What the pass count cannot tell you is which option trains the better model. That depends on two things you have to measure: how much better the kept documents are, and how quickly repeated data loses value on your data at your scale. One large study found that, for its models (up to 9 billion parameters) and data, up to about 4 passes changed the final loss negligibly compared with fresh data, and that the value of further repetition then fell off sharply (Muennighoff et al., 2023, abstract and Fig. 1). That is a useful prior, not a limit: a much better filtered set can be worth repeating more, and a slightly better one may not be worth repeating at all. CS336’s data lecture makes the same point from the other side: there is no single best filtering threshold; longer training wants more data, shorter training less but better data.

So for each stage, ask three questions:

  1. At the training budget I intend, does a model trained on the processed data do better on the capabilities I care about?
  2. What coverage did it remove? Languages, domains, code, styles, topics: read samples of the removed documents.
  3. How much data is left, and how many times will the model have to repeat it?

FineWeb answered the first question with 1.71-billion-parameter models trained on 28 to 350 billion tokens. That is strong evidence at that scale and for that benchmark suite, and a reason to re-check at yours.

Benchmark contamination

A model is evaluated on benchmark questions it should not have seen. Contamination means training-data exposure to the evaluation’s items, their answers or solutions, or close derivatives of them, such as paraphrases or translations of the same questions. It does not mean that the model learned facts that a benchmark also tests: knowing that plants absorb carbon dioxide is general knowledge, and learning it is the point of pre-training.

Take a benchmark item: “Which gas do plants absorb from the air? (A) oxygen (B) carbon dioxide (C) nitrogen (D) helium. Answer: B.” Three pages:

The usual check searches the corpus for overlapping word sequences from each item. The quiz page shares all 6 of the question’s three-word sequences and is caught. But the textbook page and the reworded item share exactly 1 each, from the air: word overlap cannot tell general knowledge from a derivative. Overlap checks catch copies; paraphrases and translations need semantic search and human judgement, and the most reliable protection is keeping your own evaluation data out of the pipeline from the start. The FineWeb paper does not describe a benchmark decontamination step, so if you train on it and evaluate on public benchmarks, that check is yours to make.

Personal information

FineWeb anonymizes email addresses and public IP addresses with regular expressions (§3.7). datatrove’s PIIFormatter on a toy sentence:

Before: Write to jane.doe@gmail.com or ping 8.8.8.8; my name is Jane Doe.
After:  Write to email@example.com or ping 22.214.171.124; my name is Jane Doe.

The email and IP address are replaced; the name, and anything else the patterns do not describe, is untouched. Pattern-based removal is cheap and predictable but narrow. Stronger privacy protection needs entity detection, an audit of what it misses and wrongly removes, and provenance so that removal requests can be honoured.

Failure modes

MistakeHow it shows upCheck
A filter removes a domain or language you needThe trained model is weak there; removed samples contain good textRead samples of each stage’s removals, per domain and language
Processing judged at the wrong budgetA filter that helped in small ablations hurts a long run through heavy repetitionCompute passes over the data at the real budget; re-test at a larger budget
Evaluation items left in the corpusHigh scores on a public benchmark, weak results on fresh questionsOverlap search on items and answers, plus semantic search and a private held-out set

Where this goes next

The corpus is still text. Before training it must become token IDs, and the tokenizer decides how many tokens each language and kind of text costs, which changes how much of the corpus a fixed budget covers. That is the next post. For the experiments behind FineWeb’s choices and what they do and do not establish, see the FineWeb review.

What to remember

Try it yourself

Sources

Further reading