LangChain 基礎概念 ─ 核心組件介紹:Models、Prompts、Output Parsers、Chains
簡介
在 LLM(大型語言模型) 與 生成式 AI 越來越普及的今天,如何把模型、提示詞、輸出解析與工作流程有條不紊地串接起來,成為開發者必備的技能。
LangChain 正是一個 以組件化方式 讓開發者快速構建、測試、部署 LLM 應用的框架,它把「模型呼叫」與「業務邏輯」分離,讓程式碼更易維護、測試與重用。
本篇文章聚焦於 LangChain 四大核心組件:
- Models – 與 LLM(如 OpenAI、Azure、Anthropic 等)互動的抽象層。
- Prompts – 系統化管理提示詞的工具,支援模板、變數與動態組合。
- Output Parsers – 把模型的文字回應轉成結構化資料(JSON、類別實例等)。
- Chains – 把上述組件串成 工作流,支援同步、非同步與條件分支。
掌握這四個概念,就能在 聊天機器人、文件摘要、資料擷取、程式碼生成 等多種場景中,快速組出可運行的原型,甚至直接投入生產環境。
核心概念
1️⃣ Models:統一的模型介面
LangChain 為各大 LLM 提供 統一的介面(BaseLanguageModel),開發者只需要換一個模型實例,即可在同一套程式碼上測試不同供應商的效能與成本。
| 供應商 | 主要類別 (JS) | 特色 |
|---|---|---|
| OpenAI | OpenAI |
支援 gpt-3.5-turbo、gpt-4,可設定 temperature、maxTokens 等參數。 |
| Azure | AzureOpenAI |
同步 Azure 訂閱、資源管理,適合企業級部署。 |
| Anthropic | ChatAnthropic |
以 Claude 系列模型為主,注重安全性與指令遵守。 |
程式碼範例 1:建立模型實例
import { OpenAI } from "langchain/llms/openai";
// 建立一個 OpenAI GPT‑4 的模型物件
const llm = new OpenAI({
modelName: "gpt-4", // 使用的模型名稱
temperature: 0.2, // 較低的 temperature 讓回應更具確定性
maxTokens: 1024, // 單次呼叫最大回傳 token 數
openAIApiKey: process.env.OPENAI_API_KEY, // 從環境變數讀取金鑰
});
小技巧:在開發階段,把
temperature設為0或0.2,可以減少隨機性,方便除錯;正式上線時再根據需求調高。
2️⃣ Prompts:模板化的提示詞管理
LLM 的表現很大程度上取決於 提示詞(Prompt) 的設計。LangChain 把提示詞抽象成 PromptTemplate,支援變數插值、條件分支與多輪對話。
2️⃣.1 PromptTemplate 基礎
import { PromptTemplate } from "langchain/prompts";
// 建立一個簡單的「問答」模板
const qaPrompt = new PromptTemplate({
inputVariables: ["question"], // 需要外部提供的變數名稱
template: `以下是一段中文說明,請直接回答使用者的問題。
說明:
{question}
答案:`,
});
使用時只要傳入一個 JavaScript 物件,即可得到完整的提示字串:
const prompt = await qaPrompt.format({ question: "什麼是 LangChain?" });
console.log(prompt);
2️⃣.2 Few‑Shot Prompt(示例提示)
Few‑Shot 能讓模型學習「格式」或「風格」:
import { FewShotPromptTemplate } from "langchain/prompts";
const examples = [
{ input: "台北101的高度?", output: "台北101高 508 公尺。" },
{ input: "什麼是區塊鏈?", output: "區塊鏈是一種去中心化的分散式帳本技術。" },
];
const fewShotPrompt = new FewShotPromptTemplate({
examplePrompt: new PromptTemplate({
inputVariables: ["input", "output"],
template: `問題:{input}\n答案:{output}\n`,
}),
prefix: "以下是幾個問題與答案範例,請依照相同格式回答接下來的問題:",
suffix: "問題:{question}\n答案:",
inputVariables: ["question"],
examples,
});
這樣的 Prompt 常用於 資訊抽取、格式化回覆 等需求。
3️⃣ Output Parsers:把文字變成結構化資料
LLM 預設回傳純文字,若要在程式中直接使用結果,往往需要 解析。LangChain 提供多種 BaseOutputParser,最常用的是 StructuredOutputParser(基於 JSON Schema)以及 RegexParser。
程式碼範例 2:使用 StructuredOutputParser 產生 JSON
import { StructuredOutputParser } from "langchain/output_parsers";
import { z } from "zod";
// 定義回傳結構(使用 zod 建立 schema)
const weatherSchema = z.object({
location: z.string().describe("城市或地點名稱"),
temperature: z.number().describe("攝氏溫度"),
condition: z.enum(["晴", "雨", "雲", "雪"]).describe("天氣狀況"),
});
// 產生對應的 parser
const parser = StructuredOutputParser.fromZodSchema(weatherSchema);
// 把 parser 的格式說明注入 Prompt
const weatherPrompt = new PromptTemplate({
inputVariables: ["city"],
template: `請根據以下城市提供天氣資訊,回傳 JSON,格式必須符合:
{format_instructions}
城市:{city}`,
partialVariables: {
format_instructions: parser.getFormatInstructions(),
},
});
呼叫模型後,直接用 parser 解析:
const prompt = await weatherPrompt.format({ city: "台北" });
const rawResponse = await llm.invoke(prompt); // rawResponse 為文字
const parsed = await parser.parse(rawResponse); // parsed 為 JavaScript 物件
console.log(parsed);
// => { location: "台北", temperature: 28, condition: "晴" }
注意:若模型回傳的 JSON 有語法錯誤,
parse會拋出例外,建議使用try / catch包起來,或在 Prompt 中加入「請勿加入額外說明」的指示。
4️⃣ Chains:把模型、提示、解析串成工作流
單一模型呼叫只能解決「一次性」的需求。實務上,我們常需要 先產生問題、再根據回覆做後續處理,這時 Chain 就派上用場。LangChain 提供 LLMChain、SimpleSequentialChain、RouterChain 等多種組合方式。
程式碼範例 3:LLMChain + OutputParser
import { LLMChain } from "langchain/chains";
import { OpenAI } from "langchain/llms/openai";
// 1. 建立 LLM(同前面的 llm 變數)
const llm = new OpenAI({ modelName: "gpt-3.5-turbo", temperature: 0 });
// 2. 建立 Prompt(使用前面的 weatherPrompt)
const chain = new LLMChain({
llm,
prompt: weatherPrompt,
outputParser: parser, // 直接把 parser 注入 chain
});
// 執行 chain
async function getWeather(city) {
const result = await chain.run({ city });
// result 已經是解析後的 JavaScript 物件
return result;
}
getWeather("高雄").then(console.log);
// => { location: "高雄", temperature: 30, condition: "雨" }
程式碼範例 4:SimpleSequentialChain(多步驟)
假設要先 產生摘要,再 根據摘要產生關鍵字:
import { SimpleSequentialChain } from "langchain/chains";
import { PromptTemplate } from "langchain/prompts";
// 步驟 1:摘要 Prompt
const summaryPrompt = new PromptTemplate({
inputVariables: ["text"],
template: `請將以下文字摘要成 3 行以內:
{text}`,
});
// 步驟 2:關鍵字 Prompt
const keywordPrompt = new PromptTemplate({
inputVariables: ["summary"],
template: `根據以下摘要,列出 5 個關鍵字(以逗號分隔):
{summary}`,
});
// 建立兩個 LLMChain
const summaryChain = new LLMChain({ llm, prompt: summaryPrompt });
const keywordChain = new LLMChain({ llm, prompt: keywordPrompt });
// 用 SimpleSequentialChain 把兩個 Chain 串起來
const workflow = new SimpleSequentialChain({
chains: [summaryChain, keywordChain],
verbose: true, // 顯示每一步的輸入/輸出,方便除錯
});
// 執行
const article = `LangChain 是一個 ... (略)`;
workflow.run({ text: article }).then(console.log);
// 輸出範例:關鍵字 => "LangChain, LLM, Prompt, Chain, AI"
程式碼範例 5:RouterChain(條件分支)
如果想根據使用者的意圖切換不同的處理流程,可使用 RouterChain:
import { RouterChain } from "langchain/chains";
import { ChatPromptTemplate } from "langchain/prompts";
// 定義意圖判斷 Prompt
const intentPrompt = new ChatPromptTemplate({
inputVariables: ["query"],
template: `請判斷以下使用者問題的意圖,回傳一個關鍵字:
1. 天氣查詢
2. 文章摘要
3. 其他
問題:{query}
意圖:`,
});
// 建立三個子 Chain(同前面的 chain)
const weatherChain = /* 前面建立的 LLMChain */;
const summaryChain = /* 前面建立的 LLMChain */;
const fallbackChain = new LLMChain({ llm, prompt: new PromptTemplate({
inputVariables: ["query"],
template: `抱歉,我無法理解您的需求。請重新描述。`,
})});
// RouterChain 設定
const router = new RouterChain({
llm,
prompt: intentPrompt,
routes: {
天氣查詢: weatherChain,
文章摘要: summaryChain,
其他: fallbackChain,
},
});
// 測試
router.run({ query: "台北今天的天氣如何?" }).then(console.log);
// => 會自動走 weatherChain,回傳天氣 JSON
常見陷阱與最佳實踐
| 常見陷阱 | 為什麼會發生 | 建議的解法 |
|---|---|---|
| Prompt 太長或缺少指示 | LLM 可能忽略關鍵資訊,或產生雜訊 | 使用 PromptTemplate 把變數明確列在 inputVariables,並在模板中加入「請勿加入額外說明」的指示。 |
| Output Parser 失敗 | 模型回傳不符合 JSON 格式或語法錯誤 | 在 Prompt 中加入 format_instructions,並使用 try / catch 包住 parser.parse,必要時 重試(可加 temperature=0)。 |
| 模型成本失控 | maxTokens、temperature 設定不當,導致大量 token 消耗 |
先在開發環境 限制 maxTokens,使用 streaming 只取需要的部分;部署前再根據需求調整。 |
| Chain 內部錯誤被吞掉 | verbose 預設關閉,除錯資訊不顯示 |
在測試階段開啟 verbose: true,或自行在每個 Chain 前後加 console.log。 |
| 多模型混用時參數不一致 | 各模型支援的參數不同(如 stop、logprobs) |
把模型相關參數抽象成 自訂的設定物件,在建立模型時統一注入。 |
最佳實踐
- 先寫 Prompt 再寫程式:先在 Playground(OpenAI、Claude)驗證提示詞的效果,再搬到 LangChain。
- 結構化輸出優先:盡量使用
StructuredOutputParser,避免事後手動正則表達式切割。 - 模組化 Chain:把每個功能(摘要、關鍵字、翻譯)封裝成獨立的
LLMChain,再用SimpleSequentialChain或RouterChain組合。 - 測試與 CI:使用
jest或mocha撰寫 單元測試,特別是parser.parse的 edge case。 - 安全與隱私:在 Prompt 中避免直接輸入機密資訊,必要時先做 脫敏 或使用 Azure OpenAI 的 Private Endpoint。
實際應用場景
| 場景 | 核心組件組合 | 範例說明 |
|---|---|---|
| 客服聊天機器人 | OpenAI + PromptTemplate + RouterChain + StructuredOutputParser |
先判斷使用者是「查訂單」還是「常見問題」,再分別呼叫不同的子 Chain,回傳 JSON 給前端渲染。 |
| 文件自動摘要與關鍵字產出 | LLMChain(摘要 Prompt) → LLMChain(關鍵字 Prompt) |
透過 SimpleSequentialChain 把 PDF 文字先摘要,再產生 SEO 關鍵字,直接寫入資料庫。 |
| 程式碼自動生成與測試 | OpenAI + FewShotPromptTemplate + RegexParser + Chain |
用 Few‑Shot 示範「輸入需求 → 輸出 TypeScript 函式」;用 RegexParser 抓出 function 標頭,並自動寫入測試檔。 |
| 金融報表分析 | AzureOpenAI + PromptTemplate + StructuredOutputParser + RouterChain |
根據使用者查詢的「報表類型」切換不同的分析 Prompt,回傳結構化的數據(如盈虧、成長率)供前端圖表使用。 |
| 教育平台自動批改 | ChatAnthropic + PromptTemplate + OutputParser + Chain |
給學生的答案與評分標準,模型產生「分數」與「改進建議」的 JSON,直接寫回 LMS。 |
總結
LangChain 以 模型、提示詞、輸出解析、工作流 四大模組化概念,為 LLM 應用提供了 可組合、可測試、可擴充 的開發體驗。
- Models 讓你輕鬆切換不同供應商;
- Prompts 把提示詞變成可重用的模板;
- Output Parsers 把文字變成程式可直接操作的結構化資料;
- Chains 則把上述所有元件串成完整的業務流程。
在實務開發時,建議先 設計 Prompt、定義輸出 Schema,再逐步把模型、解析器、Chain 組起來,最後加入 錯誤處理與日誌,即可打造出 穩定、可維護、成本可控 的生成式 AI 服務。
掌握這四個核心組件,你就能在 聊天機器人、文件處理、程式碼生成、數據分析 等多元領域,快速驗證概念、迭代產品,並將 AI 能力無縫嵌入現有系統。祝你玩得開心、寫得順利! 🚀