本文 AI 產出,尚未審核

LangChain 教學:Tools(工具系統)— 什麼是工具(Tool)

簡介

在 LLM(大型語言模型)與外部資源互動的過程中,工具(Tool) 扮演了橋樑的角色。沒有工具,模型只能根據內部的知識產生文字;而有了工具,模型可以即時查詢資料庫、呼叫 API、執行程式碼,甚至控制機器人。這使得 LLM 從「僅會說話」的聊天機器人,蛻變為「會做事」的智慧助理。

LangChain 提供了一套完整的 Tool 系統,讓開發者能夠以統一的介面把各種外部服務封裝成「工具」,再交由 LLM 依需求自行呼叫。本文將從概念、實作、常見陷阱與最佳實踐,帶你一步步掌握 LangChain 中的 Tool,並透過實務範例說明如何在專案中運用。


核心概念

1. Tool 的基本結構

在 LangChain 中,Tool 是一個具備以下三個屬性的物件:

屬性 說明 必要性
name 工具的唯一識別名稱,LLM 會在提示中看到此名稱。 必填
description 給 LLM 的說明文字,描述工具能做什麼、需要什麼參數。 必填
func 真正執行工作的函式,接受文字參數,回傳文字結果(同步或非同步皆可)。 必填

簡單來說,Tool 本質上是 「一段文字 → 處理 → 一段文字」 的轉換。LangChain 內建的 Tool 類別即是這樣的封裝。

// 基本的 Tool 實作範例
const { Tool } = require("langchain/tools");

const helloTool = new Tool({
  name: "say_hello",
  description: "回傳一個問候語。輸入參數為使用者的名字。",
  func: (input) => `Hello, ${input}!`,
});

2. 為什麼要用 Tool 而不是直接在 Prompt 中寫指令?

  • 模組化:工具的實作與 LLM 的提示分離,讓程式碼更易維護。
  • 可重用:同一個工具可以在不同的 Chain、Agent 中重複使用。
  • 安全性:只允許 LLM 呼叫「已授權」的工具,避免模型任意執行危險指令。
  • 可觀測:LangChain 能自動記錄每次工具呼叫的輸入與輸出,方便除錯與日誌分析。

3. Tool 的類型

類型 說明 典型使用情境
內建 Tool LangChain 已提供的常見工具,如 SerpAPI, PythonREPL, WikipediaAPIWrapper 等。 快速搜尋、程式碼執行、維基百科查詢
自訂 Tool 開發者自行實作的工具,封裝任何自家 API、資料庫或業務邏輯。 企業內部 ERP 查詢、訂票系統、IoT 控制
工具集合(ToolKit) 把多個 Tool 包裝成一個集合,供 Agent 同時使用。 多功能客服助理、資料分析管線

以下示範如何把自訂工具與內建工具混合使用。

const { SerpAPI } = require("langchain/tools");

// 內建搜尋工具
const searchTool = new SerpAPI({
  apiKey: process.env.SERPAPI_KEY,
  description: "使用 Google 搜尋相關資訊。輸入關鍵字,回傳前 5 筆結果的標題與連結。",
});

// 自訂天氣查詢工具
const weatherTool = new Tool({
  name: "get_weather",
  description: "取得指定城市的即時天氣資訊。輸入城市名稱。",
  func: async (city) => {
    const resp = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.OPENWEATHER_KEY}&units=metric`);
    const data = await resp.json();
    if (data.cod !== 200) return `找不到 ${city} 的天氣資訊。`;
    return `${city} 現在 ${data.weather[0].description},氣溫 ${data.main.temp}°C。`;
  },
});

4. 把 Tool 加入 Agent

LangChain 中的 Agent(代理人)會根據 LLM 的回應決定是否呼叫工具。只要把工具陣列傳給 Agent,即可讓模型自由選擇使用。

const { initializeAgentExecutorWithOptions } = require("langchain/agents");

// 建立 Agent,允許使用 searchTool 與 weatherTool
const agent = await initializeAgentExecutorWithOptions(
  [searchTool, weatherTool],
  llm, // 你的 LLM 實例,例如 OpenAIChat
  {
    agentType: "zero-shot-react-description", // 讓模型根據描述自行決策
    verbose: true,
  }
);

// 測試對話
const result = await agent.run("請告訴我今天台北的天氣,並說明為什麼最近大家在討論 AI 風險。");
console.log(result);

5. Tool 的輸入/輸出格式化

雖然 func 接收與回傳 純文字,但在實務上常需要結構化資料。常見做法:

  1. JSON 參數:在 description 中說明接受 JSON,LLM 會自行產生。
  2. Schema 驗證:使用 zodajv 等套件在 func 內先驗證輸入。
  3. 回傳 JSON:讓後續的 Chain 能直接解析結果。
const { z } = require("zod");

// 定義參數 schema
const addSchema = z.object({
  a: z.number(),
  b: z.number(),
});

const addTool = new Tool({
  name: "add_numbers",
  description: "計算兩個數字的加總。輸入 JSON:{ \"a\": number, \"b\": number }",
  func: (input) => {
    const parsed = addSchema.safeParse(JSON.parse(input));
    if (!parsed.success) return `參數錯誤:${parsed.error.message}`;
    const { a, b } = parsed.data;
    return JSON.stringify({ result: a + b });
  },
});

6. 非同步工具(Async Tool)

大多數外部 API 都是非同步的,LangChain 完全支援 async 函式。只要 func 回傳 Promise<string>,Agent 會自動等待結果。

const translateTool = new Tool({
  name: "translate_en_to_zh",
  description: "把英文句子翻譯成繁體中文。輸入純文字英文。",
  func: async (english) => {
    const resp = await fetch("https://api.deepl.com/v2/translate", {
      method: "POST",
      body: new URLSearchParams({
        auth_key: process.env.DEEPL_KEY,
        text: english,
        target_lang: "ZH",
      }),
    });
    const data = await resp.json();
    return data.translations[0].text;
  },
});

常見陷阱與最佳實踐

陷阱 說明 解決方案 / 最佳實踐
工具名稱衝突 多個 Tool 使用相同 name 時,Agent 會無法分辨。 確保每個 Tool 的 name 在同一 Agent 中唯一,建議使用 snake_case + 前綴(如 db_get_user)。
描述不夠清楚 LLM 依賴 description 判斷何時呼叫工具,描述過於簡略會導致錯誤或不呼叫。 description 中明確列出輸入格式、回傳格式、使用限制。可加入範例。
非同步錯誤未捕獲 func 拋出例外會讓 Agent 中斷,回傳不友善訊息。 func 內使用 try/catch,將錯誤轉成文字回傳;或在 Tool 建構時提供 handleError 回呼。
過度依賴單一工具 把所有邏輯塞進一個 Tool,失去模組化優勢。 把功能拆成多個專一的 Tool,例如「搜尋」與「摘要」分開。
安全風險 若工具允許執行任意程式碼(如 REPL),可能被惡意指令利用。 僅在受信任環境開啟 PythonREPLShellTool;對輸入做白名單或沙箱限制。
回傳字串過長 LLM 輸出受 token 限制,過長的工具回傳會被截斷。 只回傳必要資訊,將大檔案或大量資料分頁或存至外部儲存(如 S3),回傳 URL。

小技巧

  • 使用 verbose:在開發階段將 Agent 設為 verbose: true,可在 console 看到每次工具呼叫的細節。
  • 加入日誌:在 func 開頭 console.log("[Tool] name:", input),方便追蹤。
  • 測試獨立工具:先用單元測試驗證 func 正確性,再交給 Agent。
  • 限制呼叫次數:使用 maxIterations 防止 Agent 無限循環呼叫同一工具。

實際應用場景

1. 智慧客服助理

  • 工具search_faq(搜尋 FAQ 資料庫)、create_ticket(建立客服單)、order_status(查詢訂單狀態)。
  • 流程:使用者問「我的訂單為什麼還沒到?」 → LLM 判斷需要 order_status → 呼叫工具取得結果 → 再決定是否要 create_ticket

2. 企業內部報表產生器

  • 工具query_sales_db(SQL 查詢)、format_excel(產生 Excel 檔)。
  • 流程:使用者說「請幫我產生 2024 Q1 的銷售報表」 → LLM 產生 SQL 語句 → 呼叫 query_sales_db 取得資料 → 再呼叫 format_excel 回傳檔案下載連結。

3. 程式碼自動化測試平台

  • 工具run_test_suite(執行測試)、fetch_coverage(取得測試覆蓋率)、post_comment(在 GitHub PR 留言)。
  • 流程:Pull Request 觸發 Agent → 呼叫 run_test_suite → 若失敗呼叫 post_comment 通知開發者。

4. 多語言翻譯與摘要服務

  • 工具translate_en_to_zhsummarize_text(使用 LLM 產生摘要)。
  • 流程:使用者上傳長篇英文文件 → LLM 先呼叫 summarize_text 產生簡要 → 再呼叫 translate_en_to_zh 把摘要翻成繁體中文。

總結

  • Tool 是 LangChain 讓 LLM 與外部世界互動的核心橋樑,透過 name、description、func 三個屬性即可定義。
  • 透過 統一介面安全控制易於觀測 的特性,Tool 大幅提升了 LLM 應用的可用性與可靠度。
  • 在實作時要注意 名稱唯一性、描述完整性、錯誤處理與安全限制,並善用 非同步支援、JSON schema 讓工具更具結構性。
  • 結合 Agent 後,模型可以 自主 判斷何時使用哪些工具,實現真正的「會做事」的 AI 助理。

掌握了 Tool 的概念與實作技巧,你就能在 LangChain 生態中快速構建從簡單搜尋到複雜業務流程自動化的各種應用。祝你開發順利,打造出讓使用者驚豔的 AI 產品! 🚀