让 AI 不只是聊天:用 LangChain 工具(Tools)赋予大模型“动手能力”

63 阅读4分钟

我们常把大模型比作“聪明的嘴”——它能说会道,但不能做事。
比如你问:“北京今天天气怎么样?”
它可能会凭记忆瞎猜,或者直接回答:“我不知道。”

但如果我们能让它调用一个真实的天气接口呢?
答案就不再是猜测,而是准确数据。

LangChain 提供了一套优雅的机制——Tools(工具) ,让大模型不仅能“说”,还能“做”。
本文将通过两个简单例子(查天气 + 加法),带你掌握如何用 @langchain/core/toolsbindTools 实现函数调用。


一、为什么需要 Tools?

大模型的本质是“语言预测器”,它没有访问外部世界的能力。
但现实中的 AI 应用往往需要:

  • 查询数据库
  • 调用 API
  • 执行计算
  • 操作文件

这些能力,统称为 “工具调用”(Tool Calling)

LangChain 的 tool 函数,就是用来把 JavaScript 函数包装成模型可调用的工具
配合支持函数调用的模型(如 DeepSeek、GPT-4、Claude 等),就能实现“AI 决策 → 调用工具 → 返回结果”的闭环。


二、第一步:定义你的工具

我们先模拟一个天气数据库:

const fakeWeatherDB = {
  北京: { temp: "30°C", condition: "晴", wind: "微风" },
  上海: { temp: "28°C", condition: "多云", wind: "东风 3 级" },
  广州: { temp: "32°C", condition: "阵雨", wind: "南风 2 级" },
};

然后用 tool() 包装成一个可被模型调用的工具:

import { tool } from '@langchain/core/tools';
import { z } from 'zod';

const weatherTool = tool(
  async ({ city }) => {
    const weather = fakeWeatherDB[city];
    if (!weather) {
      return `暂无${city}的天气信息`;
    }
    return `当前${city}的天气是${weather.temp}, ${weather.condition}, 风力${weather.wind}`;
  },
  {
    name: 'weather',
    description: "查询指定城市的今日天气情况",
    schema: z.object({
      city: z.string().describe("要查询天气的城市")
    })
  }
);

关键点解析:

  • 第一个参数:实际执行的异步函数,接收结构化参数
  • name:工具的唯一标识,模型通过它决定调用哪个工具
  • description:告诉模型这个工具是干什么的(影响调用决策)
  • schema:用 Zod 定义输入参数的类型和描述,模型据此生成合法参数

Zod 是一个强大的 TypeScript 运行时校验库,LangChain 用它来确保模型传参的合法性。

同样,我们再定义一个加法工具:

const addTool = tool(
  async ({ a, b }) => String(a + b),
  {
    name: 'add',
    description: "计算两个数字的和",
    schema: z.object({
      a: z.number().describe("第一个数字"),
      b: z.number().describe("第二个数字")
    })
  }
);

现在,我们有了两个“能力”:查天气、做加法。


三、第二步:把工具绑定给模型

接下来,让模型知道它“能用哪些工具”。

import { ChatDeepSeek } from '@langchain/deepseek';

const model = new ChatDeepSeek({
  model: 'deepseek-chat',
  temperature: 0,
}).bindTools([addTool, weatherTool]);

.bindTools() 是关键——它会:

  • 自动提取每个工具的 namedescriptionschema
  • 将这些信息作为“函数签名”注入到模型的上下文
  • 告诉模型:“你可以调用这些函数,按这个格式传参”

此时,模型就从“纯聊天模式”升级为“可调用工具模式”。


四、第三步:触发调用并处理结果

我们问模型一个问题:

const res = await model.invoke("北京今天的天气怎么样?");

如果模型判断需要调用工具,res 中会包含 tool_calls 字段:

if (res.tool_calls?.length) {
  const call = res.tool_calls[0];
  if (call.name === 'weather') {
    const result = await weatherTool.invoke(call.args);
    console.log("最终结果:", result);
  }
}

输出:

最终结果: 当前北京的天气是30°C, 晴, 风力微风

整个流程如下:

  1. 用户提问 → 模型分析是否需要外部工具
  2. 若需要,模型返回 tool_calls(包含工具名 + 参数)
  3. 我们根据 name 路由到对应工具,用 args 调用
  4. 工具执行后返回真实结果
  5. (可选)把结果再喂给模型,生成自然语言回复

注意:目前我们手动处理了工具调用。LangChain 也提供了 createToolCallingAgent 等高级封装,可自动完成整个 loop。


五、结语:AI 的未来是“会用工具的人”

大模型真正的价值,不在于它能背多少知识,而在于它能否合理调度外部能力

LangChain 的 tool + bindTools 机制,正是通往这一目标的桥梁。
无论是查天气、发邮件、查订单,还是控制智能家居,背后都是同一个模式:

定义工具 → 绑定模型 → 处理调用

你不需要教模型“怎么查天气”,只需要给它一个叫 weather 的工具,它自己就知道何时用、怎么用。

而这,或许才是“智能助手”的真正含义。


试试看:把 fakeWeatherDB 换成真实 API(如和风天气),你的 AI 就能提供全国任意城市的实时天气了!