写代码时最烦的不是不会调,而是记不住参数名、分不清返回里哪层才是你要的东西,报错又只给一个状态码。这篇不重复讲协议兼容和客户端配置,只做一张工程向速查表:请求该带哪些字段、响应该读哪一层、超时和并发怎么定、出问题先看哪个日志字段。适合已经拿到 Key、正在把接口往项目里塞的人。
写代码时最烦的不是不会调,而是记不住参数名、分不清返回里哪层才是你要的东西,报错又只给一个状态码。这篇不重复讲协议兼容和客户端配置,只做一张工程向速查表:请求该带哪些字段、响应该读哪一层、超时和并发怎么定、出问题先看哪个日志字段。
适合已经拿到 Key、正在把接口往项目里塞的人。下面所有涉及具体数值的地方,都不给死数字,只给判断方向和站内核对路径;你照着排查顺序走一遍,基本能把常见的坑提前踩完。
请求参数速查:最常改的那几个
请求体字段别背,按改动频率分三档记就行。几乎每次都要写的是模型名、消息数组、是否流式;按场景才写的是采样类参数、最大输出长度、停止条件、工具定义;基本别动的是那些给特定场景预留的开关,不确定就先不传。新手最常见的错误不是漏参数,而是把结构写错——比如把消息数组套成字符串,或者角色名写成自己造的词。
- messages
- 一个数组,里面每个元素至少要有角色和内容两个键,角色用约定的那几个值,别自己造
- role 划分
- 系统角色放规则和身份,用户角色放本轮输入,助手角色放历史回复,顺序错了模型理解就偏
- stream
- 布尔值,决定响应是一次性返回还是分片推送,开了它取数据的方式整个要换
- max tokens
- 限制输出长度的上限,可写可不写,但写太小会莫名其妙被截断
- temperature 这类采样参数
- 按任务调,需要稳定就压低,需要发散就抬高,具体推荐区间到 /ai-dict/category/tips 看术语解释后自己定
有一类字段写错不会报错,但行为会悄悄变。典型是:把本该是数组的内容包成字符串、把角色名写成同义词、把流式开关的字符串当布尔用。给你一份自检顺序,提交前过一遍。
- 先验结构打印一下最终拼好的请求体,确认消息是数组、每个元素是对象、角色名来自约定枚举
- 再验类型布尔和数字别用字符串代替,很多库会静默转换,一转换行为就变
- 最后验兼容换到不同厂商的兼容接口前,先到 /stacks/agent-apis 看清单,确认你要的字段那边有没有,别假设全都有
返回结构怎么读:先定位再取字段
读响应有个固定顺序,能省掉一大半调试时间:先看顶层有没有错误对象,有就直接走异常分支;没有的话再看候选列表里那条的结束原因,判断是正常说完还是被截断;最后才去取正文内容。很多人一上来就取正文,结果截断了也不知道,还以为是模型不听话。
| 你要的东西 | 去哪一层找 | 注意点 |
|---|---|---|
| 错误信息 | 顶层错误字段 | 有它就别再往下取正文 |
| 是否说完 | 候选里的结束原因 | 值为长度类说明被截断,要调大上限 |
| 正文文本 | 候选里的消息内容 | 非流式和流式取法不一样 |
| 工具调用 | 候选消息下的专门字段 | 别去正文里找,它在另一层 |
| 用量统计 | 顶层用量对象 | 流式场景要自己累加 |
流式和非流式必须分开写代码。非流式就是一次拿到完整结构,按上面顺序读即可;流式是一串分片,每个分片只带增量,你得自己拼,还要处理结束标记,千万别把单个分片当完整 JSON 去解,那必然报解析错。被截断、内容为空但状态正常、工具调用字段藏在另一层,是流式场景里最容易踩的三个坑。
- 内容为空但状态码正常:先看结束原因,多半是被长度限制截断,或者内容跑到了工具字段里
- 分片解析失败:检查是不是把分片当完整响应解了,流式要按行或按事件切
- 工具调用取不到:确认它挂在消息对象下,而不是正文里
- 日志留证:至少记请求时间、模型名、状态码、结束原因、用量和是否流式,口径可参考 /tools/quality-monitor
超时、并发与重试:写死数字之前先量
超时要拆成三层分别设:建立连接一层、等待读取一层、整个请求一层。长文本和流式场景要单独把读取层放宽,否则首字还没吐出来就被你掐断了。并发上限别看别人写多少就抄多少,要按你自己账号的档位和后端排队能力取小值,真正的瓶颈往往在你这边而不是对面。
- 先量基线拿真实业务里的典型请求跑一批,到 /tools/speed-test 看当时的延迟分布,再定超时阈值
- 再定重试只管幂等请求和网关类错误;生成类请求要重试就先打去重标记,避免重复计费
- 退避要带抖动触发限流后指数退避加随机抖动,别原速立刻重打,否则只会更堵
- 观察上限限流频次上去就说明并发设高了,往回压而不是硬扛
日志与回归:让一次请求可复盘
想让一次请求事后能复盘,日志里这些字段是底线:请求时间、模型名、耗时按段拆开、状态码、错误码、用量、是否流式、重试次数。有这些,出问题时你能一眼看出是超时、限流还是参数写错,而不是对着一行错误码猜。
| 字段 | 为什么要记 | 缺了会怎样 |
|---|---|---|
| 耗时分段 | 区分是连接慢还是生成慢 | 只能看到总耗时,定位不到瓶颈 |
| 结束原因 | 判断是否被截断 | 以为模型答非所问 |
| 用量 | 对账和成本复盘 | 到 /price-watch 核对时对不上 |
| 重试次数 | 识别限流和抖动的真实频率 | 把重试当正常请求统计 |
提示词和参数改动要进版本记录,改动前后跑同一组固定用例做对比,粗筛可以借 /tools/quality-check。这里要说清不适用的情况:一次性脚本、本地调试,只记状态码和错误体就够了,上全套字段纯属负担;只有当你准备把这次改动推到线上、或者要长期观察趋势时,完整字段才值得。
下一步把你现在手上的请求体和日志字段对着这篇过一遍,缺哪层补哪层,具体数值到站内对应页面核对当期的数字,再决定阈值。→常见问题
接口文档该以官方为准还是以我在用的中转站为准?
以你实际调用返回的结果为准。官方文档是基线,中转站可能少字段或多包一层,所以第一次接入别只看文档,先用最小请求打一发,把真实返回存下来当对照。渠道差异和字段缺失可以到 /openai-api-compat-fields 这类页面核对,别凭记忆改代码。
请求返回 200 但内容不对,一般先查哪里?
按顺序查三处:一是 messages 有没有多包一层或者角色写错;二是 finish_reason 是不是被长度截断;三是流式分片有没有拼完整。这三处能覆盖多数「没报错但结果怪」的情况。真定位不了,就把请求体和原始返回一起存下来复现,别只贴最终文本。
并发开多少合适,有没有通用数字?
没有通用数字,取决于账号档位、后端排队能力和任务容忍度。稳妥做法是先用一个较低并发跑通,逐步加压到第一次出现限流,再回退一档作为日常值,同时把重试和排队做上。具体档位口径到 /official-api 看你所用平台当时的说明。