🎯 课程主题
讲解 tool_choice 参数的使用,控制模型在调用工具时的行为选择:不调用工具、自主选择、强制调用、以及强制调用指定工具。
📝 核心知识点
1. tool_choice 参数概述
- 概念说明:
tool_choice是在model.bind_tools()中设置的参数,用于控制模型对工具的选择策略。该字段最终会作为 payload 中的tool_choice传递给模型 API。 - 关键细节:OpenAI 和 DeepSeek 等主流模型对该参数的支持规范一致。
2. 四种取值及行为
"none":不调用任何工具。即使模型分析出问题需要调用工具,也不执行。"auto"(默认值):模型自主决定是否调用以及调用哪个工具。前面所有案例默认都是此行为。"required":强制要求模型必须调用某个工具。即使问题与工具完全无关(如 "2+3=?"),模型也会尝试调用。- 指定工具名(如
"get_weather2"):强制调用指定的那个工具。可传入工具名称字符串或工具对象,用于精确控制工具选择。
3. "any" 与 "required" 等价
- 概念说明:
tool_choice="any"等效于tool_choice="required",均表示必须调用工具。
🏗️ 架构与工作流
model.bind_tools(tools, tool_choice="none") → 永不调用工具
model.bind_tools(tools, tool_choice="auto") → 自动决定
model.bind_tools(tools, tool_choice="required") → 必须调用(任意工具)
model.bind_tools(tools, tool_choice="tool_name") → 强制调用指定工具
💻 代码实战
from langchain_core.tools import tool
from pydantic import BaseModel, Field
from langchain_deepseek import ChatDeepSeek
# ========== 工具定义 ==========
class WeatherInput(BaseModel):
city: str = Field(description="城市名称", default="北京")
@tool(args_schema=WeatherInput)
def get_weather1(city: str) -> str:
"""查询城市天气(版本1)"""
return f"[v1] {city}今天晴天,25°C"
@tool(args_schema=WeatherInput)
def get_weather2(city: str) -> str:
"""查询城市天气(版本2)"""
return f"[v2] {city}今天多云,22°C"
model = ChatDeepSeek(model="deepseek-chat")
# ========== 1. tool_choice = "none" ==========
model_none = model.bind_tools([get_weather1], tool_choice="none")
response = model_none.invoke("北京今天天气如何?")
print(response.tool_calls) # 输出: [] —— 不调用工具
# ========== 2. tool_choice = "auto" ==========
model_auto = model.bind_tools([get_weather1], tool_choice="auto")
response = model_auto.invoke("北京今天天气如何?")
print(response.tool_calls) # 输出: [{'name': 'get_weather1', ...}] —— 正常调用
response = model_auto.invoke("2+3等于多少?")
print(response.tool_calls) # 输出: [] —— 不需要工具,不调用
# ========== 3. tool_choice = "required" ==========
model_required = model.bind_tools([get_weather1], tool_choice="required")
response = model_required.invoke("2+3等于多少?")
print(response.tool_calls) # 输出: [{'name': 'get_weather1', ...}] —— 强制调用!
# ========== 4. 强制调用指定工具 ==========
model_force = model.bind_tools(
[get_weather1, get_weather2],
tool_choice="get_weather2" # 强制使用 get_weather2
)
response = model_force.invoke("北京今天天气如何?")
print(response.tool_calls) # 输出: [{'name': 'get_weather2', ...}]
⚠️ 常见问题与避坑指南
- 设为
"required"后,即使问"1+1等于几"这种无关问题,模型也会强制调用工具,这可能导致工具参数被随意填充(如 city 被填成随机值)。 - 指定工具名时,需要确保传入的名称与工具注册名称一致;如果工具不存在,可能会报错或行为异常。
tool_choice参数会影响模型的行为模式,测试时需针对性设计测试用例。
💡 个人总结与延伸
tool_choice 是细粒度控制工具调用的关键参数。在实际应用中,"required" 可用于确保 Agent 在特定场景下必须执行某个工具(如安全审核必须调用内容过滤器),而指定工具名则可用于 A/B 测试多个版本的同类工具。需要注意的是,过度使用强制调用可能导致不合理的工具参数,需要配合健壮的工具内部逻辑处理。