模型输出为什么会被截断以及怎样读取完成原因
来源:17golang原创
时间:2026-10-26 02:45:26 277浏览 收藏
模型回答只返回了半段、JSON 少了一个括号,或者流式输出停在代码中间时,先不要把问题归结为“模型突然失灵”。对于 OpenAI Chat Completions,关键字段是 choices[0].finish_reason;对于 Responses API,应该读取 status 和 incomplete_details.reason。其中 length 或 max_output_tokens 才表示触达输出上限,stop 或 completed 则表示正常完成。
官方参考:https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create
Responses 参考:https://developers.openai.com/api/reference/resources/responses/methods/create
排查顺序应是:先确认接口类型,再读取最终状态字段,最后根据原因决定是否提高输出预算、继续生成或处理工具调用。只看已经生成的文本长度,不能判断回答是否完整。
- Chat Completions:检查
choices[0].finish_reason,流式请求要等最后一个 chunk。 - Responses API:检查
status;当状态是incomplete时继续读incomplete_details.reason。 - 结构化输出:遇到
length或max_output_tokens时,不要直接解析可能不完整的 JSON。
先确认你读取的是哪一种响应对象
“完成原因”不是所有 SDK 都放在同一个位置。旧代码常见的 Chat Completions 返回对象有 choices 数组,每个 choice 包含消息和 finish_reason;新的 Responses API 直接在响应对象上给出 status,不完整时再从 incomplete_details 读取细因。
因此第一步不是加大 token 参数,而是确认请求到底调用了哪个端点。把两种字段混读,往往会得到空值,然后误判为网络超时。

Chat Completions 怎样读取 finish_reason
非流式响应可以直接读取第一个 choice。下面的代码把“正常结束”“达到长度上限”“工具调用”和“内容过滤”分开处理;示例只展示判断逻辑,不把任何示例输出冒充成实际运行结果。
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-6-astra",
messages=[{"role": "user", "content": "用三点说明如何处理分页异常。"}],
max_completion_tokens=600,
)
choice = response.choices[0]
reason = choice.finish_reason
if reason == "stop":
# stop 表示自然结束或命中了请求中的 stop 序列
print(choice.message.content or "")
elif reason == "length":
# length 表示达到请求设置的最大生成预算,内容可能不完整
raise RuntimeError("输出达到长度上限,不能当作完整答案")
elif reason == "tool_calls":
# tool_calls 表示模型交回工具调用,应用应先处理工具结果
print("等待处理工具调用")
elif reason == "content_filter":
# 内容过滤可能让结果缺少可直接使用的正文
raise RuntimeError("响应因内容过滤而未完整生成")
else:
# 兼容 SDK 或服务新增的结束原因,先记录原值再决定策略
raise RuntimeError(f"未处理的 finish_reason: {reason}")
判断重点是 finish_reason 而不是 message.content 是否非空。content 有值,只能说明服务返回了一段文本;当原因是 length 时,这段文本仍可能停在半个 JSON、半条命令或未闭合的 Markdown 代码块中。
如果使用 stream=True,中间 chunk 的 finish_reason 通常仍是 null。应用应持续拼接内容,直到收到带有最终原因的 chunk,再决定是否把结果写入业务数据库。
Responses API 怎样读取 incomplete_details
Responses API 的判断方式不同:先看响应的 status,只有状态为 incomplete 时再查看 incomplete_details.reason。官方参考中,这个原因可以包括 max_output_tokens、max_messages、content_filter 或 steered。

from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra",
input="把下面的接口说明整理成结构化 JSON:分页参数、错误码和重试建议。",
max_output_tokens=800,
)
if response.status == "completed":
# completed 才进入正常的业务解析路径
print(response.output_text)
elif response.status == "incomplete":
details = response.incomplete_details
reason = details.reason if details else "unknown"
# 先记录原因,再决定是否续写或调整预算
if reason == "max_output_tokens":
raise RuntimeError("输出预算不足,不能直接解析为完整 JSON")
if reason == "content_filter":
raise RuntimeError("输出被内容过滤打断")
raise RuntimeError(f"Responses 未完成:{reason}")
else:
# 对未知状态保留原值,避免把新状态误认为成功
raise RuntimeError(f"未处理的 response.status: {response.status}")
Responses API 的 max_output_tokens 计算的是模型可生成的总输出预算,包含不可见的推理 token;所以“可见文字不多却 incomplete”并不矛盾。遇到 max_output_tokens 时,应结合实际任务提高预算、缩短输入或拆分任务,而不是盲目重复同一个请求。
为什么看起来像截断:按结束原因排查
| 读取到的原因 | 通常说明什么 | 处理动作 |
|---|---|---|
stop | 自然结束或命中 stop 序列 | 进入正常解析,但仍按业务 schema 处理异常 JSON |
length | Chat Completions 达到生成上限 | 检查 max_completion_tokens,不要把半截内容当成功 |
tool_calls | 模型返回工具调用,而不是最终答案 | 执行或拒绝工具调用,再把结果交回模型 |
max_output_tokens | Responses 达到总输出预算 | 提高预算、减少输入或拆分任务 |
content_filter | 生成被内容过滤中断 | 记录状态并走安全处理分支,不要拼接成完整答案 |
| 流式最终原因为空 | 可能还没有收到最后一个事件,或连接中断 | 区分“未结束”和“已结束”,保存连接状态与已收集片段 |
尤其要注意流式响应:最后一个事件以前的 null 不是成功,也不是截断,它只表示生成仍在进行。只有收到终止事件或明确的传输错误,应用才能判断这次流是否完整。
生产环境的处理手册
- 先记录原始结束字段。在日志中保存接口类型、模型、请求预算、
finish_reason或incomplete_details.reason,不要只保存拼接后的文本。 - 再判断是否允许解析。结构化 JSON、代码和需要闭合标记的模板,只有正常结束时才进入解析;长度上限时保留片段供诊断。
- 最后选择恢复动作。长度不足可以调整预算或拆分任务;工具调用要完成工具链;内容过滤和未知状态应进入人工或安全策略分支。
一个实用的落库字段至少包括 api_kind、status、finish_reason、incomplete_reason、output_text 和 is_complete。其中 is_complete 应由结束原因计算,不应由“文本长度大于零”推断。
常见问题
finish_reason 是 stop 就一定代表 JSON 合法吗?
不一定。它只说明生成达到自然停止点或命中 stop 序列;JSON 是否合规则仍要交给 JSON 解析器或结构化输出处理。
流式输出最后没有 finish_reason 怎么办?
先把它视为未完成,检查是否收到了服务端终止事件以及客户端连接错误。不要因为已经收到若干 token 就把结果标记为成功。
为什么 max_output_tokens 很大仍然不完整?
Responses API 的预算包含可见输出和推理 token;长输入、复杂推理或结构化任务都可能消耗更多预算。应结合状态字段判断,必要时缩短任务或拆分输出。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
412 收藏
-
114 收藏
-
101 收藏
-
124 收藏
-
123 收藏
-
231 收藏
-
417 收藏
-
352 收藏
-
348 收藏
-
439 收藏
-
241 收藏
-
208 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习