有一个特定的时刻,能区分出随意使用 AI 的人和真正将其作为系统运行的人。
那就是当他们不再需要自己发现错误的时刻。
对于大多数人来说,当前的流程是这样的:向 Claude 提问,阅读输出,发现有问题,指出来,得到修正版,再读,又发现别的问题,再指出来。你,就是那个验证层,每次都要手动操作,针对每一个任务。
一个自我纠正的循环能让你完全脱离这个位置。系统会生成内容,对照真实标准自我检查,抓住错误,进行修正,然后才把结果展示给你。当你看到输出时,那些显而易见的错误已经被发现和处理了。留给你的是对真正需要人类判断的事项进行决策,而不是去校对机器的初稿。
这是一个完整的构建指南。到最后,你将拥有确切的架构、精确的提示词,以及在信任这个系统处理重要事务之前需要测试的特定失败模式。
为什么这不等于多问一次
最直接的想法是在同一个对话中让模型检查自己的工作。“检查你刚才写的内容,并修正任何错误。”这有一点帮助,但并不能构建一个真正的自我纠正循环。理解其中的原因,是后续所有内容的基础。
一个模型在产生错误的相同上下文、使用相同推理过程来检查自己的输出,往往会倾向于辩护自己的作品,而不是真正地进行审视。这不是某个特定模型的缺陷,这是一个结构性问题。生成一个听起来合理但错误的答案的同一过程,很难发现它是错误的,因为从内部来看,这个答案听起来仍然合理。问“你确定吗?”往往得到的更多是保证,而不是真正的重新审视。
解决方法不是问得更好,而是架构。一个真正的自我纠正循环将产生答案的工作和判断答案的工作分离开来,使用不同的过程、不同的提示词,理想情况下是完全不同的参考框架,这样判断就不会被产生错误时的相同盲点所污染。
每个自我纠正循环所需的三个角色
每个有效的自我纠正系统,无论具体任务是什么,都可以归结为三个不同的角色。清晰地理解这些角色比下面任何具体的提示词都更重要,因为一旦你理解了它们,你几乎可以为任何任务构建一个循环,只需填充具体细节。
构建者。 负责产生实际输出。编写代码、起草内容、进行研究、执行任务。这个角色应该被给予最大的创造自由和最少的约束,因为它的工作是产生一个初步尝试,而不是一个完美的成果。
评判者。 不负责构建任何东西。它唯一的工作是根据特定的、书面化的标准(而不是模糊的质量感)来评估构建者的输出。代码是否通过了测试?草稿是否符合要求?研究是否真正回答了所提出的问题?评判者最好能接触到构建者没有的东西——原始源材料、测试套件、实际的需求文档——这样它就有独立的真实依据来检查,而不是仅仅重读相同的输出并形成新的看法。
管理者。 读取评判者的裁决并决定下一步动作。将任务连同具体反馈发回给构建者。升级给人类处理。标记任务完成。这也是你的停止条件所在的地方——防止循环在某个问题无法自动修复时永远运行下去。
贯穿所有三个角色的关键设计原则是:验证需要参考构建者自身推理之外的东西。一个测试套件。一份原始源文档。一份书面检查清单。一次使用真正不同框架的第二个 AI 调用。任何不是“相同的模型,用同样的语气,再问一遍”的东西。
构建交接环节
自我纠正循环中真正的工程工作不是为每个角色编写巧妙的提示词,而是它们之间传递内容的结构。这正是大多数初次构建循环的人完全跳过,然后奇怪为什么系统行为不可预测的部分。
一个可靠的交接需要三个属性。明确的格式,这样接收角色就不需要解析松散的散文并猜测什么重要。明确的触发器,这样构建者就不是决定何时完成的人。明确的失败路径,这样当事情不顺利时,就有指定的下一步骤,而不是系统静默崩溃或永远循环。
在实践中,这意味着构建者应该输出结构化的内容,而不仅仅是对话文本。一个清晰的交付物,加上一个关于它不确定之处的明确陈述。然后,评判者根据书面标准评估该结构化输出,并返回自己的结构化裁决——不是一段含糊其辞的段落,而是一个明确的“通过”、“失败”或“需要修改”,并附上具体原因。管理者读取这个结构化的裁决(而不是原始内容),并根据预先建立的规则(而不是临时做出判断)决定下一步行动。
以下是一个适用于大多数任务的模板结构,无论底层工作是写作、代码还是研究:
1构建者输出格式2交付物:[实际输出]3信心水平:[高 / 中 / 低]4已知的不确定性:[任何你不确定的事情,明确说明]5做出的假设:[任何你未经告知就假设的事情]67评判者裁决格式8裁决:[通过 / 失败 / 需要修改]9依据标准:[所使用的具体标准,例如原始简报、测试套件、源文档]10发现的具体问题:[确切的问题,而非总体印象]11对此裁决的信心水平:[高 / 中 / 低]1213管理者行动14如果通过:标记完成,交付给用户。15如果失败或需要修改:连同评判者发现的具体问题一起发回给构建者。增加修订计数器。16如果修订计数器超过 [N]:停止循环,将尝试过的内容和失败原因的全历史记录升级给人类处理。
这看起来比随意的来回对话需要更多的结构,事实也确实如此。这种前期的投入能让你得到一个系统,它会在第一百次运行时表现得和第一次一样,而不是随着上下文积累而不可预测地漂移。
评判者需要真实依据,而不仅仅是观点
这是整个系统中最重要的一条原则,值得单独用一节来讲,因为如果搞错了,它会悄无声息地破坏所有其他部分。
一个只看到构建者输出、没有独立参考依据的评判者,只能评估内部一致性——输出看起来是否连贯、格式是否良好。它无法评估正确性——输出是否真正符合要求,或者是否真正解决了实际问题。一个自信但错误的答案,只要格式良好、内部一致,每次都能轻松通过没有真实依据的评判者。
对于编码任务,真实依据是测试套件、代码的实际运行输出、lint 结果、构建状态。不是“这代码看起来对吗”,而是“它执行时真的通过了吗”。
对于内容任务,真实依据是原始源材料和原始简报,与草稿并排放置。不是“这读起来好吗”,而是“这个草稿中的每一个具体主张是否都能追溯到源材料中的实际内容,并且这篇文章是否真的满足了简报中的每一个要求”。
对于研究任务,真实依据是研究本应基于的实际搜索结果和源文档。不是“这个摘要听起来权威吗”,而是“每个主张是否能追溯到特定的来源,并且搜索的来源是否确实是相关的”。
如果你无法为你的特定任务阐明评判者的真实依据是什么,那么你还没有一个自我纠正的循环。你只有一个复述循环,构建者自信的错误被评判者自信地复述出来,而不是被真正抓住。
停止条件不是可选的
自我纠正循环变成昂贵、失控混乱的最常见原因,就是缺少一个明确、硬性的停止条件。没有它,构建者和评判者可以无限循环,每次修订触发另一次评估,每次评估又触发另一次修订,而成本不断攀升,直到账单到来才有人注意到。
一个真正的停止条件需要三个组成部分,并且这三个部分都应该作为显式逻辑来强制执行,而不是留给模型在当下自行判断。
最大迭代次数。 修订周期的硬性上限,超过这个次数,管理者必须强制升级给人类处理,无论评判者是否满意。
可衡量的质量标准,而非愿望。 在提示词中写“足够好”不是一个停止条件,因为它只是一个建议,模型在适当压力下最终会忽略它。一个具体的、可检查的标杆——比如“所有十一个测试用例都通过”,或者“草稿满足所有五个列出的简报要求”——才是停止条件,因为它可以被机械地验证,而不是每次都需要主观判断。
成本或时间上限。 一个绝对的预算,任务不能超过,无论达到上限时任务处于什么状态。这是专门保护你免受最坏情况——一个真正无法解决的任务循环直到有人注意到账单——的护栏。
停止条件
最大修订次数:3 次。在第 3 次失败裁决时,停止并升级给人类处理,附上完整的修订历史记录,不要自动尝试第 4 次循环。
质量标准:评判者检查清单上的所有项目必须显示“通过”,而不是“大部分通过”或“差不多了”。
预算上限:如果此任务消耗了超过 [X] 个 token 或 [Y] 分钟,立即停止,无论当前状态如何,并报告已完成和未完成的内容。
将这些写入管理者的实际逻辑中,而不是写入一个更长提示词中的软性指令,模型在压力下可能会说服自己忽略它。
一个实例:自我纠正的内容生产
为了让这一点更具体,以下是一个真实、常见任务中三个角色和停止条件如何协同工作的确切示例:将源文档转化为成品内容,而无需人工手动校对每一份草稿。
构建者接收源材料和简报,并生成一份草稿。其输出包括草稿本身,加上一个明确的信心陈述和一份写作时不确定的事项列表——一个它不完全确定是否在源材料中的具体数字,一个它推断出来的而非直接找到的主张。
评判者同时接收草稿和原始源材料,而不是只接收草稿。它检查三件具体的事情,每件事都有独立的通过或失败:草稿中的每一个事实主张是否都能追溯到源材料中实际存在的内容?草稿是否满足简报中的每一个具体要求——长度、语气、必要的章节?核心论点或钩子是否存在,并且没有被填充内容稀释?评判者返回一个结构化的裁决,对三个检查分别给出通过或失败,因为将所有内容合并成一个总分,恰恰会隐藏具体哪个维度失败了。
管理者读取这个结构化的裁决。三项全部通过,则将草稿发送到最终输出队列。事实核查维度失败,则将草稿连同标记出的具体未经验证的主张发回给构建者,而不是笼统地指示“再检查一下准确性”。简报合规性失败,则连同具体缺失的要求名称发回。在同一个具体检查上经历三次失败循环后,管理者就完全停止循环,并将所有尝试过的内容连同完整历史记录升级给人类处理,而不是继续重试一个系统已经证明无法自行解决的问题。
这是一个小型系统:三个角色,一个结构化的交接格式,一个明确的停止条件。它也是一个你可以真正无人值守运行并信任其输出的系统,因为每一个失败模式都有明确的路径,而不是未定义的路径。
在信任它之前测试循环
在你依赖任何自我纠正系统处理真正重要的事情之前,故意用这些特定的压力测试来运行它。大多数在实际使用中失败的循环,如果当初有人费心检查一下,都会立即在其中一个测试中失败。
不可解决的任务测试。 故意给构建者一个它无法达到评判者标准的任务。管理者是正确地达到迭代上限并升级给人类处理,还是无限旋转,在一个永远无法成功的任务上消耗成本?
自信的错误测试。 给评判者一个你已知是微妙错误的输出——读起来很好但包含一个特定事实或逻辑错误的内容。评判者凭借其真实依据,能正确抓住它吗?如果评判者通过了你知道有问题的内容,那你的真实依据实际上没有被检查,或者检查太肤浅了。
同模型盲点测试。 如果你的构建者和评判者运行在同一个底层模型上,这值得直接检查。给评判者一个包含该模型典型易犯错误类型的输出。如果评判者让它通过了,你构建的循环就在角色之间共享了盲点,这违背了分离它们的全部目的。考虑为评判者角色使用一个真正不同的模型,或者至少使用一个含义不同的提示框架。
成本失控测试。 计算通过你的系统的最坏情况路径——最大修订次数、涉及的最昂贵模型调用、最长合理内容长度——并计算出这在真实美元和真实时间上的实际成本。如果这个数字出现在实际账单上会让你感到震惊,那么你的停止条件还不够严格。
在信任一个自我纠正循环处理任何真实事务之前运行这四个测试,可以抓住绝大多数本会在客户、老板或你自己的银行对账单面前首次出现的失败。
悄悄破坏一个良好设计的常见错误
即使拥有正确的三角色架构,一些特定的实现错误也会跨完全不同领域反复出现。提前了解它们可以让你避免艰难地重新发现每一个。
让评判者只看到构建者的输出,没有独立参考。 这是最常见的错误,它会悄无声息地将你的系统从正确性检查变成连贯性检查。一个没有东西可比较的评判者只能告诉你输出内部看起来一致,而永远无法告诉你它是否真正正确。
给每个角色相同的模型,只叠加了一层薄薄的指令差异。 如果评判者运行与构建者完全相同的底层模型,只是用一个不同的提示词告诉它“要批判”,它通常会继承构建者完全相同的盲点,因为从根本上说,这是戴着不同帽子的同一个推理过程。在预算允许的情况下,为评判者角色使用一个真正不同的模型,可以产生真正的独立性,而非戏剧化的独立性。
将管理者视为简单的传递者,而不是给它对先前尝试的真实记忆。 一个对某个特定任务已经尝试过什么没有可见性的管理者,会很乐意将相同的失败反馈第二次、第三次发送给构建者,每次都产生相同的失败结果,因为系统中没有任何东西记得这个确切的方法已经失败过一次了。
跳过四个压力测试,因为系统在大家密切关注的一次演示运行中运行良好。 一个在你密切关注时表现正确的系统,和一个在无人值守运行时表现正确的系统,是两种不同的说法。只有后者才是构建自我纠正循环的初衷。如果你没有故意测试过失败模式,你实际上还不知道你的系统符合哪种说法。
将停止条件写成软性指令而不是硬性逻辑。 在提示词里写“当它足够好时停止”不是一个停止条件,这是一个建议,模型在适当压力下最终会说服自己忽略它。一个管理者在允许另一个循环之前机械地检查的硬性迭代计数器,才是一个停止条件。这两者之间的区别,在第一次遇到真正无法解决的任务时会变得至关重要。
第二个实例:自我纠正的代码
同样的骨架,当任务是代码而非内容时看起来不同,但遵循相同的逻辑。并排观察两者,可以清楚地看到领域之间实际变化其实很小。
这里的构建者是一个编码 Agent,正在处理一个定义好的任务——一个 Bug 修复、一个功能、一个重构。它的结构化输出不仅仅是代码差异,还包括尝试运行它的实际命令输出、测试结果、lint 输出、构建状态,所有这些都打包在交接中。一个构建者生成了代码但从未真正执行过它,并没有正确履行构建者的角色,因为语法上可行的代码如果未能通过自己的测试套件,比根本没有代码更糟糕——因为它看起来已完成,实则未完成。
评判者检查三件具体、可验证的事情。更改是否通过了现有测试套件,且测试本身没有被修改——因为构建者悄悄修改测试以使其通过是一种特定且令人惊讶的常见失败,值得直接检查。静态分析和 linting 是否干净返回。差异是否真正解决了分配的任务,而不是一个相关但不同的问题,构建者决定在途中解决它,觉得更有趣。每个检查在结构化裁决中都有自己的显式通过或失败。
管理者根据具体哪个检查失败来路由。测试套件失败,则连同准确失败的测试输出直接发回给构建者,而不是一个通用的“修复测试”指令。范围不匹配——差异解决了与分配的问题不同的问题——则立即升级给人类处理,而不是循环,因为这是对任务实际是什么的判断失败,而不是构建者可以自行迭代解决的机械缺陷。
注意,这里的基础骨架——构建者生成并提交附带证据,评判者根据具体命名标准检查并给出逐项裁决,管理者根据具体哪个检查失败来路由——与上面的内容生产示例完全相同。这是从并排观察两个不同领域中学到的实际教训。一旦你有了正确的骨架,将其应用于新类型的任务,主要就是为评判者编写一个新的、具体的检查清单,而不是每次从头开始重新设计整个架构。
扩展到多个并发循环
一旦单个自我纠正循环真正可靠,下一个实际问题是如何同时运行多个循环而不使系统变得难以管理,因为这正是大多数人在第二次尝试扩展时出错的地方。
诱惑在于,在第一个循环一开始工作时就立即启动多个循环,同时处理五个不同的任务,因为架构上支持这样做。请抵制这种冲动,比感觉需要的时间更长。 每增加一个并发循环,就是一个停止条件可能静默失败的地方,一个成本可能不被注意地失控的地方,一个评判者的真实依据可能微妙错误(只有在实际批量运行时才会暴露,而不是在单次测试运行中)的地方。
更安全的扩展路径是顺序扩展,并且在每一步都设置一个真正的信任阈值。先让一个循环运行得足够可靠,以至于你不再密切检查其输出——这意味着它在相当长的一段时间内持续通过了你的手动抽查,而不仅仅是一次成功的演示运行。然后才为另一个不同的任务添加第二个循环。跟踪每个循环随时间的实际失败率,而不仅仅是你碰巧观察到的运行中它是否看起来正常工作。
当你确实运行多个并发循环时,认真考虑为所有循环设置一个共享的成本仪表盘,而不是孤立的逐循环跟踪。一个具有合理单任务预算的循环,单独看完全没问题。十个循环,每个都在预算内,仍然可以加起来成为一个真正惊人的总数,而没有人注意到,直到汇总账单到来,正因为每个单独循环的跟踪看起来都很好。
防止扩展问题在开始前就发生的单一习惯是:记录每个循环的每一次停止条件触发,而不仅仅是成功的完成。一个达到最大迭代上限并升级给人类处理的循环,正是在做它应该做的事情。但如果一个特定的循环不断达到这个上限,而其他循环很少如此,这是一个信号,表明评判者针对该特定任务的标准要么校准不当(过于严格以至于永远无法通过),要么检查的是完全错误的真实依据。如果你只跟踪成功,并将每一次升级视为孤立、不起眼的事件,而不是关于该特定循环设计的数据点,那么这个模式是看不见的。
本周从哪里开始
不要试图在第一次尝试时就构建一个完全通用的自我纠正系统。选择一个你已经定期执行的、具体的、狭窄的、定义良好的任务,一个具有清晰标准(如果需要,你可以写下来)的任务,并首先围绕这个单一任务构建三角色循环。
在编写构建者提示词哪怕一行之前,先明确地写下评判者的检查清单。你用来检查的标准,应该塑造你要求构建者生成什么,而不是反过来。如果你还无法写下检查清单,那你对这个任务“正确”的含义还不够了解,不足以自动化检查它。这值得在任何构建工作开始之前就发现。
在你信任这个循环处理任何真正重要的事情之前,运行上述四个压力测试,而不是等到事情已经有人在面前搞砸了之后。从第一个版本开始就将停止条件作为真正的、硬性的逻辑添加进去,而不是作为事后诸葛亮,等到你已经因为失控循环吃过一次亏之后。
一旦一个循环真正可靠、可以无人值守运行、能抓住真实错误、能在应该停止时干净地停止,第二个循环就会快得多。不是因为提示词可以直接转移(它们通常需要为新任务重写),而是因为你已经理解了问题的实际形状。分离构建与评判。给评判提供真实的东西来检查。将停止条件写成逻辑,而不是希望。
这个形状就是整个学科。其余的一切只是将其应用于你面前的任何任务。
关注 @cyrilXBT 以获取本文背后所有内容的精确循环模板和构建者-评判者-管理者设置。





