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

news/2024/5/18 8:36:11 标签: langchain, chatgpt, prompt

原文: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的精品内容,欢迎加入我们!


http://www.niftyadmin.cn/n/5097852.html

相关文章

【SA8295P 源码分析 (一)】41 - SA8295所有镜像位置、拷贝脚本、生成QFIL包 及 Fastboot 下载命令介绍

【SA8295P 源码分析】41 - SA8295所有镜像位置、拷贝脚本、生成QFIL包 及 Fastboot 下载命令介绍 一、SA8295 各镜像位置二、SA8295 QNX 侧镜像拷贝脚本三、SA8295 Android 侧镜像拷贝脚本四、使用QFIL 下载整包五、Fastboot 下载命令整理系列文章汇总见:《【SA8295P 源码分析…

【译】快速开始 Compose 跨平台项目

原文&#xff1a; Compose Multiplatform application 作者&#xff1a;JetBrains 注意 Compose Multiplatform 中的 iOS 部分目前处于 Alpha 状态。以后可能会有不兼容的更改&#xff0c;届时也许需要手动进行迁移。 你可以使用这个模板来开发同时支持桌面、安卓和 iOS 的跨平…

杭电oj--求奇数的乘积

Problem Description 给你n个整数&#xff0c;求他们中所有奇数的乘积。 Input 输入数据包含多个测试实例&#xff0c;每个测试实例占一行&#xff0c;每行的第一个数为n&#xff0c;表示本组数据一共有n个&#xff0c;接着是n个整数&#xff0c;你可以假设每组数据必定至少存…

LDAP协议工作原理

LDAP&#xff0c;全称Lightweight Directory Access Protocol&#xff0c;译为轻量目录访问协议&#xff0c;是一个在互联网中广泛使用的协议&#xff0c;主要用于实现网络中的信息查找和检索。在身份认证方面&#xff0c;LDAP起着重要的作用。 LDAP的工作原理主要包括以下几个…

MySql分区介绍和Range案例

MySql分区介绍和Range案例 什么是表分区&#xff1f; 通俗地讲表分区是将一个大表&#xff0c;根据条件分割成若干个小表。mysql5.1开始支持数据表分区。 如&#xff1a;某用户表的记录超过了600万条仓储信息&#xff0c;那么就可以根据入库日期将表分区&#xff0c;也可以根…

神奇的python的生成器

函数生成器代码 def num():print("message 1")yield 1print("message 2")yield 2print("message 3")yield 3f num() x next(f) # message 1 print(x) # 输出1x next(f) # message 2 print(x) # 输出2x next(f) # message 3 print(x) …

【JVM系列】- 类加载子系统与加载过程

类加载子系统与加载过程 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xff0c;欢迎指正…

电子邮件地址注册过程详解

许多人可能对如何注册电子邮件地址感到困惑&#xff0c;本文将详细解析电子邮件地址的注册过程&#xff1a;确定邮箱厂商、创建邮箱账户、设置电子邮件地址。 1、确定要注册的邮箱厂商 首先我们需要确定要注册哪种类型的电子邮件服务。目前市场上有许多不同的电子邮件服务提供商…