
先判断这次回复是哪一种结果
AIGoCode 的 OpenAI Chat Completions 响应并不只有一段可直接显示的文字。普通文本通常从 choices[0].message.content 读取;如果模型返回工具调用,官方文档要求按 tool_calls 处理。两种结果都出现在 choices[0].message 附近,但后续业务动作完全不同。
因此,拿到响应后先记录 choices 是否存在,再判断 message.content 和 message.tool_calls 哪一条分支有值。不要用“content 为空”直接判定请求失败,工具调用本来就可能把下一步动作放在 tool_calls。
普通文本分支怎么读
最小文本请求使用 messages 数组发送对话,普通回复从 choices[0].message.content 取出,结束原因位于 finish_reason。这条路径适合把模型回答展示给用户,或交给后续文本处理。
如果 content 有值,先保留 finish_reason 和完整响应中的 usage,再进入渲染或业务逻辑。不要只把字符串写入数据库,否则以后很难判断这次回复是正常结束、长度截断还是其他状态。
tool_calls 分支不能直接当文字
工具调用返回的是结构化动作信息,不是已经执行完的业务结果。官方 Chat Completions 文档明确提示,工具调用的返回内容应按 tool_calls 处理。应用可以先保存调用名称、参数和对应的调用标识,再由自己的工具执行层决定是否允许执行。
这里要把模型建议和真实执行分开:收到 tool_calls 不等于工具已经运行,也不等于数据库、文件或外部 API 已经改变。执行前仍要做参数校验、权限判断和人工确认,尤其是会写入数据或产生费用的动作。
一条安全的分支顺序
可以按下面顺序组织解析:
- 检查 HTTP 响应是否成功,再解析 JSON。
- 读取
choices[0],确认是否存在message。 content有值时走文本展示;tool_calls有值时走结构化工具分支。- 记录
finish_reason,不要把它和工具执行结果混为一谈。 - 把
usage的 token 字段送入统计路径,消费明细再到「使用统计」核对。
如果两个字段同时出现,也不要凭经验自行合并。先按当前模型和客户端协议文档确认允许的响应形态,再在测试环境验证分支。本文只解释字段边界,没有对任何模型的工具调用能力或执行成功率作保证。
需要流式输出时再看 delta
如果请求设置 stream=true,文档要求从每个事件的 choices[].delta 读取新增内容,data: [DONE] 表示流结束。流式解析与一次性读取 message.content 是两条代码路径;工具调用的增量字段也应按事件结构逐项收集,不能把每个事件当成完整 JSON。
如果应用同时支持普通和流式请求,建议先在入口处明确模式,再使用对应解析器。这样出现空白、提前结束或工具参数不完整时,能先排除“用了错误解析路径”这一类问题。
四项核对清单
- 这是普通响应还是
stream=true的 SSE 事件? choices[0].message中有content还是tool_calls?finish_reason记录的是模型结束状态,还是被误当成工具执行结果?usage是否单独进入统计,真实工具执行是否经过本地权限检查?
需要确认 OpenAI 协议地址、模型 ID 和 Key 分组时,可先看 AIGoCode OpenAI Compatible 文档 与 模型名称列表。
小结
Chat Completions 的正确处理顺序是先分辨响应类型,再选择字段路径:普通文字读 message.content,工具调用读 tool_calls,流式请求读 delta。解析字段和真实执行之间保留权限边界,才能避免把模型返回的动作建议误当成已经完成的业务操作。