🎯 课程主题
讲解 create_agent() 中 tools 参数的使用,包括自定义工具、内置工具以及多工具绑定与调用。
📝 核心知识点
1. Agent绑定工具的两种方式
- 概念说明:Agent支持静态和动态两种工具绑定方式。静态方式直接传入
tools参数(本节内容),动态方式需借助下一章的中间件。 - 关键细节:
tools参数接收一个工具列表,create_agent(model=..., tools=[tool1, tool2, ...])。
2. 工具调用流程
- 概念说明:Agent接收到用户消息后,内部模型会分析是否需要调用工具。
- 关键细节:
- 不需要工具 → 直接生成 AIMessage 返回
- 需要工具 → 生成包含
tool_calls的 AIMessage → 执行工具 → 生成 ToolMessage → 模型结合结果生成最终 AIMessage - 可能多次循环(工具失败重试、多个工具递进调用等)
3. 自定义工具
- 概念说明:使用
@tool装饰器定义工具,需包含清晰的 docstring。 - 关键细节:工具的描述(docstring)是Agent判断是否调用该工具的关键依据。
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""查询指定城市的天气信息"""
return f"{city}天气晴朗,温度15℃"
4. 内置工具(以TavilySearch为例)
- 概念说明:LangChain内置了大量工具,可直接导入使用。
- 关键细节:
TavilySearch提供联网搜索能力,每月1000次免费额度- 需在 Tavily官网 注册获取 API Key
- 配置环境变量后通过
TavilySearch(max_results=2, tavily_api_key=os.getenv("TAVILY_API_KEY"))创建
from langchain_community.tools.tavily_search import TavilySearch
web_search = TavilySearch(
max_results=2,
tavily_api_key=os.getenv("TAVILY_API_KEY")
)
5. 多工具绑定
- 概念说明:
tools列表中可以放入多个工具,Agent会根据用户问题自动选择合适的工具。 - 关键细节:当一个问题涉及多个工具时,Agent会依次调用,中间结果会全部记录在响应消息列表中。
🏗️ 架构与工作流
用户消息 (HumanMessage)
↓
Agent 分析 → 需要工具?
↓ 是
AIMessage (含 tool_calls) → 执行工具 → ToolMessage
↓ ↓
←←←←←←←← 模型整合结果 ←←←←←←←←←
↓ 否
最终 AIMessage (不含 tool_calls)
图结构示例(绑定 get_weather 工具后):
start → model → [条件判断] → tools(get_weather) → model → [条件判断] → end
💻 代码实战
import os
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langchain_core.tools import tool
from langchain_community.tools.tavily_search import TavilySearch
from rich import print as rprint
load_dotenv()
# ========== 示例一:自定义工具 ==========
@tool
def get_weather(city: str) -> str:
"""查询指定城市的天气信息"""
return f"{city}天气晴朗,温度15℃"
model = ChatDeepSeek(model="deepseek-chat")
agent = create_agent(model=model, tools=[get_weather])
response = agent.invoke({
"messages": [
{"role": "system", "content": "你是一个查询天气的助手,根据用户提问查询天气。如果问题与天气无关,可以说你不清楚。"},
{"role": "user", "content": "北京的天气如何?"}
]
})
rprint(response)
# 消息列表:SystemMessage → HumanMessage → AIMessage(含tool_calls) → ToolMessage → AIMessage(最终答案)
# ========== 示例二:内置工具 ==========
web_search = TavilySearch(max_results=2, tavily_api_key=os.getenv("TAVILY_API_KEY"))
agent2 = create_agent(model=model, tools=[web_search])
response2 = agent2.invoke({
"messages": [{"role": "user", "content": "帮我查询2024年诺贝尔物理学奖得主是谁"}]
})
rprint(response2)
# ========== 示例三:多工具绑定 ==========
@tool
def get_news() -> str:
"""获取今天的新闻头条"""
return "今日头条:AI技术取得重大突破!"
agent3 = create_agent(model=model, tools=[get_weather, get_news])
response3 = agent3.invoke({
"messages": [
"杭州的天气如何?今天有哪些新闻?"
]
})
rprint(response3)
# 消息列表会包含两个 AIMessage(含tool_calls) 和两个 ToolMessage
⚠️ 常见问题与避坑指南
- 工具的描述(docstring)极其重要——它是Agent判断是否调用该工具的唯一依据,必须清晰准确。
- 内置工具可能需要单独的 API Key 和网络环境。
- 与裸模型(LLM)不同,Agent能够自动执行工具调用,无需手动调用
tool.invoke()。 - 多工具绑定时,Agent会自动选择匹配的工具,调用顺序由内部推理决定。
💡 个人总结与延伸
工具绑定是Agent能力的核心扩展点。LangChain 1.0的 create_agent 将工具调用的编排过程全自动化——用户只需声明工具有哪些,Agent内部基于LangGraph自动完成"推理→调用→观察→再推理"的ReAct循环。工具数量建议控制在2~5个,太多或描述相似的工具有可能导致Agent选错工具。