Skip to content

fix(proxy): preserve configured chat template defaults - #1725

Merged
sitabulaixizawaluduo merged 4 commits into
mainfrom
zjw/proxy-template-defaults-followup
Sep 20, 2026
Merged

sitabulaixizawaluduo merged 4 commits into
mainfrom
zjw/proxy-template-defaults-followup

Conversation

@Le8r0nJames

@Le8r0nJames Le8r0nJames commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Follow-up to #1702 (Arena proxy-based rollouts).

Declare AgentConfig.chat_template_kwargs so structured configuration and
dataclass serialization carry proxy chat-template defaults. Regenerate both CLI
references alongside the schema change.

Merge configured defaults, session metadata, and request template settings.
Valid thinking aliases override the whole alias family from lower-priority
sources; None is not an override, while False and off are preserved. An
explicit session thinking mode remains authoritative.

The OpenAI SDK flattens extra_body into top-level JSON. This PR reconstructs
chat_template_kwargs from that form and also handles explicitly nested raw
requests. It does not provide generic passthrough of arbitrary SDK extension
fields. Supported client arguments keep their existing path; unsupported fields
remain filtered. Other fields already inside a raw nested extra_body are not
modified by the template merge.

No legacy group or reward-normalization compatibility flags are included.

Related Issue

Follow-up to #1702. No separate issue.

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📝 Documentation update
  • ♻️ Refactoring
  • ⚡ Performance improvement
  • ✅ Test coverage improvement

Checklist

  • I have read the Contributing Guide
  • Pre-commit hooks pass (pre-commit run --all-files)
  • Relevant existing tests pass; no additional UT added, as requested
  • CLI references regenerated in English and Chinese; full docs build not run
  • Branch is up to date with main
  • Self-reviewed via /review-pr command
  • This PR was created by a coding agent via /create-pr
  • This PR is a breaking change

Breaking Change Details (if applicable): None.

Additional Context

The additional UT file was removed at the author's request. Validation includes:

  • pytest -q tests/experimental/openai/test_proxy_rollout_server.py: 41 passed.
  • One-off checks using real AgentConfig and OmegaConf for configuration,
    thinking precedence, None/False, session pinning, and input non-mutation.
  • An SDK wire check through the actual proxy request-preparation function,
    verifying flattened template settings, supported arguments and filtering of
    unsupported extensions. No external model endpoint was called.
  • CLI generator succeeded in the target Python 3.12 image; pinned Markdown
    formatting passed. Lint, formatting and license checks pass. Local full-tree
    hooks remain limited by Python 3.10 and the installed Torch's FSDP API; the
    local CLI-generation hook has the same import limitation.

No full distributed training regression is claimed. Updates are new commits and
ordinary pushes; published history has not been rewritten.

kwargs["messages"] = prepared_messages

defaults = dict(
getattr(_engine.config.agent, "chat_template_kwargs", {}) if _engine else {}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The advertised configured defaults are unreachable through supported configuration paths. AgentConfig does not declare chat_template_kwargs, so structured YAML and CLI loading reject the key, while dataclass RPC serialization drops dynamically attached attributes. This lookup therefore resolves to an empty mapping in production even though the new test injects the missing field through SimpleNamespace.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e27d251, included in the new head f332351. The field is now declared on AgentConfig and both CLI references are regenerated, so it is part of structured configuration and dataclass serialization rather than a dynamically attached attribute. I verified real AgentConfig construction through OmegaConf, in addition to the existing proxy suite (41 passed). The previous mock-based check did hide this omission; no additional UT file has been added.

defaults = dict(
getattr(_engine.config.agent, "chat_template_kwargs", {}) if _engine else {}
)
extra_body = dict(kwargs.get("extra_body") or {})

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes extra_body remains nested in the request body. The pinned OpenAI SDK flattens extra_body into top-level JSON fields, so only chat_template_kwargs is recovered here and every unrelated extension field is later removed by the unsupported-argument filter. The claimed preservation therefore does not hold for the standard client path.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed the SDK flattening with an actual AsyncOpenAI serialized request passed through the proxy request-preparation function. I narrowed the PR description and scope: this change reconstructs chat_template_kwargs only, not arbitrary SDK extension fields. Arguments supported by the AReaL client signature retain their existing forwarding behavior; unsupported top-level fields remain filtered. Other fields already present in an explicitly nested raw extra_body are left untouched, but that is not a generic preservation guarantee for the standard SDK wire format. I am keeping generic extension passthrough outside this PR rather than bypassing the existing argument filter.

request_template = {
**session_template,
**(extra_body.get("chat_template_kwargs") or {}),
**(kwargs.pop("chat_template_kwargs", None) or {}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking aliases are normalized against configured defaults but not across the nested extra_body and top-level request sources. When those two request layers use different aliases, both values survive the merge; downstream code prioritizes enable_thinking, so the higher-priority request setting can be ignored.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e27d251. Each source layer now replaces the entire lower-priority thinking-alias family when it supplies a non-None thinking value, rather than only overriding identical keys. Explicit session thinking pins are reapplied afterward as before. False/off remain valid overrides, while None neither clears a valid lower-layer setting nor creates a session pin. One-off checks covered the cross-layer alias conflict, None/False handling, session pinning, and unchanged input dictionaries; the SDK-flattened template path was also verified.

@sitabulaixizawaluduo
sitabulaixizawaluduo merged commit ac5614a into main Sep 20, 2026
6 checks passed
@sitabulaixizawaluduo
sitabulaixizawaluduo deleted the zjw/proxy-template-defaults-followup branch September 20, 2026 02:32
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.

2 participants