本文将演示如何使用 RouterChain
范例创建一个Chain
,该Chain
动态选择用于给定输入的下一个Chain
。
路由器链由两个组件组成:
在本笔记本中,我们将重点关注不同类型的路由链。我们将展示在 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")
该链使用 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
使用嵌入和相似性在目标链之间进行路由。
相比上面,这里没有使用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
,进行路由。
Prompt
,利用MULTI_PROMPT_ROUTER_TEMPLATE.format()
方法得到router_template
。PromptTemplate
得到router_prompt
LLMRouterChain.from_llm(llm, router_prompt)
就得到router_chain
。MultiPromptChain()
,得到调用chain。方式二:利用embeddings,进行路由
names_and_descriptions
。EmbeddingRouterChain.from_names_and_descriptions()
得到router_chain
。MultiPromptChain()
,得到调用chain。参考地址:
https://python.langchain.com/docs/modules/chains/foundational/router