本文 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 接收與回傳 純文字,但在實務上常需要結構化資料。常見做法:
- JSON 參數:在
description中說明接受 JSON,LLM 會自行產生。 - Schema 驗證:使用
zod、ajv等套件在func內先驗證輸入。 - 回傳 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),可能被惡意指令利用。 | 僅在受信任環境開啟 PythonREPL、ShellTool;對輸入做白名單或沙箱限制。 |
| 回傳字串過長 | 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_zh、summarize_text(使用 LLM 產生摘要)。 - 流程:使用者上傳長篇英文文件 → LLM 先呼叫
summarize_text產生簡要 → 再呼叫translate_en_to_zh把摘要翻成繁體中文。
總結
- Tool 是 LangChain 讓 LLM 與外部世界互動的核心橋樑,透過
name、description、func三個屬性即可定義。 - 透過 統一介面、安全控制 與 易於觀測 的特性,Tool 大幅提升了 LLM 應用的可用性與可靠度。
- 在實作時要注意 名稱唯一性、描述完整性、錯誤處理與安全限制,並善用 非同步支援、JSON schema 讓工具更具結構性。
- 結合 Agent 後,模型可以 自主 判斷何時使用哪些工具,實現真正的「會做事」的 AI 助理。
掌握了 Tool 的概念與實作技巧,你就能在 LangChain 生態中快速構建從簡單搜尋到複雜業務流程自動化的各種應用。祝你開發順利,打造出讓使用者驚豔的 AI 產品! 🚀