LangChain中我们已经讲解了其中模型的概念,以及相关的提示工程,以及相关的结构化解析功能。

但是在LangChain中,Chain 链这个概念一直没有提到。

其主要是可以将多个组件相互组合,组合成一个连贯的应用程序。

就好比我们可以将多个链节点串联起来,将前面节点的输出作为下一个节点的输入,重新进行使用。

那么链的节点内部,则封装之前我们了解的诸如提示工程,模型等组件,也就是说在一个大型的程序之中,链的节点是最小的功能单元。

在LangChain中,提供一些预置Chain,方便我们的使用

LLMChain,最简单的链,主要充当节点这个概念,可以对用户的输入进行格式化,将格式化的提示传入模型,然后返回LLM的响应,

SequentialChain 顺序链,将多个简单链组合,上一步骤的输入作为下一步骤的输出。

TransformChain 转换链,通过设置转换函数,对输入文本进行一系列的格式转换。比如可以根据输入的文档,进行相关的分词

RouterChain 路由链,包含判断等一系列的目标链,可以由LLM 动态选择目标Chain

其他的工具链比如 LLMMathChain 可以调用大模型作为数学工具进行构建链。

那么我们依次看下上面链的使用。

首先是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)

调用其就比较简单,只需要llm_chain就可以了,这本质上是调用其内部的__call__方法

当然也可以调用其run方法,等同于调用__call__方法

或者调用predict方法,其等于升级版的run,只不过支持输入键值

result = llm_chain.predict(flower=”玫瑰”)

利用apply方法,可以一次性处理多个输入

input_list = [

{“flower”: “玫瑰”, ‘season’: “夏季”},

{“flower”: “百合”, ‘season’: “春季”},

{“flower”: “郁金香”, ‘season’: “秋季”}

]

result = llm_chain.apply(input_list)

同时得到的输出也是一个列表。

通过generate方法

是一个原始版的apply方法,返回一个LLMResult对象,而不是字符串。能够得到更多的元数据信息。

在简单介绍完LLMChain之后,我们看下Sequential Chain 顺序链。

其支持将多个Chain进行串联

我们可以如下举例

首先假设模型是一个鲜花学家,可以给出某些鲜花的知识介绍

然后假设模型是一个花店店主,根据上面的知识产出运营文案。

首先是第一个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”

)

其次是花店店主

template = “””

你是一家花店的社交媒体经理。给定一种花的介绍和评论,你需要为这种花写一篇社交媒体的帖子,300字左右。

鲜花介绍:

{introduction}

社交媒体帖子:

“””

prompt_template = PromptTemplate(

input_variables=[“introduction”],

template=template

)

social_post_chain = LLMChain(

llm=llm,

prompt=prompt_template,

output_key=”social_post_text”

)

之后是组装这些链路

overall_chain = SequentialChain(

chains=[introduction_chain, social_post_chain],

input_variables=[“name”, “color”],

output_variables=[“introduction”, “social_post_text”],

verbose=True

)

最后是运行

result = overall_chain({

“name”: “玫瑰”,

“color”: “黑色”

})

这样我们就利用两个LLM链和一个顺序链,生成了一个文案

{‘name’: ‘玫瑰’, ‘color’: ‘黑色’, ‘introduction’: ‘nn黑色玫瑰,这是一种对传统玫瑰花的独特颠覆,它的出现挑战了我们对玫瑰颜色的固有认知。它的花瓣如煤炭般黑亮,反射出独特的微光,而花蕊则是金黄色的,宛如夜空中的一颗星,强烈的颜色对比营造出一种前所未有的视觉效果。在植物学中,黑色玫瑰的出现无疑提供了一种新的研究方向,对于我们理解花朵色彩形成的机制有着重要的科学价值。’, ‘social_post_text’: ‘n欢迎来到我们的自媒体平台,今天,我们要向您展示的是我们的全新产品——黑色玫瑰。这不仅仅是一种花,这是一种对传统观念的挑战,一种视觉艺术的革新,更是一种生活态度的象征。这种别样的玫瑰花,其黑色花瓣宛如漆黑夜空中闪烁的繁星,富有神秘的深度感,给人一种前所未有的视觉冲击力。这种黑色,它不是冷酷、不是绝望,而是充满着独特的魅力和力量。而位于黑色花瓣之中的金黄色花蕊,则犹如星星中的灵魂,默默闪烁,给人带来无尽的遐想,充满活力与生机。黑色玫瑰的存在,不仅挑战了我们对于玫瑰传统颜色的认知,它更是一种生动的生命象征,象征着那些坚韧、独特、勇敢面对生活的人们。黑色的花瓣中透露出一种坚韧的力量,而金黄的花蕊则是生活中的希望,二者的结合恰好象征了生活中的喜怒哀乐,体现了人生的百态。’}

这样我们先介绍了大致链的作用和一些预置链实例。

并展示了LLMChain和SequentialChain的使用。

那么我们继续

我们接下来讲下其中核心的链,RouterChain

这里我们以一个示例举例,比如我们是一个鲜花平台的客服,主要分为两类

鲜花养护,鲜花装饰

对应的就是如何培养花朵和如何挑选花朵并装饰。

那么我们就需要根据用户的输入,选择不同的链,乃至于选取不同的大模型进行回答。

那么我们就需要先定义一个RouterChain,一个路由链,可以动态根据模型输入决定选择哪个节点作为下一个输入,如果没有合适的,会被发送到默认链路。

整体的格式为

先定义不同的LLMChain,用于应对鲜花养护和鲜花装饰

然后定义一个RouterChain,用户进行决策

之后定义一个默认链,输入不合适的的处理模板,就会触发默认的链

最后利用MultiPromptChain将LLMChain,RouterChain进行整合。

那么我们就按照上面所说,逐步构建一个路由链。

首先定义两个LLMChain

flower_care_template = “””

你是一个经验丰富的园丁,擅长解答关于养花育花的问题。

下面是需要你来回答的问题:

{input}

“””

flower_deco_template = “””

你是一位网红插花大师,擅长解答关于鲜花装饰的问题。

下面是需要你来回答的问题:

{input}

“””

之后定义对应的LLMChain,并存储在dict之中

prompt_infos = [

{

“key”: “flower_care”,

“description”: “适合回答关于鲜花护理的问题”,

“template”: flower_care_template,

},

{

“key”: “flower_decoration”,

“description”: “适合回答关于鲜花装饰的问题”,

“template”: flower_deco_template,

}

]

from langchain.llms import OpenAI

llm = OpenAI()

# 构建目标链

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

这样我们就构建了两个LLMChain,并进行了存入.

之后就是关于路由链的构建。

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

)

那么我们打印一下模板

并看下模板如何构建的提示信息

Given a raw text input to a language model select the model prompt best suited for the input.

You will be given the names of the available prompts and a description of what the prompt is best suited for.

You may also revise the original input if you think that revising it will ultimately lead to a better response from the language model.

上面告诉模型应该为我们挑选一个模型,而且期望其做的更好

然后是告诉模型应该返回的格式

Return a markdown code snippet with a JSON object formatted to look like:

之后是一些补充信息,比如

REMEMBER: “destination” MUST be one of the candidate prompt names specified below OR it can be “DEFAULT”…

告诉模型,destination这个字段的值应该是如下几个之一。

这就是利用RouterTeimplate做到的提示。

然后构造一个默认Chain节点。

from langchain.chains import ConversationChain

default_chain = ConversationChain(

llm=llm,

output_key=”text”,

verbose=True

)

最后是利用MultiPromptChain将上面的几个链整合在一起。

其中需要传入的值有

router_chain 用于决定目标链和输入的链

destination_chains 一个dict,包含key和对应的chain节点

default_chain

其处理逻辑为

现将输入传递给router_chain

然后router_chain决定使用哪个destination_chain

然后路由到destination_chain来处理并返回结果

其代码如下

from langchain.chains.router import MultiPromptChain

chain = MultiPromptChain(

router_chain=router_chain,

destination_chains=chain_map,

default_chain=default_chain,

verbose=True

)

这样就可以通过简单的chain.run进行调用了。

发表评论

邮箱地址不会被公开。 必填项已用*标注