引子:总差那么点意思
最近遇到个问题,感觉不对劲。
明明按照 skill 要求写了,结果总差那么点意思。有时候差标题,有时候差结构,有时候整篇文章的调性都偏了。我反复检查 prompt,反复强调要求,反复举例,但 Agent 就是不能每次都稳定地做对。
这种感觉就像教一个人做菜,你说"火候要适中,味道要平衡,颜色要好看",他说"好的明白了",然后端上来的菜,要么太咸,要么太淡,要么火大了烤糊了。你继续教,继续说,继续举例,但效果就是不稳定。
我不甘心只是"再叮嘱一遍"。我想知道根本原因是什么。
追问:从结果往源头追溯
我直接问:"为什么我的 skill 明明按照要求写了,效果却不如预期?"
Agent 开始展示当前的结果,但我没急着改稿。
"我们回头看看源头,"我追问,"这13篇基准要求是怎么被处理的?它们是从哪里来的,在哪个环节被用到的?"
Agent 愣了一下,然后开始往上追溯。它从当前的结果往前推,推到 skill 的定义,再推到基准要求的来源。
这个追溯过程很快就揭示了问题:13篇基准要求——那13篇定义了"什么是好文章"的标准文件——从一开始就被当成了 skill 的参数。也就是说,这些要求在执行时被传给了 Agent,像 GPS 坐标一样作为输入信息提供。
这就好比什么?就好比你给一个人工智能导航输入了目的地,但忘了设置路线规则。系统知道要开到哪里,但不知道怎么开、什么时候拐弯、遇到岔路怎么办。导航只会机械执行指令,但不会真正理解"我要去那里"背后的意图。
发现:参数和约束是两回事
问题出在"参数"和"约束"之间的区别。
参数是建议。你可以给 Agent 传递"推荐阅读量1000字以上",但 Agent 可以选择不听——它可能写800字,也可能是1200字。这是"参考"而非"必须"。
约束是规则。约束是"不满足就拒绝",是"不符合就报错",是"这里有一条线,踩过去就要付出代价"。
13篇基准要求,最初被写成 skill 参数的那一刻,就已经把自己放进了"建议"的范畴。Agent 执行时,这些要求是"参考意见",是"尽量遵循",是"大多数情况下应该这样"。但不是"必须遵守的规则"。
这才是效果不稳定的根本原因。
你告诉一个人"我建议你这样做",然后期望他每次都做到——这不是设计系统,这是许愿。系统不会读懂你的期望,系统只会执行你明确定义的逻辑。
重新设计:把要求变成代码
找到问题之后,下一步是改变。
Agent 重新梳理了整个流程。不是改 prompt,不是加更多示例,不是反复叮嘱"一定要按要求写"——这些我都试过了,没有用。
而是把13篇基准要求从"skill 参数"的位置,移动到了"代码核心判断逻辑"的位置。
具体怎么做?
原来是这样:
skill prompt = "请参考以下标准写文章:1. 标题要包含数字 2. 每个章节要有小结..."
改变后是这样:
# 文章质量前置校验
def validate_article(article):
# 必须满足:标题包含数字
assert contains_number(article.title), "标题缺少数字"
# 必须满足:每个章节包含小结
for section in article.sections:
assert has_summary(section), f"章节 {section.title} 缺少小结"
# 必须满足:字数在合理区间
assert 2500 <= word_count(article.body) <= 3500, "字数超出范围"
return True
注意到了吗?参数变成了断言。描述变成了判断。建议变成了约束。
系统不再"参考"基准要求,而是在文章生成之前,先校验每一条要求是否满足。不满足就报错,不生成,直接告诉你哪里出了问题。Agent 再也不能"差那么点意思"了,因为"差那么点意思"在这个流程里根本过不了校验关。
为什么 prompt 不够稳定
你可能会问:为什么要这么大费周章?直接在 prompt 里写清楚不行吗?反复强调不行吗?
试过了,不行。这不是 prompt 写得好不好的问题,这是语言模型行为本质的问题。
语言模型有随机性。这种随机性不是 bug,是它工作方式的一部分。即使你把要求写得再清楚,每次执行时模型的注意力分布、采样的 token、上下文窗口的激活模式都会有微小差异。这些差异累积起来,就会导致这一次写得好、那一次差一点、再下一次莫名其妙地跑偏了。
你可以在 prompt 里写"必须包含数字",然后第100次执行时模型突然觉得"我觉得这个标题不加数字更有诗意"。你没法预测,没法阻止,只能事后补救。
把要求编码为代码约束,是绕开这个随机性的方法。代码没有随机性。assert contains_number(title) 不会说"我今天心情好所以检查,心情不好就不检查"。它每次都检查,精确到 bit 级别。
这不是说 prompt 没用。好的 prompt 依然重要,它定义了写作风格、叙事节奏、读者的感受。但 prompt 定义的是"如何做",而约束定义的是"做到了没有"。前者是艺术,后者是工程。
三个把要求编码进代码的思路
回到 jp091 项目的实际经验。13篇基准要求最终是怎么被编码的?有三个思路特别实用:
第一个:前置条件校验。 写作开始前,先检查输入是否满足基准的前置条件。比如,如果基准要求"上传的图片必须是正方形",那在开始写作流程之前,先检查图片尺寸是否是正方形。不满足就提前失败,而不是等到图片生成完了才发现尺寸不对。前置校验把错误拦截在最上游。
第二个:一致性检查点。 在写作过程中设置检查点,每个检查点验证当前状态是否符合基准要求。比如,每写完一个章节就检查"这个章节有没有小结",而不是等到整篇文章写完了才检查。一致性检查让问题在发生的当时就被发现,而不是累积到后期才发现,那时候纠正的成本已经很高了。
第三个:输出过滤。 即使写作过程完成了,在最终输出之前再加一层过滤。这一层过滤不做过程管理,只做结果判断:这篇文章是否符合所有基准要求?不符合就拒绝输出,符合才允许进入下一个环节。
这三层配合在一起,构成了一套从输入到输出的完整校验体系。基准要求不再是飘在 prompt 里的一句话,而是贯穿整个写作流程的硬性关卡。
从"引导"到"定义":协作方式的跃迁
这个改变也深刻影响了我和 Agent 的协作方式。
以前,我花很多时间"引导" Agent:给它例子,告诉它我喜欢什么样的,告诉它避免什么样的。有点像教练反复强调动作要领,运动员听懂了,但上场之后动作还是会变形。
现在,我把更多精力放在"定义"系统上:把要求写成校验规则,把边界条件写成前置断言,把错误处理写成明确的分支逻辑。Agent 不再需要猜测我想要什么,它只需要通过系统设置的那些检查点。
从"引导 Agent"到"定义系统",这是一个协作层面的根本跃迁。前者的隐含假设是:Agent 会理解我的意图并执行。后者的隐含假设是:Agent 只会执行明确定义的逻辑,意图需要被编码进逻辑里才能被可靠执行。
第一种假设在简单任务上可行。在复杂任务上、重复执行上、高标准要求上,第二种假设才是正确的工程选择。
这个转变让我重新思考人机协作的本质。我以前觉得,和 AI 协作的关键是"学会提问""学会写 prompt"。但真正的问题比这更深:不是怎么问,而是问完之后,如何确保回答被正确处理。把标准从"语言描述"变成"代码约束",不是在约束 AI 自由,而是在给 AI 提供一个可靠的执行框架。框架越清晰,执行越稳定。
一个更广的教训
这个经验还教会我一个更广的教训:
写下来不等于被遵守。
很多事情我们以为"写下来就解决了"。写了基准要求,以为 Agent 就会遵守。写了规范,以为团队就会遵循。写了目标,以为就会实现。但写下来只是让信息进入了某个地方,不等于信息进入了执行路径。
真正让一个要求被遵守,需要两个条件:第一,明确到足够被执行,不能有歧义;第二,被嵌入到执行路径里,不能只是一个参考文件。
写进 prompt 是第一步,但不够。需要写进代码,写进校验,写进强制失败路径。
这和人类组织的行为模式也是相通的。一个公司的价值观写在墙上,但只有在被嵌入到绩效考核、晋升通道、奖励机制里时,才会真正影响行为。写在墙上的价值观是参数,嵌入到制度里的价值观才是约束。
下次怎么做
这次经验之后,我给自己定了一条工作原则:
当你发现自己反复叮嘱同一件事,第三次的时候就该停下来,问自己——这件事能不能写成约束?
反复叮嘱是症状,不是解决方案。症状的背后是你在用语言试图控制一个不受控的随机过程。停下来,把那件事的判断标准提取出来,写成代码里的条件判断。
不一定每次都能做到。有些要求确实很难编码,比如"文章要有温度""语气要亲切"——这类模糊的、感性的标准,语言模型或许比你编码的规则更能捕捉到。但对于"标题包含数字""字数在2500到3500之间""每个章节有小结"这类可验证的标准,编码永远比叮嘱更可靠。
不是减少沟通,而是让沟通落在正确的地方。你仍然需要和 Agent 沟通风格、方向、意图——那些无法编码的软性要求。但硬性的、可验证的标准,让代码来处理。
13篇基准要求,从 skill 参数到核心判断逻辑,不只是一个技术迁移。这是一次认知跃迁:从"希望系统做好"到"确保系统做对"。这两者之间的差别,是业余和专业的分水岭。
写作时间:2026-06-13 字数:约3200字 状态:草稿