diff --git a/AGENTS.md b/AGENTS.md index b00e4c722e2..f629a7ac598 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -73,6 +73,21 @@ BaseServer (Pydantic model with config + server_client) └── SimpleResponsesAPIAgent → implement responses(), run() ``` +`BaseServer` and `SimpleServer` live in `nemo_gym/server_runtime/base_server.py`, `SimpleResourcesServer` in +`nemo_gym/server_runtime/base_resources_server.py`, `SimpleResponsesAPIModel` in +`nemo_gym/models/base_responses_api_model.py`, and `SimpleResponsesAPIAgent` in +`nemo_gym/agents/base_responses_api_agent.py`. + +`nemo_gym/` is split into layered packages. From top to bottom: `cli`, `environment`, `eval`, `orchestration`, +`rollouts`, `data`, `agents`, `models`, `server_runtime`, `artifacts`, `metrics`, `verification`, `trajectory`, +`sandbox`, `client`, `telemetry`, `core`, `utils`, `config`. A package imports only packages below it. The +import-linter contract in `pyproject.toml` enforces the order; its `ignore_imports` list holds the known exceptions, +which are removed as the code moves and must not grow. Three modules sit directly in `nemo_gym/`: +`failure_transport.py` and `typed_exceptions.py` share the `core` layer, and `exception_inspection.py` shares the +`utils` layer. `nemo_gym/verifiers/` sits outside the layers: it runs inside Harbor verifier sandboxes and uses only +the standard library. Each package's `__init__.py` docstring says what it holds. Old flat paths such as `nemo_gym.server_utils` still import, with a deprecation warning, until 0.10.0 +(`nemo_gym/_moved_paths.py`). For a summary of each package, see `fern/versions/latest/pages/api-reference/index.mdx`. + For full architecture and concepts (environments, training approaches, verification), see `fern/versions/latest/pages/about/`. ## Creating Environments diff --git a/fern/versions/latest/pages/about/architecture.mdx b/fern/versions/latest/pages/about/architecture.mdx index 2ce4a77d20f..1c90af0eacb 100644 --- a/fern/versions/latest/pages/about/architecture.mdx +++ b/fern/versions/latest/pages/about/architecture.mdx @@ -110,6 +110,10 @@ Gym servers communicate over async HTTP (aiohttp) with: Sandbox execution and file transfer are not Gym HTTP calls. They use the configured sandbox provider's transport, such as HTTP, gRPC, a Docker CLI, or a local subprocess. +## Where the Code Lives + +Each server type has its own top-level directory: `resources_servers/`, `responses_api_agents/`, `responses_api_models/`, and `environment_servers/`. What they share lives in the `nemo_gym` library, which is split into layered packages. For the full map, see [Repository Layout](/api/reference/api-reference#repository-layout). + ## Next Steps diff --git a/fern/versions/latest/pages/api-reference/index.mdx b/fern/versions/latest/pages/api-reference/index.mdx index 28c2974ef4c..4229a9a141e 100644 --- a/fern/versions/latest/pages/api-reference/index.mdx +++ b/fern/versions/latest/pages/api-reference/index.mdx @@ -1,22 +1,93 @@ --- title: "API Reference" -description: "Auto-generated Python API reference for the nemo_gym library." +description: "Auto-generated Python API reference for the nemo_gym library, and how the repository is laid out." --- Auto-generated reference documentation for the `nemo_gym` Python package. This reference is built from docstrings in the [source code](https://github.com/NVIDIA-NeMo/Gym/tree/main/nemo_gym). Browse the sidebar to explore modules, classes, and functions. -## Key Modules - -| Module | Description | -|--------|-------------| -| `nemo_gym.server_runtime.base_resources_server` | Base classes for building resources servers (`SimpleResourcesServer`, `BaseVerifyRequest`, `BaseVerifyResponse`, `BaseMultiRewardVerifyResponse`) | -| `nemo_gym.agents.base_responses_api_agent` | Base classes for building agent servers (`SimpleResponsesAPIAgent`) | -| `nemo_gym.models.base_responses_api_model` | Base classes for building model servers (`SimpleResponsesAPIModel`) | -| `nemo_gym.config.config_types` | Pydantic configuration models for servers, datasets, and CLI | -| `nemo_gym.server_runtime.base_server` | Server utilities and middleware | -| `nemo_gym.client` | The shared aiohttp client (`request`) and the server client (`ServerClient`) | -| `nemo_gym.client.openai_client` | OpenAI API client wrapper | -| `nemo_gym.core` | Shared definitions: the Responses and Chat Completions types, episode and rollout identity, failure kinds | -| `nemo_gym.sandbox` | Provider-neutral sandbox API for isolated command execution and file transfer | +## Repository Layout + +| Directory | What it holds | +|-----------|---------------| +| `nemo_gym/` | The library: everything servers, benchmarks, and the `gym` command line share. See [The nemo_gym Package](#the-nemo_gym-package). | +| `resources_servers/` | Resources servers: one directory per server, with its tools, verifier, configs, and tests. | +| `responses_api_agents/` | Agent servers: built-in agent harnesses and integrations with external ones. | +| `responses_api_models/` | Model servers for inference providers and local models, such as vLLM. | +| `environment_servers/` | Environment servers, such as `single_agent_turn` and `legacy_agent`, that run each episode. | +| `environments/` | Environment configs that wire a resources server, an agent, and a dataset together. | +| `benchmarks/` | Benchmark definitions: config, manifest, and data preparation for each benchmark. | +| `nemotron_recipes/` | Recipe configs for Nemotron models. | +| `examples/` | Example configs, such as Slurm and Kubernetes launches. | +| `scripts/` | Repository maintenance and CI scripts. | +| `tests/` | Unit, functional, and end-to-end tests for the library. Each server keeps its own tests in its directory. | +| `docker/` | The container image build. | +| `fern/` | This documentation site. | + +## The nemo_gym Package + +`nemo_gym` is split into packages, each with one job. The packages form layers: a package builds only on packages below it, so lower packages never depend on higher ones. + +```mermaid +flowchart TB + subgraph entry["Commands and workflows"] + direction LR + cli --> environment --> eval --> orchestration + end + subgraph runs["Rollouts and task data"] + direction LR + rollouts --> data + end + subgraph servers["Servers"] + direction LR + agents --> models --> server_runtime + end + subgraph records["Records and scoring"] + direction LR + artifacts --> metrics --> verification --> trajectory + end + subgraph infra["Infrastructure"] + direction LR + sandbox --> client --> telemetry + end + subgraph base["Foundations"] + direction LR + core --> utils --> config + end + entry --> runs --> servers --> records --> infra --> base +``` + +Read the diagram top to bottom, and left to right within a group: each package may use any package after it, and none before it. + +| Package | What it handles | +|---------|-----------------| +| `cli` | The `gym` command line. | +| `environment` | Authoring environments and benchmarks: manifests, registries, scaffolding, and validation. | +| `eval` | Evaluation on top of collected rollouts. | +| `orchestration` | Starting servers and submitting jobs to clusters. | +| `rollouts` | Collecting rollouts and checking the results. | +| `data` | Datasets and task data. | +| `agents` | The shared base for agent servers. | +| `models` | The shared base for model servers, and converters between model API formats. | +| `server_runtime` | What runs inside every server, including the resources server and environment server bases. | +| `artifacts` | The files a run writes and exports. | +| `metrics` | Rollout metrics, such as reward profiles and pass@k. | +| `verification` | Helpers resources servers share for verification, such as LLM judges. | +| `trajectory` | Records of what happened in a rollout. | +| `sandbox` | Isolated command execution and its providers. See [Sandbox](/main/infrastructure/sandbox). | +| `client` | HTTP calls to Gym servers and model endpoints, including the OpenAI client. | +| `telemetry` | Optional OpenTelemetry instrumentation. | +| `core` | Types every package shares, such as the Responses API types. | +| `utils` | General helpers. | +| `config` | Loading the run config. | + +Three modules sit directly in `nemo_gym/` instead of in a package. `failure_transport` and `typed_exceptions` share the `core` layer: they define the exception a failure raises and carry its failure report from one Gym server to the next. `exception_inspection` shares the `utils` layer and reads the causes, type name, and HTTP status of any Python exception. + +`nemo_gym.verifiers` sits outside the layers. It runs inside a Harbor task's verifier sandbox, so it uses only the standard library. + +Servers, benchmarks, and other code outside `nemo_gym/` import from the package, such as `from nemo_gym.server_runtime import ...`, rather than from the modules inside it. + +### Old Import Paths + +Modules that moved when `nemo_gym` was split into packages keep their old import paths, such as `nemo_gym.server_utils`, until release 0.10.0. Each use of an old path emits a `DeprecationWarning` that names the new one. To update your code, run `python scripts/migrate_imports.py ` from a Gym checkout. diff --git a/fern/versions/latest/pages/data/download-huggingface.mdx b/fern/versions/latest/pages/data/download-huggingface.mdx index 3a5e7e3b62f..bd72127f7f6 100644 --- a/fern/versions/latest/pages/data/download-huggingface.mdx +++ b/fern/versions/latest/pages/data/download-huggingface.mdx @@ -275,9 +275,9 @@ rm -rf ~/.cache/huggingface/hub/datasets---- | Section | Source | |---------|--------| -| Config schema | `nemo_gym/config/config_types.py:306-349` | -| Download logic | `nemo_gym/data/hf_utils.py:57-115` | -| Validation rules | `nemo_gym/config/config_types.py:334-349` | +| Config schema | `DownloadJsonlDatasetHuggingFaceConfig` in `nemo_gym/config/config_types.py` | +| Download logic | `download_hf_dataset_as_jsonl()` in `nemo_gym/data/hf_utils.py` | +| Validation rules | `DownloadJsonlDatasetHuggingFaceConfig.check_output_path()` in `nemo_gym/config/config_types.py` | | Auto-download | `TrainDataProcessor.load_datasets()` in `nemo_gym/data/dataset_preparation.py` | diff --git a/fern/versions/latest/pages/environment-tutorials/mcp-resources-server.mdx b/fern/versions/latest/pages/environment-tutorials/mcp-resources-server.mdx index 23709353e0e..6dda9ef9a27 100644 --- a/fern/versions/latest/pages/environment-tutorials/mcp-resources-server.mdx +++ b/fern/versions/latest/pages/environment-tutorials/mcp-resources-server.mdx @@ -66,7 +66,7 @@ from typing import Any, Optional from fastapi import FastAPI, Request from pydantic import BaseModel, ConfigDict, Field -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseResourcesServerConfig, BaseSeedSessionRequest, BaseSeedSessionResponse, diff --git a/fern/versions/latest/pages/environment-tutorials/multi-step-environment.mdx b/fern/versions/latest/pages/environment-tutorials/multi-step-environment.mdx index f155229fc10..cb4cfe5427c 100644 --- a/fern/versions/latest/pages/environment-tutorials/multi-step-environment.mdx +++ b/fern/versions/latest/pages/environment-tutorials/multi-step-environment.mdx @@ -74,7 +74,7 @@ from typing import List from fastapi import FastAPI from pydantic import BaseModel -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseResourcesServerConfig, BaseRunRequest, BaseVerifyRequest, diff --git a/fern/versions/latest/pages/environment-tutorials/real-world-environment/resources-server-implementation.mdx b/fern/versions/latest/pages/environment-tutorials/real-world-environment/resources-server-implementation.mdx index e28267bbfb7..0f93a2c4be2 100644 --- a/fern/versions/latest/pages/environment-tutorials/real-world-environment/resources-server-implementation.mdx +++ b/fern/versions/latest/pages/environment-tutorials/real-world-environment/resources-server-implementation.mdx @@ -52,7 +52,7 @@ from typing import Any, Dict from fastapi import FastAPI, HTTPException, Request from pydantic import BaseModel, ConfigDict, Field -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseResourcesServerConfig, BaseSeedSessionRequest, BaseSeedSessionResponse, diff --git a/fern/versions/latest/pages/environment-tutorials/resources-server-apis.mdx b/fern/versions/latest/pages/environment-tutorials/resources-server-apis.mdx index 7b1719cac65..36037655bee 100644 --- a/fern/versions/latest/pages/environment-tutorials/resources-server-apis.mdx +++ b/fern/versions/latest/pages/environment-tutorials/resources-server-apis.mdx @@ -198,7 +198,7 @@ The complete server below combines the tool route with final trajectory verifica from fastapi import FastAPI from pydantic import BaseModel -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseVerifyRequest, BaseVerifyResponse, SimpleResourcesServer, diff --git a/fern/versions/latest/pages/environment-tutorials/single-step-environment.mdx b/fern/versions/latest/pages/environment-tutorials/single-step-environment.mdx index f95d38a24ab..7c9d6af97e8 100644 --- a/fern/versions/latest/pages/environment-tutorials/single-step-environment.mdx +++ b/fern/versions/latest/pages/environment-tutorials/single-step-environment.mdx @@ -189,7 +189,7 @@ from typing import ClassVar from fastapi import FastAPI from pydantic import BaseModel -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseResourcesServerConfig, BaseVerifyRequest, BaseVerifyResponse, diff --git a/fern/versions/latest/pages/environment-tutorials/stateful-environment.mdx b/fern/versions/latest/pages/environment-tutorials/stateful-environment.mdx index f315f9f1c29..4b4966f3d02 100644 --- a/fern/versions/latest/pages/environment-tutorials/stateful-environment.mdx +++ b/fern/versions/latest/pages/environment-tutorials/stateful-environment.mdx @@ -51,7 +51,7 @@ from typing import Dict from fastapi import FastAPI, Request from pydantic import BaseModel, Field -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseResourcesServerConfig, BaseSeedSessionRequest, BaseSeedSessionResponse, diff --git a/fern/versions/latest/pages/evaluation/aggregate-metrics.mdx b/fern/versions/latest/pages/evaluation/aggregate-metrics.mdx index f8a49e4d6e0..fc5cba7415b 100644 --- a/fern/versions/latest/pages/evaluation/aggregate-metrics.mdx +++ b/fern/versions/latest/pages/evaluation/aggregate-metrics.mdx @@ -186,7 +186,7 @@ Selects headline numbers from full-run `agent_metrics`. Default returns all `mea ### Example: pass@k ```python -from nemo_gym.server_runtime.base_resources_server import ( +from nemo_gym.server_runtime import ( BaseVerifyRequest, BaseVerifyResponse, SimpleResourcesServer, diff --git a/fern/versions/latest/pages/infrastructure/sandbox/adding-a-provider.mdx b/fern/versions/latest/pages/infrastructure/sandbox/adding-a-provider.mdx index 3e378e871b6..a5547e35601 100644 --- a/fern/versions/latest/pages/infrastructure/sandbox/adding-a-provider.mdx +++ b/fern/versions/latest/pages/infrastructure/sandbox/adding-a-provider.mdx @@ -8,12 +8,12 @@ Add a provider when NeMo Gym needs to create sandboxes through a new runtime bac ## Provider Contract -Providers implement the `SandboxProvider` protocol from `nemo_gym.sandbox.providers.base`. Keep common caller fields on `SandboxSpec`; put backend-specific options in `SandboxSpec.provider_options`. +Providers implement the `SandboxProvider` protocol from `nemo_gym.sandbox`. Keep common caller fields on `SandboxSpec`; put backend-specific options in `SandboxSpec.provider_options`. ```python from pathlib import Path -from nemo_gym.sandbox.providers.base import ( +from nemo_gym.sandbox import ( SandboxExecResult, SandboxHandle, SandboxSpec, diff --git a/fern/versions/latest/pages/model-server/model-call-capture.mdx b/fern/versions/latest/pages/model-server/model-call-capture.mdx index 28d7ef9c8b1..a7469c381e3 100644 --- a/fern/versions/latest/pages/model-server/model-call-capture.mdx +++ b/fern/versions/latest/pages/model-server/model-call-capture.mdx @@ -303,10 +303,7 @@ Read raw records programmatically when you need more than the rollout attachment ```python from nemo_gym.models import CaptureStore -from nemo_gym.rollouts.model_calls import ( - aggregate_model_call_metrics, - read_model_call_records, -) +from nemo_gym.rollouts import aggregate_model_call_metrics, read_model_call_records store = CaptureStore("/absolute/path/to/results/model-calls") calls = read_model_call_records(store, rollout_id) diff --git a/fern/versions/latest/pages/observability/extending.mdx b/fern/versions/latest/pages/observability/extending.mdx index 25adde777ff..6c2d8d08fcc 100644 --- a/fern/versions/latest/pages/observability/extending.mdx +++ b/fern/versions/latest/pages/observability/extending.mdx @@ -21,8 +21,7 @@ step of a verifier or a retrieval call in an agent harness. ## Adding a Span ```python -from nemo_gym.telemetry._fallbacks import is_span_group_enabled, managed_span -from nemo_gym.telemetry import GymSpanGroup +from nemo_gym.telemetry import GymSpanGroup, is_span_group_enabled, managed_span class MyResourcesServer(SimpleResourcesServer): @@ -35,8 +34,8 @@ class MyResourcesServer(SimpleResourcesServer): return BaseVerifyResponse(reward=self._score(answer)) ``` -Import from `nemo_gym.telemetry._fallbacks`, never from `nemo.lens` directly. That module -resolves to the real implementations when `nemo-lens` is installed and to no-op stubs when +Import from `nemo_gym.telemetry`, never from `nemo.lens` directly. These names +resolve to the real implementations when `nemo-lens` is installed and to no-op stubs when it is not, so your server keeps working for users who never install the extra. ## Check the Span Group First @@ -68,7 +67,7 @@ Use `safe_set_span_attributes` to set attributes after a span starts. It drops n values instead of raising, and redacts values whose keys look sensitive. ```python -from nemo_gym.telemetry._fallbacks import safe_set_span_attributes +from nemo_gym.telemetry import safe_set_span_attributes with managed_span(GymSpanGroup.VERIFY, "my_server.parse") as span: result = self._parse(body) diff --git a/fern/versions/latest/pages/reference/faq.mdx b/fern/versions/latest/pages/reference/faq.mdx index 2ad08ac5200..7e24da8114b 100644 --- a/fern/versions/latest/pages/reference/faq.mdx +++ b/fern/versions/latest/pages/reference/faq.mdx @@ -344,7 +344,7 @@ gym env start --config $config_paths Ray is involved in two places: 1. **Main process** (`RunHelper.start()` in `nemo_gym/orchestration/server_supervisor.py`): before launching servers, Gym reads each server's `ray_enabled` declaration from its entrypoint. It starts or joins Ray only if a server declares `ray_enabled = True`. Otherwise no Ray cluster is created. -2. **Server process** (`server_utils.py`): each server process, including Uvicorn managers and workers, connects only when its implementation declares `ray_enabled = True`. +2. **Server process** (`SimpleServer.run_webserver()` in `nemo_gym/server_runtime/base_server.py`, with the Ray helpers in `nemo_gym/server_runtime/ray_support.py`): each server process, including Uvicorn managers and workers, connects only when its implementation declares `ray_enabled = True`. `ray_enabled` defaults to `False`. Server implementations that use Ray declare it as a class attribute: ```python