We trained two language models from scratch that differ only in which made-up facts they read, so we know exactly what each training document did, and used them to grade the methods that claim to trace a model’s knowledge back to its training data.
Training-data attribution methods rank training documents by how responsible they are for something a model says. They are hard to grade, because for a real model nobody knows the right answer. We built the answer in. Two 110M-parameter models were pretrained from scratch on the same 5B tokens, except that each also read the documents for a different half of 528 planted facts about fictional people, places and Python packages, at 2 to 128 documents per fact and early, middle or late in training. Because the other model never saw a fact, the difference between the two is the causal effect of that fact’s documents. We graded eight methods, from keyword search to influence functions and TracIn, on two questions. Finding the documents that contain a fact was easy: keyword search scored 0.995 average precision and TracIn with influence functions 0.82. Telling which documents actually changed the model was not. Gradient methods correlated with the causal effect at first (+0.32 to +0.41), but that came from answer length and difficulty; holding both fixed, none exceeded +0.09, and only one interval cleared zero, by 0.001. Influence computed on the finished model tracked how badly it still answered a fact (+0.73), not what its training documents did. Embedding search kept a small real signal (+0.15).
Average precision of plain keyword search at finding each fact’s documents, the best of eight methods. Retrieval benchmarks reward finding the text, which is the easy part.
The highest correlation any gradient method reached with what the documents actually did, once answer length and difficulty were held fixed. Only one interval cleared zero, by 0.001.
Correlation between influence-function scores on the finished model and the model’s current loss on the fact. It measures what would help now, so forgotten facts score highest.
Facts seen in 128 documents during the first fifth of training that the finished model still answered correctly, against 5% for facts it never saw. Keyword search still found their documents perfectly.
When a model says something, which training documents put it there? Training-data attribution answers with a ranking of documents. It underpins work on data valuation, on finding the source of harmful outputs, and on understanding how models store knowledge. The methods range from plain text search to influence functions, which estimate how much each training example moved the model, and TracIn, which adds up those effects over checkpoints.
Grading them is the problem. For a real model nobody knows which documents were responsible, so evaluations either ask whether a method finds documents that contain the answer, which simple keyword search does well, or retrain models without the top-ranked documents, which is expensive and noisy. The closest recent benchmark, DataDignity, plants fabricated articles by continuing to train finished models, and its authors note that results “may not transfer to real-world pretraining”.
We built the ground truth into pretraining itself. Two models start from nothing and read the same 5B tokens in the same order; the only difference is which half of a set of invented facts each one reads. Whatever one model knows about a fact and the other does not was caused by that fact’s documents.
Both are 110M-parameter versions of Elroy, our from-scratch Llama-style model (12 layers, width 768, 1,024-token context, Elroy’s own 32k tokenizer). Each trained for 19,073 steps on 5.00B tokens of educational Python, web text and synthetic textbooks, read in a fixed order so that every document’s position in training is known. The two finished at the same loss (1.979 and 1.980).
Each fact is one attribute of a fictional entity: the capital of an invented island, the founder of an invented company, the exception an invented Python package raises on timeout. Qwen3.5-9B wrote 22,440 documents stating them in varied styles, from travel blogs to API references (median 139 words), each checked to state its fact verbatim and mention no other. The facts form a balanced grid: two domains, four frequencies (2, 8, 32 or 128 documents), three positions in training (the first fifth, the middle fifth or the last 15%), and two models. Every entity also has two distractor documents about some other detail of it, read by both models, to catch methods that only match the entity’s name. Each planted document filled its own training window, padded with held-out web text, and the two models’ streams differ only in those windows.
Gradients came from all 60 linear layers in the transformer blocks, compressed with fixed random projections (LoGra-style) to 15,360 dimensions; we checked the compression against exact gradients to one part in a million. Each method ranked a pool of 112,270 training windows per model: every planted and distractor window plus 100,000 random others. Queries were each fact in two forms, a sentence to complete and a question, with the answer appended.
For each fact, the causal effect is the log-probability of the right answer under the model that read its documents minus the same under the model that did not, averaged over both query forms. A fact counts as learned if that effect is positive and the trained model ranks the right answer first among 20 invented candidates.
Frequency and timing both mattered. Facts in the last 15% of training were learned most often; facts from the first fifth were mostly forgotten, even with 128 documents.
| Documents per fact | Early | Middle | Late | All |
|---|---|---|---|---|
| 2 | 5% | 2% | 9% | 5% |
| 8 | 9% | 3% | 20% | 11% |
| 32 | 8% | 28% | 80% | 39% |
| 128 | 12% | 66% | 82% | 53% |
| All | 9% | 25% | 48% | 27% |
This is what makes the test useful. The documents of an early fact still contain its text, so a method that only matches text will rank them as responsible, but by the end of training they no longer affect the model.
The usual test: for each query, rank the pool and see how high the fact’s own planted documents land.
| Method | AP, model A | AP, model B | Recall@10 | AP, 2 documents | AP, 128 documents |
|---|---|---|---|---|---|
| BM25 keyword search | 0.996 | 0.994 | 60% | 0.99 | 1.00 |
| TracIn, influence | 0.821 | 0.826 | 51% | 0.82 | 0.78 |
| Influence functions | 0.748 | 0.727 | 48% | 0.78 | 0.58 |
| Embedding search (bge-base) | 0.599 | 0.613 | 36% | 0.52 | 0.71 |
| TracIn, dot product | 0.220 | 0.073 | 9% | 0.05 | 0.29 |
| Gradient cosine | 0.123 | 0.028 | 6% | 0.06 | 0.11 |
| Gradient dot product | 0.075 | 0.019 | 4% | 0.02 | 0.10 |
| Hidden-state similarity | 0.003 | 0.003 | 0% | 0.00 | 0.01 |
Keyword search was nearly perfect, because each invented name appears only in its own fact’s documents. This matches what Chang and colleagues found on real pretraining data: BM25 beats gradient methods at finding passages that state a fact. Among gradient methods, the curvature correction mattered most: plain gradient similarity scored 0.05 to 0.08, influence functions 0.74, and TracIn with influence 0.82. Hidden-state similarity found almost nothing.
The harder test asks whether a method gives more weight to documents that changed the model more. For each fact we took the method’s attributed mass (the average standardized score of the fact’s own documents) and compared it with the fact’s causal effect. To keep frequency, timing and domain from driving the result, both were ranked within each of the 24 cells of the design.
Gradient methods looked promising at first: within cells, their mass correlated with the causal effect at +0.32 to +0.41. But their mass also tracked the length of the answer in tokens (+0.54 to +0.78) and how hard the answer was for the model that never saw it. Both inflate the causal effect, which is a sum of log-probabilities over the answer’s tokens, and both inflate gradients. Holding them fixed removes the signal.
| Method | vs causal effect | vs length | vs difficulty | vs causal effect, controlled |
|---|---|---|---|---|
| Embedding search (bge-base) | +0.21 [+0.14, +0.29] | +0.25 | +0.18 | +0.15 [+0.07, +0.23] |
| Hidden-state similarity | +0.08 [−0.01, +0.17] | −0.06 | −0.05 | +0.13 [+0.04, +0.21] |
| Gradient dot product | +0.32 [+0.23, +0.39] | +0.54 | +0.47 | +0.09 [−0.00, +0.17] |
| Gradient cosine | +0.32 [+0.23, +0.40] | +0.54 | +0.47 | +0.09 [+0.00, +0.17] |
| TracIn, dot product | +0.34 [+0.26, +0.41] | +0.63 | +0.56 | +0.06 [−0.02, +0.15] |
| TracIn, influence | +0.41 [+0.33, +0.48] | +0.78 | +0.71 | +0.04 [−0.04, +0.14] |
| Influence functions | +0.35 [+0.28, +0.43] | +0.70 | +0.63 | +0.03 [−0.06, +0.12] |
| BM25 keyword search | +0.13 [+0.05, +0.22] | +0.18 | +0.26 | −0.02 [−0.10, +0.06] |
Influence functions estimate how much upweighting a training example would lower the loss on a query, at the model’s current parameters. For a fact the model has forgotten, the loss is high and its own documents point straight at the answer, so they score highest. Across all 528 facts, influence-function mass correlated +0.73 with the finished model’s own loss on the fact, and facts the model never learned received more mass than facts it did (standardized 7.8 against 6.2). That is the right answer to “which data would help now” and the wrong one to “which data made the model what it is”. TracIn adds history by summing over checkpoints, but over four checkpoints it did not change the picture.
Most attribution benchmarks score whether a method retrieves documents that contain the answer. Here a keyword index won that test and carried no information about which documents mattered. A benchmark that cannot separate text that is present from text that had an effect will keep rewarding search.
Without controlling for answer length and difficulty, every gradient method would have looked like a moderate success. Any evaluation that correlates attribution scores with an effect measured in summed log-probability should report that check.
The pairing is what made the causal test possible: two models that differ only in which facts they read. At 110M parameters each run took about 10.7 hours on two workstation GPUs, so this kind of ground truth is within reach of a small lab.
The benchmark is public so others can grade their own methods. The two models, with weights saved every 0.5B tokens, are on Hugging Face as tda-124m-A and tda-124m-B. The dataset holds the 528 facts, their planted and distractor documents, the answer key, the stream order with a hash of every training window, the candidate pools and our scores. The code covers the stream builder, training, every method and the causal tests. All planted content is fictional, and everything is Apache-2.0.
Everything ran on 24 to 26 October 2026 on two NVIDIA RTX A4500 GPUs (20 GB each, NVLink) in the trifero lab, scheduled through Slurm. Pretraining used Elroy’s training code with an ordered loader, bf16 autocast, 262,144 tokens per step, learning rate 6e-4 with cosine decay to 6e-5, and ran at about 128k tokens per second. Documents were written by Qwen3.5-9B with vLLM 0.31.0. Gradient features took two to three hours per checkpoint per model on one GPU. Per-query scores and per-fact results for every method are stored in the study repository.