4. 实现多工具选择的Agent
任务目标
构建一个具备工具选择能力的Agent:解析用户自然语言请求,自动匹配并调用最合适的工具(搜索或计算器)完成任务。本案例聚焦工具选择与调用的核心机制,不涉及工具内部的具体实现细节。
核心实现
import re
from typing import Callable, Dict
# ---------- 工具定义 ----------
def search_tool(query: str) -> str:
"""模拟搜索引擎,返回格式化结果"""
return f"[搜索] 关于'{query}'的模拟结果:找到3条相关条目"
def calculator_tool(expression: str) -> str:
"""安全计算器:仅支持数字与四则运算"""
# 移除空白字符,仅保留数字、运算符、括号和小数点
cleaned = re.sub(r'[^\d+\-*/().]', '', expression)
if not cleaned or cleaned != expression.strip():
return "[计算器] 错误:表达式包含非法字符"
try:
# 使用eval但已通过白名单过滤,仅限数学表达式
result = eval(cleaned, {"__builtins__": {}}, {})
return f"[计算器] {expression} = {result}"
except Exception:
return "[计算器] 错误:无法计算该表达式"
# ---------- 工具注册表 ----------
TOOLS: Dict[str, Dict[str, Callable]] = {
"search": {
"description": "搜索互联网信息,适用于查询新闻、知识、事实等",
"keywords": ["搜索", "查找", "查询", "搜一下", "了解", "什么是"],
"function": search_tool
},
"calculator": {
"description": "执行数学计算,适用于算术表达式求值",
"keywords": ["计算", "算一下", "多少", "等于", "加减乘除"],
"function": calculator_tool
}
}
# ---------- 工具选择逻辑 ----------
def select_tool(user_input: str) -> str:
"""根据用户输入选择最合适的工具名称"""
# 优先级1:显式工具名匹配
for tool_name in TOOLS:
if tool_name in user_input.lower():
return tool_name
# 优先级2:关键词匹配(计算器优先,避免"查询计算结果"歧义)
for tool_name, config in TOOLS.items():
if tool_name == "calculator":
continue
for kw in config["keywords"]:
if kw in user_input:
return tool_name
# 优先级3:检测数学表达式模式(如"3+5*2")
if re.search(r'\d+\s*[\+\-\*/]\s*\d+', user_input):
return "calculator"
# 优先级4:计算器关键词兜底
for kw in TOOLS["calculator"]["keywords"]:
if kw in user_input:
return "calculator"
return "search" # 默认搜索
# ---------- Agent主流程 ----------
def agent_execute(user_input: str) -> str:
"""Agent入口:选择工具并执行"""
tool_name = select_tool(user_input)
tool_config = TOOLS[tool_name]
# 提取工具参数(简化:搜索取整句,计算器提取表达式)
if tool_name == "calculator":
# 提取第一个数学表达式
match = re.search(r'[\d\s+\-*/().]+', user_input)
param = match.group(0).strip() if match else user_input
else:
# 搜索:去除常见前缀词后作为查询
param = re.sub(r'^(请|帮我|搜索|查找|查询|搜一下|了解一下)\s*', '', user_input)
return tool_config["function"](param)
# ---------- 验证入口 ----------
if __name__ == "__main__":
test_cases = [
"请搜索人工智能最新进展",
"计算 25*4+18/2",
"帮我查一下Python的创始人",
"3.5*2+7等于多少",
"搜索量子计算是什么"
]
for case in test_cases:
print(f"输入: {case}")
print(f"输出: {agent_execute(case)}\n")
运行与验证
运行方式:将代码保存为 agent_tool_selector.py,执行 python agent_tool_selector.py。
验证方法:观察输出是否符合以下预期(代码逻辑可唯一推出):
- 包含"搜索"或"查询"的输入 → 调用搜索工具,返回
[搜索]前缀结果 - 包含"计算"或数学表达式(如
25*4+18/2)→ 调用计算器,返回正确数值结果 - 混合输入(如"搜索量子计算是什么")→ 正确识别为搜索意图
通过条件:5个测试用例均返回对应工具的结果,且计算器输出数值与手动计算一致(如25*4+18/2 = 109.0)。
关键说明
- 工具选择采用多级匹配策略:显式工具名 → 搜索关键词 → 数学模式识别 → 计算器关键词 → 默认搜索,确保常见请求能正确路由。
- 计算器通过正则白名单过滤非法字符,仅允许数字、四则运算符、括号和小数点,避免任意代码执行风险。
- 搜索工具为模拟实现,实际工程中可替换为真实API调用(如SerpAPI、Bing Search),只需保持相同函数签名即可。
- 参数提取采用简化策略:搜索取整句(去除前缀),计算器提取第一个数学表达式。更复杂的槽位填充可引入LLM或正则增强。