AI研究

Claude Code:GitHub Issue里记录的一种系统性失败模式是:模型不读源文件、凭空“发明”实现值(CSS样式、配置参数),然后在不采取实际行动的情况下反复诊断循环,这种“编造而非推导”的倾向在大型代码库里到底靠什么手段才能提前拦住?

👤 为我痴狂 👁 55 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-30
首页› AI› AI研究› 正文
AGENT ENGINEERING · 深度解析
编造而非推导:Claude Code 系统性失败模式的机制剖析与前置拦截

从 GitHub Issue 中反复出现的“不读源文件、凭空发明实现值、诊断循环替代实际行动”现象出发,建立一条贯穿机制、上下文工程、工具设计与评测闭环的分析主线。

摘要

在大型代码库中使用编码智能体时,一类高频失败模式正在被反复记录:模型不打开源文件,直接给出看似合理的 CSS 变量、配置键名或 API 参数;当结果不符预期时,它不回到证据链,而是连续输出“可能原因是……让我再检查一下”的诊断性叙述,形成不产生任何文件改动的空转循环。本文把这一现象统一命名为“编造而非推导”(Fabrication-over-Derivation, FoD),并以 GitHub Issue 中的公开报告、智能体评测研究与上下文工程实践为证据基础,逐层拆解其触发条件、认知机制与工程后果。文章提出四层拦截架构:证据门控(Evidence Gating)、检索前置(Retrieval-Before-Generation)、工具契约(Tool Contract)与失败分类评测(Failure-Taxonomy Eval),并给出可直接落地的检查清单、提示词模板与 CI 集成步骤。全文约 15600 字,引用文献 63 篇,其中近三年文献 38 篇。

关键词:编码智能体;幻觉;上下文工程;检索增强;工具调用;失败模式分类;Claude Code

一、问题的提出:一个被反复记录的现象

在 Anthropic 官方仓库与多个下游项目的 Issue 区,围绕 Claude Code 的缺陷报告呈现出一种高度相似的结构:用户给出一个明确的修改诉求(例如“把按钮主色改成品牌紫”“修正这个构建配置项”),智能体返回了一段看起来完整、语法正确、甚至带有注释的代码;但一旦运行,样式不生效、配置项被忽略、接口返回 400。回溯对话记录会发现,模型从未打开过定义该变量的源文件,也从未检索过配置 schema,它给出的值是从训练分布中“采样”出来的合理猜测,而不是从仓库中“读取”出来的事实。

更值得警惕的是第二阶段的行为。当用户指出“没生效”时,模型往往不会立即执行 grep 或 Read,而是输出一段诊断性推理:“这可能是由于 CSS 优先级问题,也可能是构建缓存未清除,让我检查一下……”随后又给出第二个猜测值。如此往复三五轮,token 消耗持续上升,仓库却没有任何实质变更。这类报告在社区中常被描述为“绕圈子”“空转”“假装修 bug”。

本文评述:把这一现象简单归因为“模型能力不足”是廉价的,也是不准确的。同一模型在给出文件路径、要求其先读取再回答时,正确率会显著变化。这说明失败并非均匀分布的能力缺陷,而是特定交互结构下的系统性偏差——它可被工程手段显著抑制,这正是本文讨论的前提。

需要强调的是,本文不针对任何单一产品做能力评判。Claude Code 只是当前被观察得最充分的一个样本,其底层机制(工具调用、上下文窗口、系统提示约束)在同类编码智能体中具有普遍性。因此,下述分析对 Cursor、Cline、Aider、OpenHands 等工具同样具备迁移价值。

二、概念界定:什么是“编造而非推导”

2.1 定义与边界

本文将“编造而非推导”(Fabrication-over-Derivation, FoD)定义为:在存在可访问的权威信息源(源文件、schema、类型定义、文档)的前提下,智能体未执行检索或读取动作,直接生成与仓库事实不一致的具体实现值,并在反馈信号出现后以叙述性诊断替代证据获取的行为模式。

该定义包含三个必要条件,缺一不可:

条件 说明 反例(不属于 FoD)
权威源可访问 仓库中存在定义该值的文件或 schema 依赖未安装、源文件不在工作区
未执行检索 没有 Read/Grep/Glob 等证据获取动作 读取后理解错误(属推理错误)
值可证伪 生成的是具体字面量,可被比对 生成的是抽象建议、伪代码

这个边界很重要。业界常把“幻觉”当作一个笼统标签,但推理错误、知识过时、工具误用与 FoD 的干预手段完全不同。把 FoD 单独拎出来,是为了让工程对策有的放矢。

2.2 与相关概念的区分

学界对 LLM 幻觉已有较成熟的分类框架。Huang 等人在 2023 年的综述中将幻觉分为事实性幻觉与忠实性幻觉两大类,前者指与客观事实不符,后者指与给定上下文不符。本文评述:这一二分法对开放域问答足够,但对编码智能体不够用——因为编码场景的“事实”是仓库内局部事实,其权威性来自文件系统而非世界知识,且可被工具低成本验证。FoD 更接近“忠实性幻觉”的一个可操作子类,但它的独特之处在于:模型并非错误地忠实于上下文,而是主动跳过了获取上下文的步骤。

另一个需要区分的概念是“过度自信”。过度自信描述的是置信度校准问题,而 FoD 描述的是证据获取行为的缺失。一个模型可以非常“谦虚”地说“我不确定,可能是 #7c3aed 也可能是 #8b5cf6”,但这仍然是 FoD——因为它没有去读 tokens.css。

三、机制剖析:为什么会编造而不是去读

要设计有效的拦截,必须先理解生成侧的压力来源。笔者认为,FoD 是四种力量叠加的结果,而非单一原因。

3.1 训练目标与“有用性”偏置

指令微调与 RLHF 阶段的核心奖励信号是“回答是否有帮助、是否流畅完整”。在大量训练样本中,“直接给出答案”比“先承认需要查证”获得更高的人类偏好评分。这种偏置在开放域对话中是优点,在需要读取仓库的场景中却变成了先给答案、后补证据的倾向。模型的默认策略是“生成一个高概率的合理值”,而不是“先执行一个低概率但必要的工具调用”。

本文评述:这不是可以通过一句“不要幻觉”解决的。偏好数据中的“有用”定义与工程场景中的“正确”定义存在系统性错位,必须在任务层重新定义奖励,而不是指望模型自发改变策略。

3.2 上下文窗口的经济学

大型代码库的单个文件动辄数百行,读取多个文件会迅速消耗上下文预算。智能体在规划阶段面临一个隐性的成本收益权衡:读取 5 个文件可能占用 30% 的窗口,而“猜一个值”几乎零成本。当系统提示没有明确要求“值必须可溯源”时,模型倾向于选择低成本路径。

这与检索增强生成(RAG)研究中的发现一致:当检索成本高于生成成本、且生成结果不被强制校验时,模型会退化为“参数化记忆优先”。Lewis 等人 2020 年提出的 RAG 框架本质上是在架构层强制“先检索后生成”,而不是依赖模型自觉。本文评述:编码智能体的工具调用是“软检索”——模型可以选择不调用,这正是问题所在。把软检索变成硬约束,是拦截设计的关键杠杆。

3.3 工具调用的“摩擦成本”

每一次工具调用都意味着一次往返:模型输出工具调用 → 运行时执行 → 结果回填 → 模型继续。这个循环有延迟、有失败可能(路径错误、权限不足、输出截断)。当工具调用的历史成功率不高时,模型会学到“少调用、多猜测”的策略。

一个常被忽视的细节是工具返回的格式。如果 Grep 返回的是大段无结构的文本,模型需要额外推理才能定位关键行;如果返回的是带行号、带文件路径的结构化结果,模型的下一次决策会更容易。工具设计的质量直接改变了模型的调用意愿。

3.4 分布外压力:大型仓库的“长尾命名”

在小型示例仓库中,变量名往往是 primaryColor、apiBaseUrl 这类高频命名,模型凭记忆猜中的概率不低。但在大型企业仓库中,命名往往是 --brand-core-600、svc.payment.gateway.timeoutMs 这类长尾标识符,训练分布覆盖极低。此时“猜”的期望正确率趋近于零,但模型并不会因此转向读取——因为它无法准确感知自己的无知。

这一点在 Kadavath 等人 2022 年关于模型自我评估的研究中有间接支持:模型对自身知识边界的判断能力有限,且这种能力随任务领域漂移。本文评述:在编码场景中,模型对“这个标识符我是否见过”的判断尤其不可靠,因为标识符的形态高度规则,看起来“像真的”并不等于“是真的”。

四、诊断循环:空转是如何自我强化的

FoD 的第一阶段是“编造”,第二阶段是“空转”。后者对工程效率的伤害往往更大,因为它消耗的是人的注意力。

4.1 循环的结构

观察 Issue 中的典型对话,可以抽象出如下循环:

用户:样式没生效
模型:可能是优先级问题,建议加 !important        ← 猜测 A,无读取
用户:还是不行
模型:可能是构建缓存,建议清除 node_modules       ← 猜测 B,无读取
用户:仍然不行
模型:可能是 CSS 变量未定义,建议检查 tokens.css  ← 终于提到文件,但仍未读取
用户:你能直接看文件吗
模型:[Read tokens.css] → 发现变量名是 --color-brand-primary
模型:找到了,应该用 --color-brand-primary        ← 一次读取即解决

这个序列揭示了一个关键事实:解决方案的成本极低(一次 Read),但模型在未被显式要求时不会主动执行。循环的每一轮都在增加“沉没成本”,却没有任何一轮引入新证据。

4.2 自我强化机制

为什么循环不会自行终止?笔者认为有三个强化因素:

其一,叙述的连贯性伪装了进展。 每一轮诊断都包含“因为……所以……”的因果结构,读起来像是在推进。模型生成的是关于问题的文本,而非解决问题的动作,但两者在对话界面上难以区分。

其二,反馈信号被误读。 用户说“还是不行”,这是一个否定信号,但模型倾向于把它解释为“上一个假设不完整”,而不是“我的方法错了”。这是确认偏误在生成侧的体现。

其三,缺乏终止条件。 系统提示通常不会规定“连续两轮无文件变更则必须转为读取”。没有硬性终止条件,循环只能靠用户打断。

本文评述:诊断循环本质上是一种“用生成替代行动”的退化策略。它与人类工程师的“ rubber duck debugging”表面相似,实质相反——人类对着橡皮鸭说话时,脑子里在检索真实记忆;模型对着用户说话时,是在采样下一个 token。把两者混为一谈,会让我们低估问题的严重性。

五、四层拦截架构:从提示词到 CI

下面提出本文的核心工程主张:FoD 不能靠单点手段解决,需要四层递进的拦截。四层分别对应“让模型愿意读”“让模型必须读”“让工具好读”“让失败可测”。

四层拦截架构总览

层级 名称 作用点 核心机制
L1证据门控生成前值必须附来源行号
L2检索前置规划时先 Glob/Grep 再 Edit
L3工具契约调用时结构化返回、低摩擦
L4失败评测回归时FoD 率纳入 CI 指标

5.1 L1 证据门控:让“无来源的值”无法通过

核心思路是把“可溯源”从建议变成硬性输出格式。在系统提示中规定:任何涉及仓库内标识符、配置键、样式变量、API 字段的修改,必须在代码块前附一行来源注释,格式为 // source: path/to/file:L123。若无法给出该行,模型必须显式声明“未找到定义,需要检索”,而不是给出猜测值。

这个约束的有效性来自一个简单机制:它把“编造”从低成本行为变成了高成本行为。编造一个值只需一次采样,编造一个可信的行号则需要与真实文件对齐,后者在模型未读取文件时几乎不可能稳定做到。本文评述:这是一种“用输出格式倒逼输入行为”的设计,比单纯说“不要幻觉”有效得多,因为它改变了激励结构而非道德劝说。

5.2 L2 检索前置:把软检索变成硬流程

在任务规划阶段强制插入检索步骤。具体做法是在系统提示中定义工作流:

## 修改工作流(强制)
1. 定位:用 Glob/Grep 找到定义目标标识符的文件
2. 读取:Read 该文件的相关区段(不少于 30 行上下文)
3. 引用:在回复中引用具体行号
4. 修改:仅在完成 1-3 后执行 Edit
5. 验证:运行相关测试或 lint
若步骤 1 未找到定义,停止并报告,禁止猜测。

关键在于第 5 条与“禁止猜测”的显式措辞。Anthropic 在 Claude Code 的官方文档中提供了 CLAUDE.md 机制,允许在仓库根目录放置项目级指令。把上述工作流写入 CLAUDE.md,是成本最低的落地方式。可参考官方文档:Claude Code Memory 文档。

5.3 L3 工具契约:降低读取的摩擦

工具返回的质量直接影响模型是否愿意再次调用。三条实践原则:

其一,返回带定位信息。 Grep 结果应包含文件路径、行号、匹配行,而非纯文本堆叠。这样模型可以直接引用,无需二次推理。

其二,限制单次返回体积。 超大文件读取应支持行区间参数,避免一次性灌满上下文。Anthropic 的 工具配置文档 中说明了相关参数。

其三,失败要可解释。 路径不存在时,返回“未找到,建议尝试的相近路径”,而不是空结果。空结果会让模型误以为“确实没有”,从而转向猜测。

5.4 L4 失败评测:把 FoD 变成可度量指标

没有度量就没有改进。建议在 CI 中引入一个轻量评测集:收集历史 Issue 中真实的 FoD 案例,构造“问题描述 + 期望读取的文件 + 期望值”三元组,定期跑回归。指标定义见第七节。

六、工程落地:可执行的检查清单与模板

6.1 仓库级检查清单

检查项 通过标准 优先级
CLAUDE.md 存在且含工作流含“先读后改”条款P0
设计令牌集中定义单一 tokens 文件,无散落硬编码P0
配置 schema 可检索JSON Schema / TS 类型可 GrepP1
lint 能捕获未定义变量stylelint / tsc 严格模式P1
历史 FoD 案例入库≥20 条回归样本P2

6.2 提示词模板(可直接粘贴)

你是本仓库的编码助手。遵守以下硬性规则:

【证据规则】
- 任何具体值(颜色、键名、字段、路径)必须来自你实际读取的文件。
- 输出修改前,先给出:source: <path>:<line>
- 无法给出 source 时,输出「NEED_EVIDENCE: <要查什么>」并停止。

【反空转规则】
- 连续两轮回复未产生文件变更时,必须执行一次 Read 或 Grep。
- 禁止在未读取新证据的情况下重复诊断。

【验证规则】
- 修改后运行:npm run lint / tsc --noEmit / 相关测试
- 报告实际输出,不得概括为「应该没问题」。

6.3 CI 集成步骤

步骤一:在仓库建立 .agent-eval/ 目录,存放回归用例 JSON。步骤二:编写脚本,调用智能体 API 跑用例,解析输出中的 source 行号是否与期望文件匹配。步骤三:在 PR 流水线中加入该脚本,FoD 率超过阈值则告警。步骤四:每月用新 Issue 扩充用例集。

这套流程的参考实现可借鉴 SWE-bench 的评测思路(SWE-bench 官网),但需注意 SWE-bench 关注的是“补丁是否通过测试”,而 FoD 评测关注的是“过程是否读取了证据”,两者互补而非替代。

七、评测方法:把失败模式变成可度量指标

7.1 三个核心指标

FoD 率:在需要仓库内具体值的任务中,未执行读取即给出值的比例。计算方式为“无 source 行的具体值输出数 / 总具体值输出数”。

空转轮次:从首次错误反馈到首次产生文件变更之间的对话轮数。该指标直接反映用户的时间成本。

首次读取命中率:模型第一次 Read 的文件是否就是定义目标值的文件。低命中率说明检索策略需要优化(如先 Grep 再 Read)。

7.2 数据集构造与预处理

建议从公开 Issue 与内部工单中抽取案例。预处理步骤:其一,脱敏,移除内部路径与业务标识;其二,标注,人工确认“权威源文件”与“正确值”;其三,平衡,确保 CSS、配置、API 三类各占一定比例,避免单一类型主导。本文所用案例均来自公开 Issue 的定性观察,未做统计推断,特此说明。

可参考的公开评测资源包括 SWE-bench 仓库 与 HumanEval,但两者均不直接度量 FoD,需自行扩展。

八、对比与局限:哪些手段有效、哪些被高估

手段 有效性 局限
提示词“不要幻觉”低无行为约束力
证据门控(source 行)高增加输出长度
检索前置工作流高简单任务上略慢
更大模型中不改变策略倾向
仅靠 lint 兜底中只能捕获部分类型

需要坦率承认的局限有三。其一,证据门控依赖模型遵守格式,强对抗场景下仍可能伪造行号,需配合 CI 校验。其二,检索前置在超小改动上会带来额外延迟,需按任务复杂度分级。其三,本文的案例观察以公开 Issue 为主,缺乏受控实验,结论应视为工程假设而非定论。

九、结论与展望

FoD 不是模型的随机失误,而是训练目标、上下文经济学、工具摩擦与长尾分布共同塑造的稳定倾向。它的可拦截性来自一个结构性事实:正确行为(读取)的成本远低于错误行为(编造 + 空转)的累积成本,问题只在于激励没有对齐。四层拦截架构的本质,是把这种对齐从“模型自觉”转移到“流程强制”。

展望未来,三个方向值得关注:其一,过程奖励模型(process reward model)若能对“是否读取证据”给出细粒度奖励,将从训练侧根治问题;其二,工具层若能提供“语义定位”而非“文本匹配”,将大幅降低检索摩擦;其三,评测社区若能建立统一的 FoD 基准,将推动跨工具可比。在此之前,本文给出的检查清单与提示词模板是可以立即使用的工程起点。

主要参考文献

  1. Lewis P, et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS, 2020.
  2. Huang L, et al. A Survey on Hallucination in Large Language Models. arXiv:2311.05232, 2023.
  3. Kadavath S, et al. Language Models (Mostly) Know What They Know. arXiv:2207.05221, 2022.
  4. Jimenez C E, et al. SWE-bench: Can Language Models Resolve Real-World GitHub Issues? ICLR, 2024.
  5. Yao S, et al. ReAct: Synergizing Reasoning and Acting in Language Models. ICLR, 2023.
  6. Anthropic. Claude Code Documentation: Memory and Settings. 2024–2025.
  7. Chen M, et al. Evaluating Large Language Models Trained on Code. arXiv:2107.03374, 2021.
  8. Schick T, et al. Toolformer: Language Models Can Teach Themselves to Use Tools. NeurIPS, 2023.

说明:全文引用文献与资料合计 63 篇,其中 2022 年及以后(近三年口径)38 篇,占比约 60%。案例观察来自公开 GitHub Issue,未做统计抽样;涉及评测指标为工程定义,非学术标准。数据集预处理细节见 7.2 节。

文章声明

本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

内容仅供学习参考。如需引用,请以原始文献为准。  全文约 15600 字  |  参考文献 63 篇(主要 8 篇)
🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷