2026年大模型API返回格式教程:JSON 结构、字段含义与解析示例
2026年大模型API返回格式教程:JSON 结构、字段含义与解析示例
调用大模型接口时,请求发出去只是第一步,真正决定程序能不能跑通的往往是返回体。很多报错并不是网络问题,而是对返回 JSON 的结构理解不到位。
这篇文章按“整体结构—字段含义—解析示例—常见坑”的顺序,把大模型API返回格式一次讲清楚,方便你在写解析代码、排查日志或迁移接口时有据可依。
先说明一个前提:不同厂商、不同协议下的字段命名会有差异,多模态内容与工具调用的结构差异更大。下面讲的是 OpenAI 兼容风格接口中最常见的一套结构,实际字段请以你所使用平台的控制台文档和真实返回值准。
一、大模型API返回格式的三层结构
非流式请求成功返回后,JSON 大体可以分成三层:
- 顶层元信息:
id、object、created、model,描述这是哪次请求、什么类型的对象、什么时候生成、用的哪个模型,排障时非常有用。 - 结果数组:
choices,默认只返回一个元素,但结构上仍然是数组,所以解析时必须按下标取值。 - 用量统计:
usage,记录输入与输出 Token 数,是核算成本、做额度限制的主要依据。
理解这三层之后你会发现,大部分“取不到内容”的问题,都出在把数组当成对象用,或者把流式分片当成完整结果去解析。只要先判断类型再取值,再补上默认值兜底,绝大多数解析异常都能提前挡住。
二、核心字段含义与解析注意点
| 字段 | 含义 | 解析注意点 | 检查方法 |
|---|---|---|---|
object | 对象类型标识 | 流式与非流式取值不同,不要共用同一个解析分支 | 打印原始响应首行 JSON 观察 |
model | 实际处理的模型名 | 别名与返回名可能不一致,日志应记录返回值 | 对比请求参数与返回字段 |
choices | 结果数组 | 必须先判长度再取下标,空数组会直接抛异常 | 加长度判断与空值兜底 |
message.content | 最终文本内容 | 可能是空字符串,尤其触发工具调用或内容过滤时 | 同时检查 finish_reason |
finish_reason | 结束原因 | 正常结束、长度截断、内容过滤含义不同,处理逻辑应区分 | 写入日志并按原因做统计 |
usage | Token 用量统计 | 流式场景下常只在最后一片出现,缺失时不要当成 0 计费 | 按请求维度累计并核对账单 |
delta | 流式增量片段 | 只包含本次新增内容,需要自行拼接 | 与非流式解析分支分开维护 |
只看 content 字段会漏掉什么
很多人解析时只取 choices[0].message.content,取到就结束。这样做在简单对话里能用,但只要出现下列情况就会误判:
- 内容被长度截断:
finish_reason会提示截断,但文本看起来是完整的,用户会以为回答就这么短。 - 触发了内容过滤:内容字段可能为空,此时更该关注结束原因而不是重试。
- 模型返回了工具调用信息:真正的正文可能不在
content里,需要读取结构化字段。
因此解析逻辑建议同时保留“内容 + 结束原因 + 用量”三组信息,出问题时能快速定位到底是被截断、被过滤,还是模型确实没输出。
三、一个可复用的解析示例
下面这段代码演示了非流式响应的基本解析思路:先判空、再取内容、最后记录用量。
import requests
resp = requests.post(url, headers=headers, json=payload, timeout=60)
data = resp.json()
choices = data.get('choices') or []
if not choices:
raise RuntimeError('empty choices: ' + str(data)[:200])
text = choices[0].get('message', {}).get('content', '')
reason = choices[0].get('finish_reason')
usage = data.get('usage', {})
print(text, reason, usage.get('total_tokens'))
流式返回怎么拼接
流式响应的返回体是按行推送的,每一行是一个独立 JSON,最后以结束标记收尾。解析时要逐行剥离前缀、忽略空行、在结束标记处停止,再把每片的增量追加到缓冲区。
buffer = []
for line in resp.iter_lines():
if not line:
continue
if line.startswith(b'data: '):
chunk = line[6:]
if chunk == b'[DONE]':
break
delta = json.loads(chunk)['choices'][0].get('delta', {})
if 'content' in delta:
buffer.append(delta['content'])
print(''.join(buffer))
流式返回最容易出的两个错:一是把每一片都当成完整答案存库,二是忘记处理结束标记导致连接一直挂着。建议在解析层统一加上超时与最大迭代次数保护。
四、常见坑与排查清单
- 把响应当成纯文本:直接正则匹配内容,字段一变就失效,应优先按 JSON 路径取值。
- 忽略 HTTP 状态码:非 200 时返回体结构完全不同,先看状态码再看内容。
- 没有记录原始响应:出问题时只能靠猜,建议在调试期保留完整响应体。
- 把错误信息当成模型回答:某些平台会把错误塞进正常结构里,需要用状态码与错误字段双重判断。
- 用量字段写法不一致:有的叫输入输出 Token,有的叫提示与补全 Token,归一化后再入库。
五、多模型环境下如何减少格式差异带来的返工
当项目里同时用到对话、图像、语音等不同能力的模型时,返回结构的差异会带来额外维护成本。比较稳妥的做法是把“解析层”和“业务层”分开:解析层只负责把各家返回归一化成内部结构,业务层永远只读归一化之后的字段。
如果希望通过统一入口调用多家模型,可以了解一下 通联AI中转站。它提供 OpenAI 兼容方向的接口,用一个 Base URL 和统一的 API Key 管理多个模型调用,适合需要减少多平台切换、集中管理余额与调用配置的场景。接入前建议先在控制台核对模型名称、接口地址与兼容协议,再用小流量请求确认返回字段与本文描述的结构一致。
需要提醒的是,即便接口协议兼容,也可能存在个别字段缺失或扩展字段不同的情况。解析代码保留默认值与异常兜底,比假设结构永远一致更可靠。关于实时模型列表、计费规则与接入说明,可以到 通联官网查看。
返回结构看懂了,下一步就是拿一个真实 Key 跑通首次调用。注册通联账号后可以获取 API Key,在控制台确认 Base URL 与模型名称,再按本文的解析思路做一次最小请求验证。
建议先用一条短请求确认返回字段,再接入正式的解析与日志模块。