如何基于Ollama本地模型实现上下文感知式工具路由?
针对本地LLM的上下文感知工具路由实现方案
方案一:基于Prompt工程的意图识别与工具调用
通过优化Prompt引导llama3.2理解工具调用场景,输出结构化指令后解析执行,无需依赖模型原生工具调用能力。
步骤1:更新Prompt模板,明确工具规则
修改LLMService中的prompt_template,加入工具说明、触发条件和结构化输出要求:
self.prompt_template = PromptTemplate.from_template(""" 你是{firm_name}会计网站的助手,可使用以下工具处理问题: - 账户查询工具:处理账户余额、交易记录、账单明细等账户相关需求 - 会计法规查询工具:处理会计法规、报税要求、合规政策等查询需求 - 直接回答:处理一般性会计咨询或{firm_name}网站信息类问题 工具调用格式要求: 需调用工具时,严格输出:<TOOL_CALL>工具名称|参数</TOOL_CALL> 示例:<TOOL_CALL>账户查询工具|用户ID:123, 查询范围:最近30天交易</TOOL_CALL> 无需调用工具时,直接按原有规则回答问题 上下文历史:{chat_history} 用户问题:{question} Context: {context} 输出: """)
步骤2:添加工具解析与执行逻辑
在LLMService中新增方法,解析模型输出并调用对应工具:
class LLMService: # 原有代码保持不变... def process_response(self, llm_response): # 检测并解析工具调用指令 if "<TOOL_CALL>" in llm_response: tool_segment = llm_response.split("<TOOL_CALL>")[1].split("</TOOL_CALL>")[0] tool_name, tool_params = tool_segment.split("|", 1) # 分发到对应工具执行逻辑 if tool_name == "账户查询工具": return self._run_account_query(tool_params) elif tool_name == "会计法规查询工具": return self._run_regulation_query(tool_params) # 无工具调用则返回原回答 return llm_response def _run_account_query(self, params): # 替换为真实账户查询工具逻辑 param_dict = dict(item.strip().split(":") for item in params.split(",")) return f"已查询用户{param_dict.get('用户ID')}的{param_dict.get('查询范围')}:余额15600元,交易共7笔" def _run_regulation_query(self, params): # 替换为真实法规查询工具逻辑 return f"查询到{params}相关法规:小规模纳税人季报需提交增值税申报表、财务报表等材料"
步骤3:整合到对话流程
生成响应后先处理工具调用:
# 示例调用流程 prompt = llm_service.get_prompt().format( chat_history=llm_service.get_memory().load_memory_variables({})["chat_history"], question="我最近一个月的账户交易记录有多少?", context="" ) raw_response = llm_service.get_llm().invoke(prompt) final_response = llm_service.process_response(raw_response)
方案二:使用LangChain结构化输出解析器
借助LangChain的StructuredOutputParser实现标准化工具调用判断,提升解析可靠性。
步骤1:定义工具调用的结构化输出规则
from langchain.output_parsers import StructuredOutputParser, ResponseSchema # 定义输出结构 response_schemas = [ ResponseSchema(name="tool_name", description="工具名称,可选值:account_query, regulation_query, none"), ResponseSchema(name="tool_params", description="工具参数,JSON格式,无需调用时为{}"), ResponseSchema(name="direct_answer", description="无需调用工具时的回答内容,调用工具时为空") ] output_parser = StructuredOutputParser.from_response_schemas(response_schemas) format_instructions = output_parser.get_format_instructions()
步骤2:更新Prompt模板
self.prompt_template = PromptTemplate.from_template(""" 你是{firm_name}会计网站的助手,根据用户问题选择对应操作: - account_query:处理账户相关查询 - regulation_query:处理法规政策查询 - none:直接回答问题 请严格按照以下格式输出: {format_instructions} 上下文历史:{chat_history} 用户问题:{question} Context: {context} """)
步骤3:解析输出并执行工具
# 生成并解析响应 prompt = llm_service.get_prompt().partial( format_instructions=format_instructions, firm_name="GL" ) input_prompt = prompt.format( chat_history=llm_service.get_memory().load_memory_variables({})["chat_history"], question="小规模纳税人季报需要准备什么?", context="" ) raw_response = llm_service.get_llm().invoke(input_prompt) parsed_result = output_parser.parse(raw_response) # 执行对应逻辑 if parsed_result["tool_name"] == "account_query": final_response = llm_service._run_account_query(parsed_result["tool_params"]) elif parsed_result["tool_name"] == "regulation_query": final_response = llm_service._run_regulation_query(parsed_result["tool_params"]) else: final_response = parsed_result["direct_answer"]
方案三:微调llama3.2(进阶)
如果需要更高精度的意图识别,可使用工具调用样本微调模型:
- 准备微调样本,格式示例:
用户问题:我的账户余额是多少? 工具调用:account_query|{"user_id": "123", "query_type": "balance"} --- 用户问题:一般纳税人报税截止日期是什么时候? 工具调用:regulation_query|{"topic": "一般纳税人报税截止日期"} --- 用户问题:你们公司的联系方式是什么? 工具调用:none
- 通过Ollama执行微调:
ollama create fine-tuned-llama3.2 -f Modelfile
Modelfile示例:
FROM llama3.2 ADAPTER "./微调数据集.jsonl" PARAMETER temperature 0.1
内容的提问来源于stack exchange,提问作者Ahmad Ali
相关产品推荐
相关产品推荐

