Langgraph 1. Prompt Chaining(提示链)

摘要 :Prompt Chaining(提示链)将复杂任务拆成多步小任务,每步用单一提示完成,上一步输出作为下一步输入,从而提升大模型在多阶段任务上的可靠性与可维护性。本文介绍其动机、结构化输出、典型应用场景,并以 LangGraph 的 StateGraph 实现两阶段「提取 → 转换」流水线示例,便于读者动手实践与扩展。

关键词:Prompt Chaining;提示链;Pipeline 模式;LangGraph;StateGraph;多步推理;结构化输出;Agentic Design Patterns

源代码地址:链接


1 为什么需要 Prompt Chaining?

想象一下:你让大模型「读一份市场调研报告,总结要点、找出三个趋势并附上数据、再给市场部写一封邮件」。如果只发一条超长提示,模型很容易出现:漏掉其中某一项、中途「跑题」、前面错一点后面全歪,或者因为上下文太长而表现不稳。这类问题在复杂任务里非常常见。

Prompt Chaining (提示链,有时也叫 Pipeline 模式 )的做法是:把一个大任务拆成多步小任务,每一步用一个专注的提示完成一件事,上一步的输出当作下一步的输入。就像流水线:先拧螺丝,再装外壳,最后质检------每一步职责清晰,出错也容易定位。

💡 理解要点 :单次 Prompt 在「多目标、多步骤」任务上容易指令遗漏、上下文漂移、错误放大;拆成链式多步可以显著提高可靠性和可控性。


2 Prompt Chaining 在解决什么?

  • 单一大提示的局限:任务一多,模型容易忽略部分约束、偏离主题、或在前序错误基础上继续推理,甚至因认知负载增加而更容易「幻觉」。
  • 链式分解带来的好处
    1. 每一步目标单一:例如「只做摘要」「只做趋势抽取」「只写邮件」,模型负担小、表现更稳。
    2. 上一步输出约束下一步:例如先得到「摘要」,再在摘要基础上抽趋势,再基于趋势写邮件,形成清晰的依赖链。
    3. 便于调试与迭代:哪一步效果不好,就改哪一步的提示或逻辑,不必重写整条流程。
    4. 中间可插入工具与校验:例如某步之后做格式校验、调用计算器或数据库,再交给下一步。

🔍 实际例子 :同一份市场报告,可以拆成三步------

①「请总结以下报告要点」→ ②「根据该摘要,列出前三个趋势并附支持数据」→ ③「根据上述趋势与数据,写一封给市场部的简短邮件」。每一步输入明确、输出可验证,整体更可靠。


3 结构化输出:链的「接口」

链的可靠性很大程度取决于步骤之间传递的数据是否清晰、可解析 。如果上一步输出是含糊的自然语言,下一步就容易理解偏差。因此,为中间结果和最终结果约定结构化格式(如 JSON、XML)是常见做法。

例如,趋势抽取步骤可以要求输出如下 JSON:

json 复制代码
{
  "trends": [
    {
      "trend_name": "AI 驱动的个性化",
      "supporting_data": "73% 的消费者更愿意与使用个性化体验的品牌打交道。"
    },
    {
      "trend_name": "可持续与伦理品牌",
      "supporting_data": "带 ESG 声明的产品过去五年销售增长 28%,无声明产品为 20%。"
    }
  ]
}

这样下一步(例如写邮件)可以直接解析并填入模板,减少歧义和解析错误。

💡 理解要点:链中每一步的「输出格式」相当于接口契约;用 JSON/XML 等结构化输出能减少歧义,便于程序化处理与后续节点使用。


4 典型应用场景(简述)

场景 链的典型步骤
信息处理流水线 抓取/解析 → 摘要 → 实体抽取 → 知识库查询 → 生成报告
复杂问答 拆子问题 → 分别检索 → 综合多源信息 → 生成答案
数据抽取与转换 从文档抽取字段 → 校验/补全 → 输出结构化数据,必要时插入计算或工具
内容生成 选题 → 列提纲 → 分节撰写 → 统稿与润色
对话与状态 每轮识别意图与实体 → 更新状态 → 根据状态生成回复(多轮可视为链的重复)
代码生成与优化 理解需求 → 写伪代码/提纲 → 写初版代码 → 静态分析/审查 → 修正与补充文档或测试

这些场景的共同点是:多阶段、有先后依赖;Prompt Chaining 负责把「阶段」和「依赖」显式地建模成链(或图)。


5 用 LangGraph 实现 Prompt Chaining

LangChain 的 LCEL 适合线性链;LangGraph 则用 来编排节点与边,天然适合「多步、有状态、可扩展」的流程。下面用 LangGraph 实现一个两阶段流水线 :先从文本中提取技术规格描述,再把这些描述整理成带 cpumemorystorage 的 JSON。整体是线性链:START → 提取 → 转换 → END

5.1 状态设计

图上的所有节点共享同一份状态 (State)。我们用一个 TypedDict 表示「链上传递的数据」:

python 复制代码
class ChainState(TypedDict):
    text_input: str       # 用户输入的原始文本
    specifications: str   # 第一阶段的输出:提取出的规格描述
    result: str          # 第二阶段的输出:最终 JSON 字符串
  • 输入只填 text_input
  • 第一个节点只写 specifications
  • 第二个节点只写 result

这样每个节点职责清晰,状态在节点间自动合并(默认是覆盖式更新)。

5.2 两个节点

节点一:提取(extract)

只做一件事:从 state["text_input"] 里提取技术规格,用自然语言概括,写回 specifications

节点二:转换(transform)

只做一件事:把 state["specifications"] 整理成只含 cpumemorystorage 的 JSON 字符串,写回 result

节点实现里使用 ChatPromptTemplate + ChatOpenAI + StrOutputParser(),和 LangChain 的用法一致;区别在于这里每个节点是「图上的一个节点函数」,接收 state,返回要更新的字段字典。

5.3 建图与编译

python 复制代码
workflow = StateGraph(ChainState)

workflow.add_node("extract", node_extract)
workflow.add_node("transform", node_transform)

workflow.add_edge(START, "extract")
workflow.add_edge("extract", "transform")
workflow.add_edge("transform", END)

graph = workflow.compile()

执行时传入初始状态即可:

python 复制代码
initial_state = {
    "text_input": "新款笔记本配备 3.5 GHz 八核处理器、16GB 内存和 1TB NVMe 固态硬盘。",
    "specifications": "",
    "result": "",
}
final_state = graph.invoke(initial_state)
# 使用 final_state["specifications"] 和 final_state["result"]

🔍 实际例子 :完整可运行代码(含节点实现、环境与运行说明)在本章的 demo_codes 目录中:

  • 代码入口:demo_codes/chain.py
  • 安装与运行:见 demo_codes/README.md

运行后会在控制台看到「阶段一:提取的规格」和「阶段二:最终 JSON」,便于对照理解链式数据流。

5.4 完整代码

py 复制代码
"""
Prompt Chaining 示例:使用 LangGraph 实现两阶段数据处理流水线。

流程:原始文本 → [节点1: 提取规格] → [节点2: 转为 JSON] → 最终输出

运行前请配置环境变量 OPENAI_API_KEY,或在项目根目录放置 .env 文件。
"""
import os
from typing import TypedDict

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langgraph.graph import StateGraph, START, END

from dotenv import load_dotenv
load_dotenv()
# 支持 OpenAI 或 DashScope 等兼容接口:未设置时 model 必须有默认值,否则 ChatOpenAI 会报错
dashscope_api_key = os.getenv("DASHSCOPE_API_KEY") or os.getenv("OPENAI_API_KEY")
dashscope_base_url = os.getenv("BASE_URL")  # 使用 DashScope 时配置,OpenAI 可不设
model = os.getenv("MODEL")   # 必须为有效字符串,不可为 None

# ---------------------------------------------------------------------------
# 状态定义:节点之间通过 State 传递数据
# ---------------------------------------------------------------------------

class ChainState(TypedDict):
    """图的状态:贯穿「提取」与「转换」两阶段。"""
    text_input: str       # 用户输入的原始文本
    specifications: str   # 第一阶段的输出:提取出的规格描述
    result: str          # 第二阶段的输出:最终 JSON 字符串


# ---------------------------------------------------------------------------
# 图节点:每个节点接收 state,返回要写回 state 的更新
# ---------------------------------------------------------------------------

def _build_llm():
    """构建 LLM(可从环境变量读取 API Key)。"""
    llm = ChatOpenAI(
        model=model,
        api_key=dashscope_api_key,
        base_url=dashscope_base_url,
        temperature=0.7,  # 可根据需要调整,0 更确定,1 更随机
        # max_tokens=1000,  # 可选:限制最大输出长度
        # timeout=30,  # 可选:设置超时时间
    )
    return llm


def node_extract(state: ChainState) -> dict:
    """
    节点一:从原始文本中提取技术规格描述。
    仅负责「提取」,不负责格式化,降低单步认知负担。
    """
    prompt = ChatPromptTemplate.from_messages([
        ("user", "从以下文本中提取技术规格信息,用自然语言概括即可:\n\n{text_input}"),
    ])
    llm = _build_llm()
    chain = prompt | llm | StrOutputParser()
    specifications = chain.invoke({"text_input": state["text_input"]})
    return {"specifications": specifications}


def node_transform(state: ChainState) -> dict:
    """
    节点二:将规格描述转换为带 cpu / memory / storage 的 JSON。
    依赖上一节点的 specifications,实现「链式」传递。
    """
    prompt = ChatPromptTemplate.from_messages([
        ("user", "将以下规格说明整理为 JSON 对象,仅包含键:cpu、memory、storage。"
         "只输出 JSON,不要其他说明。\n\n{specifications}"),
    ])
    llm = _build_llm()
    chain = prompt | llm | StrOutputParser()
    result = chain.invoke({"specifications": state["specifications"]})
    return {"result": result}


# ---------------------------------------------------------------------------
# 构建图:线性链 extract → transform
# ---------------------------------------------------------------------------

def build_prompt_chain_graph():
    """构建并编译 Prompt Chaining 图。"""
    workflow = StateGraph(ChainState)

    workflow.add_node("extract", node_extract)
    workflow.add_node("transform", node_transform)

    workflow.add_edge(START, "extract")
    workflow.add_edge("extract", "transform")
    workflow.add_edge("transform", END)

    return workflow.compile()


# ---------------------------------------------------------------------------
# 入口:本地运行示例
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    # 可从 .env 加载 OPENAI_API_KEY
    
    graph = build_prompt_chain_graph()

    input_text = (
        "新款笔记本配备 3.5 GHz 八核处理器、16GB 内存和 1TB NVMe 固态硬盘。"
    )
    initial_state: ChainState = {
        "text_input": input_text,
        "specifications": "",
        "result": "",
    }

    final_state = graph.invoke(initial_state)

    print("\n--- 阶段一:提取的规格 ---")
    print(final_state.get("specifications", ""))
    print("\n--- 阶段二:最终 JSON ---")
    print(final_state.get("result", ""))

打印输出:

复制代码
from dotenv import load_dotenv
from chain import build_prompt_chain_graph
from chain import ChainState

load_dotenv()

graph = build_prompt_chain_graph()

from IPython.display import Image, display
display(Image(graph.get_graph(xray=True).draw_mermaid_png()))

当然,这是一个含简单的例子,但是我们从这里开始了解 LangGraph。


6 Context Engineering 与 Prompt Engineering 的关系

Context Engineering (上下文工程)强调:在模型真正生成内容之前,为它构建完整、结构化的信息环境------包括系统提示、检索到的文档、工具调用结果、用户身份与历史等。输出质量往往更取决于「给了什么上下文」,而不仅是「问了哪一句话」。

Prompt Chaining 可以看作是 Context Engineering 在「多步流程」上的体现

  • 每一步的 prompt 负责把「当前该知道的信息」组织好(上一步结果、当前角色、格式要求等);
  • 链的编排则决定了「何时、以何种顺序」把哪些信息注入到哪一步。
    因此,在设计链时,除了写好单步提示,也要考虑:每一步的输入上下文是否足够、是否结构化(例如上一步的 JSON),以及是否需要在链中插入检索、工具或人工校验。

💡 理解要点:链中每一步都是在为模型构造「当前步骤的上下文」;把链设计好,就是在做多步的 Context Engineering。


7 小结与使用建议

  • What:Prompt Chaining 把复杂任务拆成多步小任务,每步一个专注的提示,上一步输出作为下一步输入,形成链(或管道)。
  • Why:单一大提示在多目标、多步骤任务上容易指令遗漏、上下文漂移和错误放大;链式分解能提高可靠性、可调试性和可扩展性。
  • When:任务过于复杂、包含多个明显阶段、需要在步骤间调用工具或做校验、或你要做多步推理/状态维护时,都可以考虑 Prompt Chaining。
  • How(本文) :用 LangGraph 的 StateGraph 定义状态和线性链(两个节点:提取 → 转换),状态在节点间自动传递;完整示例见 demo_codes/

关键要点

  • 链的可靠性依赖步骤间数据的结构化(如 JSON);
  • LangGraph 用图与状态清晰表达「谁先谁后、传什么」;
  • 掌握 Prompt Chaining 是构建多步 Agent、复杂工作流的基础。
相关推荐
流氓架构师2 小时前
2026年实测:Gemini 3.1 Pro vs GPT-5.4 Pro,谁更强?国内免费访问方案
大数据·人工智能·gpt
chilavert3182 小时前
技术演进中的开发沉思-376 NLP:NLP核心与困局
人工智能·自然语言处理
良许Linux2 小时前
图像处理和计算机视觉
图像处理·人工智能·计算机视觉
格林威2 小时前
工业相机图像高速存储(C#版):内存映射文件方法,附海康相机C#实战代码!
开发语言·人工智能·数码相机·opencv·计算机视觉·c#·工业相机
人道领域2 小时前
2026全球大模型深度对决:GPT-5、Claude 4、Gemini 3、DeepSeek-R1谁主沉浮?
人工智能·gpt·深度学习·chatgpt·文心一言
WJSKad12352 小时前
城市图像生成-FLUX.2-dev-GGUF量化-图像处理-AI工具[特殊字符]
人工智能·计算机视觉
AI工具指南2 小时前
从复制粘贴到一键生成:2026年AI生成PPT工具使用指南
人工智能·powerpoint·ppt
小白_史蒂夫2 小时前
【图像处理】(四)TV图像修复方法(附matlab代码)
图像处理·人工智能·matlab
weiyvyy2 小时前
机器人嵌入式开发趋势-开源生态与标准化
人工智能·嵌入式硬件·机器人·开源·信息化