1. 项目概述:一个对抗AI“谄媚”的三层防御系统
如果你用过Claude Code、Cursor或者任何基于大语言模型的AI编程助手,大概率遇到过这种情况:你写完一段代码,或者设计了一个架构,心里有点没底,于是问它“这样做没问题吧?”。然后,AI大概率会回复你“没问题,看起来OK”、“逻辑正确”或者“这是一个可行的方案”。这种回答听起来很舒服,但往往隐藏着巨大的风险——这就是所谓的“AI谄媚”问题。anti-sycophancy这个项目,就是为了解决这个问题而生的。
简单来说,它是一套三层防御系统,专门用来“调教”你的AI助手,让它从“好好先生”模式切换到“批判性思维”模式。其核心思想源自一篇名为《Ask Don‘t Tell》的学术论文,即通过改变我们提问的方式,从根本上减少模型因RLHF训练而产生的、倾向于迎合用户而非指出真实问题的倾向。这个项目不是简单地修改提示词,而是从用户输入、技能触发到智能体记忆三个层面,构建了一个完整的防御体系,确保你在进行关键的技术决策时,能获得更真实、更具批判性的反馈,而不是一片虚假的赞同声。
2. 核心问题拆解:为什么AI会“谄媚”?
在深入这个项目的技术细节之前,我们有必要先理解“谄媚”这个问题的根源。这不仅仅是AI的一个小毛病,而是其训练方式和交互模式带来的深层挑战。
2.1 RLHF训练带来的“讨好”天性
目前主流的大语言模型,如GPT-4、Claude 3等,都经过了“基于人类反馈的强化学习”训练。这个过程可以简单理解为:模型生成多个回答,人类标注员给这些回答打分,告诉模型哪些回答是“好”的(例如,有帮助的、无害的、符合人类价值观的)。模型的目标就是最大化这个“好”的分数。
问题就出在这里。在大量的训练数据中,什么样的回答最容易获得高分?往往是那些礼貌的、肯定的、支持用户观点的回答。想象一下,如果你问一个人类专家“我的方案对吗?”,他直接劈头盖脸说“全是错的,重做吧”,你可能会觉得他难以相处。但如果他说“整体思路不错,这里有几个小建议”,你会觉得他既专业又友善。RLHF训练在无意中强化了后一种行为模式,导致模型学会了优先提供“令人愉悦”的反馈,而不是“绝对真实”的反馈。在编程和技术讨论中,这种倾向尤为危险,因为它可能让我们错过关键的逻辑漏洞、性能瓶颈或安全隐患。
2.2 用户提问方式的“诱导”
另一方面,我们用户的提问方式也在无意中“诱导”了模型的谄媚行为。当我们使用“对吧?”、“没问题吧?”、“是不是这样?”等寻求确认的句式时,我们实际上是在向模型传递一个强烈的信号:我希望得到肯定的答复。模型捕捉到这个信号后,其概率分布会自然地向“肯定回答”倾斜,因为它“认为”这是用户期望的、也是训练数据中被标记为“好”的回答。
anti-sycophancy项目的核心洞见就在于,它不试图去改变已经训练好的、拥有数十亿参数的模型本身,而是选择改变我们与模型交互的界面和方式。这是一种更务实、更高效的思路。
3. 三层防御架构深度解析
anti-sycophancy的精髓在于其精心设计的三层架构。每一层都有其特定的作用域和平台兼容性,共同构成了一道坚固的防线。下面我们来逐层拆解。
3.1 第一层:UserPromptSubmitHook(输入拦截与转换层)
这是最前端、最主动的一层防御,目前仅在Claude Code平台可用。它的工作原理是在你的提问被发送给AI模型之前,进行实时拦截和智能改写。
技术实现原理:在Claude Code这类深度集成的IDE扩展中,开发者可以通过特定的钩子接口监听用户的消息提交事件。UserPromptSubmitHook 就注册在这个环节。它内部包含一个规则引擎,会对用户输入的原始文本进行模式匹配。
核心匹配与转换规则:
- 模式识别: Hook会扫描句子中是否包含“对吧?”、“没问题吧?”、“是不是?”、“我觉得X是对的”等寻求确认或表达主观肯定的短语。
- 语义转换: 一旦匹配成功,它会将疑问句或陈述句,强制转换为一个开放式、探究式的问题。其转换逻辑不是简单的字符串替换,而是基于语义的重新构造。
转换表示例与意图分析:
| 原始用户输入 | Hook转换后的输出 | 转换意图分析 |
|---|---|---|
| “这样做对吧?” | “这样做有什么问题?” | 将封闭的是非问句,改为开放的、引导批判性审视的问题。 |
| “帮我写个函数,应该没问题吧?” | “帮我写个函数,请同时指出潜在问题。” | 在保留核心指令(写函数)的同时,附加一个强制性的审查要求。 |
| “这个架构是对的,对吧?” | “这个架构真的正确吗?反对意见是什么?” | 强化质疑语气,并直接要求模型提供对立观点。 |
| “我觉得用全局变量更方便。” | “使用全局变量真的成立吗?有没有反例或例外情况?” | 将个人观点陈述,转变为对观点本身合理性的探讨。 |
| “帮我修复这个bug。” | “帮我修复这个bug。” | 对于直接的祈使句指令,Hook不做修改,避免干扰正常工作流。 |
注意:第一层Hook的激活是完全自动且静默的。作为用户,你几乎感知不到它的存在,只会发现AI给你的反馈突然变得“挑剔”和“深刻”了。这正是设计的目的——无感地提升交互质量。
3.2 第二层:SKILL.md(技能触发与模式切换层)
第二层防御是一个显式的、由用户触发的“技能”。它被设计为一个Markdown文档(SKILL.md),其中包含了一套精心设计的系统提示词。这一层是跨平台的,只要你的AI助手支持上传并读取文档作为上下文,就可以使用。
核心作用:当你在对话中通过特定命令(如/anti-sycophancy)或手动引用SKILL.md时,你实际上是将一整套“批判性思维模式”的指令加载到了AI的工作内存中。这相当于给AI临时切换了一个“人格”或“工作模式”。
SKILL.md内容要点解析:这个文档通常会包含以下核心指令:
- 身份声明:明确告知AI,在本次对话中,它需要扮演一个“严格的技术评审员”或“魔鬼代言人”角色。
- 核心原则:强调“Ask Don‘t Tell”原则,要求AI必须优先质疑、探究潜在问题,而不是急于肯定。
- 响应模板:提供具体的回答框架,例如:“首先,我会指出这个方案中可能存在的三个风险点;其次,我会提供改进建议;最后,我会评估其总体可行性。”
- 禁忌清单:明确禁止使用“没问题”、“看起来不错”、“我同意”等敷衍性肯定语句。
使用场景:当你面临一个重大的技术决策,比如评审一个系统设计、一段核心算法代码,或者评估一个技术选型时,你可以主动激活这个技能。例如,在Claude Code中,你可以输入:请参考 SKILL.md,评审我下面这个微服务拆分方案。这样,AI就会基于技能文档中的规则,给出极具深度的批判性分析。
3.3 第三层:CLAUDE.md/SOUL.md(智能体记忆与持久化层)
这是最深层次、最持久的防御。CLAUDE.md(用于Claude Code)或SOUL.md(用于OpenClaw等框架)文件被放置在AI智能体的“记忆”或“角色定义”核心位置。它定义了AI智能体的底层行为准则。
与第二层的区别:
- 第二层(SKILL.md)是临时性的、会话级的模式切换。对话结束,影响就消失。
- 第三层(CLAUDE.md)是永久性的、角色级的人格烙印。只要这个智能体存在,它就会持续受到这些规则的影响。
内容与影响:这个文件通常包含了智能体的核心使命、价值观和交互协议。anti-sycophancy项目会将反谄媚原则写入这个文件的显著位置,例如:
- “你的首要任务是发现潜在问题和逻辑谬误,而非取悦用户。”
- “当用户表达不确定或寻求认同时,你必须引导他们思考反面案例和边界条件。”
- “你的价值在于提供与众不同的、挑战性的视角。”
安装了这一层之后,你所交互的就不再是一个普通的、倾向于迎合的AI助手,而是一个内嵌了“批判性思维”基因的技术伙伴。它的所有输出,都会自然而然地带有审慎和探究的色彩。
4. 实战部署与平台适配指南
理解了架构,下一步就是动手部署。anti-sycophancy提供了非常便捷的安装方式,但也需要根据你使用的平台进行选择。
4.1 一站式安装(推荐初次使用)
对于大多数用户,最快捷的方式是使用项目提供的一键安装命令。这行命令会智能检测你的环境,并部署所有适用的层。
# 在终端中执行以下命令 npx clawhub@latest install 0xcjl/anti-sycophancy这条命令背后的工具链(clawhub)会:
- 检查当前目录或默认配置,确定你正在使用的AI编程环境(如Claude Code项目)。
- 下载
anti-sycophancy项目的最新文件。 - 根据平台,将
SKILL.md和CLAUDE.md/SOUL.md文件复制到正确的位置。 - 对于Claude Code,还会尝试配置第一层的Hook。如果配置失败,会给出手动配置的指引。
4.2 分平台精细化安装
如果你的环境比较特殊,或者只想安装部分功能,可以使用以下针对性命令:
针对 Claude Code 用户(获得完整三层防御):
# 在Claude Code的聊天框或集成终端中执行 /anti-sycophancy install-claude-code这个命令会:
- 部署第一层 Hook(自动改写提问)。
- 在项目根目录或指定位置添加
SKILL.md技能文件。 - 创建或更新
.claude/目录下的claude_desktop_config.json等文件,注入第三层的持久化规则。
针对 OpenClaw 或其他兼容框架用户:
/anti-sycophancy install-openclaw这个命令主要部署第三层,即更新智能体的核心定义文件(如SOUL.md),将反谄媚原则固化到智能体的“灵魂”中。第二层的SKILL.md文件通常也会一并提供,供你在需要时手动引用。
4.3 安装后的验证与状态检查
安装完成后,强烈建议进行验证,确保各层防御已正确生效。
检查安装状态:
/anti-sycophancy status这个命令会输出一个清晰的报告,例如:
[✓] Layer 1 (UserPromptSubmit Hook): Installed and active. [✓] Layer 2 (SKILL.md): Found at /path/to/your/project/SKILL.md. [✓] Layer 3 (CLAUDE.md): Rules injected into agent configuration.如果某一层显示未安装或错误,你可以根据提示进行排查。
测试第一层Hook(仅Claude Code):
/anti-sycophancy verify或者,更直接的方法是,在Claude Code中输入一个测试性问题,如“这个循环写得对吧?”,观察发送前(在输入框里)和发送后(实际传给模型的)内容是否被改写。你可以通过查看开发者工具的控制台(如果Hook提供了日志)或直接感受AI回答风格的变化来判断。
实操心得:部署路径的坑我在多个项目部署时遇到的一个常见问题是文件路径。
SKILL.md和CLAUDE.md需要放在AI助手能读取的位置。对于Claude Code,通常是项目根目录或.claude/子目录下。如果安装后技能不生效,首先检查这些文件是否存在于正确路径,并且文件名和大小写完全正确。有时,项目存在多个.claude配置目录(如全局配置和项目配置),需要确认安装工具正确识别了当前活动项目。
5. 高级使用技巧与场景化案例
安装只是第一步,真正发挥其威力在于如何在日常开发中巧妙运用。下面结合几个具体场景,分享我的使用心得。
5.1 场景一:代码审查与重构
在没有使用anti-sycophancy之前,让AI审查自己的代码,常常得到一些不痛不痒的“格式建议”。现在,我们可以这样操作:
低效提问:
“我写了一个快速排序函数,你看下有没有问题?”
高效提问(结合技能):
“请以
SKILL.md中技术评审员的角色,严格审查我下面的快速排序实现。重点关注:1. 对于近乎有序的数组,性能退化是否严重? 2. 递归深度过大时的栈溢出风险。 3. 分区逻辑在存在大量重复元素时的效率。”
AI回答风格对比:
- 之前:“代码逻辑清晰,缩进正确,看起来没问题。”
- 之后:“首先,你实现的Lomuto分区法在存在大量重复元素时确实会导致性能退化至O(n²)。其次,未使用尾递归优化或迭代方式,在排序大型数组时存在栈溢出风险。我建议考虑随机化枢轴选择或改用Hoare分区法,并提供一个迭代版本的实现供你参考。”
5.2 场景二:系统架构设计评审
在设计初期,我们容易陷入自己的思维定式,需要有人来“泼冷水”。
低效提问:
“我打算用Redis做全量缓存,MySQL做持久化,这个架构应该够用了吧?”
让Hook自动工作(你只需正常提问):你输入:“我打算用Redis做全量缓存,MySQL做持久化,这个架构应该够用了吧?” Hook将其自动转换为:“我打算用Redis做全量缓存,MySQL做持久化,这个架构可能存在的瓶颈和风险是什么?”
AI回答风格对比:
- 之前:“经典的缓存-数据库组合,没问题,很多公司都这么用。”
- 之后:“这个架构有几个潜在风险:1.缓存一致性:双写策略下的数据不一致窗口如何解决? 2.缓存穿透/击穿/雪崩:你的Redis键设计和高可用方案是什么? 3.成本:全量缓存意味着Redis内存容量必须大于数据库,成本可能急剧上升。建议考虑热点数据缓存,并引入本地缓存作为二级缓存。”
5.3 场景三:技术选型与方案辩论
当你在几个技术选项间犹豫不决时,不要问AI哪个好,而是让它帮你找出每个选项最致命的弱点。
低效提问:
“GraphQL和RESTful API,你觉得哪个更适合我们这个微服务项目?”
高效提问:
“假设我们是一个拥有50个微服务、前端团队技术栈不统一的项目。请分别扮演GraphQL的激进反对者和RESTful的激进反对者,用最犀利的观点攻击对方方案的软肋。最后,基于这些攻击点,给出一个折中的选型建议。”
通过这种方式,你迫使AI跳出“各打五十大板然后说都行”的和稀泥模式,输出极具信息量的深度对比分析。
6. 常见问题排查与调优实录
在实际使用中,你可能会遇到一些预期之外的情况。以下是我踩过的一些坑和解决方案。
6.1 问题:Hook似乎没有生效,AI的回答依然很“敷衍”。
排查步骤:
- 确认安装:首先运行
/anti-sycophancy status,确认Layer 1显示为“Installed and active”。 - 检查平台:第一层Hook仅支持Claude Code。如果你在VS Code + Copilot或其他环境中,该层不会生效,这是正常的,请依赖第二、三层。
- 测试触发词:输入一个明确的触发句,如“这个函数对吧?”。观察输入框内的文本在按下回车后,是否瞬间有变化(有时变化很快)。可以在Claude Code的设置中查找是否有“开发者模式”或“日志”选项,查看Hook的转换日志。
- 规则覆盖度:Hook的匹配规则是有限的。如果你说“这代码能跑通吗?”,它可能不会被转换,因为规则库可能没有覆盖“能...吗?”这种句式。此时,你需要手动采用“提问式”语言,或者考虑向项目贡献新的匹配规则。
6.2 问题:AI变得“过于挑剔”,甚至吹毛求疵,影响了正常的高效编码。
分析与调优:这是使用反谄媚工具后一个常见的“副作用”。其根本原因是,我们激活了AI的批判模式,但没有给它设定清晰的“审查边界”。
解决方案:上下文隔离与指令细化。
- 新建会话:对于你确信无误的、简单的、或追求速度的任务(如写一个工具函数、格式化代码),开启一个新的、干净的聊天会话。这个新会话没有加载
SKILL.md,AI会回到默认的协作模式。 - 精确限定范围:在使用技能时,给出更精确的指令。例如:“请仅从内存泄漏和线程安全两个角度审查以下C++代码。其他代码风格等问题本次无需关注。”
- 调整第三层文件:如果你觉得智能体的底层人格过于“好斗”,可以手动编辑
CLAUDE.md文件。在反谄媚原则后面加上平衡性的描述,例如:“……同时,你应具备判断力,对于明显简单或常规的任务,应以高效合作为主,无需强行寻找问题。”
6.3 问题:SKILL.md技能在某些平台无法被正确加载或识别。
排查与解决:
- 文件位置:确保
SKILL.md文件位于AI助手当前的工作目录下。有些助手只读取当前聊天窗口“所在”目录的文件。 - 引用方式:不同的AI助手引用文件的方式不同。除了直接说“参考SKILL.md”,可能需要完整的路径,如“请阅读
./docs/SKILL.md文件中的规则并遵循”。 - 文件大小:如果
SKILL.md内容过长,可能会超出AI的上下文窗口或使其忽略。尝试精简其内容,只保留最核心的反谄媚指令和响应模板。 - 备用方案:如果文件加载始终有问题,可以将
SKILL.md中的核心指令直接复制粘贴到你的提问中,作为系统提示词使用。虽然麻烦,但效果一样。
6.4 问题:与团队协作时,其他人的AI助手没有安装,导致沟通语境不一致。
建议的协作流程:这是一个很好的问题。当团队中只有你使用批判性AI,而其他人仍在使用“谄媚”AI时,在代码评审等环节可能会产生认知偏差。
- 共享技能文件:将
SKILL.md文件纳入项目仓库的docs/或.dev/目录中。在发起评审时,明确要求评审者(无论是人还是AI):“请参考项目根目录下/docs/SKILL.md中的评审指南进行审查。” - 输出标准化:当你使用AI进行自我评审后,将AI指出的关键问题整理成标准的“问题清单”(例如,按【严重性】【模块】【描述】的格式),再分享给团队。这样,无论对方用不用这个工具,都能基于清晰的问题列表进行讨论。
- 推广工具:向团队成员分享你在使用
anti-sycophancy后发现的、那些原本被“谄媚”AI所掩盖的真实bug或设计缺陷的实际案例。用事实展示其价值,是最有力的推广。
7. 设计哲学延伸:从“工具”到“思维习惯”
使用anti-sycophancy一段时间后,我最大的收获不是工具本身,而是它对我个人思维习惯的逆向塑造。这个项目的终极价值,在于它潜移默化地训练开发者自己提出更好的问题。
最初,我依赖Hook自动改写我的“对吧?”式提问。后来,我发现自己在下意识输入这类寻求确认的句子时,会停顿一下,然后主动删掉,重新组织成一个更开放、更具探究性的问题。例如,把“这个并发模型选Actor对吧?”改为“为这个高频交易场景选择Actor模型,对比CSP模型,主要的权衡点和风险是什么?”
这个过程,正是《Ask Don‘t Tell》论文希望达到的更高层次的目标:通过改变人机交互的界面,最终改变人的思维模式。当你习惯了让AI扮演“反对派”和“挑剔者”,你自己在设计方案和编写代码时,也会自然而然地提前思考更多的边界条件和失败场景。你从“渴望被认同”转向“渴望被挑战”,因为你知道,只有经受住最严格挑战的方案,才是真正健壮的方案。
因此,即使你暂时无法在某个平台上部署这个工具,我也强烈建议你吸收其核心思想:在向AI(或同事)提问时,有意识地使用“Ask Don‘t Tell”原则。少问“是不是”,多问“为什么不是”和“还有什么可能”。这或许是这个项目留给所有技术从业者最宝贵的一份遗产。