nemo_gym.rollouts.rollout_collection
nemo_gym.rollouts.rollout_collection
Module Contents
Classes
Functions
Data
AGENT_REQUEST_FAILED_FAILURE_CLASS
ENVIRONMENT_SERVER_FAILURE_CLASS
API
Bases: SharedRolloutCollectionConfig
Spin up all necessary servers and perform a batch of rollout collection using each dataset inside the provided configs.
Examples:
Bases: RunHealthConfig, BaseNeMoGymCLIConfig
Aggregate metrics across rollout shards produced by gym eval run --no-serve +disable_aggregation=true.
Reads every JSONL file matching input_glob, computes aggregate metrics by POSTing to each
agent server’s /aggregate_metrics endpoint over the global union of records, and writes a
single <output_jsonl_fpath stem>_aggregate_metrics.json next to the rollouts. By default
also concatenates all shards into output_jsonl_fpath.
Examples:
Bases: BaseModel
Bases: SharedRolloutCollectionConfig
Perform a batch of rollout collection.
Examples:
Bases: BaseModel
Collect rollouts by sending tasks to a running Gym deployment.
Each rollout batch fetches the deployment’s configuration from the head server.
A caller that runs many batches against one deployment can set reuse_server_client=True.
The helper then fetches the configuration once.
Build a new helper after that deployment’s configuration changes.
Call /aggregate_metrics on the environment server each rollout ran through.
Rows are grouped by the environment server stamped on them at preprocessing
(_ng_environment_server); a row without the stamp is grouped by the environment server
that fronts its agent, as before, so the identity decided at dispatch is the one aggregation
uses, across shards and resumed runs alike. Writes a single _aggregate_metrics.json with one
entry per environment server (same shape as the old _agent_metrics.json, plus the server
name). Returns the file path.
Failed requests retain an entry with empty metric collections and aggregation_error.
By default, re-raise the first original exception after saving partial metrics, preserving
its type and traceback for direct callers such as custom evaluation drivers. Collection and
aggregation entrypoints pass raise_on_error=False to write batch status first, then call
_raise_for_aggregation_errors for a summary error.
Internal dispatch shared by run_examples and Gym’s own collection paths.
record_unrouted_failures returns a failed /run that route_failures_to_sidecar would route as a
failure row whose run_error holds the error, so the collection writer can keep evidence of it before it
raises the error. Other callers keep receiving the exception.
When max_resident_tasks is set, at most that many rollout tasks are admitted
at once. When unset, all examples are scheduled as before. The collection
owner closes either iterator on completion, cancellation or error.
dispatch_budget_s stops starting rows that many seconds after this call, and
drain_margin_s stops sooner for rows that would not have time to finish. A row
drained this way resolves to a Gym-built _dispatch_drained_result.
Identical contract to run_examples, but each future resolves to a _CompletedRollout
that carries rollout_latency_ms alongside the raw /run result instead of inside it,
so internal-only timing never has to be smuggled through (and stripped back out of) a dict
that a direct caller of run_examples could also observe.
interleave_by_agent is enabled by the full evaluation path. Lower-level callers retain
the order they supplied.
Stamp compatibility-routed rows with the bound agent.
These rows never reach resolve_task_sources, so without this they carry no
agent_ref and results, aggregate metrics and reward profiling lose the agent
they ran on. A row that already names an agent is left alone; the name is validated
against the environment server by _validate_environment_servers. Materialized tasks are
skipped: they carry no agent by design, and their result projection is not the
legacy shape this key belongs to.
Fail before any dispatch when a row names an agent absent from the running config.
Without this, the first bad row dies mid-collection with a raw omegaconf ConfigKeyError after valid rows have already been dispatched.
Fail before dispatch when a row points to agent incompatible with the resources server it runs on.
The verifier’s allowed_agents is read from the row’s task_source and from the resources server the
agent binds; the dataset entry that declares the rows may also name the harnesses it admits (a Harbor
dataset’s [gym] allowed_agents, carried into its generated datasets: entry, whose rows route by
taskset to an environment server that binds no resources server). That list is checked against the agent’s
own type, so a run config edited to another harness after gym eval run admitted one is refused here as
well. A materialized row is matched to its entry by taskset, wherever the entry is declared; a flat row
meets every entry the agent declares (see _dataset_admitted_agents).
Apply run-level routing and repetition to caller-held rows.
Public entry point for direct run_examples callers (e.g. trainer integrations that
drive dispatch themselves): run_examples resolves task_sources and validates agent
names, but agent_map, fan_out and num_repeats are applied only during
preprocessing. Call this first, then pass the returned rows to run_examples.
Pass global_config_dict (the merged config) to also resolve task_source-only rows to
their agents here; leave it None to defer that to run_examples, which does it against
the head server’s config. Pass task_ids to keep only those tasks, selected by the id
stored in each row (see nemo_gym.data.task_selection.select_tasks), each task once before
repetition. Input rows are not mutated; the expanded, stamped copies are returned.
Stamp an agent_ref onto every row that carries only a task_source.
task_source names the config instance that declared the row’s dataset. Resolution is
resolve_dataset_agent — the same rules benchmark
discovery uses, so dispatch can never disagree with the listing. Conflicting agent:
pins across one instance’s datasets are a hard error (rows carry only the instance
name), as are unknown/non-routable instances; +agent_map is the disambiguator.
Rows that already have an agent_ref are left untouched, so this is a no-op on legacy datasets and on already-resolved (materialized) rows. Runs before any dispatch.
We provide this function as a lower level interface for running rollout collection.
Rows are dispatched as given: task_sources are resolved and agent names validated here,
but run-level knobs (agent_map, fan_out, num_repeats) are NOT applied — call
preprocess_examples first if you need them.
route_failures_to_sidecar makes a failed /run a failure row instead of an exception
that ends every rollout still in flight. It defaults off because those rollouts then leave
the score.
max_resident_tasks limits admitted tasks and therefore concurrent requests,
even when semaphore allows more. Admission starts when the first returned
awaitable is awaited. None schedules all examples up front, as with
asyncio.as_completed.
To stop early, await the returned iterator’s aclose(): it cancels unfinished
rollouts and waits for their client tasks in this process to end. Cancelling an in-flight
/run closes its connection; a server with ClientDisconnectCancellationMiddleware
subsequently cancels its handler. Server/agent cleanup is not awaited or acknowledged,
depends on the agent, and may continue after return. Sandbox release is not guaranteed.
Handed-out awaitables may return completed results or raise their exceptions, including
CancelledError; bounded awaitables first awaited after closure raise CancelledError.
The error propagates in the awaiting caller’s task even without cancelling that task,
and asyncio.gather and TaskGroup treat it as cancellation.
Without it, abandoned rollouts keep running to completion in the background.
To preserve completed but unconsumed work when stopping, use
await completions.aclose_and_drain() instead. It stops admission before suspending,
cancels and awaits unfinished client tasks, and returns settled (row, result)
futures, including failures. Consume those futures and any outcome already claimed
by an outstanding completion waiter; an unclaimed waiter raises CancelledError.
Repeated drains return an empty list. This also works with bounded admission without
starting more rows, and has the same server/agent cleanup limits as aclose().
Use finally to close the iterator if collection stops early:
dispatch_budget_s stops starting rows that many seconds after this call, and
drain_margin_s stops sooner for rows that would not have time to finish.
Rows start in the order given, once the returned iterator is first consumed.
A row that ran resolves to exactly the (row, result) pair Gym’s own /run endpoint
returned — no Gym-private fields are added to result. A row that produced no /run
result resolves to a Gym-built result carrying Gym-private fields instead: a row drained
by the dispatch budget gets _ng_failure_class="cancelled" with the _ng_dispatch_drained
and _ng_no_persist markers, and a failed /run under route_failures_to_sidecar gets a
failure row with _ng_failure_* fields.
retry_requests=False disables automatic HTTP replay of a mutating /run.
Connections that were never established can still be retried safely.
It does not convert failures to successful result rows.
enrich_results runs enrich_run_result on each result before it is returned, so the caller receives
what ng_collect_rollouts records: the row’s rollout identity, the captured model calls
(ng_model_call_capture, with request and response bodies unless include_model_call_payloads is false),
the standardized ng_trajectory and ng_perf. Model calls are captured only when the global config
enables observability_enabled. delete_model_call_capture removes each rollout’s capture file after it
is merged, and needs the payloads kept. With enrich_results the rows are dispatched as collection
dispatches them, on copies that name this call’s run: results are validated, and under
route_failures_to_sidecar a failed /run comes back as the typed RolloutFailureRecord, as
run_outcomes returns it; rows without a rollout identity keep the plain dispatch. With enrich_results
off, results are exactly what /run returned.
record_output_dir with record_shard also writes each rollout to that run folder through
_RunRecordWriter, as ng_collect_rollouts would: rollouts-<shard>.jsonl, its failures sidecar
with the typed failure rows collection writes, the rows as the shard’s materialized inputs, its run manifest
and its saved progress for gym eval status (omitted-rollout rows with record_omitted_rollouts). It
implies enrich_results, dispatches as collection does (typed
failure records under route_failures_to_sidecar, validated results) on copies of the rows that name the
shard’s run, and the Store, the run health check and gym eval aggregate read the shard like an eval run.
Each copy’s rollout id is the row’s own id (its _ng_rollout_id, or <task>-<rollout>) prefixed with the
shard’s run id, so the shard’s model calls are captured under keys of its own; a caller that looks a capture up
reads its key from the returned row (maybe_rollout_id_from_run_body). gym eval run with
+input_jsonl_fpath=<dir>/rollouts-<shard>_materialized_inputs.jsonl +output_jsonl_fpath=<dir>/rollouts-<shard>.jsonl +resume_from_cache=true resumes a shard and runs only what it still lacks.
Collect rollouts for a whole config. Wrapped in the run-scoped job span.
This is the driver side of an evaluation run and the outermost span Gym produces.
Rollouts are not its descendants: each dispatch opens its own trace, linked to this
span (see _dispatch_span), so a run’s traces stay bounded by one rollout each while
job keeps the run’s own lifecycle. job is in the default preset and not in
per_rollout.
Yield (row, completed_dict | RolloutFailureRecord) in completion order.
Expected HTTP, JSON and result-shape failures become bounded records. Programming
errors and cancellation still propagate. Call preprocess_examples first, or
provide stable explicit rollout ids. This does not persist or retry work; a direct
caller owns those decisions. Supply run_id to associate direct calls with
a run, overriding any row stamp. Without it, existing row stamps are preserved;
unstamped rows share a new invocation ID. Returned rows are invocation-owned copies;
input rows are not modified. run_examples retains its behavior.
On early stopping, await the iterator’s aclose() to cancel and join unfinished
client tasks, or aclose_and_drain() to also retrieve settled, unconsumed outcomes.
Both have the same server/agent cleanup limitations documented by run_examples.
Return a client for the head server, reusing the cached one when the helper opted in.
Without opt-in, every call fetches the configuration from the head server again. An opted-in helper keeps one client and fetches again only when the head config differs from the cached one. Build a new helper after the configuration behind the same head changes.
Health table for a collection whose rollouts have a per-rollout wall-clock limit.
A per-rollout limit (e.g. BrowseComp’s rollout_timeout_s) makes the score depend on the
deployment as well as the model: if the servers are too few or too slow, rollouts start late,
queue for the GPU, or run into the limit, and are scored 0 for reasons unrelated to the model.
This table shows whether a run stayed clear of that, so a score from a starved run is not
mistaken for a model result. Each row compares this run with a healthy bound:
- start coverage: rollouts started within
start_within_sand all started byall_started_within_s(late starts eat into a fixed job allocation); - rollouts ended by the wall-clock limit (above the bound, the limit is shaping the score);
- rollouts longer than
long_rollout_s(an early sign that the limit is too tight); - summed waiting / running requests on the model servers, when their URLs are given (requests queue instead of being served).
Diagnostic only: it prints a warning per unhealthy row and never stops the run.
One sample of requests waiting and running, summed over every server.
Bases: RemovedRolloutOptionsMixin, UploadRolloutsConfigMixin, RunHealthConfig, BaseNeMoGymCLIConfig
Raise the strict run’s rejection, if any; see completion_rejection for the arguments.
The error that rejects unfinished work, or None; omissions alongside completed tasks are allowed.
Collection decides this before it computes the aggregate, so a rejected run publishes no score. Drivers must supply whether any tasks can still be retried and whether this invocation saved outcomes that made progress (not just interruptions). Assuming either can cause endless automatic restarts when a driver has no work left or makes no progress.
final_zero_rows are failure rows that settle their rollout as a scored zero (see
_final_zero_failure_rows): resume does not run them again, so they are completed samples. A caller that
passes completed has already counted them.
Completion-order iterator with a bounded set of resident asyncio tasks.
A finished dispatch as collection stores it, with the facts the collector’s loop still reads.
A finished /run dispatch, with timing carried alongside (not inside) the raw result.
Start every rollout in input order on first use, yielding completion-order awaitables.
Own undelivered outcomes independently of the iterator and its handed-out awaitables.
Map completion metadata to (row, result) for the direct collection APIs.
A thin map over the internal completion iterator that keeps its aclose() reachable, so a
direct caller can stop collecting and cancel the rollouts still in flight.
Run the close hook once, after the outcomes a close still delivers have been enriched.
Cancel unfinished rollouts and await the end of their client tasks in this process.
Cancelling an in-flight /run request closes its connection. A server using
ClientDisconnectCancellationMiddleware subsequently cancels its handler. This method
does not wait for or acknowledge server/agent cleanup, which depends on the agent and may
continue after return; it does not guarantee sandbox release or retire an attempt.
A handed-out awaitable may return an already completed result or raise its exception,
including CancelledError for cancelled work. In bounded mode, an awaitable first
awaited after closure raises CancelledError even if a result was ready. This error
propagates in the awaiting caller’s task without a call to that task’s cancel();
asyncio.gather and TaskGroup treat it as cancellation. Iteration stops after closure.
Safe to call again after closure completes, or before first use (no rollouts start).
Stop admission, cancel unfinished client tasks, and preserve completed outcomes.
Before its first suspension, this operation stops admitting rollouts and snapshots
completed outcomes not yet claimed by a completion awaitable. It then cancels and
awaits unfinished client tasks, and returns settled futures yielding (row, result)
or raising the original exception. No new rollouts start while draining, including
in bounded mode. Outcomes are transferred once; repeated calls return an empty list.
A handed-out awaitable that already claimed an outcome retains it. Other issued
awaitables raise CancelledError. Callers with an outstanding waiter must also
await that waiter and consume its outcome if it was not cancelled. The returned
futures have their exceptions retrieved even if abandoned; awaiting them still raises.
An outcome already cancelled at the snapshot is returned as a cancelled future and
raises CancelledError when awaited. Tasks cancelled by this operation are excluded.
Calling this before first use starts nothing. Calling it after aclose() returns
nothing. Like aclose(), it waits only for local client tasks, not server/agent
cleanup, and does not guarantee sandbox release.
Writes finished rollouts into a run folder the way ng_collect_rollouts lays it out, one shard at a time.
Private: run_examples(record_output_dir=..., record_shard=...) is the entry point, and it hands this writer
the records the collector’s own builder produced. A caller writing rows of its own would bypass that builder.
A shard is <record_output_dir>/rollouts-<shard>.jsonl with its failures sidecar and, when the rows are
given, its materialized inputs, a verified run manifest with every attempt reserved, and its saved progress
(rollouts-<shard>_batch_status.json) beside it, so a folder of shards is what gym eval aggregate, the run
health check, the Store (including resume and recovery) and EvalRDL’s reader already read. The manifest is the one
gym eval run computes when it resumes the shard (+input_jsonl_fpath=<dir>/rollouts-<shard>_materialized_inputs.jsonl +output_jsonl_fpath=<dir>/rollouts-<shard>.jsonl +resume_from_cache=true), so that resume runs only what the shard
still lacks. The caller picks the shard label (for example a training step
and worker); Gym owns the file names. A result goes to the rollouts file, a failed one to the failures sidecar as
the typed failure row collection writes, with its attempt cap, and an interrupted or never-started try to the
sidecar as an omitted-rollout row only when record_omitted_rollouts is set. Opening a shard replaces what an
earlier run wrote under the same label, so a replayed step does not duplicate rows.
Hold the shard’s lock across processes, so opening and each write never interleave with another’s.
The lock file is never unlinked or replaced, so every writer of a label locks the same object; it also holds the token of the writer that opened the shard last.
The manifest gym eval run computes when it resumes this shard, with every row’s attempt reserved.
That resume names the shard’s materialized inputs as its input and the shard as its output, and leaves the other collection settings at their defaults: the same source file, the same rows and, with the same servers, the same configuration. Collection numbers each task’s rollouts 0, 1, … in input order, so rows numbered otherwise are recorded too, and that resume refuses them as other materialized inputs. A configuration this call cannot take an identity from still records the shard, whose manifest then verifies its own inputs only, so a resume refuses it and says why.
Write the shard’s status as it stands, for a caller that stops consuming before every row is in.
Append one finished rollout’s record; returns the file written, or None for an omitted row not kept.
Raises:
RuntimeError: Another writer opened the same shard since this one did.
One sidecar row for a /run call that came back without a result.
No reward and no response: an infrastructure failure is not a verifier score of zero, and a
placeholder would read as real generation data to token capture, aggregation and trainers.
The class says whether the rollout ran. A NeMo Gym server answers 500 when its own handler
raises, so any status it answered with means the rollout ran and broke, which is also how a
model server rejecting the model’s own output arrives here. A gateway status, or no reply to
take a status from, says nothing about the rollout. Neither class carries a reward; an evaluation that wants the
first counted names it in count_failure_classes_as_zero.
Build the metrics-file placeholder for one agent whose aggregation failed.
Keep status identities, failure classes and kinds without retaining rollout payloads.
Build the record ng_collect_rollouts stores for a finished dispatch, success or failure.
result is completed.result after the caller’s episode translation and legacy sanitizing. A failure, typed
or marked, becomes the failures-sidecar row: the typed record’s compatibility fields beside the producer’s
diagnostics and the judge reply it kept, then the identity and routing stamps and the causal failure report.
_RunRecordWriter builds its rows here as well, so an RL shard reads like an eval run.
Collection’s own failure for a failed /run dispatch, caused by the dispatch error, with the report the
reply forwarded. Routing classes remain outcome metadata; this diagnostic has a registered collection kind.
The metric-input copy of a sidecar row counted as zero.
Whether a rollout’s latest sidecar row enters the metrics as a zero: its class is wanted, or it is marked.
State how much of the input the score covers, for the runs where it is not all of it.
Silence here is what makes a partial run look complete, so this reports against the materialized input rather than the rollouts one hop happened to dispatch, and names the rollouts that are in the score only as imputed zeros.
The end of a run whose provider (sandbox, or the grading API) refused its credentials: no attempt succeeds until they are fixed.
(dataset name, allowed_agents) for each dataset entry that declares the dispatched rows with a non-empty
allowed_agents.
A materialized row names its dataset through its taskset, so only the entry that declares that taskset counts
(_datasets_declaring_taskset), not every dataset the executing agent happens to declare: a second,
unrelated entry on the agent cannot refuse the rows. The lookup covers every agent block, not the executing
agent’s alone: a Harbor dataset’s entry sits on the agent block gym eval run generated for it, and a run
config edited to route the taskset’s environment server to another agent block afterwards still has to meet
the dataset’s list. A flat row routed to an agent directly names no dataset, so every dataset that agent
declares counts. So do the executing agent’s entries that set no taskset when no entry anywhere declares
the rows’ taskset: a hand-written entry may list pre-materialized rows under a name of its own
(collate_samples accepts such rows in any entry), and those rows are still that agent’s dataset, so they are
checked rather than none; an entry that sets a taskset materializes and routes its rows as that taskset, so
one naming another taskset does not hold these rows.
A bare string is one entry, as allowed_agents_for reads a resources server’s.
The entries that declare the rows of taskset, on whichever agent block declares them: an entry whose
taskset is that name, or whose name is when it sets none (a Harbor dataset’s generated entry, named after
its taskset and routed by it).
The datasets entries one agent block declares; a list that is missing, a placeholder or not a list
declares nothing.
The result Gym builds for a row the dispatch budget never started.
No row is written anywhere: absence is the resume signal, so the task is
re-dispatched intact next allocation instead of being started and killed
part-way through. _ng_dispatch_drained keeps it out of capture, token
finalization, progress metrics and the rollouts upload, since nothing ran.
One rollout’s dispatch as the root of its own trace, linked to the run’s job span.
The /run call made inside carries this span as traceparent, so the agent’s
gym.rollout span and everything below it join the new trace instead of nesting under
gym.job. The link, not a parent edge, ties the trace back to the job; both carry the
run id as a resource attribute. The identity comes from the collector row, not from
the posted body: a materialized episode body carries it only as episode_id.
dispatch_name is the value the rollout counters record under the same key, so spans
and metrics join on it; server_name is the server the call goes to, which differs for
a row routed by agent. Only a job the driver opened as its own root is split; under an
embedder’s trace the dispatch keeps nesting (see linked_root_span). Gate on the
rollout group and the trace exporter before calling.
Yields the span’s context, which the driver keeps to attach gym.rollout.health later.
enrich_run_result for a result run_examples returns, keeping its public shape.
An Environment Server reply to a materialized task is a BaseEpisodeResponse whose evidence is nested; it is
enriched through the record the collector stores, and the enrichment keys are added to the reply’s top level.
Returns the enriched record.
Return the one environment server that fronts an agent.
A row routed by its agent cannot choose between several environment servers.
Several servers may still front one agent when every row names its server directly.
Materialized tasksets name their environment server through environment_server_routes.
Pick the environment server a row is dispatched to, or None for today’s agent path.
A materialized task (task_id.taskset plus task_input) always routes by its taskset:
it is already an episode request and no agent-server /run accepts it. A flat row follows
environment_routing_mode: agent keeps today’s routing (its agent’s environment server
is resolved at dispatch), legacy sends every flat row to environment_server_name, and
taskset refuses flat rows so a run of materialized rows cannot silently pick up legacy input.
One batch may therefore hold both kinds of rows in agent and legacy mode. The chosen
server is stamped on the row as _ng_environment_server and travels with it through the
materialized input file, retries, and results.
Map each agent name to the environment servers that front it.
Turn a BaseEpisodeResponse into the rollout record the collector stores.
A handled failure becomes a failures-sidecar row, so resume retries a non-terminal one and
never a terminal one. A result is stored as the Environment Server returned it; the collector
adds only its own _ng_* keys, so any Environment Server type can be collected without the
collector knowing its result fields.
Every Environment Server type is scored the same way: through the result’s top-level reward,
with optional top-level reward_components. A reward nested elsewhere in the result is stored as
data, and a result without a top-level reward is unscored.
A failure’s failure_kind is kept under that name, next to the _ng_failure_* diagnostics: it is
the key _record_rollout_outcome reads for the metric label and _counted_failure_row drops.
The typed failure for a reply that is neither an episode result nor a failure.
It names what the reply held (its type and top-level keys, never values), so a producer that answers an episode request with another shape is found from the failure record alone.
Expand a glob-or-comma-separated-globs string into a sorted, deduplicated list of paths.
Examples:
Keep existing sidecar routing keys and diagnostics alongside the canonical failure.
Remove these aliases when row-oriented consumers and #3180 producers migrate. The canonical record never carries generation. The sidecar envelope retains actual judge input for existing —judge-failed-only readers, without a reward. Other legacy response placeholders are discarded.
Preserve producer diagnostics outside the bounded canonical failure record.
Failure and retry counts for exporters, read from the failures sidecars.
The sidecars hold every failed attempt of the run, across resumes, so these are run totals rather
than one job’s. identity keys a sidecar row the way landed keys the rollouts that have a row.
coverage/failed/<class> counts the rollouts with no row, by the class of their last attempt.
retries/attempts counts failed attempts, retries/rollouts_retried the rollouts dispatched
more than once, and retries/at_cap the rollouts with no row that used all their attempts. Each rollout
is held to the cap its collection recorded on its last attempt (_ng_failure_max_attempts), or the
current cap for a row written before the cap was recorded. retries/max_attempts is that cap, and is
left out when the rollouts were collected with different caps. A record_omitted_rollouts row is no failed
attempt; an interrupted one is still the rollout’s latest execution, so an older failure’s class is not counted.
Sidecar rows the caller opted to count in the metrics denominator.
The last attempt of a rollout is the one that stands, so it is selected across every failure class before the wanted classes are picked out. Selecting the other way round would let a stale attempt be counted after a later one landed in a class the caller did not ask for.
A row that already carries a reward is counted as it stands. A row that carries none
records that no rollout happened, so it is counted as a zero here and only here: the score
enters the metric input, never the sidecar or the rollouts jsonl, which keeps the artifacts
free of a verdict no verifier gave. A rollout that also succeeded is never counted. A row its
producer marked with _ng_failure_counts_as_zero is counted whatever its class.
Give the rows the metric input adds, counted failures and imputed zeros, their task’s dataset fields.
Rows are ordered by repeat, so an added row can come first in its task, and metric hooks read task-level fields such as a subset label or a weight from a task’s first rollout. The fields come from the task’s materialized row, and only those that real rows of the same group carry: the aggregator averages every number it is handed, so a field no real row reports would become a metric of its own. A field the verifier computes is not in the materialized row, so the added row lacks it.
The latest failure rows that settle their rollout as a scored zero: final, and marked by their producer.
Resume does not run such a rollout again and the metrics count it as 0, so its work is done. A row counted only
because count_failure_classes_as_zero names its class is not settled: that option scores the metrics, and
resume may still run the rollout.
A rollout’s key across runs, which each number their tasks from 0.
Keys rollout collection writes itself; an Environment Server result must not use them.
ng_trajectory is not one of them: it is the producer’s slot, where an Environment Server forwards
the harness’s own turns from its session close (as an agent’s /run result does), and the collector
replaces it with the canonical projection built from those turns.
True for a BaseEpisodeResponse-shaped reply: object identities plus a result or failure key.
The collector only applies this to a row it dispatched as an episode request
(_materialized_taskset(row)), so an agent’s verify response that echoes identity fields is left alone.
Legacy judge_failsafe carries real generation that can be judged again.
The last failed attempt recorded for each rollout across the failures sidecars.
An interrupted attempt that record_omitted_rollouts recorded is the rollout’s latest execution but no
failure: it hides any older failure, so the rollout is left out here and is missing. A row the dispatch budget
never started, and the evidence of a failed /run with routing off, are skipped (is_non_superseding_rollout_row).
In-progress view of what a run is losing to its environment rather than its policy.
scored covers persisted rollouts only, split into the unmasked ones (count,
reward) and the masked ones; dropped counts what never reached the main output
at all. reward_unmasked averages over the unmasked rollouts alone, so the gap
against the existing reward series is the score lost to infrastructure. Failed and
omitted attempts are reported as counts, never folded into a quality average.
Empty until something is actually masked or dropped, so a healthy run exports exactly
what it exported before. The final numbers come from /aggregate_metrics; this is
the progress view while the run is still going.
Match the canonical class or the original legacy producer’s routing class.
The kind as a bounded label: registered or namespaced names pass, anything else is one bucket.
The environment server a rollout is scored under, as _call_aggregate_metrics groups it.
The row’s stamp, else the one server that fronts its agent, looked up only for an unstamped
row: a materialized row routed by its agent has no stamp while its result has one, and both
must land in the same group. Runs of one agent behind two servers stay apart this way. An agent
behind no server or several stays its own group; _call_aggregate_metrics rejects such a row.
Materialized rollouts that produced no row anywhere, counted as zeros.
The failure classes reach a rollout that failed and said so. This reaches the one that never got that far — killed mid-flight, or dispatched and lost — which leaves nothing in the rollouts jsonl and nothing in the sidecar. Without it such a rollout leaves the denominator as well as the numerator, so the score reads higher the more of the run went missing.
The sidecar is read here rather than trusted from the caller. A failure whose class the caller
left out of count_failure_classes_as_zero is absent from the scored keys, and counting it
here would score the very rollouts that selection excluded — silently turning the selection
into a no-op.
The zero carries the rollout’s identity: its agent, and its environment server stamp when the
row has one, which a materialized taskset row needs because it names no agent. _fill_task_fields
adds the task’s dataset fields. A row that names neither cannot reach any server’s metrics, so
it is warned about rather than counted. The score enters the metric input and nothing else, the
same way a counted failure row does.
Validate the dispatched episode identity before translating its outcome.
Print render() when Slurm’s time limit sends SIGTERM, then terminate as before.
Python’s default SIGTERM action exits without unwinding, so nothing printed in a finally
survives a time-limit kill. Returns the previous handler for _restore_sigterm, or
_NO_SIGTERM_HOOK when no hook could be installed.
The end of a run whose environment server has answered every request so far with a reply the collector cannot use: the producer is wrong, and no attempt can change that.
The end of a run whose grading provider’s quota is exhausted: nothing can be graded until it resets.
Signal failure after partial metrics and any batch status have been saved.
Parse a whole JSONL artifact, letting other tasks on the event loop run between rows.
Parsing stays on the event loop thread instead of a worker thread. The loop thread then reuses the memory it freed during collection for these rows. A worker thread allocates from its own malloc arena, so the process would hold both.
Name the agent’s configured policy server on the record (landed or failed), so offline timing needs no live config and a capture joined later from the capture dir is still partitioned by role.
Evaluate the trajectory health checks on a finished rollout and count the verdict and flagged checks.
With a dispatch_span_context, the verdict and the flagged checks also go on a gym.rollout.health span
under that dispatch span. Gated on telemetry only, not on the post-run report switch. Never raises:
telemetry must not fail a rollout.
Count a persisted attempt, including its numeric reward when scored.
Record the size of one completed rollout, while metrics are exporting.
Turns and tool calls come from the rollout’s ng_perf when rollout observability produced it.
Without it, tool calls are counted from the final response’s function_call items, and turns are not recorded.
Add a stored record’s enrichment and identity keys to the reply run_examples returns in its own shape.
Mark each shard’s run status with the outcome of the aggregation that merged it, keeping its counts.
EvalRDL sums the shards’ status files, so the merged output gets no status file of its own.
Refuse dataset rows whose explicit rollout ID names an attempt.
The suffix -a<N> is reserved: "<id>-a<N>" always means attempt N of rollout <id>,
which is how a training controller names a restored attempt.
A resume retry stamps the next attempt on a row, and an ID that already names one would then fail mid-run,
so the row is refused when the input loads.
The kind of the outermost failure in the chain an agent’s failed reply selected that is not a routing kind.
None without a report, with an omitted or broken chain, or when every failure on it only routes.
The FailureReport an environment reply carries beside its outcome; an invalid one is omitted.
Task then repeat: metrics that read a task’s repeats positionally need that order.
Interleave resolved rows by environment server or agent, preserving each input order.
Agent order is the order in which each name first appears. Rows are returned unchanged, so task/rollout indexes, repeat seeds, and the identities used by resume remain intact.
The agent a rollout ran on, or for a materialized taskset row, which names none, its environment server.
A materialized row, its result and its sidecar row all name the same one.
Yield the rows of the first limit tasks. Identical rows are one task, as in the task index.
Poll every vLLM server’s /metrics and record requests waiting and running, summed over servers.
Discard collector bookkeeping while preserving declared legacy evidence.
The record ng_collect_rollouts would store for completed, for a run_examples call recording a shard.
A try that left no result (interrupted, or never started) is a marker, not an outcome: it keeps its identity and
the writer turns it into an omitted-rollout row. Anything else goes through _collected_outcome, so a failed
/run is saved as the typed failure row collection saves, never as the marker the dispatcher returned. Every
record names the shard’s run, as collection stamps its own, so the Store checks it against the shard’s manifest.
The rollout id a recorded shard dispatches row under: the row’s own id, prefixed with the shard’s run id.
Model calls are captured under the capture key, which is this id with the attempt suffix, and capture files are kept by default. Without the prefix, two shards that dispatch the same task and rollout (a returned row fed back, or indices numbered again each step) share a key, and the later shard’s records carry the earlier shard’s calls. A row an earlier shard returned carries that shard’s prefix, which is replaced rather than nested.
Stamp the row’s identity and routing fields onto the record collection stores, as every reader expects.
The failure kind a sidecar row carries: top-level, the legacy diagnostic key, or the typed record’s.
The PROVENANCE_KEYS of a materialized row’s task_data: provenance stamps for the record.
Preparation writes them (a Harbor row carries the task folder digest as _ng_digest and the
dataset digest as _ng_dataset_digest) so that every results row names the inputs it ran, without
the materialized-inputs sidecar. An Environment Server never returns them (_ng_* is the
collector’s namespace), so the collector copies them from the row onto the record. Only the
allowlisted keys are copied: task_data comes from the dataset, and the collector reads other
_ng_* keys (_ng_no_persist, _ng_failure_class, _ng_result_type, …) that a success
record does not carry, so a dataset could otherwise drop, reroute or relabel its own results.
Decode at most the kept prefix, so a huge error page is never decoded in full.
Attach a finished rollout’s collected evidence to its /run result, in place.
These are the per-rollout steps ng_collect_rollouts runs, shared so a framework that dispatches through
run_examples records the same thing: wait for the model server’s in-flight capture writes for this rollout,
merge its captured model calls (ng_model_call_capture) and join the agent’s observations to them, project the
standardized ng_trajectory, and assemble ng_perf when observability is enabled.
The row’s rollout identity is copied onto the result where the result lacks it, because the capture key is read
from the record. Harness output and reward are never modified. A row that names no task (no task id field,
task index or trajectory identity) gets no ng_trajectory rather than a guessed task id.
include_payloads=False keeps call metadata only; delete_capture removes the rollout’s capture file once it
has been merged, so it requires the payloads to be kept.
Whether readers skip a sidecar row before they pick a rollout’s latest attempt.
A row never started is no execution. A failed /run kept as evidence with routing off is no new outcome: the
attempt it records stands no more than before it was kept, so an older failure still stands and a later attempt
still replaces it. An interrupted record_omitted_rollouts row is neither and still hides older failures.
Whether a failures-sidecar row is a record_omitted_rollouts record of a rollout that produced no result.
Whether a sidecar row records a rollout the dispatch budget never started: no execution, so no history.
Parse one JSONL line, raising a clean ConfigError (naming file + line) on malformed JSON.