# 04 - Custom Tools (自定义工具)
# 核心概念
# 工具 (Tool) = 给 AI 的函数
# 使用 @tool 装饰器,让 AI 能调用你的 Python 函数。
# @tool 基本用法
import json
from turtle import st
from langchain.tools import tool
@tool
def get_weather(city: str) -> str:
"""
获取指定城市的天气信息
参数:
city: 城市名称,如"北京"、"上海"
返回:
天气信息字符串
"""
# 你的实现
return "晴天,温度 15°C"
# 关键要点
# 必需项 说明
# @tool 装饰器 声明这是一个工具
# docstring AI 读这个来理解工具用途 ⚠️ 非常重要!
# 类型注解 参数和返回值的类型
# 返回 str 工具应该返回字符串(AI 最容易理解)
# 工具的 docstring
# AI 依赖 docstring 来理解工具!
@tool
def my_tool(param: str) -> str:
"""
工具的简短描述(AI 读这个!)
参数:
param: 参数说明
返回:
返回值说明
"""
# 好的 vs 不好的 docstring
# ❌ 不好:太模糊
@tool
def tool1(x: str) -> str:
"""做一些事情"""
...
# ✅ 好:清晰明确
@tool
def search_products(query: str) -> str:
"""
在产品数据库中搜索产品
参数:
query: 搜索关键词,如"笔记本电脑"、"手机"
返回:
产品列表的 JSON 字符串
"""
# 参数类型
# 1. 单参数
# @tool
# def get_weather(city: str) -> str:
# """获取指定城市的天气"""
# ...
# 2. 多参数
@tool
def calculator(operation: str, a: float, b: float) -> str:
"""
执行数学计算
参数:
operation: "add", "subtract", "multiply", "divide"
a: 第一个数字
b: 第二个数字
"""
# 3. 可选参数
from typing import Optional
@tool
def web_search(query: str, num_results: Optional[int] = 3) -> str:
"""
搜索网页
参数:
query: 搜索关键词
num_results: 返回结果数量,默认 3
"""
# 调用工具
# 工具有两种调用方式:
# 1. 直接调用(测试用)
# result = get_weather.invoke({"city": "北京"})
# print(result) # "晴天,温度 15°C"
from init_model import get_chat_model
chat_model = get_chat_model()
# 2. 绑定到模型(让 AI 调用)
model_with_tools = chat_model.bind_tools([get_weather])
# # AI 可以决定是否调用工具
# response = model_with_tools.invoke("北京天气如何?")
# # 检查 AI 是否要调用工具
# if response.tool_calls:
# print("AI 想调用工具:", response.tool_calls)
# # print("AI 调用工具结果:", response.additional_kwargs["function_call"]["arguments"])
# else:
# print("AI 直接回答:", response.content)
# 工具属性
# 创建工具后,可以查看其属性:
@tool
def my_tool(param: str) -> str:
"""工具描述"""
...
print(my_tool.name) # "my_tool"
print(my_tool.description) # "工具描述"
print(my_tool.args) # 参数模式
# 最佳实践
# 1. 清晰的描述
@tool
def search_flights(origin: str, destination: str, date: str) -> str:
"""
在航班数据库中搜索航班
参数:
origin: 出发地,如"北京"
destination: 目的地 如"上海"
date: 日期,格式 "YYYY-MM-DD"
返回:
航班列表的 JSON 字符串
"""
# 2. 功能单一
# ❌ 不好:一个工具做太多事
# @tool
# def do_everything(action: str, data: str) -> str:
# """做各种事情"""
# if action == "weather":
# ...
# elif action == "calculate":
# ...
# elif action == "search":
# ...
# # ✅ 好:每个工具做一件事
# @tool
# def get_weather(city: str) -> str:
# """获取天气"""
# ...
# @tool
# def calculator(operation: str, a: float, b: float) -> str:
# """计算"""
# ...
# 3. 错误处理
@tool
def divide(a: float, b: float) -> str:
"""
除法计算
参数:
a: 被除数
b: 除数
"""
try:
if b == 0:
return "错误:除数不能为零"
result = a / b
return f"{a} / {b} = {result}"
except Exception as e:
return f"计算错误:{e}"
# 4. 返回字符串
@tool
def get_user_info(user_id: str) -> str:
"""获取用户信息"""
user = {"id": user_id, "name": "张三"}
return json.dumps(user, ensure_ascii=False)