Skip to content

10-工具 (Tools):调用外部 API

💡 注意: 本教程适用于 LangChain.js v1.x

🎯 本章目标

  • ✅ 理解工具 (Tools) 的作用
  • ✅ 创建自定义工具
  • ✅ 让 AI 能够调用函数/API

🤔 什么是工具 (Tools)?

工具 = AI 可以调用的函数

大模型本身不能:

  • ❌ 访问实时数据(天气、股票、新闻)
  • ❌ 执行代码
  • ❌ 访问数据库
  • ❌ 调用外部 API

通过工具,AI 可以:

  • ✅ 查询天气
  • ✅ 计算数学题
  • ✅ 搜索网络
  • ✅ 调用任何 API

📦 创建工具

方式 1:使用 tool 函数

javascript
import { tool } from "@langchain/core/tools";

const searchTool = tool(async (query) => {
  // 执行搜索
  const results = await search(query);
  return results;
}, {
  name: "search",
  description: "搜索网络信息"
});

方式 2:使用 Tool 类

javascript
import { Tool } from "@langchain/core/tools";

class CalculatorTool extends Tool {
  name = "calculator";
  description = "计算数学表达式";

  async call(input) {
    // 计算逻辑
    return eval(input);
  }
}

💡 完整示例

javascript
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
import { tool } from "@langchain/core/tools";

const model = new ChatOpenAI({
  modelName: "MiniMax/MiniMax-M2.5",
  apiKey: process.env.MODELSCOPE_API_KEY,
  configuration: {
    baseURL: "https://api-inference.modelscope.cn/v1",
  },
});

// === 工具 1:计算器 ===
const calculatorTool = tool(async (expression) => {
  console.log(`[工具] 计算器:计算 ${expression}`);
  try {
    return String(eval(expression));
  } catch (e) {
    return "计算错误:" + e.message;
  }
}, {
  name: "calculator",
  description: "计算数学表达式,例如:2 + 3 * 4"
});

// === 工具 2:获取当前时间 ===
const timeTool = tool(async () => {
  console.log("[工具] 获取当前时间");
  const now = new Date();
  return now.toLocaleString("zh-CN");
}, {
  name: "get_current_time",
  description: "获取当前日期和时间"
});

// === 工具 3:天气查询(模拟)===
const weatherTool = tool(async (city) => {
  console.log(`[工具] 查询天气:${city}`);
  const weatherData = {
    "北京": "晴,25°C",
    "上海": "多云,28°C",
    "广州": "小雨,30°C",
    "深圳": "晴,32°C"
  };
  return weatherData[city] || "未知城市";
}, {
  name: "get_weather",
  description: "查询城市天气,参数:城市名(北京/上海/广州/深圳)"
});

// 注册工具列表
const tools = [calculatorTool, timeTool, weatherTool];

// 创建系统提示
const toolDescriptions = tools.map(t => 
  `- ${t.name}: ${t.description}`
).join("\n");

const systemPrompt = new SystemMessage(`
你是一个智能助手,可以使用以下工具帮助用户:

${toolDescriptions}

如果用户的问题需要工具,请回复:
[TOOL: 工具名] 参数
`);

// 使用工具
const messages = [
  systemPrompt,
  new HumanMessage("现在几点了?")
];

const response = await model.invoke(messages);
console.log("AI:", response.content);

// 检查是否需要调用工具
const toolMatch = response.content.match(/\[TOOL: (\w+)\] (.+)/);
if (toolMatch) {
  const [, toolName, toolInput] = toolMatch;
  const selectedTool = tools.find(t => t.name === toolName);
  if (selectedTool) {
    const result = await selectedTool.invoke(toolInput.trim());
    console.log(`[工具结果]: ${result}`);
  }
}

⚙️ tool 函数参数详解

javascript
const myTool = tool(async (input) => {
  // 工具逻辑
  return result;
}, options);

// options 参数:
// - name: string - 工具名称(必需)
// - description: string - 工具描述(必需)
// - schema?: ZodSchema - 输入参数模式(可选)
// - responseSchema?: ZodSchema - 输出模式(可选)

示例:带参数验证的工具

javascript
import { z } from "zod";

const divideTool = tool(async (input) => {
  const { a, b } = JSON.parse(input);
  return String(a / b);
}, {
  name: "divide",
  description: "计算两个数的除法",
  schema: z.object({
    a: z.number(),
    b: z.number()
  })
});

🎯 简化版:直接调用工具

如果不想要复杂的 Agent 逻辑,可以直接判断并调用:

javascript
const tools = {
  calculator: async (expr) => String(eval(expr)),
  time: async () => new Date().toLocaleString("zh-CN"),
  weather: async (city) => {
    const data = { "北京": "晴,25°C", "上海": "多云,28°C" };
    return data[city] || "未知城市";
  }
};

async function chatWithTools(userMessage) {
  // 先让 AI 判断是否需要工具
  const judgePrompt = `
判断以下问题是否需要使用工具:
"${userMessage}"

如果需要,回复:NEED_TOOL: 工具名:参数
如果不需要,直接回答问题。

可用工具:
- calculator: 计算数学表达式
- time: 获取当前时间
- weather: 查询天气(城市名)
`;

  const response = await model.invoke([new HumanMessage(judgePrompt)]);
  
  if (response.content.startsWith("NEED_TOOL:")) {
    const [, toolName, param] = response.content.split(":");
    const tool = tools[toolName.trim()];
    if (tool) {
      const result = await tool(param.trim());
      return `工具结果:${result}`;
    }
  }
  
  return response.content;
}

🔧 调用真实 API

示例:调用天气 API

javascript
const httpTool = tool(async (url) => {
  console.log(`[工具] HTTP 请求:${url}`);
  try {
    const response = await fetch(url);
    const data = await response.json();
    return JSON.stringify(data);
  } catch (e) {
    return "请求失败:" + e.message;
  }
}, {
  name: "http_get",
  description: "发送 HTTP GET 请求,参数:URL"
});

示例:数据库查询

javascript
import { Pool } from 'pg';
const pool = new Pool({ connectionString: 'postgresql://...' });

const queryTool = tool(async (sql) => {
  console.log(`[工具] SQL 查询:${sql}`);
  try {
    const result = await pool.query(sql);
    return JSON.stringify(result.rows);
  } catch (e) {
    return "查询错误:" + e.message;
  }
}, {
  name: "database_query",
  description: "执行 SQL 查询"
});

⚠️ 安全注意事项

1. 不要直接 eval 用户输入

javascript
// ❌ 危险:用户可以执行任意代码
const badTool = tool(async (input) => {
  return eval(input);
});

// ✅ 安全:使用专门的数学库
import { Parser } from 'expr-eval';
const parser = new Parser();

const goodTool = tool(async (expr) => {
  return String(parser.evaluate(expr));
});

2. 限制工具权限

javascript
const adminTool = tool(async (command) => {
  // 检查用户权限
  if (!user.isAdmin) {
    return "权限不足";
  }
  // 执行命令
}, {
  name: "admin_command",
  description: "管理员命令"
});

3. 限制输入长度

javascript
const searchTool = tool(async (query) => {
  if (query.length > 100) {
    return "查询太长";
  }
  // 执行搜索
}, {
  name: "search",
  description: "搜索"
});

📋 Tool 类方法详解

方法说明示例
call(input)调用工具await tool.call("input")
invoke(input)调用工具(Runnable 接口)await tool.invoke("input")
stream(input)流式调用for await (const c of await tool.stream(input))

📝 本章小结

  • 工具 (Tools) 让 AI 能够调用函数/API
  • 使用 tool() 函数创建工具
  • 工具需要 name 和 description
  • 注意安全问题(eval、权限、输入验证)

🎓 教程完结!

你已经完成了 LangChain.js v1.x 入门教程的全部内容!

复习清单

  • [ ] 01-基础概念
  • [ ] 02-环境搭建
  • [ ] 03-模型调用
  • [ ] 04-消息类型
  • [ ] 05-流式输出
  • [ ] 06-Prompt 模板
  • [ ] 07-输出解析器
  • [ ] 08-链 (Chain)
  • [ ] 09-记忆 (Memory)
  • [ ] 10-工具 (Tools)

下一步学习

  • 学习 Agent(智能体)
  • 学习 RAG(检索增强生成)
  • 学习 VectorStore(向量存储)
  • 实战项目:构建一个完整的 AI 应用

基于 LangChain.js v1.x 版本