feat(toolsandbox): add ToolSandbox multi-turn tool-use benchmark - #1949
Conversation
| # | ||
| # NOTE: scipy is intentionally NOT listed. Upstream used | ||
| # scipy.optimize.linear_sum_assignment for milestone scoring, but scipy is in | ||
| # nemo-gym's [tool.uv] exclude-dependencies and uv strips it from any install |
| # limitations under the License. | ||
| """Agent harness for the ToolSandbox resources server. | ||
|
|
||
| A thin fork of ``aviary_agent``. The difference: ToolSandbox is a |
There was a problem hiding this comment.
Would it be possible to extend the aviary_agent instead? I think it's worth consolidating the two for future maintenance cost.
There was a problem hiding this comment.
A fork here means mostly the structure. I've checked and their logic is way different and it's hard to find something to make it generic.
| gym env start \ | ||
| --config resources_servers/toolsandbox/configs/toolsandbox.yaml \ | ||
| --model-type openai_model \ | ||
| ++policy_base_url=https://openrouter.ai/api/v1 \ |
There was a problem hiding this comment.
These overrides can be replaced with flags, see the mapping
| ++policy_base_url=https://openrouter.ai/api/v1 \ | |
| --model-url https://openrouter.ai/api/v1 \ |
| --config resources_servers/toolsandbox/configs/toolsandbox.yaml \ | ||
| --model-type openai_model \ | ||
| ++policy_base_url=https://openrouter.ai/api/v1 \ | ||
| ++policy_api_key=$OPEN_ROUTER_KEY \ |
There was a problem hiding this comment.
| ++policy_api_key=$OPEN_ROUTER_KEY \ | |
| --model-api-key $OPEN_ROUTER_KEY \ |
| --model-type openai_model \ | ||
| ++policy_base_url=https://openrouter.ai/api/v1 \ | ||
| ++policy_api_key=$OPEN_ROUTER_KEY \ | ||
| ++policy_model_name=qwen/qwen3.5-9b |
There was a problem hiding this comment.
| ++policy_model_name=qwen/qwen3.5-9b | |
| --model qwen/qwen3.5-9b |
| @@ -0,0 +1,320 @@ | |||
| # For licensing see accompanying LICENSE file. | |||
There was a problem hiding this comment.
Consider removing this directory. Based on the info in VENDORING.md (L44) I conclude that this dir is not needed by the server. The maintenance cost might outweigh the benefits of having the ability to run offline checks.
| return kwargs | ||
|
|
||
|
|
||
| class OpenAIAPIAgent(BaseRole): |
There was a problem hiding this comment.
If you decide to remove the cli dir, this class is no longer needed (I think)
Native gym port of apple/ToolSandbox — a stateful, conversational, tool-using benchmark — built on the aviary env pattern. The agent-under-test is the gym policy model driven by the toolsandbox_agent harness; the user simulator and the Python execution environment run inside the resources server; verify() is pure scoring. Reward is the milestone similarity in [0, 1] (0 if a minefield is hit). - resources_servers/toolsandbox — ToolSandboxResourcesServer with the aviary env lifecycle: seed_session -> obs + tools, /step(action) -> obs + done, /close (computes and caches the milestone/minefield breakdown), /verify (returns the cached reward). Each seed/step/close runs its role work inside its own asyncio.Task so concurrent episodes never share the vendored process-global ambient ExecutionContext. - responses_api_agents/toolsandbox_agent — thin fork of aviary_agent that forwards the whole model output (assistant text AND tool calls) to /step and lets the resources server decide done, so a natural-language turn routes to the user simulator instead of ending the rollout. - Vendored tool_sandbox/ (Apple custom source license) is used unchanged except for the conversation driver; scipy.optimize.linear_sum_assignment is replaced by a vendored dependency-free solver (scipy is excluded from the gym install), validated bit-identical to scipy. See tool_sandbox/VENDORING.md. - prepare_toolsandbox.py writes data/test.jsonl (one row per scenario index); committed example.jsonl is the 5-row smoke set. - toolsandbox.yaml wires the server + agent for local eval/training; toolsandbox_serve.yaml serves both for nemo-evaluator via the gym:// adapter. - Opt-in heavy deps live in requirements.txt (per-server .venv); ATTRIBUTIONS.md and pyproject ruff exclude cover the vendored tree. - Unit tests cover the scenario index, seed/step/close/verify, tool-call and natural-language routing, error observations, context isolation, the message cap, and user-sim extra_body flattening (19 tests). Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…iguration Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…uilders Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
| | Component | Type | License | Author / Copyright | URL | | ||
| |------------|------|----------|--------------------|-----| | ||
| | **ToolSandbox** | Tool-use benchmark (scenarios, tools, sandbox, scoring) | Original: Apple MIT License (see full text below). NVIDIA modifications: Apache-2.0 | Copyright (C) 2024 Apple Inc.; Modifications Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES | https://github.com/apple/ToolSandbox | | ||
|
|
There was a problem hiding this comment.
Vendored code approval: https://nvbugspro.nvidia.com/bug/5519198
|
/ok to test |
@ritaneves, there was an error processing your request: See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/1/ |
|
/ok to test 639483a |
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…PDX license information Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
… modifications Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…ications Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…nd tests Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
639483a to
41d17f8
Compare
…DIA-NeMo#1949) Native gym port of apple/ToolSandbox — a stateful, conversational, tool-using benchmark — built on the aviary env pattern. The agent-under-test is the gym policy model driven by the toolsandbox_agent harness; the user simulator and the Python execution environment run inside the resources server; verify() is pure scoring. Reward is the milestone similarity in [0, 1] (0 if a minefield is hit). - resources_servers/toolsandbox — ToolSandboxResourcesServer with the aviary env lifecycle: seed_session -> obs + tools, /step(action) -> obs + done, /close (computes and caches the milestone/minefield breakdown), /verify (returns the cached reward). Each seed/step/close runs its role work inside its own asyncio.Task so concurrent episodes never share the vendored process-global ambient ExecutionContext. - responses_api_agents/toolsandbox_agent — thin fork of aviary_agent that forwards the whole model output (assistant text AND tool calls) to /step and lets the resources server decide done, so a natural-language turn routes to the user simulator instead of ending the rollout. - Vendored tool_sandbox/ (Apple custom source license) is used unchanged except for the conversation driver; scipy.optimize.linear_sum_assignment is replaced by a vendored dependency-free solver (scipy is excluded from the gym install), validated bit-identical to scipy. See tool_sandbox/VENDORING.md. - prepare_toolsandbox.py writes data/test.jsonl (one row per scenario index); committed example.jsonl is the 5-row smoke set. - toolsandbox.yaml wires the server + agent for local eval/training; toolsandbox_serve.yaml serves both for nemo-evaluator via the gym:// adapter. - Opt-in heavy deps live in requirements.txt (per-server .venv); ATTRIBUTIONS.md and pyproject ruff exclude cover the vendored tree. - Unit tests cover the scenario index, seed/step/close/verify, tool-call and natural-language routing, error observations, context isolation, the message cap, and user-sim extra_body flattening (19 tests). --------- Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Native gym port of apple/ToolSandbox — a stateful, conversational, tool-using benchmark — built on the aviary env pattern. The agent-under-test is the gym policy model driven by the toolsandbox_agent harness; the user simulator and the Python execution environment run inside the resources server; verify() is pure scoring. Reward is the milestone similarity in [0, 1] (0 if a minefield is hit).