```markdown
调用大模型接口时,返回结果里常有个不起眼的字段叫结束原因(finish_reason)。它回答一个问题:这次输出是被什么终止的。看起来只是个小标签,但回答"怎么突然断了"时,它往往是第一个该看的地方。
一句话定义
结束原因(finish_reason)是大模型 API 返回结构中的一个字段,用来说明本次生成为何停止:是正常说完了、撞到长度上限了、去调工具了,还是被内容策略拦下了。
常见的几种取值
不同厂商的命名略有差异,但大体逃不出这几类:
| 取值 | 含义 | 典型表现 |
|---|---|---|
| stop | 模型自然收尾,或命中了你设置的停止词 | 输出完整,通常是你想要的 |
| length | 达到 max_tokens 或上下文上限被截断 | 话说到一半没了,句子不闭合 |
| tool_calls / function_call | 模型决定调用外部工具 | 正文可能是空的,只有工具参数 |
| content_filter | 被安全策略拦截 | 输出中断或为空,附带拦截说明 |
另外有些实现里会出现"空结束"或"其他"之类的兜底值,具体以所用平台的官方文档为准。
打个比方
把它想成快递面单上的"投递结果"。包裹送到你手里,面单写"已签收"——这就是 stop;写"超重截单"——这是 length;写"转交第三方代送"——这是 tool_calls;写"安检扣留"——这是 content_filter。你收到一个半截包裹,光看箱子是看不出原因的,得翻面单。
为什么容易看错
最常见的误判是把 length 当成模型"变笨了"。实际上模型没变笨,只是你给的空间不够,它在半句话被硬生生掐断。另一种误判是把 tool_calls 当成"模型不回答我",其实它正等着你把工具执行结果回传,才能接着往下写。还有一种是把 content_filter 当成网络故障——重试十次也没用,得改输入。
对从业者的意义
写调用代码时,别只看 content 字段。至少做三件事:把 finish_reason 记进日志,遇到 length 就提示"回答被截断,可继续追问"或自动续写,遇到 tool_calls 就走工具执行分支而不是当失败处理。做 Agent 或长文生成时,这个字段更是循环控制的开关——不判断它,很容易陷入"截断、重试、再截断"的死循环,白烧额度。
对普通职场人来说,记住一个实用动作就够了:当 AI 回答到一半戛然而止,别急着骂它,先问一句"请接着上面没说完的继续",如果它能顺着接下去,多半就是 length 在作祟。
