# 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 ``` 结果:通过。