大模型 API 返回内容太短的完整排查:max_tokens、stop、stream 与上下文窗口配置

发布时间:2026/6/28 6:27:37
大模型 API 返回内容太短的完整排查:max_tokens、stop、stream 与上下文窗口配置 调用大模型 API 时经常会遇到一个现象网页端能生成很长的内容但换成 API 后只返回几句话明明把参数调大了回答还是很短更严重时JSON 生成到一半就断掉右括号都没有。这类问题不要一上来就改temperature也不要直接判断“模型不行”。API 输出过短通常和下面几个因素有关输出 token 上限设置不足提示词没有明确要求展开系统消息或历史对话里有“简短回答”约束stop参数提前触发输入上下文占用了太多窗口流式输出没有完整读取JSON schema、工具调用或安全策略影响了输出。这篇文章按实际排查顺序整理一套可复现的检查方法适合正在接入 OpenAI 兼容接口、Anthropic Claude API、Gemini、Vertex AI、本地 vLLM/Ollama/LM Studio 或其他大模型 API 的开发者。一、先看 finish_reason判断是被截断还是正常结束排查 API 返回内容太短第一步不是改参数而是先看响应元信息里的结束原因。不同平台字段名可能不同但常见会有类似{ finish_reason: length }或者{ finish_reason: stop }常见结束原因可以这样理解结束原因常见含义优先排查方向length输出达到最大 token 限制增大输出上限减少输入上下文stop自然结束或命中停止符检查stop参数和提示词content_filter/ safety内容被安全策略处理查看安全字段、过滤原因、错误码tool_calls模型转向工具调用工具执行后是否还需要再次总结空值或异常可能是流式没读完、连接中断查 SSE 拼接、超时、网关日志如果finish_reasonlength通常说明模型还想继续生成但被输出上限截断了。如果finish_reasonstop并不一定代表没有问题。它可能是正常结束也可能是stop sequence提前触发。二、确认 API 返回内容短的两种情况API 短输出大致分为两类一种是被截断一种是模型主动答得短。这两类问题的解决方向完全不同。1. 内容被截断如果是被截断通常会出现这些表现句子说到一半突然没了Markdown 列表停在某一项JSON 缺少右括号、右中括号或引号段落结尾很突兀响应里出现finish_reasonlength服务端或网关日志里有超时、断连记录。这类问题应优先检查max_tokens/max_output_tokens/max_completion_tokens输入上下文是否过长服务端、网关、前端是否有超时流式输出是否读取完整。2. 模型主动回答得很短另一种情况是模型并没有被截断而是它认为任务已经完成。常见表现回答语义完整只是很短finish_reasonstop没有错误码没有明显中断提示词比较泛比如“介绍一下 Redis”。这种情况通常不是 token 上限问题而是提示词没有明确要求展开或者系统消息、历史对话里存在“简洁回答”的约束。三、检查输出 token 上限max_tokens 不是目标长度大多数模型 API 都有一个“最大输出 token 数”的参数。常见字段包括平台或接口类型常见参数名说明OpenAI / 兼容 Chat Completions 接口max_tokens部分新接口使用max_completion_tokens控制最大生成 tokenGemini / Vertex AImax_output_tokens控制最大输出 tokenClaude APImax_tokens控制最大输出 tokenHugging Face Transformersmax_new_tokens控制新生成的 token 数阿里云百炼等模型平台通常是max_tokens或模型指定字段不同模型范围不同vLLM / Ollama / LM Studiomax_tokens、num_predict等取决于框架实现这些参数控制的是“最多生成多少”不是“必须生成多少”。也就是说{ max_tokens: 2000 }并不代表模型一定会写满 2000 token。如果提示词只写了“简单介绍一下 Redis”模型仍然可能生成几句话后正常结束。OpenAI 兼容接口示例如果你使用的是 OpenAI 兼容 Chat Completions 接口可以参考下面的请求体{ model: your-model, messages: [ { role: user, content: 请用不少于 1200 字介绍 Redis按概念、数据结构、应用场景、常见误区、选型建议五部分展开。 } ], max_tokens: 2000, temperature: 0.5 }如果你的接口文档要求使用max_completion_tokens则应改成对应字段{ model: your-model, messages: [ { role: user, content: 请写一篇结构完整的技术说明文不少于 1500 字。 } ], max_completion_tokens: 2500 }Claude API 示例Claude API 中通常使用max_tokens控制输出长度{ model: your-claude-model, max_tokens: 2000, messages: [ { role: user, content: 请用不少于 1200 字解释 HTTP 缓存机制分为强缓存、协商缓存、常见响应头、调试方法四部分。 } ] }具体字段、模型名和取值范围应以当前接口文档为准。四、检查 Endpoint、模型名和鉴权配置在实际接入中API 返回异常短内容有时并不是模型生成能力问题而是请求没有打到预期接口或者使用了错误的模型、错误的兼容格式。建议先确认四个基础配置。1. Endpoint 是否正确不同服务商、不同兼容层的 Endpoint 不一样。常见配置形式OPENAI_BASE_URLhttps://api.example.com/v1 OPENAI_API_KEYyour_api_key或者ANTHROPIC_BASE_URLhttps://api.example.com ANTHROPIC_API_KEYyour_api_key需要注意OpenAI 兼容接口通常会带/v1Anthropic Claude API 的路径和 OpenAI Chat Completions 不完全相同第三方网关可能提供兼容 Endpoint但仍要按它的文档填写不要把网页端地址当成 API Endpoint 使用。如果 Endpoint 配错可能会出现请求打到错误服务返回非预期模型参数被忽略流式响应格式和 SDK 预期不一致。2. 模型名是否正确模型名写错时有的平台会直接报错有的平台可能回退到默认模型或返回兼容层错误。请求前建议确认{ model: your-model }是否为当前平台支持的有效模型名。尤其在 OpenAI 兼容网关、Claude API 网关、本地模型服务中模型名通常不是随便填写的需要和平台或本地服务暴露的名称一致。3. 鉴权 Header 是否正确OpenAI 兼容接口常见写法Authorization: Bearer your_api_key Content-Type: application/jsonClaude API 常见写法通常会使用对应的 API Key Header 和版本 Header具体以平台文档为准。如果鉴权错误通常会直接返回 401、403 等错误。但在一些封装层里错误处理不清晰也可能被上层代码误判为“模型只返回了一点内容”。4. SDK 是否匹配当前接口很多开发者使用 SDK 时只改了base_url但没有确认接口协议是否兼容。需要确认当前 SDK 调用的是 Chat Completions 还是 Responses API当前 Endpoint 是否支持对应协议max_tokens、max_completion_tokens、stream等参数是否被平台识别流式返回格式是否和 SDK 解析逻辑一致。如果参数字段不被识别有些平台会报错有些平台可能直接忽略导致你以为“已经设置了大输出”实际并没有生效。五、提示词太泛模型默认给短答案很多 API 返回内容太短并不是参数设置错了而是提示词太宽泛。例如介绍一下 Redis。这个提示词没有说明面向谁写多少按什么结构写是否需要例子是否需要解释原因。模型可能只回答几句话因为从任务表述看“介绍一下”已经完成。更稳定的写法是把长度、读者对象、结构和展开方式写清楚请用不少于 1200 字介绍 Redis面向后端开发者按以下结构展开 1. Redis 的基本概念 2. 核心数据结构 3. 典型应用场景 4. 与数据库、消息队列的区别 5. 常见误区和选型建议 要求 - 每一部分至少 2 段 - 每部分给出一个实际例子 - 不要只给结论要解释原因。想让模型输出更长关键不是语气更强硬而是任务更明确。可以直接复用这个模板请围绕【主题】写一篇详细说明不少于【X】字。 结构要求 1. 先给出核心结论 2. 按【章节 A、章节 B、章节 C】展开 3. 每个章节至少包含【X】个要点 4. 每个要点需要解释原因并给出例子 5. 如果接近输出长度限制请在末尾写“未完待续”不要突然中断。六、长文生成建议先大纲再分段生成如果目标是生成很长的技术文章、方案文档、接口说明或报告不建议一次请求生成全部内容。更稳定的方式是两步走。第一步生成大纲先为【主题】生成一个 8 节大纲。不要展开正文。第二步逐节展开请根据下面大纲只展开第 1 节要求不少于 800 字包含例子和注意事项。这样做有几个好处每次输出长度更可控更不容易触发 token 上限流式输出中断后更容易重试结构更稳定JSON 或 Markdown 不容易生成到一半断掉。对于长文章、长报告、复杂技术方案分段生成通常比一次性生成更可靠。七、检查系统消息和历史对话中的短回答约束如果你在用户提示词里写了“详细说明”但模型还是很短需要检查系统消息和历史对话。常见的短输出触发词包括简洁简短简要概括摘要总结一句话三句话以内只返回结论不要解释TL;DRbriefconciseshort answersummarybrief_answershort_answer。系统消息的优先级通常高于用户消息。如果系统消息里写了“回答要简洁”后面用户再写“请详细说明”未必能完全覆盖前面的限制。建议用最小上下文单独测试一次请用不少于 1000 字详细解释 HTTP 缓存机制分为强缓存、协商缓存、常见响应头、调试方法四部分。如果最小 prompt 可以正常长输出而业务请求不行问题大概率在系统提示词历史对话RAG 文档结构化字段设计上层封装模板。八、检查 stop 参数不要用换行和句号当停止符stop的作用是告诉模型一旦生成到某个字符串就停止输出。它在控制格式时很有用但也很容易导致 API 返回过短。危险示例 1换行{ stop: [\n] }这可能导致模型只输出第一行。危险示例 2中文句号{ stop: [。] }这可能让中文回答只输出一句话。危险示例 3Markdown 分隔符{ stop: [###, END] }如果正文、Markdown 标题或代码示例里刚好出现这些字符串模型就会提前停止。排查方式临时删除stop参数使用同样 prompt 重新请求观察输出是否明显变长查看finish_reason是否仍为stop如果必须使用停止符选择正文里几乎不会出现的特殊标记。生成 JSON 时尤其要谨慎使用stop。停止符如果命中过早很容易导致 JSON 对象不完整。九、检查上下文窗口输入太长会挤压输出空间大模型的上下文窗口不是只给输出使用而是整次请求共享。一次请求中通常会占用上下文的内容包括系统消息用户输入历史对话RAG 检索片段工具定义JSON schema代码文件最终输出。如果输入内容太多即使max_tokens设置得很大实际也可能没有足够空间生成长回答。这类问题常见于RAG 一次塞入 20 段检索结果聊天机器人保留几十轮历史对话系统提示词写得过长工具定义或 JSON schema 很复杂一次性输入很长的代码文件长文档没有切块直接全文输入。优化方向对历史对话做摘要只保留关键状态减少 RAG 片段数量提高检索精度长文档先切块总结再综合回答长文章按章节生成工具定义和 schema 尽量精简必要时选择上下文窗口更大的模型但仍要控制输入质量。上下文窗口再大也不是无限的。输入堆得越多输出就越容易被挤压。十、检查 stream是否完整拼接了所有 chunk如果你使用流式输出API 返回的每个 chunk 都不是完整答案。你需要持续读取并拼接内容直到收到结束事件。常见错误包括只取了第一个delta.content没有循环读取 SSE前端请求超时后端收到一部分内容后就关闭连接Nginx、网关、Serverless 平台提前断开没有等待[DONE]或平台对应的结束事件。可以按下面的清单检查1. 是否拼接了所有 chunk 2. 是否收到了结束标记 3. 前端是否有超时限制 4. 后端是否有超时限制 5. 代理层是否开启 response buffering 6. 网关是否存在 idle timeout 7. 日志里是否有连接中断、取消请求、超时异常如果非流式输出正常而流式输出总是只有一小段优先检查读取逻辑而不是反复更换模型。十一、JSON 输出不完整的排查方法JSON 生成到一半断掉是 API 短输出中很常见的问题。常见原因包括max_tokens不够schema 太复杂字段太多嵌套层级太深stop提前命中上下文被输入占满流式拼接不完整。例如你要求模型返回{ summary: }字段名叫summary模型自然倾向于写摘要内容可能比较短。如果你希望输出更完整可以把字段设计得更明确{ detailed_answer: , steps: [], examples: [], notes: [] }如果 JSON 很复杂建议拆成多次生成先生成 section_1 到 section_3不要生成其他字段。然后再请求继续生成 section_4 到 section_6保持 JSON 字段结构一致。对于特别长的结构化输出不要指望一次请求稳定生成完整超大 JSON。更稳妥的方式是拆字段、拆章节、拆步骤。十二、工具调用和安全策略也会影响输出长度如果你启用了工具调用或函数调用模型可能不会直接输出自然语言正文而是转为生成工具参数。这时响应可能表现为{ finish_reason: tool_calls }这不是普通的短回答而是模型进入了工具调用流程。常见处理方式是接收工具调用参数执行工具把工具结果再次传回模型再让模型基于工具结果生成完整总结。另外如果平台触发安全策略也可能导致输出被缩短、替换或拒绝。遇到这种情况不要只调参数应检查响应中的 safety 字段错误码过滤原因平台日志请求内容是否触发安全策略。不同服务商表现不同具体以当前平台文档和返回字段为准。十三、不同目标下的参数调整建议目标优先调整不建议优先调整回答被截断查看finish_reason增大max_tokens/max_output_tokens盲目提高temperature回答完整但太短改提示词结构明确章节、字数和例子只改top_pJSON 不完整增大输出上限减少字段分批生成用stop强行截断长文生成分章节生成配合流式输出一次请求生成超长全文输出啰嗦但不完整明确结构和优先级减少无关输入单纯降低温度流式只返回一段检查 chunk 拼接和结束事件反复更换模型这里要特别注意temperature主要影响随机性top_p影响候选 token 范围它们不是长度控制参数。如果 API 返回内容太短优先级应该是finish_reason → 输出 token 上限 → 提示词结构 → stop 参数 → 上下文窗口 → stream 读取逻辑 → schema / tool_calls / safety十四、可直接复制的排查清单如果线上接口出现“API 只返回一点内容”可以按这个顺序排查1. 查看 finish_reason 是否为 length、stop、content_filter 或 tool_calls 2. 确认 Endpoint、模型名、鉴权 Header 是否正确 3. 确认 SDK 使用的接口协议和当前 Endpoint 兼容 4. 将 max_tokens / max_output_tokens 提高 2-3 倍测试 5. 临时删除 stop 参数确认是否提前终止 6. 删除“简短、摘要、只返回、不要解释”等提示词 7. 检查系统消息和历史对话中是否有简短约束 8. 缩短输入上下文减少 RAG 片段或清空历史对话 9. 如果使用 stream确认拼接了所有 chunk并读取到结束事件 10. 检查 JSON schema、字段名、工具调用和安全过滤 11. 如果仍然短改为“先大纲、后分段生成”十五、常见问题1. max_tokens 设置很大为什么还是短因为max_tokens只是最大上限不是目标长度。如果模型认为任务已经完成或者提示词没有要求展开它仍然可能正常停止。这种情况更应该修改提示词结构而不是继续盲目增大max_tokens。2. temperature 调高能让回答变长吗不一定。temperature影响的是输出随机性和多样性不是控制长度的开关。回答太短时应该先看finish_reason输出上限提示词stop参数上下文空间流式读取逻辑。3. 为什么网页端回答长API 回答短网页端通常会内置一些处理逻辑例如默认系统提示词默认输出上限自动续写分段生成流式拼接UI 层重试。API 调用通常需要开发者自己设置Endpoint模型名鉴权输出参数提示词结构流式读取逻辑错误处理逻辑。所以网页端长、API 短并不能直接说明模型能力不同。4. 为什么流式输出只返回一小段最常见原因是代码只读取了第一个 chunk。还可能是前端超时后端超时代理层断开Serverless 运行时间限制没有等待结束事件没有把增量内容拼接起来。建议先用非流式请求对比测试。如果非流式正常流式异常优先排查 stream 读取和链路超时。5. 为什么 JSON 经常不完整常见原因是输出上限不够schema 太复杂字段太多嵌套过深stop提前触发流式拼接不完整。解决方式增大输出上限减少字段拆分生成移除危险stop检查finish_reason验证完整拼接所有 chunk。6. 长文章应该一次生成还是分段生成更建议分段生成。一次性生成超长文章容易遇到token 上限延迟过高JSON 不完整网络中断网关超时结构跑偏。更稳的方式是先生成大纲再逐节展开。7. stop 参数怎么设置比较安全不要使用正文中常见字符作为停止符例如换行句号逗号Markdown 标题符号常见分隔符代码里可能出现的关键字。调试阶段建议先移除stop。确认不是它导致短输出后再根据业务需要添加更独特、不容易误触发的结束标记。总结API 返回内容太短通常不是单一参数问题。更可靠的排查顺序是先看 finish_reason 再查输出 token 上限 然后检查提示词结构 继续排除 stop 提前终止 再看上下文窗口是否被输入占满 最后检查 stream 拼接、JSON schema、工具调用和安全策略如果回答被截断优先处理输出上限和上下文预算。如果回答完整但太短优先改提示词结构。如果流式只返回一段优先检查 chunk 拼接和结束事件。