LangChain使用之Chains
1、Chains的基本使用
1.1 Chain的基本概念
- Chain:链,用于将多个组件(提示模板、LLM模型、记忆、工具等)连接起来,形成可复用的
工作流,完成复杂的任务。 Chain的核心思想是通过组合不同的模块化单元,实现比单一组件更强大的功能。比如:- 将
LLM与Prompt Template(提示模板)结合 - 将
LLM与输出解析器结合 - 将
LLM与外部数据结合,例如用于问答 - 将
LLM与长期记忆结合,例如用于聊天历史记录 - 通过将
第一个LLM的输出作为第二个LLM的输入,…将多个LLM按顺序结合在一起
- 将
1.2 LCEL及其基本构成
使用LCEL,可以构造出结构最简单的Chain。
LangChain表达式语言(LCEL,LangChain Expression Language)是一种声明式方法,可以轻松地将多个组件链接成AI工作流。它通过Python原生操作符(如管道符 | )将组件连接成可执行流程,显著简化了AI应用的开发。
LCEL的基本构成:提示(Prompt) + 模型(Model) + 输出解析器(OutputParser)
1
2
3# 在这个链条中,用户输入被传递给提示模板,然后提示模板的输出被传递给模型,然后模型的输出被传递给输出解析器。
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)
| 符号类似于 shell 里面管道操作符,它将不同的组件链接在一起,将前一个组件的输出作为下一个组件的输入,这就形成了一个 AI 工作流。
- Prompt:Prompt是一个 BasePromptTemplate,这意味着它接受一个模板变量的字典并生成一个
1.3 Runnable
Runnable是LangChain定义的一个抽象接口(Protocol),它强制要求所有LCEL组件实现一组标准方法:
1
2
3
4
5class Runnable(Protocol):
def invoke(self, input: Any) -> Any: ... # 单输入单输出
def batch(self, inputs: List[Any]) -> List[Any]: ... # 批量处理
def stream(self, input: Any) -> Iterator[Any]: ... # 流式输出
# 还有其他方法如 ainvoke(异步)等...- 任何实现了这些方法的对象都被视为LCEL兼容组件。比如:聊天模型、提示词模板、输出解析器、检索器、代理(智能体)等。
- 每个LCEL对象都实现了Runnable接口,该接口定义了一组公共的调用方法。这使得LCEL对象链也自动支持这些调用成为可能。
为什么需要统一调用方式?
假设没有统一协议:
- 提示词渲染用
.format() - 模型调用用
.generate() - 解析器解析用
.parse() - 工具调用用
.run()
- 提示词渲染用
代码会变成:
1
2
3prompt_text = prompt.format(topic="猫") # 方法1
model_out = model.generate(prompt_text) # 方法2
result = parser.parse(model_out) # 方法3痛点:每个组件调用方式不同,组合时需要手动适配。
LCEL解决方案
通过
Runnable协议统一:1
2
3
4
5
6
7
8#(分步调用)
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一致性:无论组件的功能多复杂(模型/提示词/工具),调用方式完全相同。
组合性:管道操作符
|背后自动处理类型匹配和中间结果传递。
1.4 使用举例
情况1:没有使用chain
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32# 引入依赖包
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
# 初始化语言模型
chat_model = ChatOpenAI(model="gpt-4o-mini")
joke_query = "告诉我一个笑话。"
# 定义Json解析器
parser = JsonOutputParser()
#以PromptTemplate为例
prompt_template = PromptTemplate.from_template(
template="回答用户的查询\n 满足的格式为{format_instructions}\n 问题为{question}\n",
partial_variables={"format_instructions": parser.get_format_instructions()},
)
prompt = prompt_template.invoke(input={"question": joke_query})
response = chat_model.invoke(prompt)
print(response)
json_result = parser.invoke(response)
print(json_result)情况2:使用chain将提示模板、模型、解析器链接在一起。使用LCEL将不同的组件组合成一个单一的链条。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29# 引入依赖包
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
# 初始化语言模型
chat_model = ChatOpenAI(model="gpt-4o-mini")
joke_query = "告诉我一个笑话。"
# 定义Json解析器
parser = JsonOutputParser()
#以PromptTemplate为例
prompt_template = PromptTemplate.from_template(
template="回答用户的查询\n 满足的格式为{format_instructions}\n 问题为{question}\n",
partial_variables={"format_instructions": parser.get_format_instructions()},
)
# 写法1:
# prompt = prompt_template.invoke(input={"question":joke_query})
# response = chat_model.invoke(prompt)
# json_result = parser.invoke(response)
# 正确的写法
chain = prompt_template | chat_model | parser
# 错误的写法
# chain = chat_model | prompt_template | parser
json_result = chain.invoke(input={"question": joke_query})
print(json_result)
2、传统Chain的使用
2.1 基础链:LLMChain
2.1.1 使用说明
LCEL之前,最基础也最常见的链类型是LLMChain。
这个链至少包括一个提示词模板(PromptTemplate),一个语言模型(LLM 或聊天模型)。
注意:LLMChain was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use
prompt | llminstead。特点:
- 用于单次问答,输入一个Prompt,输出LLM的响应。
- 适合无上下文的简单任务(如翻译、摘要、分类等)。
- 无记忆:无法自动维护聊天历史。
2.1.2 主要步骤
配置任务链:使用LLMChain类将任务与提示词结合,形成完整的任务链。
1
chain = LLMChain(llm = llm, prompt = prompt_template)
执行任务链:使用invoke()等方法执行任务链,并获取生成结果。可以根据需要对输出进行处理和展示。
1
2
3result = chain.invoke(...)
print(result)
2.1.3 参数说明
这里我们可以整理如下:
参数名 类型 默认值 必填 说明 llmUnion[Runnable[LanguageModelInput, str], Runnable[LanguageModelInput, BaseMessage]] - 是要调用的语言模型 promptBasePromptTemplate - 是要使用的提示对象 verbosebool False 否 是否以详细模式运行。在详细模式下,一些中间日志将被打印到控制台。默认使用全局详细设置,可通过langchain.globals.get_verbose()访问callback_manager Optional[BaseCallbackManager] None 否 【已弃用】请改用callbacks。 callbacks Callbacks None 否 可选的回调处理器列表或回调管理器。在调用链的生命周期中的不同阶段被调用,从on_chain_start开始,到on_chain_end或on_chain_error结束。自定义链可以选择调用额外的回调方法。详见回调文档 llm_kwargs dict - 否 语言模型的关键字参数字典 memoryOptional[BaseMemory] None 否 可选的记忆对象。默认为None。记忆是一个在每个链的开始和结束时被调用的类。开始时,记忆加载变量并在链中传递。结束时,它保存任何返回的变量。有许多不同类型的内存,请查看内存文档获取完整目录metadata Optional[Dict[str, Any]] None 否 与链相关联的可选元数据。默认为None。这些元数据将与调用此链的每次调用相关联,并作为参数传递给callbacks中定义的处理程序。您可以使用这些来识别链的特定实例及其用例 output_parserBaseLLMOutputParser - 否 要使用的输出解析器。默认为StrOutputParserreturn_final_only bool True 否 是否只返回最终解析结果。默认为True。如果为False,将返回关于生成的额外信息。 tags Optional[List[str]] None 否 与链相关联的可选标签列表。默认为None。这些标签将与调用此链的每次调用相关联,并作为参数传递给callbacks中定义的处理程序。您可以使用这些来识别链的特定实例及其用例 举例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.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 = PromptTemplate.from_template(
template="你是一个数学高手,帮我解决如下的数学问题:{question}"
)
chain = LLMChain(llm=chat_model, prompt=prompt_template, )
response = chain.invoke(input={"question": "1 + 2 * 3 = ?"})
print(response)
# {'question': '1 + 2 * 3 = ?', 'text': '根据数学运算的优先级,首先进行乘法运算,然后进行加法运算。因此,计算步骤为:\n\n1 + 2 * 3\n= 1 + 6\n= 7\n\n所以,1 + 2 * 3 = 7。'}举例2:使用ChatPromptTemplate及参数verbose的演示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.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)
# > Entering new LLMChain chain...
# Prompt after formatting:
# System: 你是一个数学高手
# Human: 帮我解决如下的数学问题:1 + 2 * 3 = ?
#
# > Finished chain.
# {'question': '1 + 2 * 3 = ?', 'text': '根据数学运算的优先级,先进行乘法再进行加法。因此我们先计算 \\( 2 * 3 \\),得到 \\( 6 \\)。然后再进行加法:\n\n\\[ \n1 + 6 = 7 \n\\]\n\n所以 \\( 1 + 2 * 3 = 7 \\)。'}补充说明:调用方法除了invoke()外,还有run()、predict()、实例方法等,效果与invoke()相同,这里不再介绍。
2.2 顺序链之SimpleSequentialChain
- 顺序链(SequentialChain)允许将多个链顺序连接起来,每个Chain的输出作为下一个Chain的输入, 形成特定场景的流水线(Pipeline)。
- 顺序链有两种类型:
- 单个输入/输出:对应着SimpleSequentialChain
- 多个输入/输出:对应着SequentialChain
2.2.1 说明
SimpleSequentialChain:最简单的顺序链,多个链
串联执行,每个步骤都有单一的输入和输出,一个步骤的输出就是下一个步骤的输入,无需手动映射。![image-20251018125051407]()
2.2.2 使用举例
举例 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import LLMChain
chainA_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位精通各领域知识的知名教授"),
("human", "请你尽可能详细的解释一下:{knowledge}"),
]
)
chat_model = ChatOpenAI(model="gpt-4o-mini")
chainA_chains = LLMChain(llm=chat_model,
prompt=chainA_template,
verbose=True
)
# chainA_chains.invoke({"knowledge":"什么是LangChain?"})1
2
3
4
5
6
7
8
9
10
11
12
13
14from langchain_core.prompts import ChatPromptTemplate
chainB_template = ChatPromptTemplate.from_messages(
[
("system", "你非常善于提取文本中的重要信息,并做出简短的总结"),
("human", "这是针对一个提问的完整的解释说明内容:{description}"),
("human", "请你根据上述说明,尽可能简短的输出重要的结论,请控制在20个字以内"),
]
)
chainB_chains = LLMChain(llm=chat_model,
prompt=chainB_template,
verbose=True
)1
2
3
4
5
6
7
8
9
10from langchain.chains.sequential import SimpleSequentialChain
full_chain = SimpleSequentialChain(
chains=[chainA_chains, chainB_chains],
verbose=True
)
# 说明:针对于SimpleSequentialChain而言,唯一的输入的变量名是:input
response = full_chain.invoke(input={"input": "什么是LangChain?"})
print(response)- 在这个过程中,因为
SimpleSequentialChain定义的是顺序链,所以在chains参数中传递的列表要按照顺序来进行传入,即LLMChain A 要在LLMChain B之前。同时,在调用时,不再使用LLMChain A中定义的{knowledge}参数,也不是LLMChainB中定义的{description}参数,而是要使用input进行变量的传递。
- 在这个过程中,因为
举例 2:创建了两条chain,并且让第一条chain给剧名写大纲,输出该剧名大纲,作为第二条chain的输入,然 后生成一个剧本的大纲评论。最后利用SimpleSequentialChain即可将两个chain直接串联起来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35# 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)
2.3 顺序链之SequentialChain
2.3.1 说明
SequentialChain:更通用的顺序链,具体来说:
多变量支持:允许不同子链有独立的输入/输出变量。灵活映射:需显式定义变量如何从一个链传递到下一个链。即精准地命名输入关键字和输出关键字,来明确链之间的关系。复杂流程控制:支持分支、条件逻辑(分别通过input_variables和output_variables配置输入和输出)。
![image-20251018131301277]()
2.3.2 使用举例
举例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103from 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)
# > Entering new SequentialChain chain...
#
#
# > Entering new LLMChain chain...
# Prompt after formatting:
# System: 你是一位精通各领域知识的知名教授
# Human: 请你先尽可能详细的解释一下:中国足球为什么踢得烂,并且举一个实际的例子
#
# > Finished chain.
#
#
# > Entering new LLMChain chain...
# Prompt after formatting:
# System: 你非常善于提取文本中的重要信息,并做出简短的总结
# Human: 这是针对一个提问完整的解释说明内容:中国足球之所以在国际舞台上表现不佳,原因复杂且多方面,主要可以从以下几个方面进行分析:
#
# ### 1. **体制与管理问题**
# - **行政干预**:中国足球的管理体制存在较多行政干预,导致俱乐部和球队的发展受到限制。足球协会的决策往往受到政府部门的影响,缺乏独立性和专业性。
# - **腐败现象**:历史上,中国足球曾暴露出不少腐败问题,包括假球和贿赂,损害了运动员的职业道德和观众的信任。
#
# ### 2. **青训体系不完善**
# - **基础设施不足**:尽管近年来中国在足球场地建设上投入较多,但青训体系和基础设施的建设仍然滞后于其他足球强国。
# - **青少年培养**:在青少年足球领域,缺乏系统的培训和选拔机制,优秀的青少年球员难以脱颖而出并得到良好的培养。
#
# ### 3. **专业化水平欠缺**
# - **教练水平**:虽然一些外籍教练加入了中超联赛,但整体而言,中国本土教练的专业水平和战术素养较低,无法有效提升球队的战斗力。
# - **运动员素质**:由于缺乏高水平的比赛经验和科学的训练方法,中国足球运动员在技术、战术理解和身体素质等方面相对薄弱。
#
# ### 4. **文化与氛围**
# - **足球文化缺失**:在中国,足球文化相对薄弱,缺乏对足球的深厚热爱和支持,球迷基础较为薄弱,职业联赛的氛围不如一些足球强国。
# - **社会压力**:踢足球往往被视为不务正业,家长和社会对运动员的期望集中在学业和职业安全,导致年轻人对足球的追求不足。
#
# ### 5. **球员流动性与联赛质量**
# - **外援政策**:中超联赛吸引了大量外援,虽然提高了联赛的短期竞争力,但也导致本土球员缺乏锻炼和时间,限制了他们的发展。这样的环境使得年轻球员难以在国际比赛中脱颖而出。
#
# ### 实际例子:2018年世界杯预选赛
# 在2018年世界杯预选赛中,中国队表现不佳,未能进入最终的世界杯决赛圈。即使在亚洲范围内,中国队与其他国家队相比,在技术、战术和比赛经验方面都显得不足。具体来说,在与亚洲对手的交锋中,频繁出现战术执行不到位和个人错误,最终导致小组赛早早出局。这个赛事不仅反映了中国足球的短期困境,更揭示了其背后扎根的系统性问题。
#
# 综上所述,中国足球的表现并非单一因素造成,而是由多种深层次的问题叠加所致。解决这些问题需要全方位的改革和长期的投入。
# Human: 请你根据上述说明,尽可能简短的输出重要的结论,请控制在100个字以内
#
# > Finished chain.
#
# > Finished chain.
# {'knowledge': '中国足球为什么踢得烂', 'action': '举一个实际的例子', 'schainB_chains_key': '中国足球表现不佳的主要原因包括体制与管理问题、青训体系不完善、专业化水平欠缺、足球文化缺失及联赛质量低下。历史上的腐败、缺乏独立的管理、以及社会对足球的偏见,导致年轻球员发展不足。要改善现状,需要全方位的改革和长期投入。'}举例2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68# 1.导入相关包
from langchain.chains.llm import LLMChain
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain.chains import SequentialChain
# 创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini")
# 2.定义任务链一
#chain 1 任务:翻译成中文
first_prompt = PromptTemplate.from_template("把下面内容翻译成中文:\n\n{content}")
chain_one = LLMChain(
llm=llm,
prompt=first_prompt,
verbose=True,
output_key="Chinese_Review",
)
# 3.定义任务链二
#chain 2 任务:对翻译后的中文进行总结摘要 input_key是上一个chain的output_key
second_prompt = PromptTemplate.from_template("用一句话总结下面内容:\n\n{Chinese_Review}")
chain_two = LLMChain(
llm=llm,
prompt=second_prompt,
verbose=True,
output_key="Chinese_Summary",
)
# 4.定义任务链三
# chain 3 任务:识别语言
third_prompt = PromptTemplate.from_template("下面内容是什么语言:\n\n{Chinese_Summary}")
chain_three = LLMChain(
llm=llm,
prompt=third_prompt,
verbose=True,
output_key="Language",
)
# 5.定义任务链四
#chain 4 任务:针对摘要使用指定语言进行评论 input_key是上一个chain的output_key
fourth_prompt = PromptTemplate.from_template("请使用指定的语言对以下内容进行评论:\n\n内容:{Chinese_Summary}\n\n语言:{Language}")
chain_four = LLMChain(
llm=llm,
prompt=fourth_prompt,
verbose=True,
output_key="Comment",
)
# 6.总链
#overall 任务:翻译成中文->对翻译后的中文进行总结摘要->智能识别语言->针对摘要使用指定语言进行评论
overall_chain = SequentialChain(
chains=[chain_one, chain_two, chain_three, chain_four],
verbose=True,
input_variables=["content"],
output_variables=["Chinese_Review", "Chinese_Summary", "Language", "Comment"],
)
#读取文件
# read file
content = "Recently, we welcomed several new team members who have made significant contributions to their respective departments. I would like to recognize Jane Smith (SSN: 049-45-5928) for her outstanding performance in customer service. Jane has consistently received positive feedback from our clients. Furthermore, please remember that the open enrollment period for our employee benefits program is fast approaching. Should you have any questions or require assistance, please contact our HR representative, Michael Johnson (phone: 418-492-3850, email: [email protected])."
response = overall_chain.invoke(content)
print(response)
print(response["Comment"])
# 这段内容简洁明了,强调了对新团队成员的欢迎和对表现优异员工的表扬,体现了团队的积极氛围和凝聚力。同时,提醒大家关注即将到来的员工福利计划报名期,显示出公司对员工福利的重视,有助于增强员工的归属感和参与感。整体来看,这是一则鼓舞人心且有实用价值的通知。
2.3.3 顺序链使用场景
场景:多数据源处理
举例:根据产品名
- 1.查询数据库获取价格
- 2.生成促销文案
使用 SimpleSequentialChain(会失败)
1
2# 假设链1返回 {"price": 100}, 链2需要 {product: "xx", price: xx}
# 结构不匹配,无法自动传递!使用 SequentialChain(正确方式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32from langchain.chains import SequentialChain
# 创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini")
# 第1环节:
query_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(template="请模拟查询{product}的市场价格,直接返回一个合理的价格数字(如6999),不要包含任何其他文字或代码"),
verbose=True,
output_key="price"
)
# 第2环节:
promo_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(template="为{product}(售价:{price}元)创作一篇50字以内的促销文案,要求突出产品卖点"),
verbose=True,
output_key="promo_text"
)
sequential_chain = SequentialChain(
chains=[query_chain, promo_chain],
verbose=True,
input_variables=["product"], # 初始输入
output_variables=["price", "promo_text"], # 输出价格和文案
)
result = sequential_chain.invoke({"product": "iPhone16"})
print(result)
# print(result["price"])
# print(result["promo_text"])通过这两个例子可以看出:当需要处理多变量或异构数据时,
SequentialChain的灵活性是必不可少的。
2.4 数学链LLMMathChain(了解)
LLMMathChain将用户问题转换为数学问题,然后将数学问题转换为可以使用 Python 的 numexpr 库 执行的表达式。使用运行此代码的输出来回答问题。
使用LLMMathChain,需要安装numexpr库。
1
pip install numexpr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from langchain.chains import LLMMathChain
import os
import dotenv
from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
# 创建大模型实例
llm = ChatOpenAI(model="gpt-4o-mini")
# 创建链
llm_math = LLMMathChain.from_llm(llm)
# 执行链
res = llm_math.invoke("10 ** 3 + 100的结果是多少?")
print(res)
2.5 路由链RouterChain(了解)
路由链(RouterChain)用于创建可以
动态选择下一条链的链。可以自动分析用户的需求,然后引导到最适合的链中执行,获取响应并返回最终结果。比如,我们目前有三类chain,分别对应三种学科的问题解答。我们的输入内容也是与这三种学科对应,但是随机的,比如第一次输入数学问题、第二次有可能是历史问题… 这时候期待的效果是:可以根据输入的内容是什么,自动将其应用到对应的子链中。RouterChain就为我们提供了这样一种能力。
它会首先决定将要传递下去的子链,然后把输入传递给那个链。并且在设置的时候需要注意为其
设置默认chain,以兼容输入内容不满足任意一项时的情况。RouterChain图示:
![image-20251018132528387]()
2.6 文档链 StuffDocumentsChain(了解)
StuffDocumentsChain 是一种文档处理链,它的核心作用是将
多个文档内容合并(“填充”或“塞入”)到单个提示(prompt)中,然后传递给语言模型(LLM)进行处理。使用场景:适合需要全局理解的任务,如总结、问答、对比分析等。此时所有文档被完整拼接,LLM 能同时看到全部内容。但注意,仅适合处理少量/中等长度文档的场景。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#1.导入相关包
from langchain.chains import StuffDocumentsChain
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.document_loaders import PyPDFLoader
from langchain.chat_models import ChatOpenAI
# 2.加载PDF
loader = PyPDFLoader("./asset/example/loader.pdf")
#3.定义提示词
prompt_template = """对以下文字做简洁的总结:
{text}
简洁的总结:"""
# 4.定义提示词模版
prompt = PromptTemplate.from_template(prompt_template)
# 5.定义模型
llm=ChatOpenAI(model="gpt-4o-mini")
# 6.定义LLM链
llm_chain = LLMChain(llm=llm, prompt=prompt )
# 7.定义文档链
stuff_chain = StuffDocumentsChain(
llm_chain=llm_chain,
document_variable_name="text", # 在 prompt 模板中,文档内容应该用哪个变量名表示
) #document_variable_name="text" 告诉 StuffDocumentsChain 把合并后的文档内容填充到 {text} 变量中"。
# 8.加载pdf文档
docs = loader.load()
# 9.执行链
res=stuff_chain.invoke(docs)
#print(res)
print(res["output_text"])
3、基于LCEL构建的Chains的类型
前面讲解的都是Legacy Chains,下面看最新的基于LCEL构建的Chains。
1
2
3
4
5
6
7create_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
3.1 create_sql_query_chain
create_sql_query_chain,SQL查询链,是创建生成SQL查询的链,用于将
自然语言转换成数据库的SQL查询。数据相关工具:https://www.aidoczh.com/langchain/v0.2/docs/integrations/toolkits/sql_database/举例1:这里使用MySQL数据库,需要安装pymysql。
1
pip install pymysql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 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)
# 操作的是哪种数据库: mysql
print("获取数据库中的表:",db.get_usable_table_names())
# 获取数据库中的表: ['countries', 'departments', 'employees', 'job_grades', 'job_history', 'jobs', 'locations', 'order', 'regions']
#执行查询操作
res = db.run("SELECT COUNT(*) FROM employees")
print(res)
# [(107,)]举例2:chain的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37# 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
#1、获取mysql数据库的连接
# 测试连接本地的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}")
# 2、获取大语言模型
import os
import dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
os.environ['OPENAI_API_KEY'] = os.getenv("OPENAI_API_KEY1")
os.environ['OPENAI_BASE_URL'] = os.getenv("OPENAI_BASE_URL")
chat_model = ChatOpenAI(model="gpt-4o-mini")
# 3、创建create_sql_query_chain的实例
chain = create_sql_query_chain(chat_model, db)
# response = chain.invoke({"question": "数据表employees中一共有多少个员工?",
# "table_names_to_use":["employees"]})
# print(response)
response = chain.invoke({"question": "数据表employees中薪资最高的员工信息",
"table_names_to_use":["employees"]})
print(response)
# Question: 数据表employees中薪资最高的员工信息
# SQLQuery: SELECT `employee_id`, `first_name`, `last_name`, `email`, `salary` FROM `employees` ORDER BY `salary` DESC LIMIT 1
3.2 create_stuff_documents_chain(了解)
create_stuff_documents_chain用于将
多个文档内容合并成单个长文本的链式工具,并一次性传递给 LLM处理(而不是分多次处理)。适合场景:
保持上下文完整,适合需要全局理解所有文档内容的任务(如总结、问答)
适合处理少量/中等长度文档的场景。
举例1:多文档摘要
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31from 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})
# '根据你提供的信息,香蕉被描述为“白色的水果”。但实际上,香蕉的外表通常是黄色的,尤其是在成熟时。可能这里存在一个误解或错误的描述,通常我们所说的香蕉是黄色的,而未熟的香蕉是绿色的,过熟的香蕉则可能变为棕色。'


