diff --git a/areal/api/cli_args.py b/areal/api/cli_args.py index 50b619ea80..76a48d1261 100644 --- a/areal/api/cli_args.py +++ b/areal/api/cli_args.py @@ -2624,6 +2624,10 @@ class AgentConfig: default="qwen3", metadata={"help": "Parser for reasoning content ( tags)."}, ) + chat_template_kwargs: dict[str, Any] = field( + default_factory=dict, + metadata={"help": "Default chat template arguments for proxy requests."}, + ) chat_template_type: str = field( default="hf", metadata={ diff --git a/areal/experimental/openai/proxy/proxy_rollout_server.py b/areal/experimental/openai/proxy/proxy_rollout_server.py index 9eb8994bb7..531d02d3d6 100644 --- a/areal/experimental/openai/proxy/proxy_rollout_server.py +++ b/areal/experimental/openai/proxy/proxy_rollout_server.py @@ -900,6 +900,42 @@ async def _call_client_create( raise HTTPException(status_code=500, detail=message) from e kwargs["messages"] = prepared_messages + defaults = dict( + getattr(_engine.config.agent, "chat_template_kwargs", {}) if _engine else {} + ) + extra_body = dict(kwargs.get("extra_body") or {}) + session_template = session_data.metadata.get("chat_template_kwargs") or {} + thinking_keys = ("thinking_option", "enable_thinking", "thinking") + template_kwargs = {} + for layer in ( + defaults, + session_template, + extra_body.get("chat_template_kwargs") or {}, + kwargs.pop("chat_template_kwargs", None) or {}, + ): + effective = { + key: value + for key, value in layer.items() + if key not in thinking_keys or value is not None + } + # Thinking aliases share precedence, even when their names differ. + if any(key in effective for key in thinking_keys): + for key in thinking_keys: + template_kwargs.pop(key, None) + template_kwargs.update(effective) + session_thinking = { + key: value + for key, value in session_template.items() + if key in thinking_keys and value is not None + } + if session_thinking: + for key in thinking_keys: + template_kwargs.pop(key, None) + template_kwargs.update(session_thinking) + if template_kwargs: + extra_body["chat_template_kwargs"] = template_kwargs + kwargs["extra_body"] = extra_body + dropped_args = [] for k, v in kwargs.items(): if k not in areal_client_allowed_args: diff --git a/docs/en/cli_reference.md b/docs/en/cli_reference.md index 5e5925dea1..6f5c5dc4c1 100644 --- a/docs/en/cli_reference.md +++ b/docs/en/cli_reference.md @@ -948,6 +948,7 @@ Consolidates proxy settings (mode, parsers, export) with agent-service orchestra | `mode` | string | `"inline"` | OpenAI proxy mode: 'inline' (in-process), 'subproc' (subprocess), or 'online' (external user sessions for online RL training). `inline` mode runs the provided agent workflow directly in the same process. `subproc` mode launches a separate process to run the agent. `online` mode waits for external users to complete sessions via the proxy gateway URL, enabling online RL training. **Choices:** `inline`, `subproc`, `online` | | `tool_call_parser` | string | `"qwen"` | Parser for tool calls in model output. | | `reasoning_parser` | string | `"qwen3"` | Parser for reasoning content ( tags). | +| `chat_template_kwargs` | `dict` | `{}` | Default chat template arguments for proxy requests. | | `chat_template_type` | string | `"hf"` | Chat template type: 'hf' (standard) or 'concat' (multi-turn concatenation). **Choices:** `hf`, `concat` | | `engine_max_tokens` | integer \| None | `None` | Maximum total tokens for the engine (prompt + completion). | | `turn_discount` | float | `1.0` | Discount factor for reward propagation in 'individual' export. Concat leaves keep their own branch-local outcome reward. | diff --git a/docs/zh/cli_reference.md b/docs/zh/cli_reference.md index 8ce06cfab6..5c0b911a74 100644 --- a/docs/zh/cli_reference.md +++ b/docs/zh/cli_reference.md @@ -946,6 +946,7 @@ Consolidates proxy settings (mode, parsers, export) with agent-service orchestra | `mode` | string | `"inline"` | OpenAI proxy mode: 'inline' (in-process), 'subproc' (subprocess), or 'online' (external user sessions for online RL training). `inline` mode runs the provided agent workflow directly in the same process. `subproc` mode launches a separate process to run the agent. `online` mode waits for external users to complete sessions via the proxy gateway URL, enabling online RL training. **Choices:** `inline`, `subproc`, `online` | | `tool_call_parser` | string | `"qwen"` | Parser for tool calls in model output. | | `reasoning_parser` | string | `"qwen3"` | Parser for reasoning content ( tags). | +| `chat_template_kwargs` | `dict` | `{}` | Default chat template arguments for proxy requests. | | `chat_template_type` | string | `"hf"` | Chat template type: 'hf' (standard) or 'concat' (multi-turn concatenation). **Choices:** `hf`, `concat` | | `engine_max_tokens` | integer \| None | `None` | Maximum total tokens for the engine (prompt + completion). | | `turn_discount` | float | `1.0` | Discount factor for reward propagation in 'individual' export. Concat leaves keep their own branch-local outcome reward. |