【LangChain】路由(Router)

LangChain学习文档

  • 基础
    • 【LangChain】LLM
    • 【LangChain】路由(Router)

概述

本文将演示如何使用 RouterChain 范例创建一个Chain,该Chain动态选择用于给定输入的下一个Chain
路由器链由两个组件组成:

  • RouterChain 本身(负责选择下一个要调用的链)
  • destination_chains:路由器链可以路由到的链

在本笔记本中,我们将重点关注不同类型的路由链。我们将展示在 MultiPromptChain 中使用的这些路由链,以创建一个问答链,该问答链选择与给定问题最相关的提示,然后使用该提示回答问题。

内容

from langchain.chains.router import MultiPromptChain
from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate

# 主要创建两个知识域的模板,一个物理学、一个数学

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise and easy to understand manner. \
When you don't know the answer to a question you admit that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. You are great at answering math questions. \
You are so good because you are able to break down hard problems into their component parts, \
answer the component parts, and then put them together to answer the broader question.

Here is a question:
{input}"""

设置prompt_infos,这里有点像tools工具。

prompt_infos = [
    {
        "name": "physics",
        "description": "Good for answering questions about physics",
        "prompt_template": physics_template,
    },
    {
        "name": "math",
        "description": "Good for answering math questions",
        "prompt_template": math_template,
    },
]

llm = OpenAI()

# 下面这段主要通过遍历得到destination_chains
destination_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)
    destination_chains[name] = chain
# 得到一个起始chain
default_chain = ConversationChain(llm=llm, output_key="text")

LLMRouterChain

该链使用 LLM 来确定如何路由。

from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE

destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)
# physics: Good for answering questions about physics
# math: Good for answering math questions
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)
# 得到路由链
router_chain = LLMRouterChain.from_llm(llm, router_prompt)
# 参数:路由Chain、目标chain、兜底chain
chain = MultiPromptChain(
    router_chain=router_chain,
    destination_chains=destination_chains,
    default_chain=default_chain,
    verbose=True,
)
print(chain.run("什么是黑体辐射?"))

结果:

    
    
    > Entering new MultiPromptChain chain...
    # 注意这里physics,说明调用的是物理知识域
    physics: {'input': '什么是黑体辐射?'}
    > Finished chain.
    
    黑体辐射是用于描述“黑体”发射的电磁辐射的术语,“黑体”是吸收入射到其上的所有辐射的物体。黑体是一种理想化的物理体,它吸收所有入射电磁辐射,无论频率或入射角度如何。它不反射、发射或传输能量。这种类型的辐射是人体原子和分子热运动的结果,并且以所有波长发射。发射的辐射光谱由普朗克定律描述,称为黑体光谱。
print(
    chain.run(
        "第一个大于 40 的质数是多少,且该质数的一加能被 3 整除"
    )
)

结果:

    
    
    > Entering new MultiPromptChain chain...
    # 注意这里math,说明调用的是数学知识域
    math: {'input': 'What is the first prime number greater than 40 such that one plus the prime number is divisible by 3'}
    > Finished chain.
    ?
    
    答案是 43。一加 43 等于 44,可以被 3 整除。
print(chain.run("冲洗的云类型的名称是什么"))

结果:

    > Entering new MultiPromptChain chain...
    # 注意这里是None,说明走的是default chain
    None: {'input': 'What is the name of the type of cloud that rains?'}
    > Finished chain.
     下雨的云类型称为积雨云。它是一种高大而浓密的云,经常伴随着雷电。

EmbeddingRouterChain

EmbeddingRouterChain 使用嵌入相似性在目标链之间进行路由。
相比上面,这里没有使用llm,来进行路由。

from langchain.chains.router.embedding_router import EmbeddingRouterChain
from langchain.embeddings import CohereEmbeddings
from langchain.vectorstores import Chroma

names_and_descriptions = [
    ("physics", ["for questions about physics"]),
    ("math", ["for questions about math"]),
]

router_chain = EmbeddingRouterChain.from_names_and_descriptions(
    names_and_descriptions, Chroma, CohereEmbeddings(), routing_keys=["input"]
)

使用没有持久性的嵌入式 DuckDB:数据将是暂时的

chain = MultiPromptChain(
    router_chain=router_chain,
    destination_chains=destination_chains,
    default_chain=default_chain,
    verbose=True,
)
print(chain.run("什么是黑体辐射?"))
    
    
    > Entering new MultiPromptChain chain...
    # 由此可知,路由到了物理知识域
    physics: {'input': 'What is black body radiation?'}
    > Finished chain.
    
    黑体辐射是来自与其环境处于热平衡的理想化物理体(称为黑体)的能量发射。它以称为黑体频谱的特征频率模式发射,该频率仅取决于物体的温度。黑体辐射的研究是天体物理学和大气物理学的重要组成部分,恒星和行星发出的热辐射通常可以近似为黑体辐射。
print(
    chain.run(
        "第一个大于 40 的质数是多少,且该质数的一加能被 3 整除"
    )
)

结果:

    
    
    > Entering new MultiPromptChain chain...
    # 由此可知,路由到了数学知识域
    math: {'input': 'What is the first prime number greater than 40 such that one plus the prime number is divisible by 3'}
    > Finished chain.
    ?
    
    答案:第一个大于 40 的质数,并且该质数的一加能被 3 整除,是 43

总结

本文主要教我们如何路由不同的prompt

方式一:利用LLM,进行路由。

  1. 创建多个Prompt,利用MULTI_PROMPT_ROUTER_TEMPLATE.format()方法得到router_template
  2. 再利用PromptTemplate得到router_prompt
  3. 利用LLMRouterChain.from_llm(llm, router_prompt)就得到router_chain
  4. 最后使用MultiPromptChain(),得到调用chain。

方式二:利用embeddings,进行路由

  1. 创建names_and_descriptions
  2. 利用EmbeddingRouterChain.from_names_and_descriptions()得到router_chain
  3. 最后使用MultiPromptChain(),得到调用chain。

参考地址:

https://python.langchain.com/docs/modules/chains/foundational/router

你可能感兴趣的:(LangChain,AI,langchain)