Add sandbox API and mini SWE agent 2 OpenSandbox evaluation - #1368
Add sandbox API and mini SWE agent 2 OpenSandbox evaluation#1368hemildesai wants to merge 24 commits into
Conversation
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
Signed-off-by: Hemil Desai <hemild@nvidia.com>
| yield | ||
| return | ||
| async with recorder.span(name, phase=phase, attributes=attributes): | ||
| yield |
There was a problem hiding this comment.
do we need all this otel stuff immediately?
There was a problem hiding this comment.
Agreed, breaking this down to a smaller PR without the observability module.
|
|
||
| A NeMo Gym Responses API agent that integrates | ||
| [mini-swe-agent](https://github.com/SWE-agent/mini-swe-agent) v2 for evaluating | ||
| language models on SWE-bench style software engineering tasks through the public |
There was a problem hiding this comment.
can we have a simple hello world like math with python tool?
| return AsyncRetrying, retry_if_exception, stop_after_attempt, wait_random_exponential | ||
|
|
||
|
|
||
| def _httpx_retryable_types() -> tuple[type[BaseException], ...]: |
There was a problem hiding this comment.
could we use aiohttp instead or this is a hard opensandbox requirement?
|
|
||
| This module is the boundary Gym code should use when it needs a sandbox. | ||
| Provider packages implement the lower-level async protocol; callers use | ||
| ``AsyncSandbox`` in async code and ``Sandbox`` in synchronous integrations. |
There was a problem hiding this comment.
maybe default should be async?
cmunley1
left a comment
There was a problem hiding this comment.
could you check the steps here, such as example.jsonl and example_rollouts.jsonl
https://docs.nvidia.com/nemo/gym/main/contribute/environments/new-environment/#contribution-workflow
| "results/*", | ||
| "/tmp/*", | ||
| "benchmarks/*", | ||
| "nemo_gym/sandbox/observability/recorder.py", |
|
|
||
|
|
||
| class _ObservedModel: | ||
| """Add an OTel span around each mini-SWE model query.""" |
There was a problem hiding this comment.
will each sandbox-using env have to do this?
There was a problem hiding this comment.
No, this is only to capture llm calls in otel telemetry and is optional
| ) | ||
|
|
||
| print(f"[EVAL]{instance_id} Running eval", flush=True) | ||
| eval_report = _run_eval_v2( |
There was a problem hiding this comment.
could this verify step become a resources server so that eval logic can be reused across agent harness? maybe this is out of scope for sandbox poc though.
There was a problem hiding this comment.
For SWE I think it needs to run on a particular image and each task will likely have a different image IIUC?
|
We are going to break this down into smaller PRs for easier review. The first split keeps the scope to the sandbox API, OpenSandbox provider, and Mini SWE Agent 2 evaluation integration, without the observability module. |
## Summary Parent PR: #1368 Refs #1337 This is the first smaller PR split out from #1368. It keeps the scope to the provider-neutral sandbox API, the OpenSandbox provider, and the Mini SWE Agent 2 evaluation integration. Observability is intentionally left out for a follow-up PR. ### Features - Adds the public `nemo_gym.sandbox` facade with async and sync sandbox clients, provider registration, image rewrite support, sandbox specs/handles, and batch create support. - Adds the OpenSandbox provider with create/connect/exec/file/close operations, SDK pool-backed batch creation, retry handling, create probes, direct exec endpoint support, and nested provider configuration sections. - Adds `responses_api_agents/mini_swe_agent_2`, a sandbox-backed mini-swe-agent v2 integration for SWE-bench style evals, including sandbox resource profiles, task metadata propagation, reward aggregation, and `ng_collect_rollouts` usage docs. - Adds focused unit coverage for the sandbox facade, provider registry, OpenSandbox provider behavior, Mini SWE Agent 2 run/aggregation behavior, and sandbox environment adapter. - Moves sandbox-related dependencies behind the `nemo-gym[sandbox]` optional extra. ### Notes - This PR does not include the sandbox observability module from #1368. - The Mini SWE Agent 2 README avoids internal deployment names and user-specific paths; examples use placeholders and local `data/` / `results/` paths. ## Validation Completed on the squashed commit: ```bash uv run ruff check nemo_gym/sandbox responses_api_agents/mini_swe_agent_2 tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py ``` Result: `All checks passed!` ```bash uv run pytest tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py responses_api_agents/mini_swe_agent_2/tests/test_app.py responses_api_agents/mini_swe_agent_2/tests/test_sandbox_environment.py -q ``` Result: `44 passed, 2 warnings` ```bash uv run coverage run --source=nemo_gym.sandbox,responses_api_agents.mini_swe_agent_2 -m pytest tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py responses_api_agents/mini_swe_agent_2/tests/test_app.py responses_api_agents/mini_swe_agent_2/tests/test_sandbox_environment.py -q uv run coverage combine results uv run coverage report --include='nemo_gym/sandbox/*,responses_api_agents/mini_swe_agent_2/*' --fail-under=90 ``` Result: focused coverage `92%`. Kubernetes smoke validation: - Model: `Qwen/Qwen3.5-27B`, served by SGLang with DFLASH draft model `z-lab/Qwen3.5-27B-DFlash`. - Launched the Mini SWE Agent 2 stack through the documented `ng_collect_rollouts` path. - Ran 8 SWE-bench Verified samples with 8 repeats and 64-way rollout concurrency against the OpenSandbox internal service path. - Result: 64/64 rollout rows, `pass@8=0.875`, 7/8 tasks resolved, mean reward `0.765625`, eval error rate `0.0`, reward profile completion `100%`. - Cleanup completed with no leftover sandboxes for the successful internal-service run. Full SWE-bench Verified validation: - Model: `Qwen/Qwen3.5-27B`, served by SGLang with DFLASH draft model `z-lab/Qwen3.5-27B-DFlash`. - Ran 500 SWE-bench Verified samples with pass@1, 500-way rollout concurrency, `step_limit=250`, and OpenSandbox cleanup metadata. - Result: 500/500 rollout rows, `pass@1=0.698`, 349/500 tasks resolved, mean reward `0.698`, eval error rate `0.6`, tests status rate `99.0`, reward profile completion `100%`. - Job duration: `4h6m`; rollout collection duration: `4h04m`. - Cleanup left no sandboxes with the run labels `run_family=mini-swe2-firstpr-q35-cell-full-p1-r9` or `cleanup_id=full-p1-r9-single-20260521-053410`. --------- Signed-off-by: Hemil Desai <hemild@nvidia.com>
## Summary Parent PR: #1368 Refs #1337 This is the first smaller PR split out from #1368. It keeps the scope to the provider-neutral sandbox API, the OpenSandbox provider, and the Mini SWE Agent 2 evaluation integration. Observability is intentionally left out for a follow-up PR. ### Features - Adds the public `nemo_gym.sandbox` facade with async and sync sandbox clients, provider registration, image rewrite support, sandbox specs/handles, and batch create support. - Adds the OpenSandbox provider with create/connect/exec/file/close operations, SDK pool-backed batch creation, retry handling, create probes, direct exec endpoint support, and nested provider configuration sections. - Adds `responses_api_agents/mini_swe_agent_2`, a sandbox-backed mini-swe-agent v2 integration for SWE-bench style evals, including sandbox resource profiles, task metadata propagation, reward aggregation, and `ng_collect_rollouts` usage docs. - Adds focused unit coverage for the sandbox facade, provider registry, OpenSandbox provider behavior, Mini SWE Agent 2 run/aggregation behavior, and sandbox environment adapter. - Moves sandbox-related dependencies behind the `nemo-gym[sandbox]` optional extra. ### Notes - This PR does not include the sandbox observability module from #1368. - The Mini SWE Agent 2 README avoids internal deployment names and user-specific paths; examples use placeholders and local `data/` / `results/` paths. ## Validation Completed on the squashed commit: ```bash uv run ruff check nemo_gym/sandbox responses_api_agents/mini_swe_agent_2 tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py ``` Result: `All checks passed!` ```bash uv run pytest tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py responses_api_agents/mini_swe_agent_2/tests/test_app.py responses_api_agents/mini_swe_agent_2/tests/test_sandbox_environment.py -q ``` Result: `44 passed, 2 warnings` ```bash uv run coverage run --source=nemo_gym.sandbox,responses_api_agents.mini_swe_agent_2 -m pytest tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py responses_api_agents/mini_swe_agent_2/tests/test_app.py responses_api_agents/mini_swe_agent_2/tests/test_sandbox_environment.py -q uv run coverage combine results uv run coverage report --include='nemo_gym/sandbox/*,responses_api_agents/mini_swe_agent_2/*' --fail-under=90 ``` Result: focused coverage `92%`. Kubernetes smoke validation: - Model: `Qwen/Qwen3.5-27B`, served by SGLang with DFLASH draft model `z-lab/Qwen3.5-27B-DFlash`. - Launched the Mini SWE Agent 2 stack through the documented `ng_collect_rollouts` path. - Ran 8 SWE-bench Verified samples with 8 repeats and 64-way rollout concurrency against the OpenSandbox internal service path. - Result: 64/64 rollout rows, `pass@8=0.875`, 7/8 tasks resolved, mean reward `0.765625`, eval error rate `0.0`, reward profile completion `100%`. - Cleanup completed with no leftover sandboxes for the successful internal-service run. Full SWE-bench Verified validation: - Model: `Qwen/Qwen3.5-27B`, served by SGLang with DFLASH draft model `z-lab/Qwen3.5-27B-DFlash`. - Ran 500 SWE-bench Verified samples with pass@1, 500-way rollout concurrency, `step_limit=250`, and OpenSandbox cleanup metadata. - Result: 500/500 rollout rows, `pass@1=0.698`, 349/500 tasks resolved, mean reward `0.698`, eval error rate `0.6`, tests status rate `99.0`, reward profile completion `100%`. - Job duration: `4h6m`; rollout collection duration: `4h04m`. - Cleanup left no sandboxes with the run labels `run_family=mini-swe2-firstpr-q35-cell-full-p1-r9` or `cleanup_id=full-p1-r9-single-20260521-053410`. --------- Signed-off-by: Hemil Desai <hemild@nvidia.com> Signed-off-by: Rita Fernandes Neves <rfernandesne@nvidia.com>
Summary
Links #1337
This PR adds the sandbox-backed SWE evaluation path centered on OpenSandbox and mini SWE agent 2.
Features
nemo_gym.sandboxAPI with sync/async facades, sandbox handles/specs, provider registration, image rewrite support, and operation observability.sandbox.opensandbox.*event names, and grouped provider config sections:connection,create,probe,operations, andpool.responses_api_agents/mini_swe_agent_2, a sandbox-backed mini-swe-agent v2 integration for SWE-bench style eval, including per-task sandbox config, resource profiles, rollout metadata, andng_collect_rolloutsexamples.nemo-gym[sandbox]optional extra and removes the provider-local OpenSandbox requirements file.User Impact
Users can run mini SWE agent 2 evaluations through the public Gym sandbox facade instead of embedding provider-specific runtime logic in the agent. OpenSandbox settings are now grouped by concern, which keeps the mini SWE config easier to scan and avoids misleading
batch_create_*create retry names.Validation
Completed locally:
uv run ruff check nemo_gym/sandbox/providers/opensandbox/provider.py nemo_gym/sandbox/providers/opensandbox/__init__.py tests/unit_tests/test_opensandbox_provider.py tests/unit_tests/test_sandbox.pyuv run pytest tests/unit_tests/test_opensandbox_provider.py tests/unit_tests/test_sandbox.py responses_api_agents/mini_swe_agent_2/tests/test_app.py responses_api_agents/mini_swe_agent_2/tests/test_sandbox_environment.py -q57 passed, 2 warningsuv run coverage run --source=nemo_gym.sandbox,responses_api_agents.mini_swe_agent_2 -m pytest tests/unit_tests/test_sandbox.py tests/unit_tests/test_opensandbox_provider.py responses_api_agents/mini_swe_agent_2/tests/test_app.py responses_api_agents/mini_swe_agent_2/tests/test_sandbox_environment.py -quv run coverage report --include='nemo_gym/sandbox/*,responses_api_agents/mini_swe_agent_2/*' --fail-under=9091%focused source coveragegit diff --checkresponses_api_agents/mini_swe_agent_2/configs/mini_swe_agent_opensandbox.yamland instantiatedOpenSandboxProvider(**kwargs)from its nested provider config.Validation plan before marking ready for review:
ng_run \ "+config_paths=[responses_api_agents/mini_swe_agent_2/configs/mini_swe_agent_opensandbox.yaml,responses_api_models/vllm_model/configs/vllm_model.yaml]" \ +mini_swe_agent_2.responses_api_agents.mini_swe_agent_2.observability.enabled=true \ +mini_swe_agent_2.responses_api_agents.mini_swe_agent_2.observability.output_dir=results/mini_swe_agent_2_observability/{trajectory_id}ng_collect_rollouts \ +agent_name=mini_swe_agent_2 \ +input_jsonl_fpath=/mnt/rl-workspace/hemild/gym_eval/refactor/inputs/mini_swe_verified_smoke8.jsonl \ +output_jsonl_fpath=results/mini_swe_agent_2/swebench_verified_smoke8.rollouts.jsonl \ +num_repeats=8 \ +num_samples_in_parallel=64 \ '+responses_create_params={max_output_tokens: 32768, temperature: 0.6, top_p: 0.95, metadata: {chat_template_kwargs: "{\"enable_thinking\": true}"}}'results/mini_swe_agent_2_observability/{trajectory_id}.