我让大模型生成 JSON,它经常生成到一半就断了、JSON 解析失败,内容长的时候尤其频繁,我对着 max_tokens 排查了大半天的复盘

做了个用大模型生成结构化数据的功能:让模型按要求输出 JSON,程序再解析。大部分时候没问题,可一旦要生成的内容比较长(字段多数组长)就频繁出问题:模型返回的 JSON 生成到一半就断了(停在半句话上),程序解析残缺 JSON 直接报错。困惑模型不是挺聪明吗连完整 JSON 都生成不完是不是模型不行?换更强模型调 prompt 内容短时好了长了还断。排查大半天才发现罪魁是随手设的参数 max_tokens 太小了:max_tokens 是输出 token 上限,模型生成到这个数就强制停止不管说完没说完;我设了 256,长内容超过它就被砍成半截。确认靠 finish_reason——正常完成是 stop、被截断是 length。这篇从 max_tokens 与上下文窗口(输入+输出≤窗口)、按预期输出设够 max_tokens/必查 finish_reason/超长用续写分批/JSON校验完整性的正解、LLM 输出处理常见坑、finish_reason 取值速查、控制输出长度的几个维度(软硬结合)、决策图与铁律,到附上一个带 finish_reason 检查和截断重试的健壮调用封装。核心领悟:工具表现不佳别急着怪工具不行,先反思是不是自己没用对没配好(我怪模型不行其实是max_tokens没设够);认真对待API返回的元信息(finish_reason)别只盯主数据content;面对不可靠的外部依赖用一层封装统一兜住各种不正常,让健壮成为调用即得的默认。

我让大模型生成 JSON,它经常生成到一半就断了、JSON 解析失败,内容长的时候尤其频繁,我对着 max_tokens 排查了大半天的复盘

那是我做的一个用大模型生成结构化数据的功能:让模型按要求输出一段 JSON,我的程序再解析它。大部分时候没问题,可一旦要生成的内容比较长(字段多、数组长),就频繁出问题:模型返回的 JSON,生成到一半就断了——比如停在 "name": "张三", "address": {"city": "北 这样的半句话上,我的程序解析这个残缺 JSON 直接报错。我一脸困惑:模型不是挺聪明的吗?怎么连个完整的 JSON 都生成不完?是不是模型不行?我换了更强的模型、调了 prompt,内容短时好了、内容一长还是断。排查了大半天,我才发现罪魁祸首,是一个我设置时随手填的参数:max_tokens(最大输出 token 数)设得太小了。这篇就把这场"输出被截断"的事故,从头复盘一遍。

故障现场:JSON 生成到一半就断了

先看现场。问题就藏在我那个随手设的 max_tokens 上:

# 我的代码: 调大模型生成JSON
resp = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "生成10个用户的完整信息, JSON格式"}],
    max_tokens=256,   # ✗✗ 我随手设的256, 太小了!
)
answer = resp.choices[0].message.content
data = json.loads(answer)   # ✗ 报错: JSON解析失败(不完整)

# 模型返回的内容(被截断了):
#   [{"id":1,"name":"张三","address":{"city":"北京","street":"长安街"}},
#    {"id":2,"name":"李四","address":{"city":"上海","stre
#                                              ↑ 戛然而止! 后面没了!
#   → 这不是合法JSON, json.loads 直接报错。

# 怎么确认是被截断的? 看返回的 finish_reason:
print(resp.choices[0].finish_reason)
#   "length"  ← 关键! 说明是"达到了max_tokens上限"被【强制截断】的!
#   (正常生成完是 "stop"; "length"就是被max_tokens砍断了)

# 为什么? max_tokens 限制了模型"最多能输出多少token":
# 1. max_tokens 是"输出(生成)的token上限"。模型生成到这个数, 就【强制停止】,
#    不管它有没有"说完"。
# 2. 我设了256, 当要生成的内容(10个用户的JSON)超过256个token时:
#    → 模型生成到第256个token, 不管JSON写没写完, 直接被【砍断】!
#    → 于是得到一个"半截的、不完整的"JSON。
# 3. 内容短时(< 256 token): 没超上限, 能完整生成 → 没问题。
#    内容长时(> 256 token): 超了上限 → 被截断 → JSON残缺 → 解析失败。
# 4. ★ 这不是"模型不行/不会生成完整JSON", 而是我【限制了它的输出长度】,
#    它还没说完就被我设的max_tokens掐断了。

# 现象拼图:
#   - max_tokens 限制输出长度, 超了就强制截断(finish_reason="length")。
#   - 我设的256太小, 长内容超过它就被砍成半截。
#   - 短内容没超, 所以"短的好、长的断"。
#   - ★ 根因: 我没意识到max_tokens会"硬截断"输出, 设了个不够用的小值,
#     导致长输出被掐断、JSON不完整。

看到 finish_reason"length" 时,我才明白这"生成到一半就断"的根子。问题的根源,是我随手设的 max_tokens=256 太小了。max_tokens 是"输出(生成)的 token 上限",模型生成到这个数就强制停止,不管它有没有"说完"我设了 256,当要生成的内容(10 个用户的 JSON)超过 256 个 token 时,模型生成到第 256 个 token、不管 JSON 写没写完就被砍断,于是得到一个"半截的、不完整的"JSON。内容短时(< 256)没超上限能完整生成、没问题;内容长时(> 256)超了就被截断、JSON 残缺、解析失败——这就解释了"短的好、长的断"。而确认它是被截断的关键,是 finish_reason:正常生成完是 "stop",被 max_tokens 砍断是 "length"根因是:我没意识到 max_tokens 会"硬截断"输出,设了个不够用的小值,导致长输出被掐断、JSON 不完整;这不是"模型不行",而是我限制了它的输出长度

第一件事:搞懂 max_tokens 与上下文窗口

要解决它,得先搞懂 max_tokens 是什么,以及它和上下文窗口的关系。

max_tokens 与上下文窗口

# 一、max_tokens 是什么?
#   - max_tokens 限制"模型这次【输出/生成】最多多少个token"。
#   - 模型生成到这个数, 就【强制停止】(不管内容说完没说完)。
#   - 它和"输入(prompt)的长度"无关, 只管"输出"。

# 二、被截断的标志: finish_reason
#   - "stop": 模型正常说完了(遇到结束标志自然停止)。✓ 完整
#   - "length": 达到了max_tokens(或上下文窗口)上限被【强制截断】。✗ 不完整!
#   - ★ 检查 finish_reason, 是判断"输出是否被截断"的关键! 别只看content。

# 三、max_tokens 和 上下文窗口(context window)的关系
#   - 上下文窗口 = 输入(prompt) + 输出(生成) 的 token 总和的上限。
#   - max_tokens 是给"输出"单独设的上限。
#   - 约束: 输入token + max_tokens ≤ 上下文窗口。
#   - 所以 max_tokens 不能设太大(否则输入+输出超过窗口会报错),
#     也不能设太小(否则输出被截断, 本文)。要在两者间取合适值。

# 四、为什么会有 max_tokens? 它的作用:
#   - 控制成本: 输出token要花钱, max_tokens 防止"生成过长、花太多钱"。
#   - 控制延迟: 输出越长生成越慢, 限制它能控制响应时间。
#   - 防失控: 防止模型"啰嗦个没完", 给个上限兜底。
#   → 它是个有用的"控制阀", 但设错了(太小)就会截断正常的输出。

# 五、默认值的坑:
#   - 有些SDK/API的max_tokens默认值很小(如某些默认256/512甚至更小)。
#   - 不显式设, 用了小的默认值, 长输出就被默认值截断了。
#   → 要根据"预期输出多长"显式设一个够用的max_tokens。

# 核心: max_tokens限制输出token数、超了强制截断(finish_reason="length"); 它受上下文窗口约束
#   (输入+输出≤窗口); 设太小截断输出(本文)、太大可能超窗口; 要按预期输出长度设够用的值并查finish_reason。

想透 max_tokens,这个坑就清楚了。一、max_tokens 是什么?——限制"模型这次输出/生成最多多少个 token",生成到这个数就强制停止(不管说完没说完),它只管输出、和输入长度无关二、被截断的标志:finish_reason——"stop" 是正常说完了、"length" 是达到上限被强制截断;检查 finish_reason 是判断"输出是否被截断"的关键,别只看 content三、max_tokens 和上下文窗口的关系——上下文窗口 = 输入 + 输出的 token 总和上限,max_tokens 是给输出单独设的上限,约束是"输入 token + max_tokens ≤ 上下文窗口";所以 max_tokens 不能太大(否则超窗口报错)也不能太小(否则截断,本文)四、为什么有 max_tokens?——控制成本(输出花钱)、控制延迟(输出越长越慢)、防失控(防啰嗦没完);它是有用的控制阀,但设太小会截断正常输出五、默认值的坑——有些 SDK/API 的 max_tokens 默认值很小,不显式设就用了小默认值、长输出被截断;要按预期输出长度显式设够用的值

第二件事:正解——设够 max_tokens、检查 finish_reason、处理超长

搞懂了原理,正解就清晰了:按预期输出设够 max_tokens、检查 finish_reason 判断是否被截断、超长内容用续写或分批、用流式输出

# ====== 正解一: 按"预期输出长度"设够 max_tokens ======
resp = client.chat.completions.create(
    model="gpt-4",
    messages=[...],
    max_tokens=4000,   # ✓ 根据"预期要生成多长"设一个够用的值(不是随手256)
)
# - 估算: 你要生成的内容大概多少token? 设比它大一些(留余量)。
#   (中文1字≈1~2token; 10个用户的JSON可能要1000~2000token)
# - 但: 别超过"上下文窗口 - 输入token"(输入+max_tokens ≤ 窗口)。

# ====== 正解二(必做): 检查 finish_reason, 判断是否被截断 ======
choice = resp.choices[0]
if choice.finish_reason == "length":
    # 输出被截断了! 不是完整结果, 要处理(别直接当完整结果用)
    log.warning("输出被max_tokens截断了!")
    # → 处理: 加大max_tokens重试, 或走"续写", 或报错提示
content = choice.message.content
# ★ 别只取content就当完整结果! 一定先看finish_reason是不是"length"。

# ====== 正解三: 输出确实很长时, 用"续写(continuation)" ======
# 如果内容本身就超过单次能生成的上限, 分多次生成、拼接:
def generate_long(messages, max_tokens=4000):
    full = ""
    while True:
        resp = client.chat.completions.create(
            model="gpt-4",
            messages=messages + [{"role":"assistant","content":full}] if full else messages,
            max_tokens=max_tokens)
        chunk = resp.choices[0].message.content
        full += chunk
        if resp.choices[0].finish_reason != "length":
            break   # 说完了
        # 没说完(length), 让它接着上次continue
    return full
# → 适合"必须生成超长内容"的场景, 但拼接JSON等结构化数据要小心(易拼坏)。

# ====== 正解四: 大量数据"分批生成", 而非一次性 ======
# 与其"一次生成100条"(容易超长被截断), 不如"分10批、每批10条":
# - 每批输出短、不会被截断、可控。
# - 还能并发、失败可重试单批。
# → 对"生成大量结构化数据", 分批比"一次性大输出"更稳。

# ====== 正解五: 用流式输出(streaming)+ 边收边处理 ======
# stream=True: 模型一边生成你一边收, 能更早展示、也能在收的过程中判断。
# (流式也要处理"中途被截断"的情况, 看最后的finish_reason)

# ====== 正解六: 结构化输出场景的稳妥做法 ======
# - 用模型的"JSON mode"/structured output(强制输出合法JSON), 但仍要设够max_tokens。
# - 解析前先校验完整性(能json.loads通过), 失败则重试/加大max_tokens。

# 核心: 按预期输出设够max_tokens(不随手小值)+ 必查finish_reason(=="length"即被截断)
#   + 超长用续写/分批生成 + 流式输出 + 结构化输出校验完整性; 别只取content就当完整结果。

修复的核心,是"给 max_tokens 设够、并通过 finish_reason 确认输出是否完整"正解一:按"预期输出长度"设够 max_tokens——估算要生成的内容大概多少 token、设比它大一些(留余量),别随手 256;但别超过"上下文窗口 - 输入 token"正解二(必做):检查 finish_reason 判断是否被截断——finish_reason == "length" 说明被截断了、不是完整结果,要处理(别只取 content 就当完整结果用)正解三:输出确实很长时用"续写"——分多次生成、拼接(但拼接 JSON 等结构化数据要小心)正解四:大量数据"分批生成"——与其"一次生成 100 条"(易超长截断),不如"分 10 批每批 10 条"(每批短、可控、可重试)正解五:用流式输出 + 边收边处理正解六:结构化输出用 JSON mode + 解析前校验完整性(失败则重试/加大 max_tokens)。归根结底:按预期输出设够 max_tokens + 必查 finish_reason + 超长用续写/分批 + 流式 + 结构化校验完整性;别只取 content 就当完整结果。

第三件事:LLM 输出处理的常见坑

排查后我把 LLM 输出处理的常见坑也系统梳理了一遍,它们一样隐蔽。

LLM 输出处理的常见坑

# 1. max_tokens太小, 输出被截断(本文)。→ 设够 + 查finish_reason。

# 2. 不检查 finish_reason, 把截断的内容当完整结果用:
#    → 残缺JSON解析失败、答案不完整却以为完整。→ 必查finish_reason。

# 3. 输入太长挤占了输出空间:
#    - 上下文窗口=输入+输出。输入(prompt+历史)太长 → 留给输出的空间不够,
#      → 即使max_tokens设大了, 实际也生成不了多少就到窗口上限。
#    → 控制输入长度(见上下文超限篇), 给输出留足空间。

# 4. JSON解析不做容错:
#    - 模型输出的JSON可能被截断、可能带markdown代码块标记(```json)、
#      可能有多余文字。直接json.loads容易失败。
#    → 解析前清洗(去掉```等)、用容错解析、失败重试。

# 5. 流式输出没处理好"中途断开/截断":
#    → 流式也要在结束时检查finish_reason、处理不完整。

# 6. 没考虑输出的成本/延迟:
#    - 输出越长越贵越慢。该控制时控制(但别为省而设太小导致截断)。
#    → 在"够用"和"不浪费"之间平衡max_tokens。

# 7. 假设模型一定按格式输出:
#    - 即使要求了JSON, 模型也可能不完全遵守(见JSON不可靠篇)。
#    → 校验 + 重试 + 兜底, 别裸信。

# 核心: LLM输出处理坑有 max_tokens截断/不查finish_reason/输入挤占输出/JSON解析不容错/
#   流式没处理截断/不管成本延迟/假设一定守格式; 核心是设够max_tokens、查finish_reason、解析容错。

排查让我把 LLM 输出处理的常见坑也梳理清了。一、max_tokens 太小输出被截断(本文)。二、不检查 finish_reason、把截断内容当完整结果(残缺 JSON 解析失败)。三、输入太长挤占了输出空间——上下文窗口=输入+输出,输入太长留给输出的空间就不够,即使 max_tokens 设大了实际也生成不了多少;要控制输入长度、给输出留足空间四、JSON 解析不做容错——模型输出的 JSON 可能被截断、带 markdown 标记、有多余文字,解析前要清洗、用容错解析、失败重试五、流式输出没处理"中途截断"。六、没考虑输出的成本/延迟(在够用和不浪费间平衡)。七、假设模型一定按格式输出(要校验+重试+兜底,别裸信)。它们的核心是:设够 max_tokens、查 finish_reason、解析容错下面这张图,是这次输出被截断的成因与解法:

第四件事:finish_reason 取值速查

这次踩坑后,我把 finish_reason 的常见取值整理成一张表,处理 LLM 输出时必查它。

finish_reason 含义 该怎么处理
stop 正常说完(遇到结束) ✓ 完整,可正常用
length 达到 max_tokens/窗口上限被截断 ✗ 不完整!加大max_tokens/续写/分批
content_filter 被内容审查拦截 内容触发了过滤,需调整
tool_calls / function_call 模型要调工具 去执行工具调用
null(流式中) 还在生成中 继续接收

这张表,把 finish_reason 的取值讲清了。最关键的是分清 stop(正常完整)和 length(被截断、不完整);看到 length 就要警觉:这个输出是残缺的,不能当完整结果用它给我的最大启发是:大模型的 API 返回里,往往藏着一些"元信息"(如 finish_reason、token 用量、是否触发审查),它们告诉你"这次生成发生了什么、结果是否可信";而我之前只盯着 content(实际内容)、完全忽略了这些元信息这让我领悟到一个使用 API/接口的通用道理:一个接口的返回,不只有"主数据(content)",往往还有"关于这次调用的元信息/状态(finish_reason、状态码、分页信息、错误码……)";而这些元信息,常常是"正确、健壮地处理结果"的关键我这次的坑,正是只取了主数据(content)、忽略了元信息(finish_reason),把一个"状态是 length(被截断)"的残缺结果,当成了完整结果所以,这件事提醒我:用任何接口/API,都要完整地理解并利用它的返回(不只主数据,还有状态、元信息);那些"看起来不起眼的元信息字段",常常是判断"结果是否可信、该如何处理"的依据认真对待返回里的每一个字段,而不只是那个最显眼的主数据——这是健壮地对接任何接口的基本功。

第五件事:控制 LLM 输出长度的几个维度

这次让我把"控制 LLM 输出"的几个维度系统梳理了一遍。

维度 作用 注意
max_tokens 硬限制输出 token 上限 设够防截断,但≤窗口-输入
prompt 引导 让模型"主动"控制长度 如"简洁回答""不超过N条"
分批/分页 大量数据拆成多次小输出 每次短、可控、可重试
流式输出 边生成边返回 体验好,仍需查截断
结构化约束 JSON mode/schema 约束格式 配够 max_tokens 防截断
上下文管理 控制输入长度给输出留空间 输入+输出≤窗口

这张表,把"控制 LLM 输出"的几个维度串了起来。它们各管一面:max_tokens 是硬限制(防截断要设够)、prompt 引导是"软控制"(让模型主动简洁)、分批/分页应对大量数据、流式改善体验、结构化约束格式、上下文管理给输出留空间它给我的最大启发是:"控制大模型的输出"是一个需要"软硬结合、多管齐下"的工程问题:""的(max_tokens 这种确定性限制)和""的(prompt 引导这种概率性影响)要配合——光靠 prompt 说"简洁点"它未必听(概率的),所以要有 max_tokens 兜底;但光靠 max_tokens 又会硬截断,所以要配合 prompt 引导和分批,让它在限制内"说完整"这让我领悟到一个驾驭大模型的核心心法:大模型是"概率的、不完全可控的",所以驾驭它往往需要"用确定性的工程手段(硬限制、校验、分批),去约束和兜底它的概率性行为";既要用 prompt"引导"它(发挥它的智能),又要用工程手段"约束和兜底"它(应对它的不可靠)——软硬结合,才能既用上它的能力、又控制住它的输出

第六件事:调用 LLM 生成内容时,我现在的习惯

现在每当我调用大模型生成内容,我都会按这张图先想清楚输出长度的处理:

这张图的精髓,是"生成前估好长度设够 max_tokens,生成后查 finish_reason 确认完整"生成前:估算预期输出多少 token、设够 max_tokens(留余量但≤窗口-输入);内容会很长就分批/续写生成后:先查 finish_reason——stop 才完整可用、length 是被截断要加大 max_tokens 重试/续写结构化输出还要解析前校验完整性、失败重试这套习惯,让我调用 LLM 时,从"随手设 max_tokens、只取 content 就用"变成了"估好长度设够、查 finish_reason、校验完整"——核心始终是:max_tokens 会硬截断输出,要按预期长度设够,并查 finish_reason 确认输出完整,别只取 content。

我立下的几条规矩

这场"输出被截断"的事故,换来了我做 LLM 应用时,刻进骨子里的几条铁律:

  1. max_tokens 会硬截断输出。生成到上限就强制停止,不管说完没说完。
  2. 按预期输出长度设够 max_tokens。别随手填小值,但别超过"窗口-输入"。
  3. 必查 finish_reason。"length"=被截断不完整,"stop"=正常完整;别只取 content。
  4. 输出很长用分批/续写。别一次性大输出,分批更稳、可重试。
  5. JSON 等结构化输出要校验完整性。解析前清洗、校验,失败重试/加大 max_tokens。
  6. 注意输入挤占输出空间。窗口=输入+输出,输入太长输出空间就不够。
  7. 认真对待 API 返回的元信息。finish_reason、token 用量等,别只盯主数据。

附:一个带 finish_reason 检查和重试的健壮调用封装

口说无凭。下面把"设够 max_tokens + 检查 finish_reason + 截断重试 + JSON 校验"合到一个封装里:

import json, re

def robust_generate(client, messages, max_tokens=2000, want_json=False, max_retry=2):
    """健壮的LLM调用: 设max_tokens + 查finish_reason + 截断时加大重试 + JSON校验。"""
    current_max = max_tokens
    for attempt in range(max_retry + 1):
        resp = client.chat.completions.create(
            model="gpt-4", messages=messages, max_tokens=current_max,
            **({"response_format": {"type": "json_object"}} if want_json else {})
        )
        choice = resp.choices[0]
        content = choice.message.content

        # 1. ★ 检查是否被截断(finish_reason == "length")
        if choice.finish_reason == "length":
            # 被max_tokens截断了 → 加大max_tokens重试(留更大空间)
            current_max = min(current_max * 2, 8000)  # 翻倍, 但别超上限
            log.warning(f"输出被截断, 加大max_tokens到{current_max}重试 (第{attempt+1}次)")
            continue

        # 2. 正常完成(finish_reason == "stop")
        if not want_json:
            return {"ok": True, "content": content}

        # 3. 要JSON: 清洗 + 校验完整性
        cleaned = _strip_markdown(content)   # 去掉可能的 ```json``` 包裹
        try:
            data = json.loads(cleaned)        # 能解析 = 完整且合法
            return {"ok": True, "data": data}
        except json.JSONDecodeError as e:
            # JSON不完整/不合法 → 重试(可能加大max_tokens, 或调整prompt)
            log.warning(f"JSON解析失败({e}), 重试 (第{attempt+1}次)")
            current_max = min(current_max * 2, 8000)
            continue

    # 重试用尽仍失败
    return {"ok": False, "error": "多次生成仍不完整/不合法, 建议分批或人工"}

def _strip_markdown(text):
    # 去掉 ```json ... ``` 或 ``` ... ``` 的包裹
    m = re.search(r"```(?:json)?\s*(.*?)\s*```", text, re.DOTALL)
    return m.group(1) if m else text.strip()

# 用法:
# r = robust_generate(client, messages, max_tokens=2000, want_json=True)
# if r["ok"]: use(r["data"])
# else: handle_failure(r["error"])

# 核心: 封装"查finish_reason(length则加大max_tokens重试)+ JSON清洗校验(失败重试)+
#   重试用尽兜底"; 调用方只管 robust_generate, 截断/不完整都被自动处理, 不会拿到半截结果。

这个 robust_generate,把这篇文章的解法,落成了一个可复用的健壮调用封装。它把几道防线编织在一起:检查 finish_reason(是 length 被截断就加大 max_tokens 重试)、JSON 输出时清洗 markdown 包裹并校验完整性(解析失败就重试)、重试用尽则返回明确的失败这样,调用方只管调 robust_generate,"输出被截断""JSON 不完整"这些情况都被它自动处理(加大重试),调用方拿到的要么是"完整可用的结果",要么是"明确的失败",绝不会拿到一个半截的、会让后续解析崩溃的残缺结果这,正是我想用这个封装,留给每个做 LLM 应用的人的最后一课:大模型的输出是"不确定、可能不完整、可能不合规范"的,而把"检查完整性(finish_reason)、校验格式、截断/失败时重试"这套处理逻辑,封装进一个统一的调用入口,能让所有调用都默认获得这层健壮性保障,而不必每处都手动处理这再次呼应了我这一整个系列复盘反复强调的核心工程思想:面对"不可靠的外部依赖"(网络、大模型、用户输入),正确的做法不是"祈祷它每次都正常",而是用一层健壮的封装/适配层,把"处理它的各种不正常"统一兜住;让"正确、健壮地使用它",成为一种"调用即得的默认能力",而非"依赖每个使用者都记得正确处理"给不确定的大模型,套一层确定性的、自动处理异常的封装——这,是把 LLM 稳定地用到生产里的关键一招。

写在最后

回头看,这场由 max_tokens 引发的、输出被截断的事故,真正教给我的,远不止"设够 max_tokens、查 finish_reason"这一套技巧。它纠正了我一个常见的归因偏差。我一开始遇到"JSON 生成不完整",第一反应是"模型不行/不够聪明"——我把问题归咎于"模型的能力"。可真相是:模型完全有能力生成完整的 JSON,是我用 max_tokens"掐断"了它,不让它说完。问题不在"模型不会",而在"我没让它好好说"(我的参数配置限制了它)。这让我领悟到一个使用工具/系统时极其重要的归因态度:当一个工具/系统的表现不如预期时,不要急于把问题归咎于"工具本身不行",而要先反思"是不是我没用对、没配好它?";很多"看起来是工具能力不足"的问题,根子其实在"使用者的配置/用法不当"这种"先从自己身上找原因"的态度,不仅更可能找到真正的问题(因为"用法问题"远比"工具缺陷"常见),也更能让我学会"正确、充分地使用一个工具"。我这次,正是因为先入为主地怪"模型不行",而没去检查"我自己的参数(max_tokens)和返回信息(finish_reason)",才走了弯路所以,这件事给我的最大启发是:遇到工具表现不佳,先假设"是我没用对"——去深入理解它的参数、配置、返回,确认自己用对了、用足了它的能力;只有在确认"正确使用下它依然做不到"后,才归咎于它的能力谦逊地先反思自己的用法、而非急于怪工具——这,是我用一次"输出被截断"的事故,换来的、关于 AI、也关于"正确归因"的、最朴素也最深刻的领悟。如果这篇复盘,能让你下次遇到 LLM 输出不完整时,先去看一眼 max_tokens 和 finish_reason,那我对着那些半截的 JSON 熬的这大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我本地跑得好好的代码一上生产就报错、复现不出来,排查发现是本地和生产环境差了好几处,我对着"在我机器上是好的"这个魔咒排查了大半天的复盘

2026-6-2 9:05:32

技术教程

我给接口加了"每分钟最多 100 次"的限流,结果它还是在某个瞬间被 200 次请求打穿了,我对着固定窗口限流的临界问题排查了大半天的复盘

2026-6-2 9:18:05

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索