004.链(Chains):构建可组合的工作流
原作者:怕浪猫
在实际开发中,大模型应用往往不是“单一提示→单一输出”的简单流程,而是需要多步骤联动(如“输入文本→翻译→总结→情感分析”)、多组件协同(提示模板+模型+解析器+工具)。
LangChain 的核心优势之一,就是提供了“链(Chains)”这一核心组件,将多个独立的模块(提示模板、模型、解析器、工具等)串联或组合起来,构建可复用、可扩展的自动化工作流。形象地说,Chain 就像“流水线”,将复杂的大模型任务拆解为多个简单步骤,每个步骤由一个组件负责,最终协同完成完整任务。
1. 什么是 Chain?链式思维的核心
Chain(链)是一个可组合的执行流程,它将多个“执行步骤”(如提示生成、模型调用、输出解析、数据处理)按一定逻辑串联起来,接收输入、依次执行每个步骤,最终输出结果。其核心价值在于“解耦与组合”——将复杂任务拆解为独立模块,再根据需求灵活组合,提升代码的可复用性和可维护性。
1.1. 链式思维的核心:拆解与组合
Chain 的本质是“链式思维”,核心逻辑分为两步:
- 拆解:将复杂任务拆解为多个独立的、简单的子任务(每个子任务可由一个组件完成,如提示生成、模型调用、解析);
- 组合:将子任务按逻辑顺序组合起来,形成一条完整的执行链,子任务之间自动传递数据(上一个步骤的输出作为下一个步骤的输入)。
举个通俗的例子:做一道“番茄炒蛋”,可拆解为“洗番茄→切番茄→打鸡蛋→炒鸡蛋→炒番茄→混合翻炒→出锅”7 个步骤,每个步骤对应一个“组件”,将这些步骤按顺序组合起来,就形成了一条“番茄炒蛋链”,执行这条链就能自动完成番茄炒蛋。
1.2. Chain 的核心组成与分类
LangChain 中的所有 Chain,都由以下两个核心部分组成:
- 步骤(Steps):每个步骤是一个独立的执行单元,可是 PromptTemplate、LLM/ChatModel、OutputParser、其他 Chain,甚至是外部工具(如数据库、API);
- 数据传递:自动将上一个步骤的输出,作为下一个步骤的输入,无需手动传递数据(可通过“输出键”控制传递的内容)。
根据执行逻辑和场景,LangChain 中的 Chain 主要分为以下 5 类(本章重点讲解前 5 类,实战部分综合运用):
LLMChain:最简单的链,仅包含“提示模板+模型”(可选输出解析),适合单一步骤的任务;SequentialChain:多步骤串行执行,上一个步骤的输出作为下一个步骤的输入,适合线性流程;TransformChain:专门用于数据预处理或后处理(如文本清洗、格式转换),不调用模型,仅处理数据;RouterChain:条件分支链,根据输入内容动态选择执行不同的子链,适合多场景、多规则的任务;LCEL:LangChain 表达式语言,一种简洁的语法,用于快速构建和组合链,替代传统的 Chain 类(LangChain v 0.1+推荐用法)。
2. LLMChain:最简单的调用链
LLMChain 是 LangChain 中最基础、最简单的链,核心作用是将“PromptTemplate(提示模板)”和“LLM/ChatModel(模型)”整合为一个可复用的单元,可选搭配 OutputParser(输出解析器),实现“提示生成→模型调用→输出解析”的一站式执行。
核心场景:单一步骤的任务(如文本生成、简单问答、格式转换),无需多步骤联动,适合作为复杂链的“子链”。
2.1. 基础用法:整合提示模板与模型
步骤:初始化 PromptTemplate、LLM/ChatModel,再用 LLMChain 整合,调用链即可自动完成提示生成和模型调用。
from langchain.chains import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 1. 初始化提示模板
prompt = PromptTemplate(
template="请为{product}撰写一句宣传语,突出{feature}优势,简洁有力(不超过15字)。",
input_variables=["product", "feature"]
)
# 2. 初始化模型
chat_model = ChatOpenAI(
model_name="gpt-3.5-turbo",
api_key=os.getenv("OPENAI_API_KEY"),
temperature=0.7
)
# 3. 构建LLMChain(整合提示模板和模型)
llm_chain = LLMChain(
llm=chat_model,
prompt=prompt,
verbose=True # 开启日志,查看链的执行过程(可选,便于调试)
)
# 4. 调用链(传入输入变量)
result = llm_chain.invoke({"product": "LangChain教程", "feature": "实战导向"})
print("宣传语:", result["text"])
运行结果:宣传语:LangChain实战教程,上手即会!
说明:调用 llm_chain.invoke()时,只需传入提示模板所需的变量,链会自动生成提示、调用模型,返回结果(默认存在"text"键中,对应模型的原始输出)。
2.2. 进阶用法:搭配 OutputParser 解析输出
在 LLMChain 中加入 OutputParser,可实现“提示→模型→解析”的一站式执行,无需手动调用解析器,示例如下(结合 PydanticOutputParser 实现强类型解析):
from langchain.chains import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
from pydantic import BaseModel, Field
load_dotenv()
# 1. 定义Pydantic模型(用于输出解析)
class AdCopy(BaseModel):
copy: str = Field(description="宣传语,不超过15字")
feature: str = Field(description="突出的产品优势")
# 2. 初始化解析器、提示模板、模型
parser = PydanticOutputParser(pydantic_object=AdCopy)
prompt = PromptTemplate(
template="为{product}撰写宣传语,突出{feature}优势(不超过15字),按要求输出:\n{format_instructions}",
input_variables=["product", "feature"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
chat_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.7)
# 3. 构建LLMChain(整合提示、模型、解析器)
llm_chain = LLMChain(
llm=chat_model,
prompt=prompt,
output_parser=parser,
verbose=True
)
# 4. 调用链,自动解析
result = llm_chain.invoke({"product": "LangChain教程", "feature": "通俗易懂"})
print("解析后的宣传语:", result.copy)
print("突出优势:", result.feature)
运行结果: 解析后的宣传语: 通俗易懂,LangChain 轻松学! 突出优势: 通俗易懂
说明:加入 output_parser 后,链的返回结果不再是字典,而是 Pydantic 模型实例,可直接通过“对象.字段”访问解析后的数据,更简洁、更安全。
2.3. 核心参数与实用技巧
- verbose:布尔值,默认 False,开启后会打印链的执行日志(提示内容、模型调用信息),便于调试;
- output_key:字符串,默认"text",用于指定模型输出在结果字典中的键名(若未使用解析器);
- 复用技巧:可将常用的 LLMChain 封装为函数,后续直接调用,比如封装一个“宣传语生成链”,适配不同产品;
- 注意事项:LLMChain 仅适用于单一步骤,若需要多步骤联动,需使用后续讲解的 SequentialChain 或 LCEL。
3. SequentialChain:多步骤串行处理
SequentialChain(顺序链)是最常用的复杂链之一,核心逻辑是“多步骤串行执行”——将多个 LLMChain(或其他 Chain)按顺序串联,上一个链的输出作为下一个链的输入,形成线性的执行流程,适合需要多步骤联动的任务(如“翻译→总结→情感分析”“关键词提取→文本生成→格式解析”)。
根据输入输出的传递方式,SequentialChain 分为两种:
- SimpleSequentialChain:最简单的顺序链,上一个链的输出直接作为下一个链的输入(仅支持单一输入、单一输出);
- SequentialChain:通用顺序链,支持多个输入、多个输出,可通过“输出键”控制数据传递(更灵活,推荐使用)。
3.1. SimpleSequentialChain(简单顺序链)
适用场景:多步骤联动,且每个步骤只有一个输入、一个输出,上一个步骤的输出直接作为下一个步骤的输入。
from langchain.chains import LLMChain, SimpleSequentialChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 步骤1:翻译链(英文→中文)
translate_prompt = PromptTemplate(
template="将以下英文文本翻译为中文,保持原意,简洁流畅:{text}",
input_variables=["text"]
)
translate_chain = LLMChain(llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")), prompt=translate_prompt)
# 步骤2:总结链(总结中文文本)
summary_prompt = PromptTemplate(
template="总结以下中文文本,不超过30字:{text}",
input_variables=["text"]
)
summary_chain = LLMChain(llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")), prompt=summary_prompt)
# 构建简单顺序链(串联两个步骤)
simple_sequential_chain = SimpleSequentialChain(
chains=[translate_chain, summary_chain],
verbose=True
)
# 调用链(仅传入初始输入text)
result = simple_sequential_chain.invoke("LangChain is a framework for building LLM applications.")
print("最终结果(总结):", result)
运行流程:
- 初始输入(英文)→ 翻译链 → 输出中文翻译;
- 翻译链的输出 → 总结链 → 输出总结结果; 运行结果:
最终结果(总结): LangChain是一个用于构建大语言模型应用的框架。
3.2. SequentialChain(通用顺序链)
适用场景:多步骤联动,且存在多个输入、多个输出,需要灵活控制数据传递(比如某个步骤的输入需要初始输入+上一个步骤的输出)。
from langchain.chains import LLMChain, SequentialChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 步骤1:翻译链(英文→中文)
translate_prompt = PromptTemplate(
template="将英文文本「{english_text}」翻译为中文,目标语言:{target_language}",
input_variables=["english_text", "target_language"]
)
translate_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=translate_prompt,
output_key="chinese_text" # 定义输出键,用于传递给下一个链
)
# 步骤2:总结链(总结中文文本,结合用户要求)
summary_prompt = PromptTemplate(
template="根据用户要求「{summary_requirement}」,总结中文文本「{chinese_text}」",
input_variables=["summary_requirement", "chinese_text"] # 输入:用户要求+上一个链的输出
)
summary_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=summary_prompt,
output_key="summary"
)
# 构建通用顺序链
sequential_chain = SequentialChain(
chains=[translate_chain, summary_chain],
input_variables=["english_text", "target_language", "summary_requirement"], # 初始输入
output_variables=["chinese_text", "summary"], # 最终输出(可返回中间结果)
verbose=True
)
# 调用链(传入所有初始输入)
result = sequential_chain.invoke({
"english_text": "LangChain provides tools for building complex LLM applications.",
"target_language": "中文",
"summary_requirement": "简洁明了,不超过20字"
})
print("中文翻译:", result["chinese_text"])
print("总结结果:", result["summary"])
3.3. 实战技巧与注意事项
- 步骤拆解原则:每个步骤尽量单一、独立,比如“翻译”“总结”“解析”分开,便于修改和复用;
- 输出键命名规范:输出键(output_key)尽量清晰(如"chinese_text"、"summary"),避免重名,便于后续调用;
- 中间结果复用:若后续步骤需要使用某个中间结果(如翻译后的文本),可将其加入output_variables,便于获取;
- 异常处理:可在每个链中加入异常捕获逻辑,避免一个步骤失败导致整个链崩溃。
4. TransformChain:数据预处理与后处理
前面讲解的 LLMChain、SequentialChain,核心是“调用模型”,而实际开发中,我们常常需要对数据进行预处理(如文本清洗、格式转换、关键词提取)或后处理(如结果格式化、数据过滤),这些操作无需调用模型,仅需处理数据。
LangChain 的 TransformChain(转换链)专门用于这类场景——它不调用任何模型,仅接收输入数据,通过自定义函数对数据进行转换,输出处理后的数据,常作为 SequentialChain 的“前置步骤”(预处理)或“后置步骤”(后处理)。
4.1. 核心用法:自定义数据转换函数
TransformChain 的核心是“自定义转换函数”——只需定义一个接收输入字典、返回输出字典的函数,即可构建转换链,示例如下(文本预处理:去除多余空格、换行,统一大小写):
from langchain.chains import TransformChain, SequentialChain, LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 1. 定义数据预处理函数(TransformChain的核心)
def text_preprocess(inputs: dict) -> dict:
"""文本预处理:去除多余空格、换行,统一为小写"""
text = inputs["raw_text"]
# 处理逻辑
processed_text = text.strip().replace("\n", " ").replace(" ", " ").lower()
return {"processed_text": processed_text}
# 2. 构建TransformChain(预处理链)
preprocess_chain = TransformChain(
input_variables=["raw_text"], # 输入键
output_variables=["processed_text"], # 输出键
transform=text_preprocess # 自定义转换函数
)
# 3. 构建LLMChain(文本总结)
summary_prompt = PromptTemplate(
template="总结以下文本:{processed_text}",
input_variables=["processed_text"]
)
summary_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=summary_prompt,
output_key="summary"
)
# 4. 串联预处理链和总结链
sequential_chain = SequentialChain(
chains=[preprocess_chain, summary_chain],
input_variables=["raw_text"],
output_variables=["processed_text", "summary"],
verbose=True
)
# 测试:原始文本(含多余空格、换行、大写)
raw_text = """
LangChain IS a framework for building LLM applications.
It provides tools for prompt engineering, output parsing, and chains.
"""
result = sequential_chain.invoke({"raw_text": raw_text})
print("原始文本:", raw_text)
print("预处理后:", result["processed_text"])
print("总结结果:", result["summary"])
运行结果: 预处理后: langchain is a framework for building llm applications. it provides tools for prompt engineering, output parsing, and chains. 总结结果: LangChain 是一个用于构建大语言模型应用的框架,提供提示工程、输出解析和链等工具。
6.4.2 进阶用法:后处理与数据过滤
TransformChain 也可作为后处理步骤,对模型输出的结果进行过滤、格式化,示例如下(过滤总结结果中的冗余词汇,调整格式):
from langchain.chains import TransformChain, SequentialChain, LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 步骤1:总结链(生成总结)
summary_prompt = PromptTemplate(
template="总结以下文本:{text}",
input_variables=["text"]
)
summary_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=summary_prompt,
output_key="raw_summary"
)
# 步骤2:后处理链(过滤冗余词汇、调整格式)
def summary_postprocess(inputs: dict) -> dict:
"""后处理:去除冗余词汇(如“总的来说”“综上所述”),首字母大写"""
raw_summary = inputs["raw_summary"]
redundant_words = ["总的来说", "综上所述", "总而言之"]
for word in redundant_words:
raw_summary = raw_summary.replace(word, "")
# 首字母大写,句末加句号
processed_summary = raw_summary.strip().capitalize() + "."
return {"processed_summary": processed_summary}
postprocess_chain = TransformChain(
input_variables=["raw_summary"],
output_variables=["processed_summary"],
transform=summary_postprocess
)
# 串联链
sequential_chain = SequentialChain(
chains=[summary_chain, postprocess_chain],
input_variables=["text"],
output_variables=["raw_summary", "processed_summary"],
verbose=True
)
# 测试
text = "LangChain是一个用于构建大语言模型应用的框架,支持提示模板、输出解析、链式调用等功能,能帮助开发者快速构建复杂的LLM应用。"
result = sequential_chain.invoke({"text": text})
print("原始总结:", result["raw_summary"])
print("后处理后:", result["processed_summary"])
运行结果: 原始总结: 总的来说,LangChain 是一个支持提示模板、输出解析等功能,能帮助开发者快速构建复杂 LLM 应用的框架。 后处理后: LangChain 是一个支持提示模板、输出解析等功能,能帮助开发者快速构建复杂 llm 应用的框架.
4.3. 实战场景与选型建议
- 常见预处理场景:文本清洗(去空格、去换行、去特殊字符)、格式转换(JSON→字符串、字符串→列表)、关键词提取、文本分割;
- 常见后处理场景:结果过滤(去除冗余内容)、格式美化(调整大小写、加标点)、数据校验(检查结果是否符合要求);
- 选型建议:只要涉及“无需调用模型的数据处理”,都建议使用 TransformChain,将数据处理与模型调用解耦,提升代码可维护性;
- 技巧:可将常用的数据处理函数封装为通用函数,搭配 TransformChain 复用,比如“文本清洗链”“格式转换链”。
5. RouterChain:条件分支与动态路由
前面讲解的 SequentialChain 是“线性执行”——无论输入是什么,都按固定顺序执行所有步骤。但在实际场景中,我们常常需要根据输入内容的不同,动态选择执行不同的子链,比如:
- 用户输入是“翻译需求”,执行翻译链;
- 用户输入是“总结需求”,执行总结链;
- 用户输入是“情感分析需求”,执行情感分析链。
LangChain 的 RouterChain(路由链)就是为解决这类场景而生——它能根据输入内容,动态判断“应该执行哪个子链”,实现条件分支的自动化执行,就像“路由器”一样,根据输入的“地址”(内容),将请求转发到对应的“子链”。
5.1. 核心组成
RouterChain 的核心由两部分组成,缺一不可:
- RouterChain(路由链):负责分析输入内容,判断应该执行哪个子链,返回子链的“路由键”;
- DestinationChains(目标子链):多个子链的集合,每个子链对应一个“路由键”,路由链根据路由键选择对应的子链执行。
LangChain 提供了两种常用的 RouterChain:
LLMRouterChain:通过模型分析输入内容,判断路由方向(最常用,灵活度高);MultiPromptChain:简化版的路由链,直接根据输入匹配对应的提示模板和子链(适合简单场景)。
5.2. 实战示例:LLMRouterChain 动态路由
场景:根据用户输入的需求类型,动态选择执行“翻译链”“总结链”“情感分析链”,示例如下:
from langchain.chains import LLMChain, LLMRouterChain, MultiPromptChain
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.runnables import RunnableMap
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 1. 定义目标子链(翻译、总结、情感分析)
# 子链1:翻译链
translate_prompt = PromptTemplate(
template="将以下文本翻译为{target_language}:{text}",
input_variables=["text", "target_language"]
)
translate_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=translate_prompt,
output_key="result"
)
# 子链2:总结链
summary_prompt = PromptTemplate(
template="总结以下文本,不超过30字:{text}",
input_variables=["text"]
)
summary_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=summary_prompt,
output_key="result"
)
# 子链3:情感分析链
sentiment_prompt = PromptTemplate(
template="分析以下文本的情感倾向(正面/负面/中性),并简要说明原因:{text}",
input_variables=["text"]
)
sentiment_chain = LLMChain(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=sentiment_prompt,
output_key="result"
)
# 2. 定义目标子链映射(路由键→子链)
destination_chains = {
"translate": translate_chain,
"summary": summary_chain,
"sentiment": sentiment_chain
}
# 3. 定义路由提示(让模型判断输入属于哪种需求,返回对应的路由键)
router_prompt = ChatPromptTemplate.from_template("""
请分析用户输入的需求类型,只能返回以下路由键中的一个,无需其他任何内容:
- translate:翻译需求(需要将文本翻译成其他语言)
- summary:总结需求(需要总结文本内容)
- sentiment:情感分析需求(需要分析文本情感倾向)
用户输入:{text}
""")
# 4. 构建路由链(LLMRouterChain)
router_chain = LLMRouterChain.from_llm(
llm=ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY")),
prompt=router_prompt,
destination_chains=destination_chains,
verbose=True
)
# 5. 测试不同需求
# 测试1:翻译需求
print("=== 翻译需求 ===")
result1 = router_chain.invoke({"text": "将“LangChain is great”翻译为中文", "target_language": "中文"})
print("结果:", result1["result"])
# 测试2:总结需求
print("\n=== 总结需求 ===")
result2 = router_chain.invoke({"text": "LangChain是一个用于构建大语言模型应用的框架,支持提示模板、输出解析、链式调用等功能。"})
print("结果:", result2["result"])
# 测试3:情感分析需求
print("\n=== 情感分析需求 ===")
result3 = router_chain.invoke({"text": "LangChain使用起来非常方便,极大提升了我的开发效率。"})
print("结果:", result3["result"])
说明:MultiPromptChain 会根据输入内容,匹配最贴合的提示模板(通过 description 判断),自动调用对应的子链执行,简化了路由链的配置。
5.4. 实战建议
- 路由提示要清晰:定义路由提示时,必须明确告知模型“只能返回指定的路由键”,避免模型返回多余内容,导致路由失败;
- 子链职责单一:每个目标子链只负责一个具体任务,便于维护和扩展(如后续新增“关键词提取”需求,只需新增子链和路由键);
- 场景适配:简单场景用 MultiPromptChain,复杂场景(多输入、多子链、复杂判断)用 LLMRouterChain;
- 异常处理:可添加“默认子链”,当路由链无法判断需求类型时,执行默认子链(如提示用户“请明确需求类型”)。
6. 使用 LCEL(LangChain Expression Language)重写链
在 LangChain v 0.1 版本之后,官方推荐使用LCEL(LangChain Expression Language,LangChain 表达式语言)来构建和组合链,替代传统的 Chain 类(如 LLMChain、SequentialChain)。LCEL 是一种简洁、灵活的语法,核心优势是“声明式编程”——只需描述“输入→处理步骤→输出”的逻辑,无需手动构建 Chain 类,代码更简洁、更易读、更易扩展。
简单来说,LCEL 用“|”(管道符)将多个组件(提示模板、模型、解析器、转换函数等)串联起来,形成一条完整的链,本质上是对传统 Chain 的简化和优化。
6.1. LCEL 核心语法与优势
1. 核心语法
LCEL 的核心语法是“管道符(|)”,用于串联组件,格式如下:
# 基础格式:输入 → 组件1 → 组件2 → ... → 输出
chain = component1 | component2 | component3
支持的组件类型:PromptTemplate、LLM/ChatModel、OutputParser、TransformChain、自定义函数、其他链,甚至是 Runnable(LangChain 的核心可运行单元)。
2. 核心优势
- 简洁高效:无需手动构建 LLMChain、SequentialChain,用管道符串联即可,代码量大幅减少;
- 灵活组合:可自由组合任意组件,支持动态调整步骤,比传统 Chain 更灵活;
- 原生支持异步:无需额外配置,即可实现异步调用(async invoke),提升性能;
- 官方推荐:LangChain v 0.1+之后,官方文档优先使用 LCEL,传统 Chain 类逐渐被替代。
6.2. 实战示例 1:用 LCEL 重写 LLMChain
传统 LLMChain 的功能(提示模板+模型+解析器),用 LCEL 可简化为一行代码,示例如下:
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
from pydantic import BaseModel, Field
load_dotenv()
# 1. 定义Pydantic模型、解析器、提示模板、模型
class AdCopy(BaseModel):
copy: str = Field(description="宣传语,不超过15字")
feature: str = Field(description="突出的产品优势")
parser = PydanticOutputParser(pydantic_object=AdCopy)
prompt = PromptTemplate(
template="为{product}撰写宣传语,突出{feature}优势(不超过15字),按要求输出:\n{format_instructions}",
input_variables=["product", "feature"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
chat_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.7)
# 2. 用LCEL构建链(管道符串联)
chain = prompt | chat_model | parser
# 3. 调用链
result = chain.invoke({"product": "LangChain教程", "feature": "实战导向"})
print("宣传语:", result.copy)
print("突出优势:", result.feature)
对比传统 LLMChain:无需手动构建 LLMChain 类,用“prompt | chat_model | parser”即可实现相同功能,代码更简洁,逻辑更清晰。
6.3. 实战示例 2:用 LCEL 重写 SequentialChain(多步骤串联)
传统 SequentialChain 的多步骤串联,用 LCEL 可直接用管道符串联多个组件,示例如下(翻译→总结→情感分析):
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 1. 定义各个步骤的组件
# 步骤1:翻译提示+模型
translate_prompt = PromptTemplate(
template="将以下英文翻译为中文:{text}",
input_variables=["text"]
)
translate_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.5)
translate_chain = translate_prompt | translate_model
# 步骤2:总结提示+模型
summary_prompt = PromptTemplate(
template="总结以下中文文本,不超过30字:{text}",
input_variables=["text"]
)
summary_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.5)
summary_chain = summary_prompt | summary_model
# 步骤3:情感分析提示+模型
sentiment_prompt = PromptTemplate(
template="分析以下文本的情感倾向(正面/负面/中性):{text}",
input_variables=["text"]
)
sentiment_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.5)
sentiment_chain = sentiment_prompt | sentiment_model
# 2. 用LCEL串联多步骤(翻译→总结→情感分析)
# 注意:需要用lambda函数传递上一步的输出作为下一步的输入
full_chain = (
translate_chain
| lambda x: {"text": x.content} # 提取翻译结果,作为总结的输入
| summary_chain
| lambda x: {"text": x.content} # 提取总结结果,作为情感分析的输入
| sentiment_chain
)
# 3. 调用链
result = full_chain.invoke({"text": "LangChain is a powerful framework that makes LLM development easier."})
print("最终情感分析结果:", result.content)
说明:用 lambda 函数提取上一步的输出(x.content,模型输出的内容),并转换为下一步所需的输入格式,实现多步骤的数据传递,比传统 SequentialChain 更灵活。
6.4. 实战示例 3:LCEL 结合 TransformChain(数据预处理)
LCEL 可直接串联 TransformChain(或自定义转换函数),实现“预处理→模型调用→解析”的一站式流程,示例如下:
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
from pydantic import BaseModel, Field
load_dotenv()
# 1. 定义数据预处理函数(替代TransformChain)
def text_preprocess(inputs: dict) -> dict:
text = inputs["raw_text"]
processed_text = text.strip().replace("\n", " ").lower()
return {"text": processed_text}
# 2. 定义解析器、提示模板、模型
class SummaryResult(BaseModel):
summary: str = Field(description="文本总结,不超过30字")
parser = PydanticOutputParser(pydantic_object=SummaryResult)
prompt = PromptTemplate(
template="总结以下文本:{text}\n{format_instructions}",
input_variables=["text"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
chat_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.5)
# 3. 用LCEL串联(预处理→提示→模型→解析)
chain = text_preprocess | prompt | chat_model | parser
# 4. 调用链
raw_text = """
LangChain IS a framework for building LLM applications.
It provides tools for prompt engineering and output parsing.
"""
result = chain.invoke({"raw_text": raw_text})
print("预处理后文本:", text_preprocess({"raw_text": raw_text})["text"])
print("总结结果:", result.summary)
说明:LCEL 可直接串联自定义转换函数(如 text_preprocess),无需手动构建 TransformChain,进一步简化代码。
6.5. LCEL 核心技巧与注意事项
- 数据传递技巧:当多个步骤的输入输出键不一致时,用 lambda 函数转换(如 lambda x: {"text": x.content}),确保数据传递正确;
- 组件复用:可将常用的组件组合(如“提示+模型”)封装为一个变量,后续直接复用,提升代码可维护性;
- 异步调用:LCEL 原生支持异步,用 await chain.ainvoke() 替代 chain.invoke(),提升并发性能;
- 兼容性:LCEL 与传统 Chain 类完全兼容,可将传统 Chain 作为组件,用管道符串联;
- 推荐场景:新开发的 LangChain 应用,优先使用 LCEL;旧应用可逐步迁移到 LCEL,提升代码简洁度。
7. 链的嵌套与复用技巧
在实际开发中,复杂的大模型应用往往需要多个链的协同工作——将一个链作为另一个链的“子链”(嵌套),或复用已有的链(避免重复开发),这是提升开发效率、降低代码冗余的关键技巧。
本节将讲解链的嵌套用法和复用技巧,结合前面所学的 Chain 类和 LCEL,实现更灵活、更可维护的链式工作流。
7.1. 链的嵌套:将链作为子链
链的嵌套核心:将一个完整的链(如 LLMChain、LCEL 链)作为另一个链(如 SequentialChain、RouterChain)的步骤,实现“链中链”的结构,适配复杂任务。
示例:构建“预处理→翻译→总结”三步链,其中“翻译→总结”是一个独立的子链,嵌套到完整链中:
from langchain.chains import SequentialChain, LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
# 1. 定义子链:翻译→总结(用LCEL简化)
translate_prompt = PromptTemplate(
template="将英文「{text}」翻译为中文:",
input_variables=["text"]
)
summary_prompt = PromptTemplate(
template="总结中文文本「{text}」,不超过30字:",
input_variables=["text"]
)
chat_model = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), temperature=0.5)
# 子链(LCEL构建)
translate_summary_chain = (
translate_prompt
| chat_model
| lambda x: {"text": x.content}
| summary_prompt
| chat_model
)
# 2. 定义预处理链(TransformChain)
def text_preprocess(inputs: dict) -> dict:
text = inputs["raw_text"]
processed_text = text.strip().replace("\n", " ")
return {"text": processed_text}
from langchain.chains import TransformChain
preprocess_chain = TransformChain(
input_variables=["raw_text"],
output_variables=["text"],
transform=text_preprocess
)
# 3. 嵌套子链:预处理链 + 翻译总结子链
full_chain = SequentialChain(
chains=[preprocess_chain, translate_summary_chain],
input_variables=["raw_text"],
output_variables=["text"], # 子链的输出
verbose=True
)
# 测试
raw_text = """
LangChain provides a set of tools for building complex LLM applications,
including prompt templates, output parsers, and chains.
"""
result = full_chain.invoke({"raw_text": raw_text})
print("最终总结结果:", result["text"])