Agent中tool selection该怎么做?

在 Agent 系统中,Tool Selection(工具选择) 是决定“当前该调用哪个工具”的关键决策环节。它直接影响推理效率、准确性和用户体验。根据系统复杂度和应用场景,有多种方法可选 —— 从简单规则到高级模型驱动均有成熟方案。


🧭 一、Tool Selection 的核心目标

  1. 准确性:选对工具,参数能填对
  2. 效率:避免试错、减少跳数
  3. 鲁棒性:面对模糊输入、工具变更仍能工作
  4. 可扩展性:新增工具时无需重写逻辑

🧩 二、主流 Tool Selection 方法分类

✅ 1. 基于 LLM 的自然语言推理(最主流)

让大语言模型(LLM)直接根据当前状态和可用工具列表,“思考”该调用哪个工具。

实现方式:

  • Prompt 工程:在 prompt 中列出工具描述 + 用户问题 + 当前观察 → 让 LLM 输出工具名和参数
  • Function Calling / Tool Calling(推荐):OpenAI、Anthropic、本地模型(如 Qwen、GLM、Llama3)原生支持结构化工具调用

📌 示例(OpenAI Function Calling):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名,如 Beijing"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
},
{
"name": "search_web",
"description": "用关键词搜索最新信息",
"parameters": { ... }
}
]

response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "北京今天适合出门吗?"}],
tools=tools,
tool_choice="auto"
)

# LLM 自动选择并结构化输出
tool_call = response.choices[0].message.tool_calls[0]
print(tool_call.function.name) # → "get_current_weather"

✅ 优点:

  • 灵活,支持复杂语义推理
  • 支持多工具、多参数、嵌套调用
  • 与 multi-hop reasoning 无缝集成

⚠️ 注意:

  • 需要高质量工具描述(description)
  • 需配合 约束解码 保证参数格式正确
  • 成本较高(token 消耗)

✅ 2. 基于 Embedding + 相似度检索(轻量级 / 快速)

将“用户问题”或“当前状态”编码为向量,与“工具描述向量”做相似度匹配,选最相关的工具。

实现步骤:

  1. 预计算所有工具的描述 Embedding(如用 text-embedding-3-small)
  2. 对当前 query 做 embedding
  3. 计算余弦相似度,取 Top-1 或 Top-K
  4. 可选:加一层 LLM 精排或参数填充

📌 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from sklearn.metrics.pairwise import cosine_similarity

# 工具库预编码
tool_embeddings = {
"get_weather": embed("获取某城市当前天气情况"),
"search_web": embed("搜索互联网上的最新信息"),
"calculator": embed("执行数学计算,如加减乘除、百分比等")
}

query = "北京今天多少度?"
query_emb = embed(query)

# 计算相似度
scores = {
name: cosine_similarity([query_emb], [emb])[0][0]
for name, emb in tool_embeddings.items()
}

best_tool = max(scores, key=scores.get) # → "get_weather"

✅ 优点:

  • 极快,适合高并发/低延迟场景
  • 不依赖 LLM,成本低
  • 可作为 LLM 的前置过滤器(减少候选工具数)

⚠️ 缺点:

  • 无法处理复杂意图(如“比较A和B”需要两个工具)
  • 无法自动填充参数
  • 描述质量敏感

✅ 3. 基于规则 / 关键词匹配(确定性系统)

人工编写 if-else 或正则规则匹配工具。

📌 示例:

1
2
3
4
5
6
7
8
9
10
def select_tool_by_rule(query: str) -> str:
query_lower = query.lower()
if "天气" in query_lower or "多少度" in query_lower:
return "get_weather"
elif "计算" in query_lower or re.search(r'\d+[\+\-\*\/]\d+', query):
return "calculator"
elif "查一下" in query_lower or "搜索" in query_lower:
return "search_web"
else:
return "general_chat"

✅ 优点:

  • 100% 可控、零幻觉
  • 速度快、零成本
  • 适合垂直领域(如客服、内部工具)

⚠️ 缺点:

  • 维护成本高(规则爆炸)
  • 泛化能力差
  • 无法处理复合意图

✅ 4. 混合方法(Hybrid)—— 推荐生产使用

“先用轻量方法筛选候选工具,再用 LLM 精选并填充参数”

典型架构:

1
2
3
4
5
6
7
用户输入

[Embedding 检索] → Top-3 工具候选

[LLM 精选 + 参数填充] → 最终工具调用

执行工具

📌 优势:

  • 减少 LLM 输入长度(只传 Top-K 工具描述)
  • 降低选错工具概率
  • 节省 token,提升速度
  • 易于扩展(加新工具只需更新 Embedding 库)

✅ 5. 基于强化学习 / 反馈学习(高级/研究向)

让 Agent 通过历史成功/失败案例,学习“在什么状态下选什么工具更好”。

  • 记录:状态 → 工具选择 → 结果(成功/失败/用户满意度)
  • 训练一个“工具选择策略模型”(可微调小模型如 BERT / T5)
  • 在线学习:根据用户反馈动态调整

✅ 适合:

  • 长期运行的个性化 Agent
  • 有大量用户交互日志的系统

⚠️ 门槛高,需数据闭环 + 模型训练 + A/B 测试


🧠 三、进阶技巧:提升 Tool Selection 质量

1. 工具描述(Tool Description)要写好!

❌ 差描述:

“获取天气”

✅ 好描述:

“获取指定城市当前的天气状况,包括温度、湿度、风速。适用于回答‘XX今天热吗?’‘该穿什么衣服?’等问题。参数 location 必填。”

📌 技巧:

  • 包含使用场景
  • 举例说明
  • 标注参数约束
  • 避免歧义词

2. 多工具协同选择(Multi-tool Selection)

有时一个问题需要多个工具按顺序调用,如:

“特斯拉和苹果哪家市值更高?” → 需先后调用两次 get_market_cap

→ 可让 LLM 输出多个 tool_calls(GPT-4o / Claude 3 支持),或分步决策。


3. 上下文感知选择(Context-aware)

不只是看当前 query,还要结合:

  • 历史对话
  • 已执行的工具和结果
  • 用户画像/偏好

→ 在 LangGraph 中,这些都在 State 里,可一并传给 LLM 做决策。


4. 工具分组 / 分层选择(Hierarchical)

工具太多时(>20个),可先选“工具类别”,再选具体工具:

1
2
3
用户问:“帮我订明天从北京到上海的机票”
→ 第一层:选择“出行类工具”
→ 第二层:在“出行类”中选择“book_flight”

降低 LLM 选择负担,提升准确率。


🧪 四、在 LangGraph 中如何实现?

你可以在一个 node 中实现工具选择逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def tool_selection_node(state: AgentState) -> AgentState:
# 获取当前 query + 上下文
context = f"用户问题:{state.input}\n已知信息:{state.current_observation}"

# 方法1:直接 LLM Function Calling
selected_tool_call = llm_with_tools.invoke(
[{"role": "user", "content": context}],
tools=TOOL_DEFINITIONS,
tool_choice="auto"
)

# 方法2:混合模式 — 先检索,再 LLM
# candidate_tools = embedding_retriever.retrieve(context, top_k=3)
# selected_tool_call = llm_with_tools.invoke(..., tools=candidate_tools)

return {
**state,
"next_tool": selected_tool_call.function.name,
"next_parameters": json.loads(selected_tool_call.function.arguments),
"selected_tool_call": selected_tool_call # 供后续节点使用
}

然后在图中:

1
2
3
4
builder.add_node("select_tool", tool_selection_node)
builder.add_node("execute_tool", execute_tool_node)

builder.add_edge("select_tool", "execute_tool")

📊 五、方法对比表

方法 准确性 速度 成本 可控性 适用场景
LLM Function Calling ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐ ⭐⭐ 通用 Agent、复杂任务
Embedding 检索 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ 高并发、简单意图、前置过滤
规则匹配 ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 垂直领域、确定性系统
混合方法 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ 生产级推荐方案
强化学习 ⭐⭐⭐⭐ ⭐⭐ ⭐⭐ 长期个性化 Agent(研究/高级)

✅ 最佳实践建议

  1. 起步用 LLM Function Calling —— 快速原型,能力最强
  2. 生产环境用 Hybrid(Embedding + LLM) —— 平衡速度、成本、准确率
  3. 关键系统加规则兜底 —— 如“重启服务器”等高危操作,必须人工确认或规则限制
  4. 记录选择日志 —— 用于后续分析、优化工具描述或训练模型
  5. 定期评估工具选择准确率 —— 定义评估集,监控下降趋势

🎯 一句话总结

在 Agent 中,Tool Selection 推荐使用 “LLM Function Calling” 或 “Embedding + LLM 混合方法”,并结合高质量工具描述、上下文感知和状态记录(如 LangGraph State),实现准确、高效、可控的工具决策。

合理选型,可让你的 Agent 从“乱调工具”升级为“运筹帷幄”。

如需,我可以提供一个完整的 LangGraph + Tool Selection + 跳数控制的可运行示例 👍