多步提示编排:把复杂任务拆成链
复杂任务一次说清很难。多步提示编排(prompt chaining)把任务拆成若干可管理的环节,每一步产出明确的中间结果,再串联成最终答案。它不是把一句话写得更长,而是把”一个难题”重构成”一串小问题”,让每一步都更可控、可观测、可调试。在检索增强生成(RAG)、代码评审、长文摘要等场景里,链路化几乎是默认做法。
是什么
多步提示编排指:用一组预先设计(或条件化生成)的子提示,把输入逐段加工。上一步的输出作为下一步的输入变量,形成一条数据流水线。每个节点通常包含三要素:明确的角色与任务、清晰的输入约定、结构化的输出格式(如 JSON、Markdown 表格、固定分隔符)。
它和”把全部指令塞进一个超长提示”本质不同。单提示里模型要在同一段上下文里同时完成理解、推理、约束遵守和格式输出,认知负载高;而链路把这些问题拆到不同节点,每个节点只需专注一件事。这带来一个关键收益:可观测的中间态。每一步都有人能读、能断言、能回放的产物,而不是模型内部一段看不见的隐式推理。
一个典型的四段链:
1. 需求解析:把用户目标拆成有序子任务清单
2. 逐段求解:对每个子任务调用一次 LLM,产出中间产物
3. 汇总与自检:拼接结果,检查前后一致、约束是否被满足
4. 结构化输出:落盘为下游系统可直接消费的数据
为什么有用
单条超长提示至少有三类问题。其一,约束易被淹没:当指令、示例、格式要求、禁忌全部堆在一处,模型常常”顾此失彼”。其二,难以调试:一旦输出不对,你无法判断是需求理解错、某步计算错,还是格式指令没生效。其三,难以复用:把十个子任务写进一个提示,意味着任何一处改动都可能影响全局。
分步之后,每一步目标单一,错误更易定位,也方便在节点之间插入校验、缓存与并行。例如”先抽取实体、再判定关系、最后生成摘要”的三段链,若实体抽取异常,你直接看到空列表,而不是等到最终摘要才发现离题。质量上,链路还能做”逐步评分”:对每步输出用一个小模型或规则打分,低于阈值就重生成或告警,这是单提示难以做到的。
成本侧也有好处:稳定且昂贵的节点结果可以缓存,相同输入直接复用,不必每次重算;彼此无依赖的节点还能并行,缩短端到端延迟。当然,链路也有开销——多次调用带来额外延迟与 token 成本,因此对特别简单的任务,单提示反而更直接,不必为了”架构感”而强行拆链。
# 极简的链式调用骨架(示意,非特定框架)
def run_chain(text):
entities = llm(prompt_entities, text=text) # 第 1 步:抽取
relations = llm(prompt_relations, entities=entities) # 第 2 步:关系
summary = llm(prompt_summary, relations=relations) # 第 3 步:摘要
return summary
怎么用
编排形态大致分三种。固定链路:步骤与顺序写死,适合流程稳定的批处理,例如”清洗→分类→打标”。条件路由:根据上一步结果选择下一节点,例如先判断工单语言,再走中文或英文处理分支。扇出/汇总(fan-out / fan-in):把大输入切分后并行处理多个分片,再合并,典型如”先各段摘要、再全局归纳”的 Map-Reduce 摘要。
真实工程里,LangChain 的 SequentialChain、LlamaIndex 的 QueryPipeline、以及 DSPy 的 Module/Predict 都提供了声明式编排能力。以 DSPy 为例,你可以把每步定义为一个带签名的模块,框架负责把上一步的输出字段自动喂给下一步:
import dspy
class Extract(dspy.Signature):
"""从文本抽取关键事实。"""
doc: str = dspy.InputField()
facts: list[str] = dspy.OutputField()
class Summarize(dspy.Signature):
facts: list[str] = dspy.InputField()
summary: str = dspy.OutputField()
extract = dspy.Predict(Extract)
summarize = dspy.Predict(Summarize)
# Extract 的 facts 自动成为 Summarize 的输入
out = summarize(facts=extract(doc=text).facts)
一个完整的实战例子是”技术文章审稿”链:第一步 critique 让模型按维度(正确性、清晰度、新颖性)列出评审点;第二步 score 把评审点映射为各维度 1–5 分与理由;第三步 report 汇总成给作者的结构化反馈。每步用 JSON 衔接,下游只消费上游的明确字段:
// 第 1 步输出
{"points": [{"dim": "正确性", "issue": "公式(3)漏了归一化"}]}
// 第 2 步输入 points,输出
{"scores": {"正确性": 3, "清晰度": 4}, "rationale": "..."}
关键是把好”接口契约”:每步输出必须可被下一步消费。建议用强 schema(如 JSON)约束输出,并在节点间做轻量断言,例如”facts 不能为空""summary 长度不超过 200 字”。对于并行分片,汇总节点要明确如何处理冲突与重复。
注意点
误差累积是最常被低估的风险。每步都有概率性错误,N 步串联后整体正确率约等于各步正确率的乘积(以下为示意:假设单步 95% 为例,五步后约 77%,十步后仅约 60%)。因此要控制步数、在关键节点加校验提示,并对高代价步骤做失败回退(如重试、降级到规则方案)。
它与 Agent 的区别要厘清:多步提示是固定或条件化的流程,节点与顺序基本由你设计;Agent 则带工具调用、环境反馈与循环决策(典型如 ReAct)。简单链路用提示编排足够,不必上 Agent;当任务需要检索、调 API、根据结果反复试探时,再考虑 Agent。Anthropic 在其”构建高效能 Agent”的文章中,把 prompt chaining 列为成本更低、更可控的工作流类型之一,正是这个取舍。
常见反模式要避开:其一,步数过多——把本可用规则或普通代码完成的步骤也交给 LLM,既慢又易错;其二,接口泄漏——某步把原始长文本直接透传给下一步,导致上下文膨胀、约束失效;其三,无校验的盲传——上游出错下游照单全收,错误被放大。
如何评估一条链:对每一步准备少量标注样本,跑出逐步准确率;再在任务级指标上测端到端表现。哪一步是瓶颈,就优先优化那一步,而不是笼统地调整条链。这比”凭感觉改提示”要可靠得多。
单提示 / 链路 / Agent 的取舍(定性):
- 单提示:任务简单、一步能说清 → 最快最省
- 链路:流程稳定、要可控可调试 → 成本适中、易维护
- Agent:需检索/调 API/动态决策 → 能力强但更难控成本与正确性
其它注意:保留中间结果便于排查;不要让模型在链中段”自由发挥”改写上游产物;批量任务可对稳定节点做缓存以省 token;对需要确定性的环节,固定随机种子或改用更严格的输出约束;链过长时考虑把部分步骤下沉为确定性的传统代码,而非都交给 LLM。
小结
多步提示编排用”拆任务、串中间结果”换取可控与可调试,适合流程稳定的复杂任务。它不是 Agent,但确实是许多智能体系统的底层骨架。落地口诀:接口强约束、节点可观测、关键处校验、步数要克制、稳定处下沉、瓶颈处优先优化。
参考与延伸阅读
- Anthropic《Building Effective Agents》——将 prompt chaining 列为工作流类型之一。已核验(https://www.anthropic.com/engineering/building-effective-agents)。
- DSPy 官方文档(模块化提示与管线编排)。已核验(https://dspy.ai/)。
- LangChain 文档中 Chains / SequentialChain 章节。已核验(https://python.langchain.com/docs/)。
- LlamaIndex QueryPipeline 文档。待核实。