如何在LangChain中实现模型自动选择多提示词执行任务?
以下几种方法可以解决模型自动选择对应提示词的问题,同时避开输入变量不匹配的坑:
1. 前置意图分类判断
先通过大模型把用户问题分成「文档问答」和「发票表格生成」两类,再针对性调用对应的提示词和传入变量,逻辑直接清晰。
示例代码(基于LangChain):
from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate # 意图分类提示词,只要求输出指定标签 intent_prompt = ChatPromptTemplate.from_messages([ ("system", "用户的请求只有两种类型:1. 文档问答(需基于给定上下文回答);2. 生成发票表格(需输出JSON格式发票)。只输出对应的标签:DOC_QA 或 INVOICE_TABLE。"), ("human", "{user_question}") ]) llm = ChatOpenAI(temperature=0) intent_chain = intent_prompt | llm # 示例:处理用户问题 user_question = "帮我把聊天里的交易记录做成发票表格" intent = intent_chain.invoke({"user_question": user_question}).content # 根据意图执行对应逻辑 if intent == "DOC_QA": # 传入文档问答所需的全部变量 doc_qa_prompt.invoke({ "context": "你的文档上下文内容", "question": user_question, "chat_history": "之前的聊天记录", "username": "用户名" }) elif intent == "INVOICE_TABLE": # 只传入发票生成所需的聊天历史 invoice_prompt.invoke({ "chat_history": "之前的聊天记录" })
2. 使用LangChain RouterChain路由链
LangChain的RouterChain专门为多提示词场景设计,可以自动判断用户请求应该走哪个任务链,同时处理变量传递,完美解决之前pipeline的变量不匹配问题。
示例代码:
from langchain.chains.router import MultiPromptChain from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser from langchain.prompts import PromptTemplate from langchain.chat_models import ChatOpenAI # 定义两个任务的提示词模板 doc_qa_template = """你是文档问答助手,基于给定上下文回答用户问题,参考聊天历史并称呼用户名。 上下文:{context} 聊天历史:{chat_history} 用户名:{username} 用户问题:{question} 回答:""" invoice_template = """根据聊天历史生成JSON格式的发票表格,字段包含:发票编号、日期、商品名称、数量、单价、总价。 聊天历史:{chat_history} 输出JSON:""" # 定义每个任务的路由信息 prompt_infos = [ { "name": "文档问答", "description": "处理需要基于文档上下文回答的问题", "prompt_template": doc_qa_template }, { "name": "发票表格生成", "description": "根据聊天记录生成JSON发票表格", "prompt_template": invoice_template } ] # 生成路由提示词,让模型判断任务并输出变量映射 router_template = """给定用户输入,判断该用哪个任务链处理,按指定JSON格式输出: ```json {{"destination": "任务名称", "next_inputs": {{输入变量键值对}}}}
可选任务:
{destinations}
用户输入:{input}
注意:文档问答需传入context、question、chat_history、username;发票生成只需传入chat_history。"""
router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
partial_variables={"destinations": "\n".join([f"{p['name']}: {p['description']}" for p in prompt_infos])},
output_parser=RouterOutputParser()
)
llm = ChatOpenAI(temperature=0)
router_chain = LLMRouterChain.from_llm(llm, router_prompt)
destination_chains = {}
for p_info in prompt_infos:
prompt = PromptTemplate(
template=p_info["prompt_template"],
input_variables=PromptTemplate.from_template(p_info["prompt_template"]).input_variables
)
destination_chains[p_info["name"]] = prompt | llm
multi_prompt_chain = MultiPromptChain(
router_chain=router_chain,
destination_chains=destination_chains,
default_chain=destination_chains["文档问答"], # 设置默认任务
verbose=True
)
multi_prompt_chain.invoke({
"input": "根据上下文说下产品保修政策",
"context": "产品保修1年,非人为损坏免费维修",
"chat_history": "[用户:你好,产品保修多久?]",
"username": "张三"
})
multi_prompt_chain.invoke({
"input": "把刚才的交易记录做成发票表格",
"chat_history": "[用户:我买了2个笔记本,每个50元;1支钢笔20元]",
})
## 3. 单提示词动态分支(适合简单场景) 把两个任务的逻辑整合到一个提示词里,让大模型自行判断执行哪个任务,同时允许部分变量为空(比如发票任务不需要context和username)。 示例提示词: ```python combined_prompt = """你需要根据用户请求执行以下两个任务之一: 任务1【文档问答】:当用户问题需要基于给定上下文回答时,参考聊天历史并称呼用户名,输出自然语言回答。可用变量:context、question、chat_history、username 任务2【发票表格生成】:当用户需要生成发票时,根据聊天历史输出JSON格式的发票表格,字段包含发票编号、日期、商品名称、数量、单价、总价。可用变量:chat_history 请先判断任务类型再执行: 用户请求:{user_question} 上下文(可选):{context} 聊天历史:{chat_history} 用户名(可选):{username} 输出:"""
内容的提问来源于stack exchange,提问作者Faiq Aslam

