Files
sglang/docs/references/para_openai_serving_alignment.md
laoyao0822 9c8e3e99cb Align OpenAI serving behavior with Para deployments
Absorb PR 11's final Para compatibility surface as an opt-in OpenAI serving layer rather than hard-coding business defaults into protocol models. The change adds server args for Para chat defaults, Kimi/GLM compatibility, tool-choice normalization, tool-role text flattening, and streaming first-chunk error preflight while preserving default upstream behavior unless explicitly enabled.

Reasoning token usage is also propagated through chat/completion usage paths, with GLM compatibility emitting completion_tokens_details.reasoning_tokens. Low-risk protocol fixes accept string image_url content parts and preserve GLM function-call argument value whitespace.

Constraint: Online Para-compatible deployments require request/response semantics that differ from default OpenAI serving behavior.

Constraint: Current CP/HiCache/bs>1 work must not be coupled to OpenAI serving compatibility changes.

Rejected: Merge PR 11 history directly | intermediate commits briefly hard-code chat max_tokens=32768 before later gating it by server args.

Rejected: Enable Para compatibility by default | would change non-Para OpenAI-compatible deployments.

Confidence: high

Scope-risk: moderate

Directive: Keep Para-specific serving policies behind explicit server args unless the business contract changes globally.

Tested: PYTHONPATH=python:. python -m unittest discover -s test/registered/unit/entrypoints/openai -p 'test_para_serving_protocol.py' -v (19 tests OK)

Tested: python -m py_compile modified OpenAI serving, tokenizer manager, server_args, function-call detector, and test files

Not-tested: Live router/prefill/decode OpenAI serving E2E after enabling Para flags.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-06-11 05:59:08 +08:00

160 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Para OpenAI Serving 对齐说明
本文总结当前分支对 `sglang-para` OpenAI API / serving 相关行为的对齐范围、默认策略和启用方式。
## 总体策略
本分支已经实现 Para 侧高风险 serving 行为,但为了降低耦合,**默认不启用 Para 兼容策略**。需要对齐 Para 业务行为时,通过 server args 显式打开。
默认保持上游/本分支原行为:
- chat 请求不自动填 `max_tokens=32768`
- 不强制把 `tool_choice` 改为 `auto`
- 不按模型路径自动启用 Kimi / GLM 特化逻辑。
- 不默认 flatten tool role 的 content list。
- streaming 不默认预拉首 chunk 做 HTTP error 转换。
## 启用 Para 兼容的参数
完整启用 Para OpenAI serving 对齐时,可在启动参数中加入:
```bash
--openai-chat-default-max-tokens 32768 \
--openai-force-tool-choice-auto \
--openai-kimi-compat \
--openai-glm-compat \
--openai-flatten-tool-role-text-content \
--openai-streaming-error-preflight
```
参数含义:
| 参数 | 默认值 | 启用后行为 |
| ----------------------------------------- | ------- | ----------------------------------------------------------------------------------------- |
| `--openai-chat-default-max-tokens 32768` | `0` | chat 请求未传 `max_tokens/max_completion_tokens` 时,在 serving 层补默认输出上限。 |
| `--openai-force-tool-choice-auto` | `False` | 将显式非 `auto` 的 chat `tool_choice``auto` 服务。 |
| `--openai-kimi-compat` | `False` | 根据 `model_path` 识别 Kimi启用 Kimi `thinking` 映射和固定采样参数。 |
| `--openai-glm-compat` | `False` | 根据 `model_path` 识别 GLM启用 GLM tool choice 降级、413 超长错误和 GLM usage details。 |
| `--openai-flatten-tool-role-text-content` | `False` | 将 tool role 的纯 text content parts list flatten 成字符串后交给 chat template。 |
| `--openai-streaming-error-preflight` | `False` | streaming 先预拉首 chunk若首 chunk 是错误,转成普通 HTTP error而不是 SSE 内报错。 |
## 已对齐的功能点
### 1. Chat 默认输出长度
Para 行为:未传 `max_tokens/max_completion_tokens` 时默认 `32768`
当前实现:
- `ChatCompletionRequest.max_tokens` 仍保持 `None`,避免协议模型硬编码业务默认值。
- serving 层读取 `openai_chat_default_max_tokens`
-`--openai-chat-default-max-tokens 32768` 后,效果与 Para 一致。
### 2. Kimi 兼容
启用 `--openai-kimi-compat` 后:
- 支持 chat 请求中的 `thinking` 字段。
- Kimi 模型下将 `thinking.type != "disabled"` 映射到 `chat_template_kwargs["thinking"]`
- 对 Kimi 应用 Para 固定采样参数:
- `top_p=0.95`
- `presence_penalty=0.0`
- `frequency_penalty=0.0`
- `n=1`
### 3. GLM 兼容
启用 `--openai-glm-compat` 后:
- 根据 `model_path` 包含 `glm` 识别 GLM。
- GLM 下 `tool_choice="required"` 降级为 `"auto"`
- GLM input token 已超过 context length 时,抛 `PayloadTooLargeError`OpenAI serving 返回 HTTP `413`
- GLM chat usage 使用 `completion_tokens_details.reasoning_tokens`
未启用时GLM 超长输入仍走普通 `ValueError -> HTTP 400` 路径。
### 4. Tool choice 全局兼容
启用 `--openai-force-tool-choice-auto` 后:
- chat 请求中显式非 `auto``tool_choice` 会在 serving 层转为 `auto`
- 协议层不再改写 `tool_choice`,便于关闭该行为并降低耦合。
### 5. Tool role content flatten
启用 `--openai-flatten-tool-role-text-content` 后:
-`role="tool"` 且 content 是纯 text parts list 的消息,将内容拼成字符串。
- 仅 flatten 纯 text parts包含其他结构字段的 list 保持原样,避免破坏依赖结构化 tool content 的模板。
### 6. GLM function call 参数保留空格
无条件对齐 Para
- `glm4_moe_detector.py`
- `glm47_moe_detector.py`
两处 detector 不再对参数值执行 `strip()`,只 strip 参数 key。这样可以保留模型输出或客户端参数值里的前后空格。
### 7. `image_url` 字符串兼容
无条件对齐 Para
- 支持 OpenAI multimodal content part 中 `image_url` 直接传字符串。
- Pydantic validator 自动转成 `{ "url": ... }`
### 8. Streaming 首包错误转换
启用 `--openai-streaming-error-preflight` 后:
- chat streaming 会先拉取首个 chunk。
- 如果首 chunk 是 SSE error payload会转成普通 HTTP error response。
- 如果首 chunk 正常,会 prepend 回 stream不影响正常 streaming。
### 9. Usage / reasoning tokens
已对齐 Para usage 聚合能力:
- `UsageInfo` 增加 `completion_tokens_details`
- `UsageProcessor` 聚合 `reasoning_tokens`
- Chat/Completion serving 都向 usage processor 传递 reasoning token 计数。
- 启用 GLM compat 后GLM chat 使用 `completion_tokens_details.reasoning_tokens`
## 主要改动文件
- `python/sglang/srt/server_args.py`
- `python/sglang/srt/entrypoints/openai/protocol.py`
- `python/sglang/srt/entrypoints/openai/serving_chat.py`
- `python/sglang/srt/entrypoints/openai/serving_base.py`
- `python/sglang/srt/entrypoints/openai/usage_processor.py`
- `python/sglang/srt/entrypoints/openai/serving_completions.py`
- `python/sglang/srt/managers/tokenizer_manager.py`
- `python/sglang/srt/function_call/glm4_moe_detector.py`
- `python/sglang/srt/function_call/glm47_moe_detector.py`
- `test/registered/unit/entrypoints/openai/test_para_serving_protocol.py`
## 验证
本地 macOS 使用 uv 虚拟环境完成轻量单测验证:
```bash
VIRTUAL_ENV=/private/tmp/sglang-para-test-venv \
PATH=/private/tmp/sglang-para-test-venv/bin:$PATH \
UV_CACHE_DIR=/private/tmp/uv-cache \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=python:. \
uv run --active --no-sync python -m unittest discover \
-s test/registered/unit/entrypoints/openai \
-p 'test_para_serving_protocol.py' -v
```
结果:`Ran 19 tests ... OK`
同时执行:
```bash
govctl check
```
结果:通过。