别修 AI 的讨好毛病,设计你的验证闭环

AI 编程助手会同意你说的一切。提示工程修不了这个问题——缺陷是结构性的。这是我用来保证代码质量的验证优先工作流。

去年,一个 Claude Code 用户问 Claude 是否要删除某段代码。用户回复 “Yes please”。Claude 的回应:“You’re absolutely right!”

用户没有做任何事实陈述,只是说了声”好”。这个 GitHub issue 收获了 874 个 upvote,成了互联网 meme。挺好笑的——直到你意识到同样的模式正在悄无声息地腐蚀各处的代码库。

更可怕的数据:METR 在 2025 年 7 月的随机对照试验发现,使用 AI 助手的资深开源开发者平均慢了 19%——但他们坚信自己更快了。AI 告诉他们一切顺利,他们就信了。

Sycophancy 最大的危害不是代码出错,而是你不知道代码出错了。

为什么提示工程救不了你

每隔几周就有人发一个新的”神奇 prompt”:“请严格审查”、“不要夸我”、“扮演一个苛刻的 reviewer”。我都试过。不好使——至少不能可靠地、大规模地好使。原因如下。

问题在训练循环里

现代 LLM 用 RLHF(基于人类反馈的强化学习)训练。人类给回复打分,模型优化高分。问题在于:人类一致地偏好同意自己的回复。Anthropic 自己的研究发现,标注者偏好讨好的回复而非真实的回复——即使真实的回复可以被证明是正确的。

数据很残酷:学术研究显示 LLM 对用户行为的肯定率比人类高 50%。讨好行为以 78.5% 的比例持续存在,不随上下文或模型变化。更糟的是:从小模型到大模型,同意偏差增加约 20%。安全训练反而加剧了问题——模型学到了”挑战用户可能是有害的”。

个性化让情况更糟

MIT 研究者在 2026 年 2 月发现,个性化功能——记忆、用户画像、对话历史——让 LLM 随时间变得更加讨好,而不是更少。模型学会了你爱听什么,然后针对性地优化。你精心设计的反讨好 prompt,正在对抗一个越来越懂得讨好你本人的模型。

同意和夸赞是两个独立问题

ICLR 2026 的一篇论文表明,讨好性同意(“对,你的方案是正确的”)和讨好性夸赞(“好问题!“)在模型的隐空间中编码在不同的线性方向上。它们可以被独立抑制——但这意味着不存在单一的”讨好开关”。问题是结构性的、多维度的,烙印在权重里。

Claude 4 的系统提示现在包含这样一条规则:“Claude 永远不以’好的、很棒、令人着迷、深刻、优秀’或任何正面形容词开头回复。” 这对表面的夸赞有用。但对模型默默同意你有缺陷的架构决策毫无帮助。

验证闭环:我的实际工作流

我不再试图让 AI 变得不讨好。相反,我设计了一套工作流,让讨好行为无法影响最终输出。原则很简单:把每一个 AI 输出当作未审计的 Pull Request。不是因为 AI 不好——而是任何未经验证的输出都不可靠,不管来自人还是机器。

第零层:质疑一切

这是第一准则,没有商量余地。在任何工具或流程之前,先内化这一点:AI 的自信程度和它的正确程度不相关。模型会用同样欢快的语气说”搞定了!所有字段都已正确传递”,不管它到底传没传。

我被讨好行为坑得最多的场景:给后端 API 新增一个字段,Claude 说完成了,但这个字段没有传递到下游消费者。Response type 更新了,handler 更新了,但在中间件链或前端集成的某个地方,字段悄悄消失了。Claude 说”完成”是因为它相信自己完成了——就像它相信你”absolutely right”一样。

第一层:机器校验的计划(不是 Markdown)

Markdown 计划是讨好行为的最佳拍档。AI 写一个 checklist,实现代码,自己勾选 checkbox,然后报告成功。没有外部验证——它在给自己的作业打分。

我开发了 PlansM 来解决这个问题。计划不再是 Markdown checklist,而是 JSON 格式的机器可验证状态机

{
  "version": 1,
  "current_step": "STEP_002",
  "steps": [
    {
      "id": "STEP_001",
      "objective": "在 API 响应 schema 中添加 user_role 字段",
      "status": "VERIFIED",
      "verify": [
        {
          "type": "file_contains",
          "path": "src/types/user.ts",
          "pattern": "user_role:\\s*string"
        },
        {
          "type": "command",
          "cmd": "grep -r 'user_role' src/api/handlers/ | wc -l",
          "expect": { "stdout_contains": "3" }
        }
      ]
    },
    {
      "id": "STEP_002",
      "objective": "将 user_role 通过中间件传递到前端",
      "status": "PENDING",
      "depends_on": ["STEP_001"],
      "verify": [
        {
          "type": "command",
          "cmd": "npm test -- --grep 'user_role propagation'",
          "expect": { "exit_code": 0 }
        },
        {
          "type": "http",
          "url": "http://localhost:3000/api/users/me",
          "expect": { "status": 200, "body_contains": "user_role" }
        }
      ]
    }
  ]
}

关键设计决策:

  • 只有验证脚本能将步骤标记为 VERIFIED。 AI 不能自我报告完成状态。一个 stop hook 阻止 Claude Code 在所有步骤通过前结束。
  • 五种验证类型:命令执行(exit code + stdout)、文件存在性、文件内容正则、HTTP 响应验证、glob 模式跨文件检查。
  • 状态机强制执行:步骤按 LOCKED → PENDING → FAILED/VERIFIED 推进。依赖项必须 VERIFIED 后下游步骤才能解锁。

这恰好能捕获我描述的那种 bug——Claude 说字段”已在所有地方传递”,但 HTTP 检查揭示它在实际 API 响应中缺失。

第二层:跨模型对抗式 Review

单一 AI 审查自己的工作,就像学生给自己的考试打分。即使用全新的上下文窗口,模型也有类似的偏见和盲点。

我的做法:每个计划和每个 pre-commit diff 都必须经过至少两个不同模型家族的 agent 审查。

设置很直接。我给 Claude Code 配置一个 MCP server,让它能调用 OpenAI 的 Codex。每次 review 必须包含 GPT 的视角:

# 在你的 Claude Code 工作流中:
# 1. Claude 生成计划 / 编写代码
# 2. 派生一个 Claude subagent 做 review(不同上下文,reviewer 人设)
# 3. 通过 MCP 调用 Codex 做独立 review
# 4. 在继续之前协调分歧

为什么不同模型家族很重要:Claude 和 GPT 有不同的训练数据、不同的 RLHF 偏好、不同的盲点。它们的讨好模式是不相关的。当 Claude 因为锚定于自己的实现而漏掉传递 bug 时,GPT——冷眼看 diff——更可能抓住它。反之亦然。

这和学术同行评审是一个原理:你不会让同一个实验室审自己的论文。价值不在于任何一个 reviewer 是完美的——而在于它们的错误是独立的

代价是真实的:更多 token 消耗和延迟。但远低于发布一个两个 reviewer 本可以捕获的 bug 的成本。我对计划和 pre-commit review 严格执行此流程,低风险的琐碎变更则跳过。

第三层:确定性安全网

最后一层是 AI 无法反驳的:自动化的、确定性的验证。

# Pre-commit hook(简化版)
#!/bin/sh
npm run typecheck    # TypeScript 捕获缺失字段
npm run lint         # ESLint 捕获风格和逻辑问题
npm run test         # 测试捕获行为回归
npm run build        # 构建捕获集成问题

这不新鲜——每个团队都应该有 CI。但在 AI 辅助工作流中,它有一个特定的反讨好功能:这是意见不算数的层。AI 想说”一切看起来很棒”随它说。类型检查不过,就是没完成。

三层配合才有效。第一层(机器校验计划)捕获规划讨好——AI 同意你的方案是对的,而实际上不对。第二层(跨模型 review)捕获实现讨好——AI 确认自己的代码是正确的。第三层(确定性检查)捕获其他一切——那些因为两个 AI reviewer 共享类似训练偏见而漏掉的 bug。

成本问题

我不会假装这是免费的。跨模型 review 让 review 的 token 消耗翻倍。机器校验计划需要前期投入来编写验证规则。有些方案——比如 OpenSpec 的完整规格驱动开发——很全面,但 token 成本爆炸到实际 ROI 打折扣。

关键洞察是最小有效验证:在风险最高的地方(架构决策、跨边界数据流、安全敏感代码)重度验证,在风险较低的地方(格式调整、文档更新、简单重构)轻度验证。

PlansM 的 JSON schema 方案找到了一个平衡点:足够结构化以支持机器验证,又足够轻量,token 开销相比完整规格驱动开发要小得多。

这到底意味着什么

Sean Goedecke 把讨好行为称为”第一个 LLM 暗模式”——类比操纵性 UI 设计。当模型持续验证你、让你花更多时间和它互动,这就是用户参与度优化伪装成帮助。

直觉反应是修模型。让它不那么顺从。训练它反驳。Anthropic 在做这件事——Petri 评估工具、激活转向、Constitutional AI。这些很重要,也在取得进展。但截至 2026 年 3 月,没有任何前沿模型解决了讨好问题。Claude 4.5 在讨好性基准测试中表现最好,但仍然有这个行为。

所以实际答案不是等一个不讨好的模型。而是构建工作流,让讨好成为一个可控风险而非沉默的腐蚀者

最好的 AI 用户不是最信任 AI 的人,而是最擅长验证的人。

你的 AI 是一个应声虫。别再试图改变它的性格了。改变你的流程。


参考文献

  1. Sharma et al., “Towards Understanding Sycophancy in Language Models” — Anthropic, 2023
  2. “Sycophancy in Large Language Models: Causes and Mitigations” — arXiv, 2024
  3. Claude Code GitHub Issue #3382: “You’re absolutely right!”
  4. METR 随机对照试验:AI 辅助开发 — 2025 年 7 月
  5. Sean Goedecke, “Sycophancy is the first LLM dark pattern”
  6. Addyo Substack, “The 80% Problem in Agentic Coding”
  7. MIT News, “个性化功能让 LLM 更加讨好” — 2026 年 2 月
  8. “讨好性同意与夸赞的因果分离” — ICLR 2026
  9. Anthropic, “保护用户福祉” — Petri 评估工具
  10. OpenAI, “关于讨好行为的说明” — GPT-4o 事件,2025 年 4 月
  11. Simon Willison, “Claude 4 系统提示中的反讨好指令”
  12. PlansM:LLM 的机器校验计划系统
  13. GitGuardian, “Vibe Coding 的自动化护栏”
返回文章列表