第 21-1 篇:/v1/chat/completions——兼容协议的最小面
发布时间:2026/9/26 19:10:08 作者:尧图编辑部 阅读量:1,286

上一篇20-3《SSE 流式——响应怎么写一半就发给客户端》下一篇21-2《对话模板与角色注入》真机实测通过本文实验已在 RK3588 板端实测完成2026-09方法学与原始记录见仓库 docs 与《实验脚本》目录一句话导读OpenAI 兼容的最小面怎么定先声明实现哪些字段、其余忽略或明确拒绝messages 必填与 400 分支、被尊重与被忽略的字段用板端实测逐一摊开。关键词chat/completions、OpenAI 兼容、兼容最小面、推理引擎、RK3588Day 20 把 HTTP 传输层与路由讲完。Day 21 进业务层让引擎能冒充 OpenAI 的/v1/chat/completions。这篇讲兼容的最小面——不是把 OpenAI 的全部参数搬过来而是搬够用且诚实的一小撮并用板端实测把哪些字段被尊重、哪些被忽略、哪里会 400摊开。1. 知识点兼容协议是接口契约不是功能对赌OpenAI 的 chat/completions 请求字段很多temperature/top_p/max_tokens/n/stream/tools/…。对推理引擎而言每个字段背后都是一段采样/调度/协议逻辑——支持 n1 意味着要改批处理面支持 tools 意味着要引入函数调用。一个小引擎的正确姿势是先声明自己实现了哪些字段其余字段要么忽略要么明确拒绝而不是假装全兼容。引擎的实际最小面vllm_server.c2014–2042 行逐字段读取请求字段类型处理messages数组必填缺失 →400 messages array is required20-2 实测max_tokensnumber生成长度上限读进后参与调度/截断finish_reason:lengthtemperaturenumber采样温度无值时用默认top_pnumbernucleus 采样streambooltrue 走 SSE20-3 实测modelstring只作回显标签未指定时回qwen3-vl-8b默认串见 2239 行响应里的自家扩展要单独说明history_tokens2593 行服务端回显会话 token 流与 SSE 的metrics/tokens事件——它们是非 OpenAI 标准字段客户端不认识就跳过本系列刻意保留它们是为了让测试能对着 token 验证而不是让生态依赖它。2. 对应代码一个 chat 请求的生命周期沿 Day 15 主循环的路径服务层再看一遍全链POST /v1/chat/completions → 自研 JSON 解析vllm_http.c VJson → 字段映射vllm_server.c 2014-2042messages/temp/top_p/max_tokens/stream → 多模态? detect_media19-2: 纯文本 qwen_tokenizer_encode → 前缀复用判定 → prefill → decode 循环逐 token / SSE → 组装 OpenAI 形状响应choices[0].message.roleassistant … → 附 history_tokens / metrics自家扩展注意messages的裁剪2083–2084 行超长时按行clipped——兼容层还要管上下文太长怎么办这是它比转发器多出来的部分。3. 改动后果参数被尊重与被忽略的实证实测口径板端 serve模型已加载 x86 客户端2026-09-07。全部请求max_tokens限制 history_tokens回显验证。① messages 缺失 → 400 messages array is required 最严 ② temperature0.0 的请求 → 200确定性采样方向 被尊重 ③ stream:false → 200 整包 JSON含 choices[0].message ④ stream:true → SSE 流20-3 已实测 ⑤ 未知字段如 n3 → 200未解析即忽略不报错 宽容 ⑥ roleuserr → 200角色按字面 token 化20-2 已实测给前端/测试的两个铁律测试兼容性别只看 200——要看choices/delta结构加字段前先看它会不会被静默忽略n3会被当成 1 处理这个在文档里要写明避免调用方以为拿到了 3 条候选。4. 学员调试任务A 档本地动手对着 §1 表逐字段发请求temperature:0、top_p:0.1、max_tokens:3看finish_reason:length、stream:true看事件序列、n:3看是否被忽略把messages传成{}与[]各看一次返回。B 档纯读源码读vllm_server.c2000–2100 与 2580–2600回答①messages裁剪2083发生在哪个阶段、为什么裁剪要保留首条 system 消息②history_tokens2593在什么条件下写入响应、它是prompt tokens还是含生成 token 的全序列用你 21-1 实测的一轮对比③ 若你要加seed字段支持固定随机种子需要动哪几处解析 → 采样器 → 文档预期输出一张参数 × 行为实测表并能解释为什么n3这类字段会 200 但没实现是兼容层的诚实设计而非 bug。收尾本篇源码点名vllm_server.c字段映射 2014–2042、history_tokens 2593、模型 id 回显 2239开源仓库Kestrel-LLM (Gitee)AGPL-3.0-or-later 或商业许可二选一下篇预告字段映射完messages里的 system/user/assistant 怎么变成模型真正看到的 prompt21-2 讲对话模板与角色注入——|im_start|那套标记是谁拼的、拼错会怎样。