Repository navigation
feat(osworld): add exact multi-turn training support - #2554
Closed
JeffPengCoder wants to merge 45 commits into
Closed
JeffPengCoder wants to merge 45 commits into
JeffPengCoder wants to merge 45 commits into
Conversation
JeffPengCoder
force-pushed
the
feature/osworld-exact-trace-training
branch
from
August 14, 2026 08:38
1ede45f to
57c9970
Compare
Capture semantic model calls and reconstruct exact multi-turn trajectory evidence for policy training. Add the OSWorld resources server, remote sandbox integration, reproducible runtime dependency checks, and focused coverage needed to exercise the trace contract end to end. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Carry scheduler-owned rollout purpose through both the run schema and Responses metadata, cross-check the carriers at the OSWorld boundary, and emit payload-free diagnostics. Keep standalone benchmark callers compatible when purpose is absent while bounding complete rollout attempts and sandbox cleanup. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Reject agent and model servers resolved outside scheduler-approved Gym roots so stale image copies cannot silently serve a mixed source stack. Expose payload-free purpose markers at the final vLLM proxy boundary and cover both accepted and rejected component paths. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
JeffPengCoder
force-pushed
the
feature/osworld-exact-trace-training
branch
from
August 14, 2026 09:27
57c9970 to
e191ef9
Compare
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Allocate a fresh execution ID for each Gym /run dispatch, propagate it through OSWorld child/model/sandbox/result evidence, and keep it out of semantic exact-trace digests. Disable hidden transport replay for non-idempotent /run requests while preserving the public BaseRunRequest JSON shape. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Apply the repository-pinned Ruff 0.9.9 formatter to the execution-trace changes and drop a stale status-poll warning that loses its logging import when merged with current main. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
JeffPengCoder
force-pushed
the
feature/osworld-exact-trace-training
branch
from
August 15, 2026 02:34
6d77121 to
f799a54
Compare
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Contributor
|
/claude review |
Contributor
|
@ananthsub + @hemildesai could you take a look on the RL contract + sandbox logic respectively |
Contributor
|
SHIP WITH CARE — the OSWorld env additions are solid and well-tested; my concern is a few shared-path changes riding along in an OSWorld-scoped PR. Verifier / scoring correctness
Async / operability — looks good
API compatibility — preserved
Dependency hygiene
Notes (author's call)
No BLOCKERs. Recommend confirming the two shared-collector changes are intended for non-OSWorld agents before merge. |
Capture semantic model calls and reconstruct exact multi-turn trajectory evidence for policy training. Add the OSWorld resources server, remote sandbox integration, reproducible runtime dependency checks, and focused coverage needed to exercise the trace contract end to end. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Carry scheduler-owned rollout purpose through both the run schema and Responses metadata, cross-check the carriers at the OSWorld boundary, and emit payload-free diagnostics. Keep standalone benchmark callers compatible when purpose is absent while bounding complete rollout attempts and sandbox cleanup. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Reject agent and model servers resolved outside scheduler-approved Gym roots so stale image copies cannot silently serve a mixed source stack. Expose payload-free purpose markers at the final vLLM proxy boundary and cover both accepted and rejected component paths. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Allocate a fresh execution ID for each Gym /run dispatch, propagate it through OSWorld child/model/sandbox/result evidence, and keep it out of semantic exact-trace digests. Disable hidden transport replay for non-idempotent /run requests while preserving the public BaseRunRequest JSON shape. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Apply the repository-pinned Ruff 0.9.9 formatter to the execution-trace changes and drop a stale status-poll warning that loses its logging import when merged with current main. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
JeffPengCoder
force-pushed
the
feature/osworld-exact-trace-training
branch
from
September 2, 2026 04:01
c90f2fe to
ccbb506
Compare
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Brings NVIDIA-NeMo/Gym 428ff23 into the OSWorld exact-trace branch, moving the baseline from nemo_gym 0.5.1 to 0.7.0rc0. 621 files merged cleanly; six needed a decision, and none of them is a pure 'take one side': server_utils.py -- upstream added a base-URL cache keyed by server name and relocated _build_server_base_url. The branch's _connectable_client_host fix (a wildcard bind address is not a connectable client target, and a proxy-aware client will route 0.0.0.0 externally) is reapplied on upstream's single surviving definition rather than kept as a second one. rollout_collection.py -- both sides restructured the same /run dispatch. The result is a union: the branch's dispatch summary, retry_transport_errors=False (replaying /run can create a second physical VM run) and execution-identity validation, plus upstream's wall-clock latency and route_failures_to_sidecar handling. The branch's masked_sample classification now runs after upstream's token-capture finalization, so a mask raised there is classified too, not only one the agent set itself; its duplicate no_persist/failure_class assignment is dropped in favour of upstream's earlier one. osworld_agent/tests/test_app.py -- both sides define setup_server_client_mocks with incompatible signatures: the branch patches the loader, upstream passes the client. Upstream's definition survives and the branch's six call sites pass mock_load_from_global_config.return_value, which is the client the code under test actually receives, so their intent is unchanged. The remaining test conflicts were additive on both sides with no colliding definition names.
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
The 621-file automerge left four defects that no conflict marker pointed at. Each was found by running the suites, not by reading the diff: - rollout_collection lost 'from copy import deepcopy'. The branch dispatches a deep copy of every row so a fresh execution id never mutates the caller's object; without the import every dispatch raised NameError. 27 tests. - server_utils kept the branch's '_retry_transport_errors' guards but upstream had meanwhile extracted the retry loop into _request_with_retries, leaving the guards reading a name that function does not take. The flag is now threaded through both _traced_request and _request_with_retries, so enabling HTTP tracing cannot silently restore retries on a non-idempotent /run. - The osworld agent now reads global config off its own server_client rather than reloading it globally, so tests that patched app.ServerClient.load_from_global_config were patching a symbol upstream had removed. They build the client through make_server_client() instead, which wires the attribute the agent actually reads. - Two test bodies had been spliced from both sides, so upstream's construction silently overwrote the branch's and the assertions below it tested nothing. Also corrects a resolution of my own: masked_sample classification is back where the branch had it, before token-capture finalization. Moving it after looked like an improvement -- it would also catch masks raised by capture -- but it reclassified a rollout that upstream's own test expects to score, and faithfully merging the branch is the job here, not improving it. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
JeffPengCoder
force-pushed
the
feature/osworld-exact-trace-training
branch
from
September 7, 2026 09:34
24d7905 to
405e953
Compare
This was referenced Sep 7, 2026
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Integrate main dbd26a9 while preserving role-local uv policy and sandbox recovery. Honor explicit prebuilt-venv reuse and shared setup locking. Align OSWorld score aggregation with shared masking/coverage semantics and add regression coverage. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Describe optional dataset metadata without changing session initialization or canonical tasks. Cover legacy and migrated row shapes, preserve task payloads, and allow verify-only rows. Schema and OSWorld resources suite: 330 passed. Signed-off-by: Jeff Peng <jepeng@nvidia.com>
This was referenced Sep 22, 2026
bxyu-nvidia
pushed a commit
that referenced
this pull request
Sep 22, 2026
…3592) ## What does this PR do? Extract the OSWorld-owned changes from #2554 and #3140 into one environment-focused PR. Both original PRs and their branches remain unchanged. This branch is based on upstream `6bbc05ed9`; the implementation comes from the AgentENV benchmark source `360b0df13`. - Exact multi-turn evidence, logical rollout identity, fixed-window/hysteresis history policies, and explicit train/eval contracts. - Runner-owned episode limits and termination facts, evaluator-owned rewards, and separate admission decisions. Canonical OSWorld tasks and evaluator semantics are preserved. - Stateful OSWorld resources server, remote environment support, runtime declarations, benchmark preparation, and regression tests. - AgentENV desktop adaptation through Gym's E2B provider: prebuilt templates, service-port forwarding, configurable noVNC port, and bounded cleanup after failed startup. Changes are limited to `benchmarks/osworld`, the relevant `examples` config, `resources_servers/osworld`, and `responses_api_agents/osworld_agent`. OSWorld-specific dependency-policy tests move into the agent suite. ### Companion and merge dependency The companion **Gym Core runtime-contracts PR #3591** owns the generic installer, rollout collection, HTTP lifecycle, sandbox providers, and shared `vllm_model` changes. E2B gateway/hostname endpoint resolution and SDK transport integration belong there because they serve any E2B consumer, not just OSWorld. The two diffs have no overlapping files and both target `main`. This is review/scope separation, not a claim of runtime independence: **the complete AgentENV path requires the companion Core PR**, particularly `E2BProvider.endpoint()`. The Core PR should land first for complete AgentENV enablement. ## Validation - OSWorld agent/resources/benchmark suites: **353 passed**. - Combined OSWorld + Core tree: **1,425 passed, 2 skipped** across both component suites and focused core, sandbox, transport, model, and compaction regressions. This includes local HTTP connection-sharing tests. - `pre-commit run --all-files`, `uv lock --check --offline`, and `git diff --check`: passed. - Both skips require the optional E2B SDK, absent locally: real-SDK call-shape introspection and E2B/OpenSandbox cross-provider connection sharing. Other local HTTP-sharing fixtures passed. GitHub lint, copyright, DCO and secret detection passed. - Commands for the environment suite: ```bash NEMO_GYM_EXTRA_ROOTS="$PWD" PYTHONPATH=. python -m pytest \ responses_api_agents/osworld_agent/tests resources_servers/osworld/tests \ benchmarks/osworld/tests --import-mode=importlib -q -o addopts='' -o log_cli=false ``` An exhaustive Git-object reconstruction audit accounts for all **92** predecessor change paths: **80 byte-identical**, six clean upstream/source merges, two E2B transport/test conflict adaptations, three dependency/test-organization updates, and one comment-only false-positive annotation on the golden-prompt SHA256. The hash and assertion are unchanged. No unaccounted paths; unrelated upstream files and original executable modes are preserved. Runtime-policy assertions for `vllm_model` remain in the companion PR rather than making the OSWorld test suite own them. ## Rollouts The recorded predecessor completed **361/361** canonical OSWorld tasks on AgentENV: **46.9182% raw reward**, **159/361 binary successes**, no missing/duplicate/masked rows. It used Omni v3, fixed-three-image history, 100 steps, temperature 0.60, and top_p 0.95. Four model-format terminations were evaluator-scored; this is not a claim of zero format failures. The actual CW-DFW run checkout was rechecked: `360b0df131de7671e2a6e243f21c8150a061c5ce`, clean. [Recipe and run evidence](https://gitlab-master.nvidia.com/jepeng/rl/-/blob/36462b79e257cf054c67228d0942c069af29deee/osworld/recipes/benchmarking/nano-omni-osworld-bench/models/nano-omni-v3/cw-dfw-h100-x86_64/agentenv-canonical-s100/README.md). **No fresh GPU rollout or full 361-task evaluation was run for this split.** These scores belong to the predecessor; they are not a new benchmark claim for the split on newer main. No new environment behavior was intentionally introduced by the split. ## Compatibility and benchmark impact The task definitions, evaluator, prompts, parser, history-policy implementation, and exact-trace implementation are unchanged from the tested source. Training's hysteresis policy remains configurable; the recorded benchmark's fixed-3 setting is not imposed on training. The obsolete `httpx-aiohttp` requirement is removed because newer upstream owns `GymAiohttpTransport`; Core preserves the no-config worker guard/fallback. Other agent implementations are not modified here. The automatic Claude review currently fails while obtaining its OIDC token (`ACTIONS_ID_TOKEN_REQUEST_URL` is unavailable). This is an upstream workflow permission issue, not a code-review finding; no CI configuration is changed in this PR. --------- Signed-off-by: Jeff Peng <jepeng@nvidia.com>
Glorf
added a commit
that referenced
this pull request
Sep 28, 2026
## Summary Add an opt-in `sink_window` history policy to the OSWorld Nemotron adapter: retain the earliest screenshots alongside a recent-image window, with intervening turns represented as text in chronological order. This branch includes upstream `main` at `d4c0f86c7` through a normal merge, including the NumPy metadata fix #3649, CI preflight update #3658, and sandbox lifecycle telemetry #3633. The OSWorld foundation from #2554/#3140 was consolidated and merged through #3592, so this PR no longer carries the old exact-trace/Core stack or depends on #2554. It does not require #3591. No separate issue is needed for this follow-up policy extension. ## Changes - Add configurable sink, low-water and high-water counts. Both watermarks include the sink; equal watermarks slide, while unequal watermarks provide hysteresis. - Represent non-contiguous image selections with intervals and render folded text in chronological order. - Distinguish context overflow, transport failure, truncated output, empty output and unparseable output; retain `agent_outcome_family=model_response_invalid` for compatibility. - On context overflow, reduce the recent-image window within the existing retry budget, preserve the sink/current observation, record actual shrink events, and stop when further reduction is impossible. - Preserve main's immediate model-timeout propagation. Report the terminal attempt's completion fact so an earlier malformed sample cannot hide a subsequent transport failure. The latest synchronization also annotates six deterministic SHA-256 prompt goldens that the previous secrets-detector run falsely identified as credentials. Only those literal lines are annotated; the digest values, assertions, repository scanner configuration, and baseline are unchanged. ## Design and compatibility History policy selects image/text turns; the adapter owns model protocol rendering and parsing. The runner owns horizon and runtime failure handling, the evaluator owns reward, and runtime admission owns masking. This PR does not change those ownership boundaries or add a training/evaluation switch. Fixed-window and hysteresis policy IDs and normal-path rendered prompts remain covered by deterministic golden tests, including fixed-3 and 3-10-3. Sink-window is opt-in, not a new default or a claim of improved benchmark score. Context-overflow recovery and more precise failure outcomes are intentional behavioral changes and may affect failed-run outcomes. The legacy scalar `image_window_start` accessor rejects non-contiguous plans; consumers should use `image_intervals` or per-turn decisions. Scope relative to current main remains limited to `responses_api_agents/osworld_agent/`: two implementation files, documentation, and tests. No Gym Core, dependency, deployment, sandbox-provider or model-server changes are included in the PR diff. ## Validation Re-run on the final main-synchronized tree: - **440 passed, zero skipped** across OSWorld agent, resource-server and benchmark tests; one non-failing Starlette deprecation warning. - `pre-commit run --all-files`: passed. - `uv lock --check --offline`: passed. - `git diff --check`: passed. - The same `detect-secrets==1.5.0` hook and checked-in baseline used by CI passed on all nine PR-scoped files after the inline false-positive annotations. - Existing model-timeout propagation, runner admission, prompt-parity, sink selection, overflow recovery and policy-identity regressions passed. The unchanged-overflow retry and mixed parse/transport completion bugs had been reproduced before their earlier fixes. Test invocation, using an existing compatible development environment from this checkout: ```bash export PYTHONPATH="$PWD" export NEMO_GYM_EXTRA_ROOTS="$PWD" python -m pytest \ responses_api_agents/osworld_agent/tests \ resources_servers/osworld/tests \ benchmarks/osworld/tests \ --import-mode=importlib -o addopts='' -o log_cli=false -q pre-commit run --all-files ``` The explicit source root prevents an older editable checkout from shadowing the branch under test; importlib mode avoids the shared `osworld` test-package name collision. These checks are local evidence, not a claim that the upstream CI run has completed. ## Score reproduction OSWorld 361 tasks, Nemotron-3-Nano-Omni v3 (`24e67ea0`), fixed-3 history, 100 steps, one A/B run per arm. Control = main `d4c0f86c7` + #3591 (needed for the E2B `endpoint()` on AgentEnv); treatment = control + this PR. Raw SR 44.61% → 46.62% (Δ +2.01 pp, paired 95% CI [−2.12, +6.07] pp); binary 154 → 159 of 361 (McNemar p = 0.59); 0 masked and 0 missing in both arms; identical history-policy and agent-contract IDs. No degradation. The context-overflow shrink path was not triggered in either run. --------- Signed-off-by: Jeff Peng <jepeng@nvidia.com> Co-authored-by: Michał Bień <mbien@nvidia.com>
Collaborator
Author
|
Closing this original combined PR in favor of the scope-separated follow-ups:
The legacy compaction-session change was dropped from the core split in favor of #3368, which is also still open. The remaining work continues in those focused PRs. The source branch is retained for provenance. |
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.
Summary
This PR adds first-class OSWorld support to NeMo Gym for both standalone evaluation and exact multi-turn RL training. It keeps one OSWorld task/evaluator path while allowing training callers to request the evidence needed to reproduce the model calls that actually drove the desktop.
Gym records the semantic trajectory and the real per-turn prompt, generation, token/logprob, media, identity, termination, and evaluator facts. A trainer such as NeMo-RL remains responsible for validating that evidence, converting it into trainable rows, choosing loss masks, computing advantages, and running backward. Gym never invents an append-only token history when a later multimodal prompt was independently rendered or compacted.
The runtime supports Gym Sandbox with local or remote Docker and a pre-provisioned OpenSandbox KVM Pool. The pinned OSWorld dependency retains canonical task configs and evaluator semantics; Gym owns orchestration and does not patch task setup at runtime.
Scope split and follow-ups
The branch stack is:
Both follow-ups are based directly on this PR and are independent siblings. Because this head lives in a personal fork, they temporarily target upstream
main; their diffs shrink to their own increments after #2554 merges. Transport-contract hardening is also kept out of this PR until it can be reviewed as a separate layer.Design
The ownership boundaries are deliberate:
FAIL, score a task, or decidemax_steps.max_stepsdoes not rewrite its result.mask_sampleview.Logical rollout identity is separate from physical execution identity, so scheduler retries cannot silently merge two attempts. Non-idempotent
/runtransport calls are not retried in place; the scheduler may start a new, separately identified execution.rollout_purposecarries explicit scheduler intent without changing task, prompt, evaluator, or reward semantics, and legacy benchmark callers remain valid when it is absent.History policy and model protocol are separate contracts. This PR includes fixed-window behavior and the hysteresis low/high-water policy used for 3-10-3 training. Each actual model-call boundary is preserved even when compaction changes the prompt prefix. Additional experimental policies remain in focused follow-ups rather than adding model-specific branches to the runner.
Main changes
/dev/kvm, immutable qcow2 identity, and run-scoped cleanup.Standard preparation and execution
From a clean Linux checkout, prepare a five-task Nano Omni smoke run against a Docker/KVM environment:
After the control log reports ready, run from a second terminal or supervisor:
cd benchmarks/osworld tools/run_eval.sh /absolute/run/rootThe benchmark README documents the equivalent OpenSandbox Pool flow, split-host Docker setup, full-population task generation, runtime dependency preparation, evidence locations, and run-scoped recovery.
Validation
mainat9d164bf38; feat(osworld): add exact multi-turn training support #2554 currently contains 85 changed files relative to that base.git diff --checkpass..gitignore, pre-commit, GitHub workflow, root dependency-policy, or lockfile changes relative to currentmain.405e9537acarries the required DCO sign-off.Operational requirements and non-goals
/dev/kvm, the verified qcow2, and sufficient host memory/disk. OpenSandbox instead requires a reachable management API and a compatible pre-provisioned KVM Pool.