使用 LangChain 构建链式工作流

本篇中级 Python 教程将教你如何在 LangChain 中通过串联多个操作,构建强大的顺序化工作流。你将掌握不同类型的链(Chain),并通过逐步示例和最佳实践,学会搭建复杂的 AI 流水线。

🎯学习目标

  • 理解"链"(Chains)的概念及其强大之处
  • 使用管道操作符(|)构建简单链
  • 创建能在各步骤间传递数据的顺序链
  • 为链实现错误处理与调试机制

📚本教程前置要求(中级 Python)

本教程假设你已具备以下基础:

  • 已完成第 5--6 课(LangChain 环境配置与提示模板)
  • 具备中级 Python 编程能力
  • 理解 LangChain 的提示模板(Prompt Templates)
  • 对 async/await 概念有所了解(非必需,但有帮助)

🔗什么是 Chains?

在 LangChain 中,Chains 是一系列按顺序处理数据的组件。你可以将其想象成一条装配流水线------每个环节对数据进行加工后,再传递给下一个环节。

🔑 核心优势:

  • 模块化:将复杂任务拆解为简单、可复用的步骤
  • 灵活性:轻松修改或扩展工作流
  • 清晰性:明确的数据流向使调试更简单
  • 可复用性:同一链条可用于不同输入
  • 链式流程可视化

链式流程可视化

text 复制代码
输入 → [提示模板] → [大语言模型 LLM] → [输出解析器] → 结果
         ↓                ↓                  ↓
     格式化输入      生成文本内容        结构化输出

使用管道操作符(|)构建简单链

你的第一条 Chain

在 LangChain 中,管道操作符(|) 是构建链的现代方式:

🔍 流程解析:
  • 提示模板(Prompt Template):接收变量(如 {adjective} 和 {topic}),生成完整的提示语
  • 模型(LLM):接收格式化后的提示,生成响应
  • 输出解析器(Output Parser):从模型返回的响应对象中提取纯文本内容
  • 结果:你最终得到一个干净的字符串,而非复杂的响应对象
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.output_parsers import StrOutputParser
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 定义组件
prompt = ChatPromptTemplate.from_template(
    "给我讲一个关于 {topic} 的 {adjective} 笑话"
)
model = ChatGoogleGenerativeAI(
    model="gemini-2.0-flash",
    google_api_key=os.getenv("GOOGLE_API_KEY")
)
output_parser = StrOutputParser()

# 使用管道操作符创建链
chain = prompt | model | output_parser

# 执行链
result = chain.invoke({
    "adjective": "搞笑的",
    "topic": "编程"
})

print(result)

💡 注意:管道操作符(|)会自动将前一个组件的输出作为下一个组件的输入。这种方式比旧版的 LLMChain 更直观、更符合现代编程习惯。

✨ 为何要使用 Chains?

  • 模块化:每个组件职责单一
  • 可复用:组件可在不同链中重复使用
  • 可读性强:数据流向一目了然
  • 灵活组合:轻松增删或替换组件

多步骤处理(Multi-Step Processing)

链可以包含多个处理步骤:

🔄 链式流程分解:

  1. idea_prompt | model:生成 5 个公司名称(文本形式)
  2. | list_parser:将文本解析为 Python 列表 ["Name1", "Name2", ...]
  3. | RunnableLambda:将列表转换为字典 {"names": "Name1, Name2, ..."}
  4. | evaluate_prompt:基于这些名称生成评估提示
  5. | model:由 LLM 给出评分与分析
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.output_parsers import CommaSeparatedListOutputParser
from langchain_core.runnables import RunnableLambda
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 步骤1:生成创意名称
idea_prompt = ChatPromptTemplate.from_template(
    "为一家 {product_type} 公司生成 5 个有创意的名称"
)

# 步骤2:评估名称
evaluate_prompt = ChatPromptTemplate.from_template(
    "请对以下公司名称的记忆度打分(1-10 分):{names}"
)

# 初始化模型
model = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    api_key=os.getenv("GOOGLE_API_KEY")  # 注意:新版参数名是 api_key,不是 google_api_key
)

# 输出解析器:将 LLM 输出解析为逗号分隔的列表
list_parser = CommaSeparatedListOutputParser()

# 构建多步骤链
chain = (
    idea_prompt
    | model
    | list_parser  # 输出: ["Name1", "Name2", ...]
    | RunnableLambda(lambda names: {"names": ", ".join(names)})  # 转为字典供 evaluate_prompt 使用
    | evaluate_prompt
    | model
)

# 执行链
result = chain.invoke({"product_type": "AI 软件"})

# 打印最终结果(result 是 AIMessage 对象)
print(result.content)
💡 关键概念:
  • 数据转换:RunnableLambda 允许你在链的步骤之间自定义数据转换逻辑
  • 解析器集成:输出解析器确保数据以正确格式传递到下一步
  • 顺序处理:每一步都依赖前一步的输出
  • 灵活设计:可轻松在流水线中添加、删除或修改步骤

🛠️ 专家建议:构建多步骤链时,先单独测试每个步骤。这样一旦出错,调试会容易得多!

用于复杂工作流的顺序链(Sequential Chains)

构建一个完整的内容创作流水线

我们来构建一个能生成、优化并格式化内容的完整内容创作流水线:

🔍 流水线说明:
  • 步骤1:根据主题、重点方向和受众生成初步文章
  • 步骤2:通过添加具体例子,让文章更具吸引力
  • 步骤3:并行生成元数据(标题、摘要、要点)与最终内容
  • RunnableParallel:同时执行多个操作,提升效率
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 初始化模型
model = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    temperature=0.7,
    api_key=os.getenv("GOOGLE_API_KEY")
)

# 链 1:生成初稿
generate_prompt = ChatPromptTemplate.from_template("""
撰写一篇关于 {topic} 的简短文章。
重点涵盖:{focus_areas}
目标读者:{audience}
""")

# 链 2:优化内容
improve_prompt = ChatPromptTemplate.from_template("""
请优化以下文章,使其更具吸引力,并加入具体示例:

{article}

请保持原有主题和目标读者不变。
""")

# 链 3:生成标题与摘要
metadata_prompt = ChatPromptTemplate.from_template("""
针对以下文章:
{article}

请生成:
1. 一个吸引人的标题
2. 一段两句话的摘要
3. 3 个关键要点

请以 JSON 格式输出。
""")

# 构建完整流水线
pipeline = (
    # 步骤 1:生成初稿
    RunnablePassthrough.assign(
        article=generate_prompt | model | (lambda x: x.content)
    )
    # 步骤 2:优化内容
    | RunnablePassthrough.assign(
        improved_article=lambda x: model.invoke(improve_prompt.format(article=x["article"]))
    )
    # 步骤 3:并行生成最终文章与元数据
    | RunnableParallel(
        final_article=lambda x: x["improved_article"].content,
        metadata=lambda x: model.invoke(metadata_prompt.format(article=x["improved_article"].content))
    )
)

# 执行流水线
result = pipeline.invoke({
    "topic": "远程办公的未来",
    "focus_areas": "生产力、工作生活平衡、技术工具",
    "audience": "考虑远程办公的专业人士"
})

print("文章内容:", result["final_article"])
print("\n元数据:", result["metadata"].content)
⚠️ 常见陷阱:

在链中使用 lambda 函数时,prompt.format() 返回的是字符串,不是可运行的 Runnable 对象。因此必须显式调用 model.invoke(),而不能使用 | 管道操作符。

✨ 此模式的优势:
  • 迭代优化:内容经过多轮改进
  • 并行处理:元数据生成不阻塞主内容流程
  • 关注点分离:每一步职责清晰
  • 易于扩展:可随时添加新处理步骤

实用链式模式

1. 转换链(Transformation Chain)

通过多个阶段将数据从一种格式转换为另一种。

🔄 理解转换链:

转换链将数据逐级处理,每一步输出作为下一步输入。这种模式特别适用于复杂工作流,其中每个阶段都建立在前一阶段的基础上。

  • 用户故事 → 技术规格:将高层需求转为详细技术文档
  • 技术规格 → 代码:基于规格生成实现代码
  • 优势:关注点分离、便于调试、组件可复用
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 初始化模型
model = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    api_key=os.getenv("GOOGLE_API_KEY")
)

# 用户故事 → 技术规格
user_story_to_spec = ChatPromptTemplate.from_template("""
将以下用户故事转换为技术规格说明:
{user_story}

请包含:API 端点、数据模型、验证规则。
""")

# 技术规格 → 代码
spec_to_code = ChatPromptTemplate.from_template("""
根据以下技术规格生成 Python Flask 代码:
{specifications}

请包含完善的错误处理和文档注释。
""")

# 构建转换链
transform_chain = (
    RunnablePassthrough.assign(
        specifications=user_story_to_spec | model | StrOutputParser()
    )
    | RunnablePassthrough.assign(
        code=lambda x: model.invoke(spec_to_code.format(specifications=x["specifications"]))
    )
)

# 执行
result = transform_chain.invoke({
    "user_story": "作为一名用户,我希望创建和管理带有截止日期的待办事项"
})

# 输出结果
print("原始用户故事:")
print(result["user_story"])
print("\n" + "="*50 + "\n")
print("技术规格:")
print(result["specifications"])
print("\n" + "="*50 + "\n")
print("生成的代码:")
print(result["code"].content)
💡 此示例展示了:
  • 渐进式细化:每阶段基于前一阶段输出
  • 清晰数据流:可明确追踪各阶段输入输出
  • 便于调试:可检查中间结果
  • 组件复用:每个提示模板可用于其他链

🛠️ 专家建议:构建转换链时,务必先单独测试每个阶段,确保输出格式符合下一阶段预期。

2. 验证链(Validation Chain)

生成内容后,验证其是否满足特定要求。

🔍 理解验证链:
  • 验证链将"生成"与"验证"分离,便于独立调试和修改。典型流程:
  • 根据需求生成初始内容
  • 将内容传给验证器
  • 获取是否符合标准的反馈
  • (可选)若验证失败则重新生成
python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.runnables import RunnableLambda
from langchain_core.output_parsers import StrOutputParser
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 初始化模型
model = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    api_key=os.getenv("GOOGLE_API_KEY")
)

# 生成邮件
generate_email = ChatPromptTemplate.from_template("""
撰写一封关于 {purpose} 的专业邮件。
语气:{tone}
关键点:{key_points}
""")

# 验证邮件
validate_email = ChatPromptTemplate.from_template("""
请审核以下邮件,检查是否满足:
1. 保持 {tone} 语气
2. 包含所有关键点:{key_points}
3. 字数不超过 150 字
4. 包含恰当的开头问候与结尾致意

邮件内容:
{email}

请回复:"APPROVED" 或 "NEEDS_REVISION: [原因]"
""")

# 构建生成链
def create_email_chain():
    return (
        generate_email 
        | model 
        | StrOutputParser()
        | RunnableLambda(lambda email: {"email": email})
    )

email_chain = create_email_chain()

# 参数
email_params = {
    "purpose": "安排项目评审会议",
    "tone": "友好但专业",
    "key_points": "下周四下午 2 点,A 会议室,请携带进度报告"
}

# 生成邮件
result = email_chain.invoke(email_params)

# 单独执行验证
validation_prompt = validate_email.format(
    email=result["email"],
    tone=email_params["tone"],
    key_points=email_params["key_points"]
)
validation_result = model.invoke(validation_prompt).content

print(f"邮件内容:\n{result['email']}")
print(f"\n验证结果: {validation_result}")
💡 预期输出:

验证结果应为 "APPROVED" 或 "NEEDS_REVISION: [原因]",取决于邮件是否满足所有标准(语气、关键点、长度、格式)。

📌 注意:此例展示基础验证模式。生产环境中,可加入自动重试逻辑,或使用更复杂的验证规则。

错误处理与调试

构建健壮的链式实现

为链添加完善的错误处理与调试能力:

🛡️ 核心理念:
  • 错误包装器:在每个步骤捕获并记录错误
  • 日志记录:追踪执行流程,识别性能瓶颈
  • 回调机制:监控中间输出以便调试
  • 优雅降级:返回有意义的错误信息,而非直接崩溃
python 复制代码
from langchain_core.callbacks import StdOutCallbackHandler
from langchain_core.runnables import RunnableLambda
from langchain_core.prompts import ChatPromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.output_parsers import StrOutputParser
import logging
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 初始化组件
model = ChatGoogleGenerativeAI(
    model="gemini-2.5-flash",
    api_key=os.getenv("GOOGLE_API_KEY")
)
generate_prompt = ChatPromptTemplate.from_template("写一篇关于 {topic} 的短文")
output_parser = StrOutputParser()

# 错误处理包装器
def safe_chain_step(func, step_name):
    def wrapper(*args, **kwargs):
        try:
            logger.info(f"正在执行: {step_name}")
            result = func(*args, **kwargs)
            logger.info(f"已完成: {step_name}")
            return result
        except Exception as e:
            logger.error(f"步骤 {step_name} 出错: {str(e)}")
            return f"错误发生在 {step_name}: {str(e)}"
    return wrapper

# 构建带错误处理的链
robust_chain = (
    RunnableLambda(safe_chain_step(
        lambda x: generate_prompt.format(**x),
        "格式化提示"
    ))
    | RunnableLambda(safe_chain_step(
        lambda x: model.invoke(x),
        "LLM 生成"
    ))
    | RunnableLambda(safe_chain_step(
        lambda x: output_parser.parse(x.content),
        "解析输出"
    ))
)

# 添加回调用于调试
callbacks = [StdOutCallbackHandler()]

# 执行链(带回调)
result = robust_chain.invoke(
    {"topic": "AI 安全"},
    config={"callbacks": callbacks}
)

print(f"\n最终结果:\n{result}")
✨ 此示例展示了:
  • 逐级日志:每个步骤记录执行状态
  • 错误隔离:错误被捕获并标注具体步骤
  • 回调集成:StdOutCallbackHandler 显示详细执行信息
  • 生产就绪:该模式可扩展至复杂链
🔍 调试技巧:
  • 使用回调查看中间输出
  • 在每个步骤添加日志
  • 先单独测试每个组件
  • 使用 try-except 实现优雅失败

🛠️ 专家建议:生产环境中,应将 print 替换为文件或监控服务的日志记录。推荐使用结构化日志(如 JSON 格式),便于后续分析。

✨ 链式开发最佳实践

设计原则

  • 保持链简洁且目标明确
  • 使用有意义的变量名
  • 为链添加用途和流程说明
  • 用多种输入进行测试

性能优化建议

  • 缓存重复的 LLM 调用
  • 对长输出启用流式响应(streaming)
  • 对独立步骤进行并行处理
  • 监控 Token 使用量

📚 快速参考:链的类型

类型 示例
简单链 `prompt
顺序链 `step1
并行链 RunnableParallel(a=chain1, b=chain2)
条件链 使用 RunnableLambda 配合 if/else 逻辑

🎉 下一步:为你的链添加记忆功能

干得漂亮!你已经掌握了 LangChain 链的核心------这是构建复杂 AI 工作流的基石。你现在能够创建顺序操作、组合多步骤,并搭建高级 AI 流水线。

准备好让你的链变得更智能了吗?在下一课中,你将学习 记忆(Memory)与上下文管理,从而构建能记住历史交互、维持对话状态的 AI 应用!

相关推荐
Volunteer Technology5 小时前
LangGraph的Agent的上下文
人工智能·后端·python·langchain
SunnyRivers6 小时前
LangChain 架构与环境搭建
架构·langchain·环境搭建·记忆
SunnyRivers8 小时前
提示模板与输出解析器
langchain·提示词模板·输出解析器
大模型真好玩21 小时前
大模型训练全流程实战指南工具篇(六)——OCR工具实战指南(以DeepSeek-OCR-2为例)
人工智能·langchain·deepseek
高可用架构1 天前
LangChain创始人:Agent 连接沙箱的两种模式(附深度架构解析)
架构·langchain
曦云沐1 天前
第四篇:LangChain 1.0 Community 生态全览:第三方集成与厂商包最佳实践
人工智能·langchain·大模型开发框架
无名修道院1 天前
AI大模型-LangChain
langchain·agent·ai大模型
梧桐1681 天前
基于 LangChain 的Text2SQL 智能体开发实践
人工智能·langchain·大模型·text2sql