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

6.1 KiB
Raw Blame History

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 对齐时,可在启动参数中加入:

--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_choiceauto 服务。
--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 时,抛 PayloadTooLargeErrorOpenAI serving 返回 HTTP 413
  • GLM chat usage 使用 completion_tokens_details.reasoning_tokens

未启用时GLM 超长输入仍走普通 ValueError -> HTTP 400 路径。

4. Tool choice 全局兼容

启用 --openai-force-tool-choice-auto 后:

  • chat 请求中显式非 autotool_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 虚拟环境完成轻量单测验证:

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

同时执行:

govctl check

结果:通过。