让 LLM 自动选择不同的 Prompt
在上一篇文章中,我们学会了如何让 langchain 来自动选择不同的 LLM Chain,以便回答不同的问题,只需要使用 RouterChain
和 MultiPromptChain
就可以实现这一功能。
但 MultiPromptChain
被设计出来并不只是为了实现不同 LLM Chain 的选择,我们还能用它来实现让 LLM 选择不同的 Prompt,原理跟 RouterChain
差不多,只不过选择的是 Prompt
而不是 LLM Chain
。
也就是说,其实另外一种场景是:使用相同的大语言模型,只是让它选择不同的 Prompt 来回答问题。
例子
下面是一个例子,我们使用 MultiPromptChain
来让 LLM 自动选择不同的 Prompt 来回答问题:
- 当我们问关于 Python 编程的问题时,LLM 会选择 Python 的 Prompt 来回答。
- 当我们问关于 Golang 编程的问题时,LLM 会选择 Golang 的 Prompt 来回答。
from langchain.chains.router import MultiPromptChain from langchain_openai import ChatOpenAI py_template = """ 你是一名 Python 工程师,擅长解答关于 Python 编程的问题。 下面是需要你来回答的问题: {input} """ go_template = """ 你是一名 Golang 工程师,擅长解答关于 Golang 编程的问题。 下面是需要你来回答的问题: {input} """ prompt_infos = [ { "name": "python", "description": "适合回答关于 Python 编程的问题", "prompt_template": py_template, }, { "name": "golang", "description": "适合回答关于 Golang 编程的问题", "prompt_template": go_template, } ] chain = MultiPromptChain.from_prompts( llm=ChatOpenAI(model="gpt-3.5-turbo", temperature=0), prompt_infos=prompt_infos, verbose=True ) print(chain.invoke({"input": "如何在 Python 中定义一个函数?"}))
原理
既然涉及到自动选择不同的 Prompt
的操作,其实底层还是使用了 RouterChain
,如果我们去看 from_prompts
代码,发现跟前一篇文章使用的是相同的 Prompt
,
也就是 MULTI_PROMPT_ROUTER_TEMPLATE
。
- 构建一个
router_prompt
,使用MULTI_PROMPT_ROUTER_TEMPLATE
模板,将所有Prompt
的信息传入。 - 使用
RouterChain
构建一个RouterChain
,并将router_prompt
传入。 - 构建
destination_chains
,这一步会为不同的Prompt
创建一个LLMChain
。 - 创建一个
default_chain
,这个链会在没有匹配到任何Prompt
时触发。 - 创建一个
MultiPromptChain
实例,将RouterChain
和default_chain
传入。
实际调用 chain.invoke
的时候,会经历如下过程:
- 将
RouterChain
的Prompt
(格式化之后的,带有我们的Prompt
简易描述)传递给 LLM,让 LLM 选择一个LLMChain
来处理。 - LLM 会根据输入的
Prompt
选择一个LLMChain
,然后调用这个LLMChain
(对应某个具体的Prompt
,也就是上面prompt_infos
中的一个)来处理输入。 - 如果没有匹配到任何
Prompt
,则会调用default_chain
来处理输入。 - 再次调用 LLM,让 LLM 回答用户的问题,最终,我们会得到一个回答。
自动选择 Prompt 的 Prompt
我们可以在 LangSmith 中看到实际发送给 LLM 选择 Prompt 的 Prompt 是怎样的:
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 >> python: 适合回答关于 Python 编程的问题 golang: 适合回答关于 Golang 编程的问题 << INPUT >> 如何在 Python 中定义一个函数? << OUTPUT (must include ```json at the start of the response) >> << OUTPUT (must end with ```) >>
说明:
- 先是一个简单的引导语句,告诉模型你将给它一个输入,它需要根据这个输入选择最适合的模型。
- 指定输出的格式,告诉模型输出应该是一个 JSON 对象。
- 一些关于输出的额外说明,比如如果没有匹配到任何
Prompt
,则应该返回DEFAULT
。 - 接着是所有可选的
Prompt
,以及它们的描述。 - 最后是用户输入的问题。
LLM 在拿到这个 Prompt
之后会进行分析推理,然后选择一个最适合的 Prompt
,然后返回给我们。
当然拿到选择的具体的 Prompt
之后,并不是拿到了最终的答案,接着,使用选中的 Prompt
以及用户的问题再次调用 LLM,最终得到一个回答。
总结
MultiPromptChain
是对 RouterChain
的一个扩展,它可以让 LLM 选择不同的 Prompt
来回答问题,这样我们可以更灵活地使用不同的 Prompt 来回答问题。
而 RouterChain
是可以自动选择不同的大模型来回答问题。也就是说:
- 如果我们只是想让 LLM 选择不同的 Prompt 来回答问题,可以使用
MultiPromptChain
。 - 如果我们想让 LLM 选择不同的大模型来回答问题,可以使用
RouterChain
结合MultiPromptChain
来实现。