一.链
1.概念
链是链接LangChain的各个组件和功能——模型之间彼此链接,或模型与其他组件链接的工具。下面是链的具体的几种类型:
2.LLMChain:最简单的链
from langchain import PromptTemplate, OpenAI, LLMChain
template = "{flower}的花语是?"
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(template))
# 调用LLMChain,返回结果
result = llm_chain("玫瑰")
print(result)
我们可以看到,在这段代码中提示模板的构建和模型的调用被封装在一起了。于是我们不用再调用prompt_temp.format()
方法来填充模板,而直接调用LLMChain,将要填充的内容输入到Chain中就可以直接生成输出了。
二.链的调用方式
1.直接调用
prompt = PromptTemplate(
input_variables=["flower", "season"],
template="{flower}在{season}的花语是?",
)
llm_chain = LLMChain(llm=llm, prompt=prompt)
print(llm_chain({
'flower': "玫瑰",
'season': "夏季" }))
这里我们就是先构造模板,然后构造链,最后调用Chain获取输出。
2.通过run方法
llm_chain.run("玫瑰") 等价于 llm_chain("玫瑰")
3.通过predict方法
result = llm_chain.predict(flower="玫瑰")
print(result)
这里的唯一不同点就是输入键被指定为关键字参数而不是 Python 字典。
4.通过apply方法
# apply允许您针对输入列表运行链
input_list = [
{"flower": "玫瑰",'season': "夏季"},
{"flower": "百合",'season': "春季"},
{"flower": "郁金香",'season': "秋季"}
]
result = llm_chain.apply(input_list)
print(result)
apply方法允许我们针对输入列表运行链,一次处理多个输入。
5.通过generate方法
result = llm_chain.generate(input_list)
print(result)
generate方法类似于apply,只不过它返回一个LLMResult对象,而不是字符串。LLMResult通常包含模型生成文本过程中的一些相关信息,例如令牌数量、模型名称等。我们来看看结果:
三.Sequential Chain:顺序链
Sequential Chain可以把几个LLMChain串起来,形成一个顺序链。
下面我们来看一个示例:
- 第一步,我们假设大模型是一个植物学家,让他给出某种特定鲜花的知识和介绍。
- 第二步,我们假设大模型是一个鲜花评论者,让他参考上面植物学家的文字输出,对鲜花进行评论。
- 第三步,我们假设大模型是易速鲜花的社交媒体运营经理,让他参考上面植物学家和鲜花评论者的文字输出,来写一篇鲜花运营文案。
1.导库
import os
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains import SequentialChain
2.添加第一个LLMChain
第一个链我们来实现生成鲜花的知识性说明
# 这是第一个LLMChain,用于生成鲜花的介绍,输入为花的名称和种类
llm = OpenAI(temperature=.7)
template = """
你是一个植物学家。给定花的名称和类型,你需要为这种花写一个200字左右的介绍。
花名: {name}
颜色: {color}
植物学家: 这是关于上述花的介绍:"""
prompt_template = PromptTemplate(input_variables=["name", "color"], template=template)
introduction_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="introduction")
这里我们初始化模型,构造模板,然后生成模板提示。最后搭建成功第一条链。链中包括模型,提示模板和output_key="introduction"
参数,它定义了生成的鲜花介绍的输出键,也就是存储最后的输出结果。
3.添加第二个LLMChain
# 这是第二个LLMChain,用于根据鲜花的介绍写出鲜花的评论
llm = OpenAI(temperature=.7)
template = """
你是一位鲜花评论家。给定一种花的介绍,你需要为这种花写一篇200字左右的评论。
鲜花介绍:
{introduction}
花评人对上述花的评论:"""
prompt_template = PromptTemplate(input_variables=["introduction"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review")
步骤和搭建第一条链相同。
3.添加第三个LLMChain
# 这是第三个LLMChain,用于根据鲜花的介绍和评论写出一篇自媒体的文案
template = """
你是一家花店的社交媒体经理。给定一种花的介绍和评论,你需要为这种花写一篇社交媒体的帖子,300字左右。
鲜花介绍:
{introduction}
花评人对上述花的评论:
{review}
社交媒体帖子:
"""
prompt_template = PromptTemplate(input_variables=["introduction", "review"], template=template)
social_post_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="social_post_text")
依然同理。
4.添加SequentialChain
这步是关键,我们要用顺序链串起前三个链。
# 这是总的链,我们按顺序运行这三个链
overall_chain = SequentialChain(
chains=[introduction_chain, review_chain, social_post_chain],
input_variables=["name", "color"],
output_variables=["introduction","review","social_post_text"],
verbose=True)
# 运行链,并打印结果
result = overall_chain({"name":"玫瑰", "color": "黑色"})
print(result)
在这里,我们调用顺序链生成了一个总链,包括了几种链,输入参数,输出参数。verbose=True
是为了让链在执行过程中打印详细的信息(比如子链的输入输出等等)。
我们来看看输出结果:
四.RouterChain:路由链
0.引入路由链
这里假设咱们的鲜花运营智能客服ChatBot通常会接到两大类问题。
- 鲜花养护(保持花的健康、如何浇水、施肥等)
- 鲜花装饰(如何搭配花、如何装饰场地等)
如果接到的是第一类问题,你要给ChatBot A指示;如果接到第二类的问题,你要给ChatBot B指示。我们可以根据这两个场景来构建两个不同的目标链。遇到不同类型的问题,LangChain会通过RouterChain来自动引导大语言模型选择不同的模板。
1.构建提示信息的模板
# 构建两个场景的模板
flower_care_template = """你是一个经验丰富的园丁,擅长解答关于养花育花的问题。
下面是需要你来回答的问题:
{input}"""
flower_deco_template = """你是一位网红插花大师,擅长解答关于鲜花装饰的问题。
下面是需要你来回答的问题:
{input}"""
# 构建提示信息
prompt_infos = [
{
"key": "flower_care",
"description": "适合回答关于鲜花护理的问题",
"template": flower_care_template,
},
{
"key": "flower_decoration",
"description": "适合回答关于鲜花装饰的问题",
"template": flower_deco_template,
}]
这里我们首先构造了两个提示模板,分别对应两种遇到的两个问题。然后使用一个列表来组织和存储这两个处理模板的关键信息,如模板的键、描述和实际内容。
2.初始化语言模型
# 初始化语言模型
from langchain.llms import OpenAI
import os
llm = OpenAI()
3.构建目标链
# 构建目标链
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
chain_map = {}
for info in prompt_infos:
prompt = PromptTemplate(template=info['template'],
input_variables=["input"])
print("目标提示:\n",prompt)
chain = LLMChain(llm=llm, prompt=prompt,verbose=True)
chain_map[info["key"]] = chain
这里我们遍历prompt_infos
这个列表,根据这个列表中的信息生成提示后构造出了两条链,分别处理两个问题。
代码中chain_map = {}
构造了一个空字典,chain_map[info["key"]] = chain
是很重要的一步,将几个链中的key
值联系在一起,为后面构建 MultiPromptChain
时,根据输入的不同,模型可以选择合适的 LLMChain
来处理输入并生成输出。
4.构建路由链
from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import (
MULTI_PROMPT_ROUTER_TEMPLATE as RounterTemplate,
)
destinations = [f"{p['key']}: {p['description']}" for p in prompt_infos]
router_template = RounterTemplate.format(destinations="\n".join(destinations))
print("路由模板:\n", router_template)
router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
output_parser=RouterOutputParser(),
)
print("路由提示:\n", router_prompt)
router_chain = LLMRouterChain.from_llm(llm, router_prompt, verbose=True)
destinations = []
:这段代码从prompt_infos
列表中提取每个提示信息的key
和description
,并将它们格式化为一个字符串列表。router_template = RounterTemplate.format()
:使用格式化字符串的方法,将上面构建的目的地描述字符串插入到路由模板中。router_prompt = PromptTemplate()
:创建了一个PromptTemplate
对象,它使用路由模板作为提示,并指定了输入变量为"input"
,同时使用RouterOutputParser
作为输出解析器。
简而言之,这个构造允许你将用户的原始输入送入路由器,然后路由器会决定将该输入发送到哪个具体的模型提示,或者是否需要对输入进行修订以获得最佳的响应。
5.构建默认链
from langchain.chains import ConversationChain
default_chain = ConversationChain(llm=llm,output_key="text",verbose=True)
默认链是在模型没有找到合适的链去处理问题时,可以用默认链进行回答。
6.构建多提示链
我们使用MultiPromptChain
类把前几个构造的链(路由链,两条目标链整合而成的chain_map
,以及默认链)整合在一起,实现路由功能。它是一个多路选择链,它使用一个LLM路由器链在多个提示之间进行选择。
from langchain.chains.router import MultiPromptChain
chain = MultiPromptChain(
router_chain=router_chain,
destination_chains=chain_map,
default_chain=default_chain,
verbose=True)
观察代码,我们看到MultiPromptChain中有三个关键元素:
router_chain
:用于决定目标链和其输入的链。destination_chains
:我们可以看到它的值是chain_map,而chain_map中包含的就是各个链的key,通过这条链我们实现的就是根据输入的不同,提供特定的回答或处理逻辑。default_chain
:当 router_chain 无法将输入映射到destination_chains中的任何一个链时,LLMChain 将使用此默认链。
它的工作流程如下:
- 输入首先传递给
router_chain
。 router_chain
根据某些标准或逻辑决定应该使用哪一个destination_chain
。- 输入随后被路由到选定的
destination_chain
,该链进行处理并返回结果。 - 如果
router_chain
不能决定正确的destination_chain
,则输入会被传递给default_chain。
这样,MultiPromptChain
就为我们提供了一个在多个处理链之间动态路由输入的机制,以得到最相关或最优的输出。
7.运行路由链
这里我们选择了三个问题:
# 测试1
print(chain.run("如何为玫瑰浇水?"))
# 测试2
print(chain.run("如何为婚礼场地装饰花朵?"))
# 测试3
print(chain.run("如何区分阿豆和罗豆?")
第一个回答:
这里没有放完整的答案,我们可以看到这里成功调用了第一条链。
第二个回答:
我们可以看到这里成功调用了第一条链。
第三个回答:
我们发现模型的并没有准确的回答,因为这里没有找到合适的链来回答问题,所以最终使用了默认链进行了文本输出。
以上就是学习链的全部知识了。