← 大模型应用基础

如何控制大模型的输出长度并处理截断?

高频 中等 Token 预算与输出长度 · 第 2 / 2 问 更新于 2026/10/05
大模型输出长度Token流式生成
本题落地项目AI智能简历优化系统

简化版

输出长度要同时靠任务设计、输出 Schema、max_output_tokens 和停止条件控制。先按分类、抽取、问答、报告等任务设置不同预算,提示模型优先给结论并限制章节或数组数量;收到响应后必须检查停止原因。若因长度截断,结构化结果应判失败并重新生成或缩小范围,长文则用带状态的分段续写,不能把半个 JSON 或半段代码当成功。

详细版

输出预算与输入共享上下文,先计算 可用输出 ≤ 窗口上限 - 实际输入 - 安全余量。任务层再设置较小业务上限,例如分类 32~64 token、字段抽取 256~512、普通解释 800~1500;具体数值要按 tokenizer 和评测校准。

requested_max = min(task_limit,
                    context_limit - input_tokens - safety_margin,
                    remaining_cost_budget)

提示中的“简洁一些”不具备硬保证,应给明确结构、字段数和优先级。流式接口累计 token 与字节,允许用户取消;完成时区分正常停止、长度上限、内容过滤、工具调用和错误。长文采用章节计划、逐段生成、每段验收与最终一致性检查,避免无状态地说“继续”造成重复或漂移。

完整版教学

一、长度控制有三种不同目标

上下文硬上限防止请求不可执行,业务长度限制保证用户体验,成本预算限制最坏费用。三者不能只用一个 max_tokens 代替。

客服回答可能要求 200 字内,即使模型还能生成 4000 token 也应停止;代码生成则不能为了短而删掉必要函数。先定义完整性的最低要求,再决定最大长度。

记忆钩子:窗口上限是天花板,业务上限是房间高度,任务完整性是人至少要站得下。

二、输入和输出共享容量

一个 8192 token 窗口,输入 7000,安全余量 192,最多只能预留 8192-7000-192=1000 token。若接口请求输出 2000,可能报错、截输入或在服务端缩小上限。

因此在实际序列化聊天模板、工具定义和检索片段之后重新计数。不能按字符粗估,也不能忘记特殊 token。

输入过长时先减少低价值上下文,而不是无声压缩输出到无法完成。

输入太长被拒绝和输出被截断是两种情况,处理方式见「什么是大模型的上下文窗口?长度越长越好吗?」。

三、按任务建立输出档位

统一上限会让简单任务浪费资源、复杂任务经常截断。可根据历史长度分布和业务要求建立档位,再允许少量动态调整。

任务示例上限完整性检查
分类64 token标签在枚举内
JSON 抽取512 tokenSchema 完整
普通问答1200 token必答点覆盖
分章节报告每节 1500 token章节状态完成

示例不是通用标准。中文、代码与不同 tokenizer 的长度分布不同,应使用本业务 P95/P99 数据设置。

四、结构约束比模糊形容词有效

“简洁回答”会因模型和问题变化而波动。更可执行的要求是“先给 3 条结论,每条不超过两句,再给一个 4 行表格”,或用 JSON Schema 限制数组 maxItems 与字段长度。

但提示仍是软约束。字符或字数必须由应用检查,硬上限由生成参数执行。模型偶尔超出时可做一次受控改写,不能无限压缩导致事实丢失。

重要信息应排在前面,避免达到上限时只留下背景、没有结论。

五、停止原因决定响应能否使用

正常结束、命中停止序列、长度耗尽、内容过滤、工具调用和网络错误语义不同。应用不能只看有没有文本。

JSON 在 length 状态下即使能补一个右括号,也可能缺少后续字段;代码可能少清理逻辑;自然语言可能缺结论。因此结构化与高风险任务应判未完成。

日志记录请求上限、实际输出 token、停止原因和解析结果,才能判断截断来自预算太小还是模型冗长。

六、长文使用有状态分段生成

一次生成 10,000 token 报告容易截断、结构漂移和重复。可先生成章节计划,为每节分配目标长度,再逐节提供共享事实与已完成摘要,最后检查跨节一致性。

outline -> section_1(validated)
        -> section_2(validated)
        -> ... -> consistency pass

每段保存 section_id、covered_points、open_points。续写指令引用状态,而不是只说“继续”,否则模型可能从任意位置重复。

七、流式输出也要硬控制

流式传输改善首字延迟,不会自动减少 token。服务端应累计生成量、支持取消并处理客户端断开;用户关闭页面后若仍后台生成,费用继续产生。

若业务按字符限制,注意 UTF-8 字节、Unicode 字符和 token 不相等。不要在任意字节位置截断,也不要在 JSON 字符串中间切割。

达到业务展示上限时,可停止上游生成或继续生成到安全边界后存为完整 artifact,选择取决于产品需求。

八、用长度—质量—成本曲线校准

在固定评测集上测试 256、512、1024、2048 等上限,比较必答点覆盖、截断率、冗余率、延迟和费用。选择质量达到平台后边际收益低的位置。

例如 512 token 覆盖率 82%,1024 为 94%,2048 为 95%;从 1024 翻倍只提升 1 个百分点,却增加解码时间,1024 可能更合理。

线上按任务类型监控 length 停止率、实际/上限比、用户主动取消率和续写次数。模型升级后长度习惯会改变,需要重新校准。

九、常见误区与追问

  • 误区:提示里写“控制在 500 字”就是硬限制。 仍需参数限制和应用计数验证。
  • 误区:达到长度上限后补一个括号即可。 内容可能不完整,结构合法不代表任务完成。
  • 误区:流式输出天然更省成本。 未取消的流仍会生成同样 token。
  • 误区:所有任务用同一个上限最易维护。 长度分布和完整性要求不同,应分档。
  • 误区:让模型无限续写可以完成任何长文。 无状态续写会重复、矛盾并继续膨胀上下文。
  • 追问:如何判断被截断? 检查 API 停止原因,同时验证结构与任务必答点。
  • 追问:输入太长与输出预算冲突怎么办? 先压缩低价值输入、分解任务或换窗口,不能牺牲必要输出。
  • 追问:长报告怎样续写? 先定章节,保存已覆盖与待覆盖状态,逐段验收后做一致性检查。

十、加强记忆

输出长度控制记住“先算容量、按任务分档、用结构约束、看停止原因、长文分段”:输入与输出共享窗口,实际计数后为输出预留;分类、抽取和报告用不同上限;提示负责组织,参数负责硬停,验证器负责判断是否完整。出现 length 不把残片当成功,分段续写携带章节状态,最终用长度—质量—成本曲线选择配置。

项目实战落地

项目里怎么做的

《AI智能简历助手》的五个 AI 功能调模型时,都取带元数据的完整响应 chatResponse(),而不是只拿正文的 content(),再用同一个方法检查结束原因:

private void checkNotTruncated(Generation generation) {
    // 有的服务商在某些帧里不带元数据,取不到结束原因就不判断
    if (generation == null || generation.getMetadata() == null) {
        return;
    }
    // length 表示到达长度上限被迫停止,stop 才是正常说完
    if ("length".equalsIgnoreCase(generation.getMetadata().getFinishReason())) {
        throw new CustomException("5008", "AI输出到达模型的长度上限被截断了,这次结果不完整。"
                + "通常是简历正文太长导致的,请回到【简历工作台】精简正文(删掉和目标岗位无关的内容)后重试");
    }
}

流式的四个功能多做两件事:结束原因只出现在最后一帧,所以用 AtomicReference 一路记着最后一帧的 Generation,整段输出结束后再判断;这个判断放在捕获调用异常的 try 外面。

另外两个项目在「上限定多少」上各有做法:

  • 《AI个人学习计划助手》的模型配置表有 max_tokens 字段,默认 8000,按全项目单次输出最长的一次调用来定:30 天学习计划要返回 30 条任务,每条 5 个字段;输出越长耗时越长,超时也从 60 秒放宽到 120 秒。检测到截断时提示去把 max_tokens 调大,并带上当前配置值。
  • 《AI Agent旅游行程智能规划平台》按用途分别配置模型:行程编排模型最大输出 32000,偏好抽取模型 2048。截断检查放在「返回内容是否为空」的判断之前。

《AI Agent岗位匹配与求职规划系统》的统一出口 AiChatService 同样取 chatResponse() 检查结束原因,是 length 就报「AI输出达到模型长度上限,结果不完整」;ReAct Agent 取最终结论时也做同样的检查。上限来自模型配置表的 max_tokens,生成求职报告时配置值低于 3000 就临时按 3000 调用;仍被截断时换一份更短的提示词再生成一次,做法见「Agent 如何管理上下文窗口?」。

《AI 多 Agent 长租公寓智能合租匹配平台》的执行器每一轮拿到回复先调 check_truncated:response_metadata 里的 finish_reason 是 length 就报「模型输出超过了最大长度被截断。请到【AI模型配置】调大最大输出 Token,或者缩短输入内容后重试」。最大输出取自每条模型配置的 max_tokens,模型工厂的注释写明它要真下发给模型;预置的四条配置里审核是 1024,其余 2048。

为什么这样取舍

  • 截断不算报错。 输出到达上限时服务商返回的 HTTP 状态码还是 200,内容也是正常文本,只是缺了后半截;只拿正文,就分不清「说完了」和「被截断了」。不拦的话,评分会因为 JSON 只有半截而解析失败,改写、面试题这类功能会把半截结果当成正常结果。
  • 判断放在 try 外面。 截断不是调用失败,而是调用成功但结果不完整;写在 try 里,会被兜底的 catch 包成「AI模型流式调用失败」,真正的原因就被盖掉了。
  • 截断检查先于判空。 输出被上限吃光时正文也是空的,这时报「返回内容为空,请检查模型名称和 API Key」,会把人引到完全不相干的地方去查。

面试官还会追问

  • 流式输出被截断时,前面的内容已经显示在页面上了,这次结果还会存进记录表吗?
  • 同样是「太长」,简历正文太长和输出被截断,服务商的反应有什么不同?分别在哪里拦?

学完《AI智能简历助手》,上面这些追问你都会迎刃而解。

本题落地项目小试牛刀AI智能简历优化系统基于大模型完成简历上传解析、AI评分、问题诊断、优化建议、内容改写、Word下载、模拟面试题和生成记录管理,覆盖从简历诊断到求职准备的完整流程,并沉淀Prompt模板和改写策略。SpringbootSpringAILLMPromptSSE源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目 也可以学AI个人学习计划与资料助手小试牛刀 查看项目 也可以学AI Agent旅游行程智能规划平台地狱锤炼 查看项目 也可以学AI Agent岗位匹配与求职规划系统地狱锤炼 查看项目 也可以学AI 多 Agent 长租公寓智能合租匹配平台地狱锤炼 查看项目