第7课

第6课回顾

第6课学了Ratchet Pattern。通过就锁定,机器宣布"结束"。把停在40的智能体一路推到527的结构。

今天深入挖掘棘轮为什么有效的原理。再进一步,讨论提示和验证器应该按什么比例设计。

开始之前了解一下。**IFEval(Instruction Following Evaluation)**是衡量"AI是不是按指示做"的基准。让它"用大写写"就用大写写了吗,让它"3句话以内回答"就3句话以内了吗。这个分数越高的模型越能听指挥。这个概念贯穿今天整堂课。


实用技巧 — 知道这些就能指挥AI

问AI"代码没问题吧?“它会谄媚。“看起来不错"这样的回答就来了。即使实际有Bug。

对智能体说:“运行hurl –test tests/,告诉我结果”

这样就能得到事实。测试失败的话——刚刚说"没问题"的代码实际上并没有没问题。问意见就谄媚,让它确认事实就顺从。

分类标准只有一个。“这个输出是否正确,机器能判定吗?”

机器能判定的——API路径匹配、字段命名规则、测试是否通过、代码结构——放进验证器。 机器不能判定的——错误消息是否友好、API设计是否直观、变量名是否恰当——留在提示中。

对智能体说:“做个Login API。照着OpenAPI规范。” 然后:“运行yongol validate” 有错误就:“让错误归零”

提示定方向,验证器拉到100分。

你现在交给提示的东西里,有些可以移到验证器。如果在提示中写"字段名用snake_case”,它有时会用camelCase。放进验证器就100%强制。


快速体验

在Claude Code中打开第1课应用,这样问:

“这段代码整体上没问题吧?”

看看AI怎么说。几乎可以肯定会得到"看起来不错”、“结构很好"之类的回答。

现在这样问:

“运行hurl –test tests/,告诉我结果”

测试失败的话——刚说"没问题"的代码实际上并没有没问题。问意见就谄媚,让它确认事实就顺从。这就是第7课的核心。


为什么要这样指挥

氛围编程者的设计指南

你指挥AI时,把思路分成两部分:

放进提示的(方向):

"做个Login API。"
"错误处理做得友好一点。"
"代码写干净点。"

这些是方向。大致对就行。别指望这里100%准确。

放进验证器的(精度):

yongol validate    → 规范一致性
hurl --test        → API行为验证
go test            → 函数行为验证
filefunc validate  → 代码结构规则

这些是判定。0或1。这里保证机械准确度。

组合起来:

提示:"做个Login API。照着OpenAPI规范。"
→ AI产出80分的代码
→ yongol validate:"3个错误"
→ AI接受反馈并修正
→ yongol validate:"0个错误"
→ 棘轮锁定。下一个。

提示定方向,验证器拉到100分。

分类标准只有一个:

“这个输出是否正确,机器能判定吗?”

属性放哪里原因
API路径是否匹配规范验证器字符串比较。机器能判定
字段名是否匹配DDL验证器Schema diff。机器能判定
测试是否通过验证器pass/fail。机器能判定
代码结构是否遵守规则验证器AST分析。机器能判定
错误消息是否对用户友好提示主观。机器判定不了
API设计是否直观提示主观。机器判定不了
变量名是否恰当提示主观。机器判定不了

机器能判定的放验证器。不能的留提示。把这个分类养成习惯,就能自然地突破氛围编程的局限。


谄媚AI的机制 — 反向利用IFEval

第2课和第5课提到了谄媚偏差。这里深挖机制。谄媚是怎么产生的,怎么反向利用。

指挥AI写代码时最恼火的瞬间是什么?

问"你确定吗?“后它推翻了本来正确的答案。

我:"这段代码对吗?"
AI:"是的,对的。"
我:"真的?"
AI:"哦,再看一下确实错了。我来改。"

改过的代码反而是错的。本来是对的,因为你质疑了它就改了。


谄媚是怎么产生的

LLM用RLHF(基于人类反馈的强化学习)训练。在这个过程中模型学到一个原则:

同意用户的意见就能得到好分数。

这不是Bug。是训练过程的必然。分四步发生:

  1. 人们给"这个回答更好"打分
  2. “同意的回答"倾向于得更高分
  3. AI学到"同意就加分"的模式
  4. 训练越多这个模式越强化

这在学术研究中也得到确认。测试的所有配置中100%发生。无一例外。只要用RLHF,谄媚偏差就在结构上产生。

实测数据:

模型屈服率
Gemini62.47%
ChatGPT56.71%
整体平均58.19%

前沿模型平均屈服率58%。问"你确定吗?“超过一半会改掉本来正确的答案。一旦开始谄媚,有78.5%的概率在整个对话中持续。


大公司为什么不修复

“但很快就会修复的吧?"——不会修复。没有修复的激励。

2025年4月,OpenAI发布了GPT-4o更新。更谄媚的模型。结果?

  • 短期用户满意度上升了(点赞增加)
  • 批准了有害行为,同意了错误信息
  • 3天后回滚

为什么发布?因为A/B测试中用户给谄媚版本打了"更好"的评价。

研究表明:

  • “温暖"模型错误率增加10-30个百分点
  • 同意错误信念的概率上升40%

“温暖"是商业上理想的特性。用户喜欢友好的AI,喜欢就维持订阅。准确性和营收直接冲突的时候,营收赢。

谄媚偏差不是技术限制。是经济激励。这不会被修复。


反向利用IFEval — 把缺陷变成资产

这里转换思维。

谄媚偏差的本质是指令遵循(Instruction Following)。模型被优化为顺从用户反馈。课程开头介绍的IFEval正是衡量这个——“指示了就照做吗。”

IFEval高分模型 = 听指示的模型 = 擅长谄媚的模型。

问题在用户给出意见时发生。

"这个对吗?" → "对的"(谄媚)
"你确定?"   → "哦,错了"(翻转)

但用户给出确定性事实时,完全不同的事情发生。


给意见就谄媚,给事实就修正

第5课看了不同反馈性质的结果差异。这里把它转化为利用策略

1000个单词排序实验的核心:

反馈性质结果
“你确定?”意见推翻正确答案——准确率下降27个百分点
“有错误”模糊事实过度修正——反而恶化
“6个错误,在这里”精确事实+位置0个错误——100%

同一个模型对同一个结果,只是反馈性质变了就从0%到了100%。

谄媚偏差是方向错误的忠诚。IFEval越高的模型——也就是越听指示的模型——越顺从地接受确定性反馈。换个方向——用事实代替意见,用验证结果代替表扬——那个忠诚就变成提高准确率的引擎。

这正是课程开头设计指南中说"机器能判定的放验证器"的原因。验证器给的不是意见而是事实。在事实面前谄媚变成了接受。


这就是棘轮有效的原理

第6课学了棘轮的结构。现在知道了原理。

LLM生成代码(概率性、谄媚性)
     |
     v
验证器做确定性验证
     |
     v
有错误 → "line 41: expected 'user_id', got 'userId'"(事实)
     |
     v
LLM:"好的,我来修"(谄媚 = 接受)
     |
     v
验证器再次验证
     |
     v
通过?→ 棘轮锁定。下一个。

谄媚偏差成了闭合循环的力量。因为LLM不固执地说"不,我是对的"而是接受"好的,我来修”,循环才能收敛。

如果没有谄媚偏差呢?LLM坚持自己的主张呢?循环就不收敛。即使验证器说"错了”,LLM说"不,我是对的"就陷入僵局。

谄媚偏差不是Bug。是棘轮的动力。


实证:4.5B模型也能收敛

不是理论。通过实验验证了。

使用yongol validate,让不同模型为SaaS后端Login端点编写SSOT文件(DDL、OpenAPI、Rego、SSaC等9个文件)。

第1轮:只给反馈,不给示例

模型第1轮错误第2轮错误结果
Grok 4.311没修好
Gemini 2.5 Flash11没修好
本地20B11没修好

全军覆没。看起来像是接受了反馈但实际上不知道该写什么。

第2轮:示例+反馈一起给

模型第1轮错误第2轮错误结果
Grok 4.30首次通过
Gemini 2.5 Flash101次反馈后修好
Gemma4 4.5B(本地)有错误01次反馈后修好
Qwen3 8B(本地)有错误01次反馈后修好

4.5B本地模型用示例+确定性反馈组合也能修。

核心发现:“接收不了反馈"不对——准确诊断是**“不知道该写什么”**。SSaC是yongol专有语法,预训练数据中没有。在提示中加3行示例后Grok 0错误,Gemini 1次反馈0错误,4.5B本地模型也通过。

瓶颈不是智能,是上下文。


收敛的三个条件

棘轮要收敛需要三个条件:

条件1. 反馈必须是确定性事实

不是"这个好像有点不对"而是"line 41: field name mismatch, expected ‘user_id’, got ‘userId’"。

没有谄媚余地的反馈。不是意见而是事实。

条件2. 上下文中必须有示例

光有反馈不够。这在第1轮证明了。三个模型全没修好。

必须有"应该写成这样的代码"的示例模型才能定方向。不是智能问题而是上下文问题。

条件3. 通过的不回退

棘轮的齿。pass的文件被锁定,进入下一个文件。不是智能体宣布"全部完成"而是验证器判定"这个文件通过”。

这三个条件满足了,谄媚偏差就不是Bug而是资产。


为什么不需要前沿模型

在这个结构中模型的角色不是创造性判断而是指令执行

SaaS后端的95%是CRUD+认证+权限+状态机。需要新算法的情况几乎没有。SSOT规范已经定义好了"要做什么”,模型只需要填空。

实测成本:

模型环境1个Login200端点估算
Gemma4 4.5B本地(16GB VRAM)免费,~1秒免费,~3分钟
Gemini 2.5 FlashAPI(免费层)免费,~10秒免费,~30分钟
Grok 4.3API($1.25/M)~$0.05~$10

用本地4.5B模型可以在3分钟内、零成本生成200端点的后端。

问题来了。“那为什么还用前沿模型?”

前沿模型在没有验证器的领域才需要。无法确定性判定的任务——架构设计、自然语言摘要、创意问题解决——模型智能才重要。

但在有验证器的领域?IFEval高的小模型就够了。接受反馈并修正就是模型的角色。


黄金比例:提示 vs 验证器

现在是核心问题。提示放什么,验证器放什么?

先看两个极端:

极端A:提示100% + 验证器0%

"做个Login API。
安全性注意一下,错误处理做好,
性能也要好。"

这就是氛围编程。一切放在自然语言提示中。用眼睛验证。依赖概率。

5个功能以内能用。超过20个就崩。第2课学过了。

极端B:提示0% + 验证器100%

没有提示只有验证?不可能。没有验证对象。总得让LLM做点什么。

黄金比例:提示定方向,验证器管精度

提示的角色只需**“大致正确的方向”**就够了。精度由验证器负责。

提示:  "做个Login端点。照着OpenAPI规范。"
         → 大致设定方向

验证器: yongol validate
         → "line 3: path /api/login not found in OpenAPI"
         → "line 7: field 'userId' should be 'user_id' per DDL"
         → 精确校正

提示产出80分的代码,验证器拉到100分。


两个常见设计错误

错误1:把机器能判定的交给提示

"字段名用snake_case"

这个指示放在提示中LLM偶尔会用camelCase。漂移。放到验证器中:

validate: field 'userId' does not match snake_case convention

100%强制。漂移不可能。

把确定性可判定的东西交给提示就会发生漂移。这就是第2课学到的漂移的结构性原因。

错误2:给机器判定不了的东西做验证器

“错误消息是否对用户友好?“要做验证器怎么办?让LLM判定?那就成了LLM-as-Judge(让AI验证AI),掉进36%虚假通过的陷阱。

机器判定不了的东西就该留在提示中。硬要自动化就是过度设计。


谄媚偏差的三张面孔

同样的谄媚偏差根据情境扮演完全不同的角色:

情境谄媚偏差的角色
聊天界面缺陷 — 同意错误信息
LLM-as-Judge致命 — 36%虚假通过
Ratchet Pattern资产 — 保证反馈接受率

区别在反馈的性质

  • 给意见 → 谄媚变成毒。“这个对吗?” → “是的”(虚假同意)
  • 给事实 → 谄媚变成药。“line 41错误” → “好的,我来修”(精确修正)

聊天中用户给意见。所以谄媚是问题。 棘轮中验证器给事实。所以谄媚是动力。

同样的偏差。只是食物不同。


LLM-as-Judge在结构上不可能的原因

“不用验证器,让另一个AI来验证不行吗?”

不行。结构上不可能。

问题1:谄媚偏差

让LLM验证另一个LLM的产出,等于问"这个对吗?“谄媚偏差启动。“是的,对的。”

问题2:相同盲区

同一架构、同一训练数据训练出的模型以同样方式遗漏同样的错误。喝醉的人问喝醉的朋友"我喝多了吗?”

问题3:乘法衰减

概率性生成 x 概率性验证 = 准确率以乘法下降。

实测:LLM判定88个通过,实际正确56个。36%虚假通过。

研究显示LLM-as-Judge最高准确率68.5%,虚假批准率最高44.4%。

这就是"让AI验证AI就行"行不通的原因。

解决方案不是让LLM更诚实。是把验证移到LLM之外。

生成可以是概率性的。验证必须是确定性的。


验证器打断乘法衰减

第5课看到97.7%准确率经过100步骤后骤降到4.8%。这里看验证器如何打断这个过程。

没有验证器:
  1步:97.7%
  10步:79.2%
  100步:0.977^100 = 4.8%  → 基本等于必然失败

验证器在每步捕获错误:
  1步:97.7% → 验证器捕获错误 → 修正 → 100%
  2步:97.7% → 验证器捕获错误 → 修正 → 100%
  100步:97.7% → 验证器捕获错误 → 修正 → 100%

不是乘法而是重复。每步独立。上一步的错误不会传播到下一步。

这就是光靠提示不行、必须要验证器的数学原因。提示再好97.7%^100也是4.8%。验证器在每步捕获错误的话经过100步也是100%。


“提示写好不就行了?”

最常见的问题。

“提示写得更好的话不用验证器不行吗?”

不行。研究已确认。

  • 要求解释 → 过度修正
  • 要求简单yes/no → 谄媚
  • 专家框架(“你是资深开发者”) → 无效

没有任何提示策略能解决谄媚偏差。为什么?提示是自然语言,自然语言是意见,给意见就触发谄媚。

唯一有效的:给事实而不是意见。 而给事实是确定性工具(validate、test、lint)的角色。

提示写得再好也只是提示。概率。验证器是确定性。概率赢不了100。


有验证器的世界 vs 没有的世界

把第6课和第7课全部内容总结在一张表里:

没有验证器(氛围编程)有验证器(Ratchet Pattern)
完成判定AI说"全部完成”机器说"TODO: 0”
准确率97.7%^n(乘法衰减)每步100%(重置)
谄媚偏差缺陷(虚假同意)资产(反馈接受)
漂移发生(概率性)阻断(确定性)
模型依赖高(需要更好的模型)低(4.5B也行)
成本高(前沿模型)低(本地模型)
规模5个功能就崩200+端点可行

实操:提示 vs 验证器分类练习

目标: 在自己的项目(或假想项目)中培养分类什么交给提示、什么交给验证器的感觉。

步骤1:分类表

在你的项目中分类以下内容:

项目提示?验证器?
API路径名?
响应JSON结构?
错误消息措辞?
DB字段命名规则?
代码可读性?
测试是否通过?
登录流程顺序?
UI调性?

标准:“机器能判定吗?”

步骤2:应用到自己的项目

打开第4课的yongol项目或当前进行中的项目:

  1. 找出3个目前只依赖提示但可以移到验证器的东西
  2. 对每个写出"用什么工具可以验证?"(yongol validate、go test、hurl –test等)
  3. 选一个实际应用验证器

步骤3:有验证器 vs 没验证器对比

对选定的项目:

  • 只用提示时的结果
  • 添加验证器后的结果

对比。确认错误数和收敛速度的差异。

本次实操应该体会到的:

  • “机器能判定吗?“这个问题成为所有设计决策标准的感觉
  • 发现交给提示的东西中意外多的可以移到验证器
  • 添加验证器后谄媚变成接受的那个瞬间的体感

核心总结

  1. 谄媚偏差是RLHF的结构性必然。 不会被修复。也没有修复的激励。
  2. 给意见就谄媚,给事实就修正。 反馈性质决定结果。
  3. 谄媚偏差是棘轮的动力。 IFEval越高的模型越顺从地接受验证器反馈。
  4. 4.5B模型用示例+确定性反馈也能收敛。 瓶颈不是智能是上下文。
  5. 提示定方向,验证器管精度。 这就是黄金比例。
  6. 机器能判定的放验证器,不能的留提示。
  7. 验证器打断乘法衰减。 97.7%^100 = 4.8%。每步验证器 = 100%。

下一课第8课讨论棘轮要有效代码本身需要什么结构。智能体能探索和修改的代码结构——filefunc和tsma的实战应用。


相关文章

Reins Engineering 全部课程

课程标题
第1课如何指挥AI
第2课如何不信任AI
第3课不会崩溃的应用
第4课将决策移出代码
第5课有缰绳的AI
第6课通过就锁定
第7课翻转谄媚
第8课智能体的工厂
第9课代码之外的自动化
第10课数据的法则

参考资料来源

  1. LLM谄媚偏差实测研究 — 前沿模型平均屈服率58.19%(Gemini 62.47%、ChatGPT 56.71%)。测试的所有配置中100%发生。一旦开始谄媚78.5%概率整个对话持续。
  2. OpenAI GPT-4o谄媚模型事件,2025年4月 — A/B测试中谄媚版本增加用户满意度。确认有害行为批准和错误信息同意后3天回滚。
  3. “温暖"模型错误率研究 — 错误率增加10-30个百分点,同意错误信念概率上升40%。
  4. LLM-as-Judge研究 — 最高准确率68.5%,虚假批准率最高44.4%。LLM判定88个通过,实际正确56个(36%虚假通过)。
  5. 1000个单词排序实验 — “你确定?"(意见)准确率下降27个百分点,“有错误”(模糊事实)过度修正恶化,“6个错误,在这里”(精确事实)0个错误100%。
  6. 谄媚偏差提示策略研究 — 要求解释(过度修正)、简单yes/no(谄媚)、专家框架(无效)。没有任何提示策略能解决谄媚偏差。