反思(Reflection):给 AI 输出加一层质量检查

AI 经常能一次写出一个看起来不错的答案。

但「看起来不错」和「真的合格」不是一回事。代码可能少处理边界,方案可能漏风险,文章可能有正确废话,JSON 可能格式不合法。

这有点像发文章前找同事过一遍。写初稿的人负责把东西写出来,审稿的人负责挑问题,最后作者再按问题修改。不是因为作者不会写,而是因为写和检查本来就是两种注意力。

Reflection 模式解决的是这个问题:

先生成,再按明确标准检查,最后根据检查结果修改。

它不是让 AI 自我感动式地说「我再优化一下」,而是把质量检查变成一条可执行流程。

一、最小流程

流程图画布 · 115%
Mermaid 流程图加载中...

这条流程里有三个角色:

角色职责不该做什么
Generator生成初稿不负责证明自己合格
Judge按标准找问题不直接重写全文
Refiner根据问题修改不随意扩大范围

Reflection 的关键是标准明确。没有标准,反思只会变成「再润色一下」。

一个可用的 Judge 标准,最好写到能直接判断,而不是只表达愿望:

不够可执行更适合做 Judge 标准
代码要健壮是否处理空值、非法类型、除零、超时
文章要清晰是否解释目标读者、核心概念、适用边界
JSON 要正确是否能解析,字段名和类型是否符合 schema
回复要安全是否涉及权限、隐私、不可执行承诺

二、为什么需要反思

一次生成容易出错,尤其是任务同时包含多个要求时。

比如让 AI 写一个函数:

写一个 divide(a, b) 函数:
1. b 为 0 时返回 None;
2. 输入必须是数字;
3. 保留两位小数;
4. 给出简单测试。

模型可能写出主体逻辑,但漏掉类型检查,或者测试只覆盖正常情况。

这时不要只让它「再优化」。更稳的做法是让 Judge 按清单检查:

请检查这段代码是否满足:
1. b 为 0 时返回 None;
2. 非数字输入会被处理;
3. 返回值保留两位小数;
4. 至少有正常、除零、非法输入三类测试。
 
只输出发现的问题,不要重写代码。

然后 Refiner 只根据这些问题修改。

三、Self-Refine 和 Reflexion

Reflection 常见有两种形态。

方式关注点反馈来源存储内容适合场景常见误用
Self-Refine当前任务内反复修改AI 自评或规则评审不长期保存写作、代码、结构化输出无标准地反复润色
Reflexion跨任务积累经验真实执行结果、测试、环境反馈失败原因和下次策略Agent 多轮任务、工具使用把错误总结成空泛鸡汤

Self-Refine 更像「这次作业先自查再改」。Reflexion 更像「这次失败的经验要进入经验本,下次别再犯」。

经验本应该记录具体信息:

{
  "task_type": "code_generation",
  "failure": "forgot_zero_division_case",
  "evidence": "unit test test_divide_by_zero failed",
  "next_time_rule": "before returning math code, check zero/empty/null boundary cases"
}

不要只写:

下次要更仔细。

这句话没有任何可复用价值。

四、完整案例:代码生成 + 自动审查 + 修改

目标:

生成一个安全的 divide 函数,并通过基础检查。

1. Generator 提示词

请用 Python 写一个 divide(a, b) 函数。
 
要求:
1. a 和 b 必须是 int 或 float;
2. b 为 0 时返回 None;
3. 正常结果保留两位小数;
4. 给出 3 个测试:正常、除零、非法输入。

2. Judge 提示词

你是代码审查员。
 
请根据标准检查下面代码。
 
标准:
1. 是否处理非数字输入;
2. 是否处理 b == 0;
3. 是否保留两位小数;
4. 是否包含正常、除零、非法输入测试;
5. 是否有不必要的复杂逻辑。
 
输出 JSON:
{
  "pass": true/false,
  "issues": [
    {
      "severity": "must_fix|suggestion",
      "problem": "...",
      "fix_hint": "..."
    }
  ]
}
 
代码:
{{draft_code}}

3. Refiner 提示词

请只根据审查问题修改代码。
 
要求:
1. 不要重写无关部分;
2. 每个 must_fix 都必须处理;
3. 保留原有函数名;
4. 输出完整代码。
 
原代码:
{{draft_code}}
 
审查问题:
{{review_issues}}

五、最小实现结构

生产系统不能只靠 prompt。至少要有最大轮数、结构化校验、真实反馈、日志和降级。

def reflection_loop(task, max_rounds=3):
    draft = call_ai("generate", task)
    history = []
 
    for round_index in range(max_rounds):
        checks = run_checks(draft)
        review_raw = call_ai("judge", {
            "task": task,
            "draft": draft,
            "checks": checks,
        })
        review = parse_json_or_none(review_raw)
 
        if not review or "pass" not in review:
            history.append({
                "round": round_index,
                "status": "judge_invalid_json",
                "raw": review_raw,
            })
            break
 
        history.append({
            "round": round_index,
            "status": "reviewed",
            "checks": checks,
            "pass": review["pass"],
            "issues": review.get("issues", []),
        })
 
        if review["pass"]:
            return {
                "status": "success",
                "output": draft,
                "history": history,
            }
 
        draft = call_ai("refine", {
            "task": task,
            "draft": draft,
            "issues": review.get("issues", []),
        })
 
    return {
        "status": "needs_human_review",
        "output": draft,
        "history": history,
    }

这段代码表达了几个底线:

  • 反思循环必须有最大次数;
  • Judge 输出必须能解析;
  • 能跑测试、schema 或规则检查时,先把真实反馈交给 Judge;
  • 每一轮都要记录;
  • 多轮仍不合格时要降级给人,而不是无限自我修改。

六、工程风险与防护

失败模式触发条件防护措施是否必须
Judge 误判标准模糊或只看表面标准拆细,关键任务用测试/真实反馈必须
Refiner 越改越偏修改器拿不到具体问题只传 issues,不让它自由重写必须
JSON 解析失败Judge 输出解释性文字schema 校验,失败重试一次必须
无限循环每轮都发现新问题设置最大轮数和停止条件必须
成本失控长文或代码多轮修改限制轮数、限制上下文、记录 cost建议
隐私泄露日志保存用户原文对日志脱敏,限制访问权限必须
标准和用户目标冲突Judge 只按通用规则评审把用户目标放进评审标准必须

Reflection 的风险在于:系统看起来更严谨,但如果 Judge 本身不可靠,它会把错误包装成「已审查」。

七、什么时候不要用反思

场景是否适合原因
低风险短回答不一定反思成本可能高于收益
需要严格事实核查单靠反思不够需要检索、引用或真实工具
强实时聊天谨慎多轮检查会增加延迟
标准无法写清谨慎Judge 容易变成主观润色
代码、结构化输出、重要文档适合有明确标准,能检查和修改

不要把 Reflection 当成万能质量开关。它适合「错误能被描述,改动能被验证」的任务。

八、和其他 Agent 模式的关系

模式解决的问题和 Reflection 怎么组合
提示词链把任务拆成步骤链路末尾加审查和修改
路由判断走哪条分支不同分支使用不同评审标准
并行化同时处理独立任务多个 Judge 并行评审不同维度
工具调用获取真实信息或执行动作Judge 可以调用测试、lint、检索工具

真实系统里,Reflection 往往不是单独存在。它更像一层质量门禁,放在生成之后、交付之前。

九、最后给一份检查清单

设计 Reflection 流程时,先问:

1. 这件事有没有明确质量标准?
2. Judge 只评审,还是会越权改稿?
3. Refiner 是否只根据具体问题修改?
4. Judge 输出是否结构化?
5. 最大反思轮数是多少?
6. 哪些失败需要交给人?
7. 真实反馈、测试或工具结果能不能进入评审?
8. 日志里是否保存了每一轮的问题和修改?

一句话记住:

Reflection 不是让 AI 多想一会儿,而是把生成、评审、修改和停止条件拆成一条可检查的流程。