本文 AI 產出,尚未審核

LangChain 多代理系統(Multi‑Agent Systems)

主題:自動化工作流程 Orchestration


簡介

在現代 AI 應用中,單一的大語言模型(LLM)往往只能解決「單一步驟」的問題,若要完成 跨領域的複雜任務(如資料蒐集 → 分析 → 報表生成),就需要把多個專精於不同功能的代理(Agent)串起來,形成一條自動化的工作流程。

LangChain 為開發者提供了 Agent、Tool、Memory 等抽象層,讓我們可以在程式碼中快速組合多個代理,並透過 Orchestration(編排) 控制它們的執行順序、錯誤處理與資訊共享。掌握這套編排機制,開發者就能把「聊天機器人」升級為「自動化助理」,在客服、商務分析、資料工程等領域大幅提升效率。


核心概念

1. Agent 與 Tool 的角色分離

  • Agent:負責決策、規劃以及與使用者的對話。它會根據上下文選擇要呼叫哪個 Tool。
  • Tool:實際執行具體功能的程式模組,如搜尋 API、資料庫查詢、檔案寫入等。Tool 只需要提供 namedescriptionfunc 三個屬性,LangChain 會自動將它們包裝成可被 Agent 呼叫的介面。

重點:Agent 只需要關心「要做什麼」,Tool 則專注「怎麼做」,兩者解耦後才能靈活組合。

2. Orchestrator(編排器)

Orchestrator 是一個負責 管理多個 Agent 執行流程 的元件。它的工作包括:

  1. 流程定義:以序列、條件或迭代的方式描述各 Agent 的執行順序。
  2. 狀態追蹤:保存每一步的輸入/輸出、錯誤訊息,供後續 Agent 參考。
  3. 錯誤恢復:當某個 Agent 失敗時,可自動重試、跳過或切換備援 Agent。

LangChain 官方提供的 AgentExecutorSequentialChainConditionalChain 等類別,就是為了簡化這些編排工作。

3. Memory(記憶)在多代理系統中的重要性

在單一 Agent 中,我們常使用 ConversationBufferMemory 來保存對話歷史。多代理系統則需要 共享或隔離的記憶體

  • 共享 Memory:所有 Agent 都能讀寫同一個記憶體,適合資訊必須在不同步驟間傳遞的情境(例如:搜尋結果要給分析 Agent 使用)。
  • 隔離 Memory:每個 Agent 各自擁有獨立的記憶體,避免資訊污染,適合平行執行的任務。

LangChain 允許開發者自行實作 BaseMemory,或直接使用 ConversationSummaryMemory 來自動摘要長篇資訊。


程式碼範例

以下示範如何使用 JavaScript(Node.js) 版 LangChain 建立一個簡單的三步驟工作流程:

  1. 搜尋(SearchAgent) → 2. 分析(AnalyzeAgent) → 3. 產生報告(ReportAgent)。

注意:範例以 @langchain/core@langchain/openai@langchain/agents 為基礎套件,實際使用前請先 npm install

1️⃣ 建立 Tool

// tools.js
const { Tool } = require("@langchain/agents");

// 1. 網路搜尋工具
const searchTool = new Tool({
  name: "search",
  description: "使用 Bing API 進行關鍵字搜尋,回傳前 5 筆結果。",
  func: async (input) => {
    // 假設已設定好 bingClient
    const results = await bingClient.search(input);
    return results.slice(0, 5).map(r => r.title + ": " + r.snippet).join("\n");
  },
});

// 2. 文本分析工具
const sentimentTool = new Tool({
  name: "sentiment_analysis",
  description: "分析給定文字的情緒(positive/negative/neutral)。",
  func: async (text) => {
    const response = await openaiClient.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: [{ role: "user", content: `請判斷以下文字的情緒:\n${text}` }],
    });
    return response.choices[0].message.content.trim();
  },
});

module.exports = { searchTool, sentimentTool };

2️⃣ 定義 Agent

// agents.js
const { OpenAIChat, ChatPromptTemplate } = require("@langchain/openai");
const { initializeAgentExecutor } = require("@langchain/agents");
const { searchTool, sentimentTool } = require("./tools");

// SearchAgent:只會呼叫 searchTool
const searchAgent = await initializeAgentExecutor(
  new OpenAIChat({ temperature: 0 }),
  [searchTool],
  { agentType: "zero-shot-react-description" }
);

// AnalyzeAgent:會先呼叫 searchTool 再呼叫 sentimentTool
const analyzeAgent = await initializeAgentExecutor(
  new OpenAIChat({ temperature: 0.3 }),
  [searchTool, sentimentTool],
  { agentType: "zero-shot-react-description" }
);

// ReportAgent:只負責產出最終報告文字
const reportAgent = async (analysis) => {
  const prompt = ChatPromptTemplate.fromMessages([
    ["system", "你是一位專業的報告撰寫助手,請把以下分析結果整理成條列式報告,字數控制在 300 字以內。"],
    ["human", "{analysis}"],
  ]);
  const chain = prompt.pipe(new OpenAIChat({ temperature: 0.2 }));
  const result = await chain.invoke({ analysis });
  return result.content;
};

module.exports = { searchAgent, analyzeAgent, reportAgent };

3️⃣ 建立 Orchestrator(流程編排)

// orchestrator.js
const { SequentialChain } = require("@langchain/chains");
const { searchAgent, analyzeAgent, reportAgent } = require("./agents");

// 步驟 1:搜尋關鍵字
async function stepSearch(query) {
  const result = await searchAgent.run(`搜尋關鍵字:${query}`);
  return result; // 文字列表
}

// 步驟 2:情緒分析
async function stepAnalyze(searchResult) {
  const analysis = await analyzeAgent.run(`
    以下是搜尋結果,請針對每一筆結果做情緒分析,並回傳 JSON 陣列:
    ${searchResult}
  `);
  return analysis; // JSON 字串
}

// 步驟 3:產生報告
async function stepReport(analysis) {
  const report = await reportAgent(analysis);
  return report;
}

// 組合成 SequentialChain
const workflow = new SequentialChain({
  inputVariables: ["query"],
  outputVariables: ["report"],
  chains: [
    { name: "search", chain: { call: stepSearch } },
    { name: "analyze", chain: { call: stepAnalyze } },
    { name: "report", chain: { call: stepReport } },
  ],
});

// 執行範例
(async () => {
  const { report } = await workflow.call({ query: "LangChain 多代理系統" });
  console.log("=== 最終報告 ===\n", report);
})();

4️⃣ 使用共享 Memory(可選)

// sharedMemory.js
const { ConversationBufferMemory } = require("@langchain/memory");

// 建立一個全域共享的記憶體
const sharedMemory = new ConversationBufferMemory({ returnMessages: true });

// 在每個 Agent 初始化時注入 memory
const searchAgent = await initializeAgentExecutor(
  new OpenAIChat({ temperature: 0 }),
  [searchTool],
  { agentType: "zero-shot-react-description", memory: sharedMemory }
);
// 其餘 Agent 同理...

5️⃣ 錯誤恢復與重試機制

// retryWrapper.js
async function withRetry(fn, maxAttempts = 3, delayMs = 1000) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (err) {
      console.warn(`第 ${attempt} 次嘗試失敗:${err.message}`);
      if (attempt === maxAttempts) throw err;
      await new Promise(res => setTimeout(res, delayMs));
    }
  }
}

// 在 Orchestrator 中使用
async function stepSearch(query) {
  return await withRetry(() => searchAgent.run(`搜尋關鍵字:${query}`));
}

常見陷阱與最佳實踐

陷阱 為什麼會發生 解決方法 / 最佳實踐
Tool 輸入/輸出格式不一致 Agent 依賴自然語言指令,若 Tool 回傳的文字無法被後續 Agent 正確解析,就會卡住流程。 為每個 Tool 設計明確的 JSON schema,並在 Agent Prompt 中加入「回傳格式」的說明。
忘記設定 Memory 多代理系統的資訊流容易斷層,導致後續 Agent 無法取得前一步的結果。 使用 共享 Memory 或在 SequentialChain 中手動傳遞 intermediateSteps
過度依賴單一 LLM 若 LLM 回答不一致,整條流程的穩定性會下降。 為關鍵步驟(如資料驗證)加入 Rule‑Based 判斷,或使用 多模型備援(OpenAI + Anthropic)。
未控制 Token 數量 長串的搜尋結果或分析報告會使 Token 超過模型上限,拋出錯誤。 在每一步加入 摘要或截斷ConversationSummaryMemory),或使用 maxTokens 參數限制回傳長度。
缺乏錯誤回報機制 當某個 Tool 拋出例外時,整個流程直接失敗,使用者無法得知失敗原因。 透過 withRetry 包裝每個步驟,並在 Orchestrator 中捕獲錯誤,回傳結構化的 errorReport

最佳實踐總結

  1. 明確定義 Tool 的 I/O 協議(JSON + 範例)。
  2. 使用 Memory 來保存關鍵上下文,避免資訊遺失。
  3. 在 Orchestrator 中加入重試與超時控制,提升容錯性。
  4. 將 LLM 產出限制在可驗證的範圍(如固定格式、字數上限)。
  5. 持續監控 Token 使用與 API 請求成本,避免意外超支。

實際應用場景

場景 需求 多代理編排的價值
客服自動化 先從知識庫搜尋答案 → 判斷情緒 → 若情緒負面則升級給人工 代理分工明確、情緒判斷與升級流程自動化,縮短回應時間。
市場情報蒐集 抓取多個新聞網站 → 文字摘要 → 情感分析 → 產出每日簡報 多工具串接一次完成,減少手動整理的工時。
資料清理工作流 從資料湖讀取原始檔 → 使用 LLM 產生正規化規則 → 執行 ETL → 產出報表 LLM 可動態產生清理規則,整條流程自動化,提升資料品質。
研發文件生成 收集 Git commit 訊息 → 生成變更說明 → 自動寫入 Release Note 代理間共享 Memory,確保變更資訊不遺失,文件生成更一致。
金融風險評估 抓取即時市場數據 → 計算風險指標 → 產出警示報告 → 發送 Slack 通知 透過條件分支(若風險指標超過閾值才發送),降低噪音訊息。

總結

LangChain多代理系統 + Orchestration 為開發者提供了一條從 「原始需求 → 多步驟自動化」 的完整路徑。

  • Agent 負責決策與對話,Tool 執行具體功能,二者解耦後可自由組合。
  • Orchestrator(如 SequentialChain)讓我們用程式化的方式描述流程、追蹤狀態、處理錯誤。
  • Memory 則是資訊在不同代理間流通的橋樑,適當的共享或隔離策略是系統穩定的關鍵。

透過本文的 範例程式碼陷阱對照表實務場景,讀者不僅能快速上手,也能在設計自己的 AI 工作流時避免常見錯誤,打造出 可擴充、可維護且成本可控 的自動化解決方案。未來,隨著 LLM 能力的持續提升,結合多代理編排的應用將變得更為廣泛,值得每位開發者持續關注與實驗。祝開發順利!