面试官问:「ReAct 和 Plan-and-Execute 怎么选?」——三种规划范式,只答区别只值 60 分
《AI Agent 面试 30 问》· 第 02 问 第 01 问我们把「控制流」讲清了:Agent 把「下一步做什么」的决策权交给模型。这篇往下钻一层——模型是怎么决定下一步的。这就是 Planning。
承接上一篇:控制流定了,决策本身怎么组织?
第 01 问的结论是:Agent 的本质是自主循环。但循环里每一步「想什么」,是有不同组织方式的。
面试官问规划范式,问的其实是:你有没有在「灵活性」和「可控性」之间做过取舍。
先把三个词摆正,因为大部分人从第一步就错了:
ReAct和Plan-and-Execute是两种规划粒度(步级 vs 任务级),是并列关系;Reflexion不是第三种规划范式,它是叠加在循环外面的纠错层,本身不产生计划。
把 Reflexion 和另外两个并列成「三大范式」,是这道题最常见的减分点。
一、真题还原
「你们 Agent 的规划是怎么做的?ReAct 和 Plan-and-Execute 有什么区别?什么时候该用哪个?」
三层考察意图:
- 读过实现没有:能不能说清 Thought / Action / Observation 是怎么进上下文的,而不是「边想边做」四个字。
- 有没有代价意识:每种范式的 token 成本、步数、失败模式分别是什么。
- 能不能做选型:给一个具体场景,你能不能说「我用哪个、为什么、混合怎么混」。
第 3 层是分水岭。只会讲区别的人停在 60 分,能给出选型判断的到 90 分。
二、60 分 vs 90 分
60 分
「ReAct 就是边想边做,走一步看一步;Plan-and-Execute 就是先规划再执行;Reflexion 是让模型反思自己的错误然后改进。」
不能说错,但三个问题:
- 没说出规划粒度这个本质差异;
- 把 Reflexion 当成了第三种并列范式;
- 完全没提代价——面试官下一句一定是「那成本呢」。
90 分
「这三个不是一个维度的东西。 ReAct 和 Plan-and-Execute 的区别是规划粒度:ReAct 是步级规划,每一步都重新决策一次,适应性强但全局性差、步数不可控;Plan-and-Execute 是任务级规划,先把任务拆成一个结构化的计划(通常是 DAG 或步骤列表)再执行,全局一致、可并行、可审计,但计划错了整条链都废,所以必须有 replan。 Reflexion 不是第三种规划,它是外挂的纠错层:跑完一轮 → 评估 → 把失败教训写回记忆 → 重跑。它的前提是你得有一个可靠的 evaluator,否则就是模型自说自话。 生产里我一般用外层 Plan、内层 ReAct 的混合:骨架用计划保证确定性,每个计划节点内部允许 ReAct 自由探索。」
三、一张表看清代价
| 规划粒度 | 每步开销 | 适应性 | 全局一致性 | 可审计性 | 典型失败模式 | |
|---|---|---|---|---|---|---|
| 单步调用 | 无 | 1 次 | 无 | 无 | 弱 | 没有第二次机会 |
| ReAct | 步级 | 每步 1 次 LLM | 高 | 低 | 中(靠 trace) | 局部最优、绕圈、步数爆炸 |
| Plan-and-Execute | 任务级 | 1 次规划 + N 次执行 | 低(依赖 replan) | 高 | 强(计划是结构化产物) | 计划不可行、依赖断裂 |
| Reflexion | 叠加层 | 每轮 +1~2 次 | 中 | 不改计划 | 中 | 无 evaluator 时空转、成本翻倍 |
记这一句:ReAct 把决策成本摊在每一步,Plan-and-Execute 把决策成本前置到一次。
这是这道题的高分点。ReAct 每步都要一次完整 LLM 调用(上下文还越来越长),Plan-and-Execute 只在开头花一次「贵」的调用,后面执行可以便宜、甚至可以并行。
四、代码:三种结构的骨架
ReAct(步级)
def react(goal, llm, tools, max_steps=8):
ctx = [goal]
for _ in range(max_steps):
thought, action, args = llm.decide(ctx) # 每步都重新看一遍全局上下文
if action == "Finish":
return args["answer"]
ctx.append(f"Observation: {tools[action](**args)}")
return None
特点:ctx 不断变长,每步都在「重新理解任务」。这就是为什么它灵活,也为什么它贵、容易飘。
Plan-and-Execute(任务级)
def plan_and_execute(goal, llm, tools, max_replan=2):
plan = llm.plan(goal) # 结构化:步骤 + 依赖 + 工具 + 参数
done = {}
replans = 0
while plan:
step = plan.pop(0)
if not all(d in done for d in step["depends_on"]):
if replans >= max_replan:
return {"status": "blocked", "done": done}
plan = llm.replan(goal, plan, done) # 依赖断裂 → 重规划
replans += 1
continue
try:
done[step["id"]] = tools[step["tool"]](**step["args"])
except Exception as e:
done[step["id"]] = {"error": str(e)} # 错误也落进 done,供 replan 参考
return llm.summarize(goal, done)
三个关键设计:
- 计划必须是结构化产物(步骤 id、依赖、工具、参数),不能是一段自然语言——否则没法校验、没法并行、没法审计。
replan是生命线。没有 replan 的 Plan-and-Execute 就是「一次性赌一把」。- 错误要落进
done,让 replan 看到「哪一步炸了、炸成什么样」。
Reflexion(纠错层)
def reflexion(goal, llm, run_once, evaluate, max_rounds=3):
lessons = []
traj = None
for _ in range(max_rounds):
traj = run_once(goal, lessons) # 把上一轮的教训带进上下文
ok, feedback = evaluate(traj) # 外部信号,不是模型自己说好
if ok:
return traj
lessons.append(llm.reflect(goal, traj, feedback))
return traj
注意 evaluate 是外部传进来的:单元测试、规则校验、另一次 LLM 打分、人工反馈。
没有它,Reflexion 就退化成「模型再想一遍」,往往只是把同一个错误换个说法。
五、选型:给一个场景,你说哪个
面试官很爱给场景。记住一条判断链:
- 路径能不能提前枚举? 能 → Workflow 或 Plan-and-Execute;不能 → ReAct。
- 步骤间有没有强依赖、要不要并行? 有 → Plan-and-Execute(DAG 天然支持拓扑排序与并行)。
- 要不要审计 / 复现? 要 → Plan-and-Execute,因为计划本身是可存档的结构化对象。
- 有没有可靠的成功判据? 有 → 可以在外面套 Reflexion;没有 → 别套,纯烧钱。
- 任务长且开放? → 混合:外层 Plan 定骨架,每个节点内部用 ReAct 探索。
两个具体例子,面试时说出来很有说服力:
- 「把这份财报 PDF 整理成结构化表格」:步骤基本可枚举(抽取 → 校验 → 补全 → 格式化),用 Plan-and-Execute,多页可并行。
- 「调研竞品最近的动作,写份简报」:搜什么、搜到之后往哪查,取决于上一步结果,无法预先枚举 → ReAct;但若要求「必须覆盖 5 个维度」,就再加一层 Plan 做骨架。
加分句:「Plan-and-Execute 解决的是全局一致性,ReAct 解决的是局部适应性。真实任务两个都要,所以是嵌套,不是二选一。」
六、连环追问
Q1:ReAct 为什么会绕圈? 三个原因:每步只看局部上下文,没有「我已经试过 A 了」的显式记录;没有步数与预算意识;Observation 太长,把早期目标挤出了上下文。解法:动作去重检测、维护显式的「已排除假设」列表、把目标固定在 system 里而不是埋在历史里。
Q2:Plan 出来的计划根本不可行怎么办? 这就是 replan 的触发条件设计:依赖缺失、工具连续失败 N 次、执行结果偏离预期、步数超预算。同时要限次数(比如 2 次),否则会变成「反复重规划」的新死循环。
Q3:Reflexion 什么时候完全无效? 三种情况:没有可靠 evaluator(最常见);任务本身有随机性(同样的做法这次成功下次失败,反思会学到错误因果);反思污染上下文(把一次偶发失败总结成「铁律」,反而拉低后续成功率)。所以生产里我更倾向离线反思:把失败案例沉淀成 few-shot 或规则,而不是每轮在线反思。
Q4:成本怎么控? 规划阶段用强模型(只调一次,值得),执行阶段用便宜模型或直接代码;计划节点可并行;ReAct 设步数上限;Reflexion 只在离线 eval 里跑,不进线上主链路。
Q5:怎么评估规划质量? 拆四个指标:计划可行率(plan 出来后能不能跑通)、平均步数、replan 次数、端到端成功率。只看最后一条会掩盖问题——成功率没降但步数翻倍,成本已经崩了。
七、加分项与踩坑
说出来就加分的词
规划粒度、replan、DAG / 拓扑排序、evaluator / verifier、在线反思 vs 离线反思、步数预算。
别踩的坑
- 把 Reflexion 和 ReAct / Plan-and-Execute 并列成「三种范式」——最典型的错;
- 说 Plan-and-Execute 就是「多了一步 planning 的 ReAct」——粒度不同,不是加个步骤;
- 只讲灵活性不讲成本,全程不提步数和 token;
- 说「Reflexion 让模型自我批评就能变好」——没有外部信号的自我批评基本无效。
八、面试前 30 秒版
「ReAct 和 Plan-and-Execute 的差别是规划粒度:ReAct 步级决策,每步重新看全局,灵活但步数和成本不可控、容易局部最优;Plan-and-Execute 任务级规划,先出结构化计划再执行,全局一致、可并行、可审计,代价是计划错了要 replan。 Reflexion 不是第三种范式,是外挂纠错层,必须有可靠 evaluator 才有意义,否则就是自说自话。 生产里我用外层 Plan、内层 ReAct 的嵌套结构,再用离线反思把失败案例沉淀成规则,而不是在线反复自我批评。」
小结与下期预告
规划这题的锚点是粒度:步级换灵活,任务级换可控,纠错层换成功率但要付 evaluator 的钱。
下一期聊工具层头号事故:Function Calling 参数幻觉——为什么 prompt 里写「不要编造」没用,以及四层治理怎么搭。
本系列默认以 OpenAI 兼容接口 + Python 为例,示例为教学用最小实现,生产代码需补充鉴权、并发与审计。