Log documents_seen / num_documents and offer it as a W&B x-axis#559
Merged
Conversation
Reintroduce the per-step document count and cumulative documents-seen metrics on the static-schedule path, independent of `docs_per_step`. `ScheduleRunner` exposes the whole-step DP-summed document count (`num_documents_in_batch`, the loss-normalization divisor) as `_num_documents_in_batch`, set once per step in `_preprocess_data`; it is `None` when the data carries no document counts (non-RL runs). The trainer accumulates it into `_documents_seen` every step (persisted in checkpoint metadata) and logs `num_documents` + `documents_seen` when available. `Wandb` lazily declares `training/documents_seen` as an alternative `step_metric` for `training/*` on the first log that carries it, so it can be used as a cross-run x-axis without affecting non-RL runs. The global `wandb.log(step=...)` step is unchanged, so both axes remain available. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 8, 2026
…rop dead check, reword comments
- Return `num_documents_in_batch` as a 4th element of `ScheduleRunner.run_step`'s tuple instead of
having the trainer reach into the runner's private `_num_documents_in_batch` attribute — the
runner already returns everything else it computes (`reduced_losses`, `update_successful`,
`metrics`) this way, and the private attribute is also mutated by evaluation's `run_step` calls
on the same shared runner later in the same iteration.
- Drop the `isinstance(values, dict)` guard in `Wandb.log_metrics`: `metrics` is always
`dict[str, dict[str, float | int]]` per its own type signature.
- Reword comments that named "RL" as the consumer to describe the value instead.
- Dedupe the repeated `f"{PhaseType.training}/documents_seen"` literal into a local variable.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ssing flag Document counting was only enabled indirectly, by whichever loss's preprocessing config happened to request it (currently only GRPO/GSPO). Flip `TokenPreprocessingConfig.return_document_count` to default `True` so `documents_seen`/`num_documents` populate for any run, and drop the now-redundant explicit request from the policy-gradient loss config. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Now that document counting is unconditional (previous commit), the flag itself has no consumer that can turn it off. Drop the field and make the count computation in TokenBatch._get_model_input unconditional; update the preprocessing test's cross-product accordingly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tch_data num_documents is now always set by _get_model_input (no opt-in flag left to gate it), and no other production or test path constructs a TokenModelInput bypassing _get_model_input, so the check was always true. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…onfig TokenPreprocessingConfig added no fields of its own after the previous commit removed return_document_count. Use LengthPreprocessingConfig (its only base) directly, matching the sibling PatchPreprocessingConfig. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
documents_seen is now always present in the training metrics (document counting is unconditional), so the lazy define-on-first-log dance and its _defined_documents_axis flag were dead weight. Declare the custom x-axis once, at the same point as the rest of the one-time wandb setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Document counting is unconditional now, so the presence check was dead; num_documents/documents_seen show up in both the console log line and W&B on every logging step instead of only when the check happened to pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… W&B x-axis - run_step's document count is always an int (all top-level inputs are TokenModelInput); drop the illusory int|None plumbing and the trainer's None guard. - Drop the consumer-naming duplicate comment on _num_documents_in_batch. - Drop the redundant class-level _documents_seen = 0 default. - Drop the define_metric block so global step stays the default x-axis; documents_seen remains a logged, selectable metric. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Extract the real-document-count local in _get_model_input and reuse it for both num_documents and num_documents_in_sequence. - Reword the num_documents comment to describe this rank's contribution. - Drop the comment restating the documents_seen accumulation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude Sonnet 5, on behalf of @jlamypoirier.
Summary
Extracted from #553 as the first, independent piece of the RL diagnostics umbrella: the
documents_seendocument-clock counter itself. Split out ahead of theweights_readydocument-count model version + reward/model_version staleness metrics (separate PRs) because
those both depend on this counter existing (the model version is
documents_seen, andstaleness is computed as
documents_seen - model_version) — this PR has no dependents-sideprerequisites and stands alone.
ScheduleRunnerexposes the whole-step DP-summed document count (num_documents_in_batch,the loss-normalization divisor) as
_num_documents_in_batch, also returned as part ofrun_step's return tuple._documents_seenevery step (persisted in checkpointmetadata, restored on resume) and logs
num_documents+documents_seenin the step metrics(console + W&B) on every logging step.
Wandbdeclarestraining/documents_seenas an alternativestep_metricfortraining/*atsetup, so it can be used as a cross-run x-axis. The global
wandb.log(step=...)step isunchanged, so both axes remain available.
activate only as a side effect of GRPO/GSPO's loss preprocessing config requesting it (for
their own, unrelated loss-normalization divisor) — an obscure, indirect enablement path for a
training-level metric. Document counting is a real, DP-wide
all_reduceper step, so this is adeliberate tradeoff (sync cost accepted for every run) rather than an oversight. The now-dead
return_document_countflag and its now-emptyTokenPreprocessingConfighost class were bothremoved, along with a couple of downstream now-always-true conditionals this uncovered
(
TokenModelInput.share_batch_data's guard, the lazy W&B metric-definition dance, themetrics-dict presence check).
Tests
tests/data/test_streaming.py: 23 passed (CPU).test_preprocessing.py,test_streaming.py,test_random.py,test_attention.py,test_varlen.py,test_ssm.py,test_lm_losses.py,test_lm_head.py— 1450 passed / 35 skipped, 0 failures.documents_seenaccumulator/checkpoint round-trip; wouldrequire new checkpoint-test infrastructure for GRPO/GSPO models (currently marked
not_implementedintests/utils/model_configs.py) — out of scope here, left as a known gap.tests/models/test_streaming.py::test_model_streaming,which exercises
documents_seen) was not run here (no GPU) — worth running in CI beforemerge.