Tools使用指南

LangChain Tools 使用指南

一、Tools 是什么?

Tool(工具) 是连接 LLM 和外部能力的桥梁。

LLM 本身只能"思考",不能执行操作。Tool 让 LLM 可以:

  • 调用计算器做精确计算
  • 读写文件
  • 查询数据库
  • 调用外部 API
  • 执行任意 Python 函数

核心思路:LLM 决定"要不要调"和"调什么",你负责执行。

二、完整使用案例

python 复制代码
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
import json

# ====== 1. 定义工具 ======

@tool
def add(a: int, b: int) -> int:
    """两数相加,返回它们的和"""
    return a + b

@tool
def multiply(a: int, b: int) -> int:
    """两数相乘,返回它们的积"""
    return a * b

@tool
def get_weather(city: str) -> str:
    """查询某个城市的当前天气"""
    data = {"北京": "晴 25C", "上海": "小雨 22C", "深圳": "多云 28C"}
    return data.get(city, f"暂无{city}的天气数据")

@tool
def write_file(filename: str, content: str) -> str:
    """写入内容到桌面文件"""
    path = f"C:\\Users\\Enty\\Desktop\\{filename}"
    with open(path, "w", encoding="utf-8") as f:
        f.write(content)
    return f"已写入 {path}"

tools = [add, multiply, get_weather, write_file]


# ====== 2. 绑定工具到 LLM ======

llm = ChatOpenAI(
    model="deepseek-v4-flash",
    api_key="sk-xxx",
    base_url="https://api.deepseek.com",
)

llm_with_tools = llm.bind_tools(tools)


# ====== 3. 运行 Agent 循环 ======

def run_agent(prompt: str, max_turns: int = 5):
    messages = [{"role": "user", "content": prompt}]

    for turn in range(1, max_turns + 1):
        response = llm_with_tools.invoke(messages)
        messages.append(response)

        # LLM 没有调工具,直接给出回答
        if not response.tool_calls:
            return response.content

        # LLM 想调工具,逐个执行
        for tool_call in response.tool_calls:
            tool_name = tool_call["name"]
            tool_args = tool_call["args"]

            # 找到对应的工具函数并执行
            matched = next(t for t in tools if t.name == tool_name)
            result = matched.invoke(tool_args)

            # 把结果放回消息列表,LLM 会继续推理
            messages.append({
                "role": "tool",
                "content": json.dumps(result, ensure_ascii=False),
                "tool_call_id": tool_call["id"],
            })

    return "达到最大轮数"


if __name__ == "__main__":
    result = run_agent("北京天气怎么样?")
    print(result)

三、各步骤详解

第 1 步:@tool 装饰器

python 复制代码
@tool
def add(a: int, b: int) -> int:
    """两数相加,返回它们的和"""
    return a + b

@tool 把普通 Python 函数注册为 LangChain 工具。

自动生成三样东西:

来源 作用
函数名 add LLM 知道这个工具叫 add
文档字符串 两数相加... LLM 知道什么时候该用这个工具
参数签名 a: int, b: int LLM 知道需要传什么参数、类型是什么

LLM 看到这段 JSON Schema(自动生成,开发者看不到):

json 复制代码
{
  "name": "add",
  "description": "两数相加,返回它们的和",
  "parameters": {
    "type": "object",
    "properties": {
      "a": {"type": "integer"},
      "b": {"type": "integer"}
    },
    "required": ["a", "b"]
  }
}

第 2 步:bind_tools()

python 复制代码
llm_with_tools = llm.bind_tools(tools)

把工具列表注册到 LLM 实例上。之后每次调用 llm_with_tools.invoke(),API 请求里都会带着工具定义。

LLM 收到问题后有两种选择:

  • 直接回答response.tool_calls 为空
  • 调用工具response.tool_calls 有内容

第 3 步:run_agent 循环

3.1 调用 LLM
python 复制代码
response = llm_with_tools.invoke(messages)

把当前消息发给 LLM,LLM 返回回答或工具调用请求。

3.2 判断要不要调工具
python 复制代码
if not response.tool_calls:
    return response.content

response.tool_calls 为空 → LLM 直接回答了,结束循环。

response.tool_calls 有内容 → LLM 想调工具,继续执行。

3.3 解析工具调用
python 复制代码
tool_call["name"]  # "add"        → 调哪个工具
tool_call["args"]  # {"a": 3, "b": 5}  → 参数是什么
tool_call["id"]    # "call_xxx"   → 本次调用的唯一 ID
3.4 执行工具
python 复制代码
matched = next(t for t in tools if t.name == tool_name)
result = matched.invoke(tool_args)

从工具列表中找到名称匹配的函数,传入参数执行。

3.5 返回结果给 LLM
python 复制代码
messages.append({
    "role": "tool",
    "content": json.dumps(result, ensure_ascii=False),
    "tool_call_id": tool_call["id"],
})

工具执行结果必须放回消息列表,LLM 才能继续推理。tool_call_id 用于对应这次调用。

3.6 继续下一轮
python 复制代码
# LLM 拿到工具结果后,可能再调下一个工具,或者直接回答
response = llm_with_tools.invoke(messages)

四、完整交互流程

复制代码
用户: "北京天气怎么样?写到一个文件里"

第 1 轮:
  LLM 回复 → tool_calls = [get_weather(city="北京")]
  执行 → "晴 25C"
  放回消息列表

第 2 轮:
  LLM 回复 → tool_calls = [write_file(filename="weather.txt", content="北京: 晴 25C")]
  执行 → "已写入 ..."
  放回消息列表

第 3 轮:
  LLM 回复 → content = "已完成!已查询北京天气并写入文件"
  tool_calls 为空 → 结束

五、关键概念总结

概念 一句话
@tool 把函数变成 LLM 能调用的工具
函数签名 决定了 LLM 能填什么参数
文档字符串 决定了 LLM 什么时候调这个工具
bind_tools() 把工具注册到 LLM
tool_calls LLM 返回的"我想调 XX 工具"信号
tool_call_id 关联工具调用和结果
循环 LLM 可以调多次、跨多步,直到给出最终回答
相关推荐
码语智行1 小时前
操作日志注解模块
java·前端·python
MageGojo1 小时前
实时电影票房 API 接入实战:用 GET 请求获取影片票房榜单数据
python·电影票房·api 接口接入
weixin_468466851 小时前
Scrapling 高效网络爬虫实战指南
爬虫·python·编程·scrapling
yubo05091 小时前
计算机视觉第十课:摄像头实时 颜色 + 形状 识别
python·opencv·计算机视觉
Dxy12393102161 小时前
Django 三种 ENGINE 的区别
python·django·sqlite
Wang ruoxi1 小时前
Pygame 小游戏——记忆方格
python·pygame
shuaiqinke1 小时前
[Windows] 屏幕亮度调节工具
python
本地化文档1 小时前
sphinxcontrib-rust-docs-l10n
python·rust·github·gitcode·sphinx
麻雀飞吧1 小时前
2026年期货量化行情订阅层设计:主流平台Quote、K线与Tick取舍
python