Repository navigation
Conversation
|
🌿 Preview your docs: https://nvidia-preview-pr-4885-0ca5d400dfd4.docs.buildwithfern.com/nemo/gym |
bf57998 to
ad4850b
Compare
e54313a to
0f694d1
Compare
| class GDPValResourcesServer(SimpleResourcesServer): | ||
| config: GDPValResourcesServerConfig | ||
|
|
||
| def multiple_workers_unsupported_reason(self) -> Optional[str]: |
There was a problem hiding this comment.
Non-blocking: could we keep the refusal before dependency setup? With num_workers=2, GDPVal now calls ensure_libreoffice() before the shared guard; VoiceBench's IFEval path similarly calls _ensure_nltk(). This can install dependencies unnecessarily or mask the worker-count error with a setup failure. Calling the shared guard early in these constructors would preserve the previous fail-fast behavior.
There was a problem hiding this comment.
Fixed. gdpval, voicebench, the partner_if mock tools and speed_bench now call refuse_unsupported_num_workers(self) at the start of model_post_init, before LibreOffice, the NLTK data, the tool backend or the startup metrics snapshot. run_webserver still checks it once the server is built, so nothing else changes.
The other refusing servers build only in-memory objects or read small files in model_post_init, so their worker-count error already comes first.
The gdpval and voicebench tests now fail if LibreOffice or the NLTK data is set up before the refusal, and both fail without the early check.
ad4850b to
d9751c1
Compare
0f694d1 to
8be02af
Compare
8be02af to
de7392b
Compare
d9751c1 to
cbd84bc
Compare
cbd84bc to
9af254e
Compare
de7392b to
3850380
Compare
3850380 to
7a64c60
Compare
9af254e to
5fd928c
Compare
Some servers keep state that session routing cannot reach, or own a resource that one process must hold, so they cannot run with several workers. They now override multiple_workers_unsupported_reason(), and run_webserver refuses num_workers > 1 with that reason before uvicorn starts: - aviary and toolsandbox keep environments in memory by the env_id in the request body, and their agents send step, verify and close without the session cookie; - critpt pools verify calls in memory into batches submitted together; - osworld owns the Docker host capacity, startup cleanup and its state file; - longmt_eval builds a Ray GPU actor pool per worker; - gdpval claims deliverable directories in memory by task and rollout ID; - terminal_bench_4 deduplicates seeds by the client_session_id and rollout_id in the request body; - vlm_eval_kit waits in memory for every row of an MMBench group; - voicebench's legacy scoring draws every rule-scored row from one random stream shared by the whole server; - enterpriseops_gym sessions and the partner_if mock-tool episodes are process-local, and agentic_if sessions hold their sandbox connections in one process; - the Legal Agent Bench Harbor bridge has an entrypoint outside its server directory, which uvicorn workers cannot import. speed_bench, wmt_translation, proof_judge, genrm_compare, ns_tools and terminus_2_sandboxed_agent refuse only in the configurations that need one process, and get the module-level app otherwise: speed_bench with the Prometheus metrics source, which measures from a snapshot in memory; wmt_translation with COMET, which builds a Ray GPU actor pool per worker; proof_judge with zero_reward_incorrect_groups; genrm_compare with cohort verification; ns_tools with the HTTP PythonTool sidecar on a fixed port; and terminus_2_sandboxed_agent without a resources server, which serves only process-local episode sessions. proof_judge's debug log also takes a file lock around each append, and still writes the record on a filesystem without file locks. The checks that did this job in model_post_init, in config validators and as num_workers: Literal[1], including those main added to voicebench, enterpriseops_gym, agentic_if, the partner_if mock tools and terminus_2_sandboxed_agent, become the method with the same conditions. gdpval, voicebench, the partner_if mock tools and speed_bench check the refusal at the start of model_post_init as well, before they install dependencies, load their backend or take a metrics snapshot, so a misconfigured server fails on the worker count rather than on that setup. A unit test reads every server entrypoint without importing it, including the entrypoints configs name outside app.py, and fails when a server has neither the module-level app nor a refusal. It fails on the parent commit. Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
7a64c60 to
676aded
Compare
5fd928c to
0ca5d40
Compare
What changed and why
Stacked on #4790. This is the last of three changes that let every resources, agent and environment server either run with
num_workers > 1or refuse it at startup with a reason. #4884, now merged, added the refusal method, and #4790 gave every server that is safe with several workers its module-levelapp.The servers below keep state that session routing cannot reach, or own a resource that one process must hold. Each now overrides
multiple_workers_unsupported_reason(), andrun_webserverrefusesnum_workers > 1with that reason before uvicorn starts, and before a dry run returns.aviary(all five entrypoints)env_idin the request body, and the aviary agent sends step, verify and close without the session cookie.toolsandboxenv_idin the request body, andtoolsandbox_agentsends step, close and verify without the session cookie.critptverifycalls are pooled in memory into batches submitted together; the batches, submission counters and API key rotation must be shared by every request.speed_benchmetrics_source: prometheusosworldsessions.jsonstate file are each owned by one process.longmt_evalwmt_translationcompute_cometgdpvalterminal_bench_4client_session_idandrollout_idin the request body, which session routing does not route.vlm_eval_kitharbor_agentdirectory, so the module path uvicorn workers import does not resolve.voicebenchenterpriseops_gympartner_ifmock toolsproof_judgezero_reward_incorrect_groupsgenrm_comparefixed_baselineornum_rollouts_per_prompt > 1)ns_toolsPythonToolpython_tool_port.terminus_2_sandboxed_agentresources_serveragentic_ifspeed_bench,wmt_translation,proof_judge,genrm_compareandns_toolsget the module-levelapptoo, because they are safe in their other configurations:speed_bench's defaultresponsemetrics source scores each request on its own, andwmt_translationwithout COMET, as the IN22 profile runs it, keeps nothing between requests.proof_judge's debug log takes a file lock around each append, asproof_genselectandproof_verificationdo since #4790, and still writes the record on a filesystem without file locks.terminal_bench_4,osworld,genrm_compare,gdpval,voicebench,enterpriseops_gym,agentic_if, thepartner_ifmock tools andterminus_2_sandboxed_agentalready refused several workers, inmodel_post_init, in a config validator or withnum_workers: Literal[1]. Those checks now go through the method with the same conditions, so they all fail the same way and a dry run reports them. A review of the current code suggests thatenterpriseops_gym, thepartner_ifmock tools andterminus_2_sandboxed_agentkeep their per-session state where routing reaches it, so their owners may be able to lift these refusals; this pull request keeps their behavior.run_webserverasks for the reason after it builds the server, and building a server runsmodel_post_init.gdpval,voicebench, thepartner_ifmock tools andspeed_benchdo setup there: installing LibreOffice, downloading NLTK data, loading a tool backend, or taking a metrics snapshot. So each also checks the refusal at the start ofmodel_post_init, which keeps the fail-fast behavior their own checks had: a server with several workers fails on the worker count, not on that setup.A unit test reads every server entrypoint without importing it: each server directory's
app.pyand each module a config names, anywhere in the repository. It fails when a server has neither the module-levelappnor an override of the method, on its class or on a parent server class in the repository, and the message says which to add. The only exemptions are the Gymnasium base class module and the local SEC search library, which configs name but which start no server. The resources server guide now mentions the test.Issue
No separate issue: this follows #3905 and completes its multi-worker support for every resources, agent and environment server.
Validation
pytest -n 16 tests/unit_testsin a virtual environment synced with the extras the unit-test workflow installs (uv sync --extra dev --extra ray --extra sandbox --extra openshell --extra mlflow --extra wandb), on main at 390c954. Every failure also fails on main at the same commit in that environment, apart from onedocker_ptytest that fails under parallel load and passes on its own.gym env testcreates):aviary,toolsandbox,critpt,speed_bench,longmt_eval,wmt_translation,osworld,gdpval,terminal_bench_4,vlm_eval_kit,voicebench,enterpriseops_gym,partner_if,terminus_2_sandboxed_agent,agentic_if,legal_agent_bench,proof_judge,genrm_compareandns_tools. They include a refusal test for each server whose refusal depends on its config, and one forvlm_eval_kit.wmt_translation's venv needs its current requirements, which add the IN22 normalizer.NEMO_GYM_MULTIWORKER_E2E=1 pytest tests/e2e/session_routing.pre-commit run --files <changed files>.Rollout evidence
N/A: the change is a startup check and a debug log lock; no verifier or agent logic changes.
Compatibility
num_workers > 1on a refusing server now fails at startup with the reason, instead of failing in its own way or starting and misbehaving.genrm_comparein its stateless mode (rollout_cohortwithnum_rollouts_per_prompt == 1),speed_benchwith its defaultresponsemetrics source,wmt_translationwithout COMET, andproof_judgeandns_toolsin their other configurations acceptnum_workers > 1.gdpvalrefusesnum_workers > 1inrun_webserverinstead of inmodel_post_init.