问题从哪来
在多智能体系统里搭硬约束层时,遇到一个反复出现的争论:某个「不许出现 X」的规则, 应该写在 prompt 里,还是做成代码校验?
直觉答案通常是 prompt——快、灵活、改起来不用发版。这个答案在演示时总是有效, 在真实运行里单次调用可能确实也有效,但它没有把规则变成规则,只是把这个规则变成了一个较高的概率。
说清楚这句话的含义:写进 prompt 的约束,模型每一轮都会重新做一次是否遵守的决策。 绝大多数轮次它遵守,偶尔它不遵守——而你不控制它什么时候不遵守。 写进代码的约束没有这个概率成分,它要么通过要么失败。
这是两类东西,不是程度不同的同一件事。
分界在哪
实际可用的分法不是按「重要程度」,而是按违反后的可发现性。
| 约束类型 | 违反了会怎样 | 该放哪 |
|---|---|---|
| 风格倾向 | 读起来不理想,但一眼能看出来——人读到就知道了 | prompt,越自然越好 |
| 事实边界 | 说了不该说的内容,读者不可能发现,因为它读起来同样通顺 | 代码,而且要前置拦截 |
| 结构要求 | 格式不对,下游解析失败——会立刻报错 | 代码,但可以后置校验 |
| 口径一致性 | 同一件事前后说法不同,只有通读全文才发现 | 两者都要:prompt 引导 + 代码抽查 |
第二行是分界线的核心。判断标准是一句话: 这个错误如果发生了,读者能不能自己发现?
能发现 → 用 prompt 就够了,因为错误会被后续环节自然拦下。 不能发现 → 必须用代码,因为没有人会替你发现,它会一直流到产出里。
算错的数字是典型:读起来一样通顺,甚至更通顺。结构化数据传递中丢字段也是—— 下游不会报错,只会「合理地」补一个。
但代码约束不是越多越好
这是我实际踩过的地方。早期把契约设计得过细,结果模型为了满足结构而牺牲内容质量—— 它把精力花在「填满字段」上,而不是把话说对。
放宽非关键字段的必填要求之后,产出质量反而回升了。原因是: 过多的结构约束占用了模型的注意力预算。它的能力是有限的, 花在满足格式上的部分,就是从内容理解上扣掉的。
所以真正要问的不是「这个约束严不严格」,而是 「不遵守它的代价,和大面积降低产出质量的代价,哪个更大」。 只有前者显著更大时,才值得做成硬约束。
一条实操判据。如果一条约束做成硬拦截后,在正常输入上也会频繁拒绝, 那它大概率约束错了层级——你要管的是产出质量,却卡在了中间过程的形态上。 这种情况应该把它降级为「事后校验 + 标记」,而不是前置拦截。
什么条件下这个结论会失效
- 任务本身是模糊的如果对约束的要求需要按情况判断、无法预先枚举,硬编码规则会变成枷锁,产出被压得千篇一律。这时应该把规则降级为提示加事后校验。
- 还在探索期产出应该长什么样还没稳定时,过早的硬约束会频繁误拦,反而拖慢迭代。门禁的标准要随项目成熟度逐步收紧——一开始就按最终标准卡,会卡死在半路。
- 错误可被下游消化如果下游有独立校验、或者有人工复核环节,某些约束可以依赖那层兜底,不必重复实现。
一句话
按违反后的可发现性,而不是按重要性,决定一条约束放 prompt 还是放代码。 可发现的交给语言,不可发现的交给代码。然后再问一遍:这条约束值得付出多少注意力成本。