Langchain Chain - RouterChain 根据输入相关性进行路由的路由链

37 篇文章 0 订阅
24 篇文章 0 订阅

原文:Langchain Chain - RouterChain 根据输入相关性进行路由的路由链 - 知乎

目录

收起

一、什么是RouterChain?

二、MultiPromptChain

三、LLMRouterChain

四、过程回顾

五、关于”玩转Langchain“

上节链接:Langchain Chain - 连接一切工具,创造更复杂的应用! (zsxq.com)

通过上一节,我们介绍了什么是Langchain框架的Chian,它可以做为AI应用的底座,通过连接不同的工具,创造功能复杂的应用;同时,我们还介绍了Chain中最基础的类型 —— LLMChain。

本节开始,我们将介绍其他更复杂的Chain,以及来讲一讲它们的应用场景,让我们先从RouterChain开始吧!

一、什么是RouterChain?

让我们回顾目前所学的内容,我们能够创建一个llmchain,从中放置一个prompt模板,这个chain能够接收一个用户input,并输出一个结果;如果我们想让它成为某个方向的专家机器人,我们可以为它接入一个外部数据源,使用LLMchain,接入一个txt文本,并在chain中接入一个文档检索器就已经能完成这个需求了,我们会在什么场景需要用到RouterChain呢?

我们来考虑这样一个需求:如果我们想设定的专家机器人不仅仅是用于某一个专业领域,而是多个专业领域,那我们岂不是要复制n个这样的chain,并且每个接入不同的txt文本?

没错,在这样的场景下,就会需要用到RouterChain了!根据Langchain的介绍,Router Chain往往会配合下游的destination chain一起使用,成为“一个网关路由+多个下子链”的架构,其能根据user input自动路由到最相关的下游chain:

上图中是一个RouterChian使用场景的示意图,我们可以看到,一个RouterChain连接了多个下游的子链,每个链都是一个小应用,当RouterChain接收用户的输入,其可以根据用户输入路由到和输入最相关的子链上,并由子链产生输出;例如,用户输入是“请帮我写一首诗”,当RouterChain接收后,会自动路由到“诗人”这个子链,由它来输出结果。

通过RouterChain,我们可以创建一个能解决多种复杂问题的AI应用。

根据Langchain的介绍,一个标准的RouterChain应用应包含两个标准组成部分:

1. 路由链RouterChain:其本身就是一个chain应用,能够根据用户输入进行下游子链的选择;Langchain框架提供了多种RouterChain,其中着重介绍了LLMRouterChain  EmbeddingRouterChain两种:

- LLMRouterChain 将用户输入放进大语言模型,通过Prompt的形式让大语言模型来进行路由

- EmbeddingRouterChain 通过向量搜索的方式,将用户输入

2. 子链DestinationChain:直译为目标链,即可路由到的链,按照上图,我们会存在4个目标链,分别是lawyer chain,sales chain,english teacher chain 和 poet chain

二、MultiPromptChain

当我们配置好路由链和下游子链,我们需要把这两个链通过一个 MultiPromptChain 来进行连接,先让我们来看看Langchain框架提供的MultiPromptChain把!

Langchain提供的MultiPrompt包含以下必传参数:

router_chain:接收一个RouterChain实例,作为路由链进行路由

default_chain:接收一个LLMChain实例,当Router Chain无法找到合适的下游子链时,会自动路由到的默认链,可以认为是一个兜底备选链

destination_chains:接收一个Mapping[str, LLMChain] 字典,key为可以路由到的destination chain的名称,value为该destination chain的LLMChain实例

此外,还有其他主要的可选参数:

memory: 接收一个BaseMemory实例,能为路由链添加上下文记忆

verbose: bool值,若为True则会打印该链的调用过程

接下来我们再来看看两类RouterChain。

三、LLMRouterChain

LLMRouterChain 将用户输入放进大语言模型,通过Prompt的形式让大语言模型来进行路由,如果采用该chain作为RouterChain,那么需要传入两个核心的参数,作为基底的大语言模型,和用作路由的 prompt。

使用LLMRouterChain进行路由时的Prompt可能会比较复杂,因为其包含对用户输入的解析,对路由的指引,同时要约束其输出必须要是MultiPromptChain能够解析的;Lanchain这里提供了一个 MULTI_PROMPT_ROUTER_TEMPLATE ,通过这个template的.format() 方法可以直接生成能被MultiPromptChain使用的 router_prompt;当然,.format()方法的格式化也是有一定模板的,我们可以直接根据以下流程来创建router_prompt:

1. 首先,定义4个子链prompt模板

lawyer_template = """ 你是一个法律顾问,你需要根据用户提出的问题给出专业的法律意见,如果你不知道,请说"我不知道",请不要提供超出文本范围外的内容,也不要自创内容。


用户提问:
{input}
"""


sales_template = """ 你是一个销售顾问,你需要为用户输入的商品进行介绍,你需要提供商品基本信息,以及其使用方式和保修条款。


用户输入的商品:
{input}
"""


english_teacher_template ="""你是一个英语老师,用户输入的中文词汇,你需要提供对应的英文单词,包括单词词性,对应的词组和造句。


用户输入的中文词汇:
{input}
"""


poet_template=""" 你是一个诗人,你需要根据用户输入的主题作诗。


用户输入的主题:
{input}
"""

2.接下来,我们要创建一个“路由目录”,这个目录会记录子链名称,子链描述和子链prompt template,构造这个目录的目的主要有有两个,一个便于创建子链,另一个是便于生成路由链用于路由的PromptTemplate

prompt_infos = [
    {
        "name": "lawyer",
        "description": "咨询法律相关问题时很专业",
        "prompt_template": lawyer_template,
    },
    {
        "name": "sales",
        "description": "咨询商品信息时很专业",
        "prompt_template": sales_template,
    },
    {
        "name": "english teacher",
        "description": "能够很好地解答英语问题",
        "prompt_template": english_teacher_template,
    },
    {
        "name": "poet",
        "description": "作诗很专业",
        "prompt_template": poet_template,
    },
]

3. 接下来,我们要为创建MULTI_PROMPT_ROUTER_TEMPLATE做准备

#创建一个list储存对应的子链名称和描述
destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]


#把描述连接成一个str
destinations_str = "\n".join(destinations)

destinations_str 输出的文本如下,这个格式就是MultiPromptRputer Tempalte接收格式化的文本摹本:

lawyer: Good for answering questions about law
sales: Good for answering sales questions
english teacher: Good for answering english teaching questions
poet: Good for making poet

4. 接下来使用 MULTI_PROMPT_ROUTER_TEMPLATE.format() 进行格式化

from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE


router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)

格式化完毕后,其会生成一个str,这个字符串能作为prompt template了,我们来打印以下router_template

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.


<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
```json
{{
"destination": string \ name of the prompt to use or "DEFAULT"
"next_inputs": string \ a potentially modified version of the original input
}}
```


REMEMBER: "destination" MUST be one of the candidate prompt names specified below OR it can be "DEFAULT" if the input is not well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input if you don't think any modifications are needed.


<< CANDIDATE PROMPTS >>
lawyer: 咨询法律相关问题时很专业
sales: 咨询商品信息时很专业
english teacher: 能够很好地解答英语问题
poet: 作诗很专业


<< INPUT >>
{input}


<< OUTPUT >>

5. 有了router_template后,我们要生成一个PromptTemplate实例,我们可以看到,上面的template中包含一个input作为输入,同时我们需要用到RouterOutputParser作为输出解析器

from langchain.chains.router.llm_router import RouterOutputParser


router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)

6. 完成这一步后,我们就可以定义LLMRouterChain了!

from langchain.chains.router.llm_router import LLMRouterChain
from langchain.llms import OpenAI
import os


#创建一个OpenAI作为大语言模型的基底
llm = OpenAI()


os.environ["OPENAI_API_KEY"]="你的key"


router_chain = LLMRouterChain.from_llm(llm, router_prompt)

上述步骤有一些复杂,但是这是通过大语言模型构建复杂应用的关键步骤,在完成上述步骤后,我们已经有一个RouterChain作为路由链了,只剩下:

1. 生成各子链

2. 生成一个default chain作为兜底chain

2. 用MultiPromptChain将子链和路由链连接

让我们一步步来:

# 首先,创建一个候选链,包含所有的下游子链
candadite_chains = {}


# 遍历路由目录,生成各子链并放入候选链字典
for p_info in prompt_infos:
    name = p_info["name"]
    prompt_template = p_info["prompt_template"]
    prompt = PromptTemplate(template=prompt_template, input_variables=["input"])
    chain = LLMChain(llm=llm, prompt=prompt)
    candadite_chains[name] = chain


# 生成默认链
default_chain = ConversationChain(llm=llm, output_key="text")

MultiPromptChain所必须的三大要素:router_chain, destination_chain 以及 default_chain 都已经准备完毕,最后来组装一下吧!

chain = MultiPromptChain(
    router_chain=router_chain,
    destination_chains=candadite_chains,
    default_chain=default_chain,
    verbose=True,
)

组装完毕,来试一试把!

print(chain.run("帮我写一首关于春天的诗"))

四、过程回顾

回顾一下上面的流程,我们都做了哪些工作?

1. 创建子链和默认链

2. 创建路由链,同时路由链的路由模板需要根据子链进行特殊设计

3. 创建MultiPromptChain,将路由链、默认链和子链组装成一个整体

五、关于”玩转Langchain“

"玩转Langchain"是一个Langchain框架和Langchain开发的知识星球,我们将会每周分享关于Langchain的精品内容,欢迎加入我们!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
chain-of-thought代码是一种用来构建和理解思维条的程序代码。思维条是指思考过程中的逻辑思维的一系列连接。这种代码的作用是帮助我们在程序中整理和管理思维的流程,使其更加清晰和易于理解。 chain-of-thought代码的实现可以使用各种编程语言,例如Python或Java等。它通常包含以下几个关键元素: 1. 节点:节点是思维条的基本单元,代表了一个关键的思考点或一个执行的步骤。每个节点都有一个唯一的标识符和相关的属性。 2. 连接:连接用于建立节点之间的联系,表示它们之间的逻辑关系。例如,节点A可能需要在节点B之前执行,这时可以通过连接来表达这一关系。 3. 流程:流程是思维条中节点和连接的组合,描述了整个思考过程。可以通过定义和组织节点和连接的方式来构建和管理流程。 4. 输入和输出:节点可以接收输入参数,并且会产生输出结果。输入和输出数据可以在节点之间通过连接进行传递,从而形成输入输出条。 通过使用chain-of-thought代码,我们可以更加系统地组织和管理我们的思维过程。它可以帮助我们跟踪和追溯思考中的每个步骤,清晰地展示了我们的思维逻辑。这对于团队合作和项目管理非常有帮助,在多人协作的环境中,大家可以共享和理解彼此的思考过程。 总而言之,chain-of-thought代码是一种用来构建和理解思维条的程序代码。它通过定义节点、连接、流程以及输入输出来描述和管理思考过程,从而帮助我们更加清晰地表达和理解思维的逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值