Skip to content

chore(deps): pin openai to 2.44.0 - #2456

Merged
ananthsub merged 10 commits into
mainfrom
ananthsub/openai-window-bump
Aug 26, 2026
Merged

chore(deps): pin openai to 2.44.0#2456
ananthsub merged 10 commits into
mainfrom
ananthsub/openai-window-bump

Conversation

@ananthsub

@ananthsub ananthsub commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Closes #2452

This change pins openai==2.44.0 and updates the Responses and Chat schemas used by Gym.

Gym subclasses OpenAI SDK models and copies several request schemas into Pydantic models. The dependency is pinned to one audited version because a version range would allow schema changes that Gym has not handled. OpenAI 2.44.0 is the latest usable release in this update; 2.45.0 makes InputTokensDetails.cache_write_tokens required and breaks NeMoGymResponseInputTokensDetails construction.

Responses items

OpenAI 2.44.0 adds the Codex tool family and context-management items:

  • shell_call and shell_call_output
  • apply_patch_call and apply_patch_call_output
  • tool_search_call and tool_search_output
  • compaction and compaction_trigger
  • additional_tools

The model-generated calls are generation boundaries. Client results, approvals, tool carriers, and compaction records are non-boundaries. Types without a Chat Completions representation remain explicitly inconvertible.

Output and replay input

OpenAI 2.44.0 gives some same-tag output and input models different value domains. NeMoGymResponseOutputItem and NeMoGymResponseInputItem use separate owners for those items.

flowchart LR
    PROVIDER["Provider response"] --> OUTPUT["NeMoGymResponseOutputItem"]
    OUTPUT --> PRESERVE["Preserve provider fields"]
    PRESERVE --> REPLAY["Next request input"]
    REPLAY --> NORMALIZE["Normalize output-only values"]
    NORMALIZE --> INPUT["NeMoGymResponseInputItem"]
    INPUT --> API["OpenAI 2.44 input schema"]
Loading

additional_tools.role is preserved on provider output. Replay changes non-developer roles to developer, which is the only value accepted by the SDK input model.

computer_call_output.status="failed" is preserved on provider output. Replay omits that optional status because the SDK input model does not accept failed.

Local agents may construct a response with the replay-input function_call_output model. The output union continues to accept that model alongside the SDK provider-output model.

Request schemas

The Responses request model includes the fields added through OpenAI 2.44.0, including context management, conversation, moderation, cache controls, and safety identifiers. Native Responses model servers forward these fields.

The Chat Completions request model includes moderation, prompt_cache_key, prompt_cache_retention, safety_identifier, and verbosity. Unknown fields are rejected instead of being silently removed. Deprecated function_call and functions remain disabled.

Shared request fields round-trip through the converter. text.verbosity maps to Chat verbosity. reasoning.effort maps to Chat reasoning_effort, including the 2.44 values none and xhigh. See the Responses reasoning configuration and Chat reasoning effort references.

Nested reasoning controls without a Chat equivalent are rejected. text.format is also rejected until its different Chat and Responses object shapes have an explicit conversion.

Function tools preserve strict. Deferred loading and tool types without an implemented conversion raise NotImplementedError instead of being partially converted. See the Responses tools reference.

flowchart TD
    REQUEST["Responses request"] --> ROUTE{"Model server API"}
    ROUTE -->|"Responses"| PASS["Forward supported Responses fields"]
    ROUTE -->|"Chat Completions"| CHECK{"Lossless Chat conversion?"}
    CHECK -->|"Yes"| CONVERT["Map shared fields"]
    CHECK -->|"No"| ERROR["Raise NotImplementedError"]
Loading

Replay safeguards

OpenAI 2.44.0 adds values that Chat Completions cannot represent. Downconversion now rejects them before information is lost:

  • message.phase
  • function-call namespace
  • function-tool defer_loading=true
  • input images referenced by file_id
  • input-image detail original

Other Responses-only items and fields retain the same explicit rejection path.

Streaming and component compatibility

The streaming sanitizer removes stream_options when it removes stream, because the option is only valid for streaming requests. It consumes additional_tools after hoisting supported function tools into the top-level tools field.

Response comparisons in affected agent tests remove null values recursively. This accounts for optional fields added inside nested output items. Duplicate item fixtures were removed so each type tag has one payload.

The resources_servers/cvdp OpenAI pin was removed. The package-level pin is the source used when server environments are created.

@copy-pr-bot

copy-pr-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from 1a97f98 to 5ee8d2b Compare August 10, 2026 17:19
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 1062c9b to 9353d58 Compare August 10, 2026 17:19
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from 5ee8d2b to fb66669 Compare August 10, 2026 17:41
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 9353d58 to 5321712 Compare August 10, 2026 17:41
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from fb66669 to ce8d900 Compare August 10, 2026 18:00
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 5321712 to 1d159b4 Compare August 10, 2026 18:00
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from ce8d900 to a4d7eb2 Compare August 10, 2026 23:05
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 1d159b4 to 3eb5a07 Compare August 10, 2026 23:05
@copy-pr-bot

copy-pr-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from a4d7eb2 to eb1cae4 Compare August 10, 2026 23:31
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 3eb5a07 to aa1614d Compare August 10, 2026 23:31
@ananthsub ananthsub changed the title chore(deps): move the openai window to >=2.25.0,<2.30.0 chore(deps): pin openai to 2.44.0 Aug 10, 2026
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from eb1cae4 to 26e9411 Compare August 11, 2026 12:18
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from aa1614d to e5ff4b4 Compare August 11, 2026 12:18
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from 26e9411 to 96f1bd6 Compare August 11, 2026 12:31
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from e5ff4b4 to 13ada0c Compare August 11, 2026 12:31
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from 96f1bd6 to a435628 Compare August 11, 2026 13:08
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 13ada0c to 4a504ef Compare August 11, 2026 13:08
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from a435628 to a4b7b43 Compare August 11, 2026 13:39
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 4a504ef to 8b84e47 Compare August 11, 2026 13:39
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from a4b7b43 to 54f7fdf Compare August 11, 2026 18:38
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 8b84e47 to c6c4e42 Compare August 11, 2026 18:38
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from 54f7fdf to 36c5a30 Compare August 11, 2026 18:43
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from c6c4e42 to 99d4b83 Compare August 11, 2026 18:43
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from 36c5a30 to cf4fd16 Compare August 11, 2026 19:11
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 99d4b83 to 0470100 Compare August 11, 2026 19:11
@ananthsub
ananthsub force-pushed the ananthsub/responses-item-coverage branch from cf4fd16 to dcd8fce Compare August 11, 2026 19:16
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 0470100 to 6915198 Compare August 11, 2026 19:16
@ananthsub
ananthsub marked this pull request as draft August 12, 2026 16:06
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch from 965cf79 to 220bfa3 Compare August 12, 2026 23:44
ananthsub pushed a commit that referenced this pull request Aug 13, 2026
… nemo-gym's constraint; explicit opt-in for version skew (#2447)

## Problem

`head_server_deps` pins the parent process's openai version into every
server venv. When the parent environment ships an openai release outside
nemo-gym's own constraint (e.g. openai 2.52.x preinstalled in a base
image while nemo-gym caps `openai<=2.7.2`), that pin makes **every
server venv resolution unsatisfiable**. This does not fail cleanly: the
dry-run prefetch bakes venvs that contain nothing but pip, and the
problem surfaces only at runtime as import errors far from the cause.

## Change (after review)

- **Fail fast, loudly:** the parser now raises `ConfigError` at parse
time when the parent openai violates nemo-gym's constraint, naming both
versions and the remedy. This preserves the install-time guarantee the
previous behavior *intended* to give, minus the empty-venv mystery.
- **Explicit, scoped skew mode:** a new reserved top-level key
`allow_openai_version_skew: true` opts into letting server venvs resolve
openai from nemo-gym's own constraint, with a `logging.warning` naming
both versions. Parent and servers exchange requests across the HTTP/JSON
boundary, so the skew surface is the JSON contract, not Python type
identity — we run this topology in production (parent 2.52.x, servers on
the nemo-gym pin) on 64-node RL trainings.
- Requirement-name comparison canonicalized per PEP 503.
- The constraint is read from the installed distribution metadata at
runtime (never hardcoded), so pin bumps like #2456 need no change here.

## Tests

Parser-level (through `get_global_config_dict`): compatible parent → pin
present in `head_server_deps`; incompatible parent → `ConfigError`
naming the opt-in key; incompatible parent + opt-in → pin omitted. Plus
unit coverage of the constraint matcher (case-insensitive names,
marker'd requirements skipped, missing metadata → conservative
pin-preserving fallback).

---------

Signed-off-by: Michal Futrega <mfutrega@nvidia.com>
Signed-off-by: Michal Futrega <michal.futrega@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@ananthsub
ananthsub force-pushed the ananthsub/openai-window-bump branch 2 times, most recently from 5d29fce to beddd20 Compare August 24, 2026 14:06
@ananthsub
ananthsub marked this pull request as ready for review August 24, 2026 14:06
@github-actions github-actions Bot added the sla:review-overdue Review response is over the one-business-day SLA label Aug 24, 2026
@ananthsub

Copy link
Copy Markdown
Contributor Author

/claude review

@claude

claude Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

SHIP — LGTM, no reliability concerns.

Reviewed the openai 2.7.2→2.44.0 bump and the Responses/Chat converter expansion end-to-end.

What I checked and why it's sound:

  • Converter correctness (responses_converter.py): the new responses_to_chat_completion_create_params fails loudly (NotImplementedError) on every field/tool/tool-choice with no Chat representation (context_management, conversation, defer_loading, message phase, function namespace, custom-tool grammar, hosted tool choices, text.format) rather than silently dropping — the correct failure mode for a downconverter feeding a training/eval run. exclude_none=True on the dump means null Responses-only fields are treated as absent (tested), so callers passing explicit None aren't spuriously rejected.
  • Behavior change worth flagging as intentional, not a bug: function-tool strict now round-trips to the model (previously pop("strict", None) dropped it) — the vLLM test asserts strict: True now reaches the backend. This is a lossy-drop fix, and it's covered.
  • Item-union expansion: new Codex-family output items (apply_patch/shell/tool_search/compaction/additional_tools) are mirrored in both input and output unions, with normalize_output_items_for_replay correctly rewriting additional_tools→role=developer and dropping status=failed from computer_call_output on replay. test_gym_output_union_represents_every_sdk_output_type and test_request_model_carries_every_sdk_request_field pin the union to the SDK so future bumps fail fast.
  • genrm_compare grouping key: exclude_none=True stabilizes the prompt-hash against SDK field additions; grouping stays consistent within a run, no scoring impact.
  • Dependency hygiene: exact pin is deliberate and documented (2.45.0 breaks InputTokensDetails), overrides files reconciled (finance_agent floor now compatible, strands bumped, cvdp de-duplicated), uv.lock consistent.
  • Test robustness: _drop_nulls on both sides of equality only masks None==None; a real-value vs None mismatch still fails, so assertions keep their teeth.

No async-path, public-API-break, or silent-corruption issues found. Merge.

bxyu-nvidia
bxyu-nvidia previously approved these changes Aug 26, 2026
@ananthsub

Copy link
Copy Markdown
Contributor Author

/ok to test 9097819

kajalj22
kajalj22 previously approved these changes Aug 26, 2026
@ananthsub

Copy link
Copy Markdown
Contributor Author

/ok to test a9fc2b6

Gym pins openai to a version it has audited against, and 2.44.0 is the newest it can use.

Pinned to one version rather than a range. Gym subclasses the SDK's pydantic models and mirrors
its Responses item union by hand, so each version needs its own audit and a range would claim
support for versions nobody tested. `head_server_deps` in nemo_gym/global_config.py already
propagates the installed version into every server venv as an exact pin, so a range here was never
what servers resolved.

2.44.0 is the newest usable version. 2.45.0 makes `InputTokensDetails.cache_write_tokens`
required, and `NeMoGymResponseInputTokensDetails` subclasses it, so constructing usage there
fails. There is no 2.44.x patch release.

Moving from 2.7.2 to 2.44.0 needs nine new Responses item types represented, because an item
`NeMoGymResponseInputItem` cannot represent is a 500 on the non-streaming path and a silent drop
from the replayed transcript on the streaming path:
- the Codex tool family: `shell_call`, `apply_patch_call`, `tool_search_call` and their outputs
- the opaque `compaction` context record, and `compaction_trigger`, the client's request for one
- `additional_tools`, the tool carrier Codex code mode sends

The client-supplied result types are not in that list. The pinned SDK moves them into
`ResponseOutputItem`, but 2.7.2 already accepts them as input items, so they are a gap at the
current pin and are fixed in the change before this one.

Each is a plain subclass that inherits the SDK's typing unchanged. All nine are declared
chat-inconvertible: a shell command, a patch, a tool result and a compaction record have no Chat
Completions representation, so `responses_to_chat_completion_create_params` raises for them and
only Responses pass-through model servers can replay them. `additional_tools` is also declared as
consumed by the streaming sanitizer, which hoists its tools into `tools` and discards the item.

Two behaviour changes in the SDK needed test updates:

`reasoning.context` is now a modelled field. Codex sends it, the old pin forbade it, and
`validate_streaming_responses_params` pruned it. It is now forwarded.
`test_prunes_nested_extra_fields` was asserting the pruning against a field the SDK later adopted,
so it now uses an invented field name, and a new test records that `reasoning.context` survives.

`FunctionTool.defer_loading` is `Optional[bool] = None` on the model but a plain `bool` in the
`FunctionToolParam` TypedDict, so `FunctionTool(...).model_dump()` produces a dict the params
model rejects. The single_step_tool_use_with_argument_comparison test now builds a
`FunctionToolParam` directly, which is what it wanted.

The Responses output types this version adds are classified here, in the change that makes them
real: the Codex calls as generation boundaries, and the client-supplied results, the approval and
the compaction record as non-boundaries. Misfiling a result as a boundary would label replayed
prompt as sampled tokens.

`Response` gained four optional fields (`completed_at`, `prompt_cache_retention`, `moderation`,
`conversation`), which broke every server test that compared a whole `model_dump()` against a
literal. Rather than adding the new keys to each literal, those tests now compare only what they
assert, or drop null-valued keys on both sides where the payload nests a Response.
`tests/unit_tests/test_openai_utils.py` pins `NeMoGymResponse`'s field set so a future addition
fails once, in one place, instead of across five servers.

resources_servers/cvdp pinned `openai==2.7.2` in its requirements. It never imports openai; the
pin came from a dependency bump and now makes venv resolution fail, so no test in that server
runs. Removed, leaving pyproject.toml as the only source.

Verified with per-server venvs at 2.44.0: simple_agent, cvdp_agent, tool_simulation_agent, tau2,
cvdp, single_step_tool_use_with_argument_comparison and arc_agi all pass. 1965 core unit tests
pass.

`STREAMING_CONSUMED_TYPES` gets the same dead-entry check as the lists in the change before this
one. The test that reads it is parametrized over the fixtures, so it never visits a tag that has
none, and a stale entry would leave the type it names checked as if the sanitizer had not consumed
it.

The audit that picked 2.44.0 found the request model and several item models had drifted from the
SDK independently of the item unions:

- seven request fields were missing, so they were a 422 when sent plainly and were silently
  filtered out when streaming. Three arrive in this window: `context_management`, `moderation` and
  `prompt_cache_retention`. `context_management` is what configures the compaction this change also
  adds items for.
- `phase` on assistant messages and `namespace` on function calls are new here and were dropped
  during validation without an error. Codex sends `phase` back on follow-up requests, and
  `namespace` is what says which tool a call refers to.
- `computer_call_output` carries `status="failed"` on the SDK's output model and not on its input
  model, so a failed computer action was a 500. The wrapper widens the literal.
- `additional_tools` is the reverse: the output model accepts eight roles where the input model
  accepts only `developer`, so an item validated against the wider set could not always be replayed
  as input, which is the one thing the type exists for. The wrapper narrows to the input literal.

Three corrections to the above, found by running the components rather than the core suite.

The new optional fields appear inside `output`, so the server tests that compared a response dict
had to stop filtering only its top-level keys. `simple_agent` and `cvdp_agent` now drop null values
at every depth, as `tool_simulation_agent` and `tau2` already did. One assertion in `simple_agent`
compares a list of message dicts rather than the response, and needed the same treatment.

`stream_options` only means anything alongside `stream: true`, and mirroring it into the request
model left it on the body after the streaming flag was removed. It is dropped with the flag.

`ITEM_FIXTURES` defined five keys twice after the client-supplied result types moved down a change.
Python keeps the last of a repeated literal key silently, so the duplicates neither failed nor
changed behaviour, and the earlier definitions were dead. Ruff's F601 reports this and is not in
the repository's current selection.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Separate provider output from replay input where OpenAI uses different domains, and reject Responses-only fields during Chat downconversion.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Keep the combined OpenAI parity test import block compliant after rebasing the stack.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Keep local agent observations valid in response trajectories and make 2.44-added optional fields neutral to hashes and legacy fixtures.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Construct parallel-tool fixtures as `FunctionToolParam` dictionaries.
Remove stale `FunctionTool` references that break lint and test collection.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Preserve request fields that have direct equivalents and reject 2.44 values that Chat Completions cannot represent instead of silently dropping them.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
The model-library floor is compatible with OpenAI 2.44. Removing the old
2.7.2 overrides lets isolated Finance Agent environments use Gym's pin.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Translate function and custom tools, grammar formats, and structured tool
choices between the Chat Completions and Responses wire schemas. Reject
Responses-only choices instead of forwarding incompatible shapes.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Keep Simple Strands on Gym's audited SDK version and remove the Finance Agent parity assertion for an override that is no longer needed.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Treat explicit nulls like omitted optional fields during Chat downconversion while continuing to reject populated Responses-only behavior.

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bump openai version to support new vllm versions

3 participants