LangChain最详细教程之Chains
目录
简介
一、Chains的基本使用
1 、Chain的基本概念
2 、LCEL 及其基本构成
3 、Runnable
二、传统Chain的使用
1、 基础链:LLMChain
2 、顺序链之 SimpleSequentialChain
3、 顺序链之 SequentialChain
4、其他链
三、基于LCEL构建的Chains的类型
1 create_sql_query_chain
2 create_stuff_documents_chain
简介
本系列教程将以「系统梳理 + 实战落地」为核心,从基础到进阶全面拆解 LangChain—— 这个目前最流行的大语言模型(LLM)应用开发框架。之前对langchain进行了系统的概述,现在我们就来详细看看每一个板块。
LangChain最详细教程之Model I/O(一)调用模型
LangChain最详细教程之Model I/O(二)Prompt Template
LangChain最详细教程之Model I/O(三)Output Parsers
一、Chains的基本使用
1 、Chain的基本概念
- 将 LLM 与 Prompt Template (提示模板)结合
- 将 LLM 与 输出解析器 结合
- 将 LLM 与 外部数据 结合,例如用于问答
- 将 LLM 与 长期记忆 结合,例如用于聊天历史记录
- 通过将 第一个LLM 的输出作为 第二个LLM 的输入,...,将多个LLM按顺序结合在一起
2 、LCEL 及其基本构成
# 在这个链条中,用户输入被传递给提示模板,然后提示模板的输出被传递给模型,然后模型的输出被传
递给输出解析器。
chain = prompt | model | output_parser
chain.invoke({"input":"What's your name?"})
- Prompt:Prompt 是一个 BasePromptTemplate,这意味着它接受一个模板变量的字典并生成一个 PromptValue 。PromptValue 可以传递给 LLM(它以字符串作为输入)或 ChatModel(它以消息序列作为输入)。
- Model:将 PromptValue 传递给 model。如果我们的 model 是一个 ChatModel,这意味着它 将输出一个 BaseMessage 。
- OutputParser:将 model 的输出传递给 output_parser,它是一个 BaseOutputParser,意味着它可以接受字符串或 BaseMessage 作为输入。
- chain:我们可以使用 | 运算符轻松创建这个Chain。 | 运算符在 LangChain 中用于将两个元素组合在一起。
- invoke:所有LCEL对象都实现了 Runnable 协议,保证一致的调用方式( invoke / batch / stream )
3 、Runnable
class Runnable(Protocol):
def invoke(self, input: Any) -> Any: ... # 单输入单输出
def batch(self, inputs: List[Any]) -> List[Any]: ... # 批量处理
def stream(self, input: Any) -> Iterator[Any]: ... # 流式输出
# 还有其他方法如 ainvoke(异步)等
- 提示词渲染用 .format()
- 模型调用用 .generate()
- 解析器解析用 .parse()
- 工具调用用 .run()
prompt_text = prompt.format(topic="猫") # 方法1
model_out = model.generate(prompt_text) # 方法2
result = parser.parse(model_out) # 方法3
#(分步调用)
prompt_text = prompt.invoke({"topic": "猫"}) # 方法1
model_out = model.invoke(prompt_text) # 方法2
result = parser.invoke(model_out) # 方法3
#(LCEL管道式)
chain = prompt | model | parser # 用管道符组合
result = chain.invoke({"topic": "猫"}) # 所有组件统一用invoke - 一致性:无论组件的功能多复杂(模型/提示词/工具),调用方式完全相同
- 组合性:管道操作符 | 背后自动处理类型匹配和中间结果传递
二、传统Chain的使用
1、 基础链:LLMChain
- 用于 单次问答,输入一个 Prompt,输出 LLM 的响应。
- 适合 无上下文 的简单任务(如翻译、摘要、分类等)。
- 无记忆:无法自动维护聊天历史
主要步骤
chain = LLMChain(llm = llm, prompt = prompt_template)
result = chain.invoke(...)
print(result)
| 参数名 | 类型 | 默认值 | 必要 | 说明 |
|---|---|---|---|---|
| llm | Union[RunnableLanguageModel, str, Awaitable] | - | 是 | 要调用的语言模型 |
| prompt | BasePromptTemplate | - | 是 | 要使用的提示对象 |
| verbose | bool | False | 否 | 显示详细调试信息。在聊天模式下,默认 会使用颜色编码,而在 langchain.global.set_verbose () 设置为 T rue 时,一些中间步骤将被列出来 |
| callback_manager | Optional[BaseCallbackManager] | None | 否 | 【已弃用】请改用 callbacks。可选的回调管理器或回调管理器列表,用于处理运行时 的回调。如果未指定,将使用全局默认值 |
| callbacks | Callbacks | None | 否 | 可选的回调列表或回调管理器,用于处理 运行时的回调。如果未指定,将使用全局 默认值。另见 on_chain_start/on_chain_end/on_chain_error 方法,自定义回调逻辑 |
| llm_kwargs | dict | - | 否 | 语言模型的关键字参数字典 |
| memory | Optional[BaseMemory] | None | 否 | 可选的记忆对象。默认为 None。记忆是 一个在会话开始时初始化的键值存储,存 储输入、输出和其他变量在上下文中。有 许多不同类型的内存,请查看有关默认记 忆的部分 |
| metadata | Optional[Dict[str, Any]] | None | 否 | 与链相关的可选元数据,默认为 None。这些元数据将与调用链的每次 log 相关联,并作为参数传递给 AwaitableCallbackHandler 的方法,例如在返回的 Generation 对象中附加元数据 |
| output_parser | BaseLLMOutputParser | - | 否 | LLM 输出解析器。默认为 StrOutputParser |
| return_final_only | bool | True | 否 | 是否只返回最终结果。默认为 True。如果 为 False,则返回包含生成信息的对象 |
| tags | Optional[List[str]] | None | 否 | 与链相关的可选标签列表。默认为 None。这些标签将与调用链的每次 log 相关联,并 作为参数传递给 AwaitableCallbackHandler 的方法,例如在返回的 Generation 对象中附加标签 |
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate, ChatPromptTemplateimport os
import dotenv
from langchain_openai import ChatOpenAIdotenv.load_dotenv()os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")# 1、创建大模型实例
chat_model = ChatOpenAI(model="gpt-4o-mini")# 2、提供提示词模板
# BasePromptTemplate的典型子类有:PrompTemplate、ChatPromptTemplate
prompt_template = ChatPromptTemplate.from_messages([("system", "你是一个数学高手"),("human", "帮我解决如下的数学问题:{question}")])chain = LLMChain(llm=chat_model,prompt=prompt_template,verbose=True, #显式执行过程中的详细日志情况
)
response = chain.invoke(input={"question": "1 + 2 * 3 = ?"})
print(response)
2 、顺序链之 SimpleSequentialChain
- 单个输入/输出:对应着 SimpleSequentialChain
- 多个输入/输出:对应着:SequentialChain

# 1.导入相关包
from langchain.chains import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain.chains import SimpleSequentialChain# 2.创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini")# 3.定义一个给剧名写大纲的LLMChain
template1 = """你是个剧作家。给定剧本的标题,你的工作就是为这个标题写一个大纲。
Title: {title}
"""
prompt_template1 = PromptTemplate(input_variables=["title"], template=template1)
synopsis_chain = LLMChain(llm=llm, prompt=prompt_template1)# 4.定义给一个剧本大纲写一篇评论的LLMChain
template2 = """你是《纽约时报》的剧评家。有了剧本的大纲,你的工作就是为剧本写一篇评论
剧情大纲:
{synopsis}
"""
prompt_template2 = PromptTemplate(input_variables=["synopsis"], template=template2)
review_chain = LLMChain(llm=llm, prompt=prompt_template2)# 5.定义一个完整的链按顺序运行这两条链
#(verbose=True:打印链的执行过程)
overall_chain = SimpleSequentialChain(chains=[synopsis_chain, review_chain],verbose=True
)
# 6.调用完整链顺序执行这两个链
review = overall_chain.invoke({"input":"日落海滩上的悲剧"})# 7.打印结果
print(review)
3、 顺序链之 SequentialChain
- 多变量支持 :允许不同子链有独立的输入/输出变量。
- 灵活映射 :需 显式定义 变量如何从一个链传递到下一个链。即精准地命名输入关键字和输出关键字,来明确链之间的关系。
- 复杂流程控制 :支持分支、条件逻辑(分别通过 input_variables 和 output_variables 配置输入和输出)。

from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import SequentialChain
from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain
from openai import OpenAI
import os# 创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini")schainA_template = ChatPromptTemplate.from_messages([("system", "你是一位精通各领域知识的知名教授"),("human", "请你先尽可能详细的解释一下:{knowledge},并且{action}")]
)schainA_chains = LLMChain(llm=llm,prompt=schainA_template,verbose=True,output_key="schainA_chains_key")# schainA_chains.invoke({
# "knowledge": "中国的篮球怎么样?",
# "action": "举一个实际的例子"
# }
# )schainB_template = ChatPromptTemplate.from_messages([("system", "你非常善于提取文本中的重要信息,并做出简短的总结"),("human", "这是针对一个提问完整的解释说明内容:{schainA_chains_key}"),("human", "请你根据上述说明,尽可能简短的输出重要的结论,请控制在100个字以内"),]
)schainB_chains = LLMChain(llm=llm,prompt=schainB_template,verbose=True,output_key='schainB_chains_key')# 一定要声明出两个变量:input_variables、output_variables
Seq_chain = SequentialChain(chains=[schainA_chains, schainB_chains],input_variables=["knowledge", "action"],output_variables=["schainA_chains_key","schainB_chains_key"],verbose=True)response = Seq_chain.invoke({"knowledge":"中国足球为什么踢得烂","action":"举一个实际的例子"})print(response)
4、其他链
- 数学链 LLMMathChain LLMMathChain将用户问题转换为数学问题,然后将数学问题转换为可以使用 Python 的 numexpr 库执行的表达式。使用运行此代码的输出来回答问题。
- 路由链 RouterChain 路由链(RouterChain)用于创建可以 动态选择下一条链 的链。可以自动分析用户的需求,然后引导到最适合的链中执行,获取响应并返回最终结果。比如,我们目前有三类chain,分别对应三种学科的问题解答。我们的输入内容也是与这三种学科对应,但是随机的,比如第一次输入数学问题、第二次有可能是历史问题... 这时候期待的效果是:可以根据输入的内容是什么,自动将其应用到对应的子链中。RouterChain就为我们提供了这样一种能力。
- 文档链 StuffDocumentsChain(了解) StuffDocumentsChain 是一种文档处理链,它的核心作用是将 多个文档内容合并 (“填充”或“塞入”)到单个提示(prompt)中,然后传递给语言模型(LLM)进行处理。 使用场景 :由于所有文档被完整拼接,LLM 能同时看到全部内容,所以适合需要全局理解的任务,如总结、问答、对比分析等。但注意,仅适合处理 少量/中等长度文档 的场景。
三、基于LCEL构建的Chains的类型
create_sql_query_chain
create_stuff_documents_chain
create_openai_fn_runnable
create_structured_output_runnable
load_query_constructor_runnable
create_history_aware_retriever
create_retrieval_chain
1 create_sql_query_chain
# pip install -U langchain langchain-community langchain-openai
from langchain_openai import ChatOpenAI
from langchain.chains import create_sql_query_chain
from langchain_community.utilities import SQLDatabase# 测试连接本地的mysql数据库
db_user = "root"
db_password = "abc123"
db_host = "localhost" #或 127.0.0.1
db_port = "3306"
db_database = "atguigudb"
# mysql+pymysql://用户名:密码@ip地址:端口号/数据库名
db = SQLDatabase.from_uri(f"mysql+pymysql://{db_user}:{db_password}@{db_host}:{db_port}/{db_database}")print("操作的是哪种数据库:",db.dialect)
print("获取数据库中的表:",db.get_usable_table_names())#执行查询操作
res = db.run("SELECT COUNT(*) FROM employees")
print(res)
2 create_stuff_documents_chain
- 保持上下文完整,适合需要全局理解所有文档内容的任务(如总结、问答)
- 适合处理 少量/中等长度文档 的场景
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.documents import Document# 定义提示词模板
prompt = PromptTemplate.from_template("""
基于文档{docs}中说的情况,香蕉是什么颜色的?
""")# 创建链
llm = ChatOpenAI(model="gpt-4o-mini")
chain = create_stuff_documents_chain(llm, prompt, document_variable_name="docs")# 文档输入
docs123 = [Document(page_content="苹果,学名Malus pumila Mill.,别称西洋苹果、柰,属于蔷薇科苹果属的植物。苹果是全球最广泛种植和销售的水果之一,具有悠久的栽培历史和广泛的分布范围。苹果的原始种群主要起源于中亚的天山山脉附近,尤其是现代哈萨克斯坦的阿拉木图地区,提供了所有现代苹果品种的基因库。苹果通过早期的贸易路线,如丝绸之路,从中亚向外扩散到全球各地。"),Document(page_content="香蕉是白色的水果,主要产自热带地区。"),Document(page_content="蓝莓是蓝色的浆果,含有抗氧化物质。")
]
# 执行摘要
chain.invoke({"docs": docs123})
