在前一篇文章中,我們介紹了 提示模板(Prompt Templates),透過模組化與參數化設計,讓提示語更具彈性與可讀性。不過,提示模板解決的只是「輸入」問題;若要打造真正穩定、可控的應用,還必須進一步處理並驗證模型的「輸出」。
為此,LangChain 提供了 輸出解析器(Output Parsers),能將模型生成的自然語言結果,轉換為結構化且可程式化處理的資料格式,讓我們更容易將 AI 回應整合進應用邏輯之中。
在多數情境下,LLM 生成的內容都是自然語言的自由文字,例如:
這是一個範例回應。
這樣的輸出對人類閱讀沒問題,但在工程應用裡,往往需要的是可被程式直接處理的結構化資料,例如 JSON、清單或固定格式的物件。舉例來說,如果我們希望模型輸出一個帶有標題與關鍵字的結果,就可能需要長這樣:
{
"title": "範例回應",
"keywords": ["範例", "回應"]
}
問題是,模型不一定會嚴格遵守我們的要求:有時會多加描述性文字,有時 JSON 格式不完整,甚至可能產生語法錯誤。
這時候就需要 輸出解析器(Output Parsers) 來協助控管。它的作用主要包含:
透過這種方式,我們能大幅降低「模型輸出不可控」所帶來的風險,讓 LLM 真正能成為工程流程的一部分。
在 LangChain 裡,輸出解析器不只是單純的「後處理」工具,它同時也是「提示設計」的一部分。因為解析器能自動生成格式指令,讓我們插入到提示中,引導模型輸出更可控、更符合需求的結果。它的運作流程大致可以分為以下步驟:
OutputFixingParser
)讓模型重新生成。整體流程可以用下圖來概括:
有了這層機制,開發者不必再額外撰寫繁瑣的字串處理程式,就能直接獲得結構化且可靠的結果,讓模型輸出更容易整合進實際應用。
LangChain 內建了多種常用的輸出解析器,開發者可以依照不同的需求選擇合適的工具,讓模型輸出更符合應用場景。常見的解析器包括:
StringOutputParser
:直接回傳模型的原始文字輸出,不做任何解析。JsonOutputParser
:將模型回應解析為 JSON 格式的物件或陣列,適合資料驅動的應用。CommaSeparatedListOutputParser
:將逗號分隔的字串轉為字串陣列,常用於列舉清單。StructuredOutputParser
:搭配 zod
schema 定義結構化欄位,並自動解析與驗證。透過這些解析器,我們能讓 LLM 的輸出更有結構、更可控,避免不必要的格式錯誤,也能更順暢地整合進應用程式流程中。
Note:zod 是一個用於型別安全的 TypeScript/JavaScript 資料驗證與解析套件。它允許開發者以宣告式的方式定義資料結構(Schema),並在程式運行時對輸入或輸出的資料進行驗證。
StringOutputParser
:最基礎的文字輸出在所有輸出解析器中,StringOutputParser
是最基礎也最單純的一種。它不會對模型的回應進行任何額外處理,而是直接回傳原始文字。
以下是一個簡單範例,我們請模型用一句話介紹 Node.js,並透過 StringOutputParser
直接回傳結果:
import { ChatOpenAI } from '@langchain/openai';
import { StringOutputParser } from '@langchain/core/output_parsers';
const model = new ChatOpenAI({
model: 'gpt-4o-mini',
});
const parser = new StringOutputParser();
const response = await model.invoke("請用一句話介紹 Node.js。");
const parsed = await parser.parse(response.content);
console.log(parsed);
執行後,輸出可能會是:
Node.js 是一個基於 Chrome V8 引擎的 JavaScript 執行環境,適合開發高效能伺服器應用。
如同範例所示,StringOutputParser
只是單純把模型輸出轉為字串並回傳,不會進行格式檢查或驗證。這種方式非常適合那些只需要直接取用模型文字內容的場景,例如對話回覆、文章摘要或自由生成的內容。
JsonOutputParser
:將模型回應轉成結構化物件在需要讓模型輸出結構化資料的情境下,JsonOutputParser
是非常實用的工具。它能將模型回應中的 JSON 直接轉換為 JavaScript 物件或陣列,讓程式能安全地存取欄位,而不需要再手動處理字串。
以下是一個範例,我們要求模型輸出一部電影的基本資訊,並以 JSON 格式回傳,再透過解析器將其轉換成 JavaScript 物件:
import { ChatOpenAI } from '@langchain/openai';
import { JsonOutputParser } from '@langchain/core/output_parsers';
import { PromptTemplate } from '@langchain/core/prompts';
const model = new ChatOpenAI({
model: 'gpt-4o-mini',
});
const parser = new JsonOutputParser();
const response = await model.invoke("請提供一部電影的基本資訊,並以 JSON 格式輸出,包含 title, genre, year。");
const parsed = await parser.parse(response.content);
console.log(parsed);
執行後的輸出結果會是一個結構化物件,例如:
{ title: 'Inception', genre: 'Science Fiction', year: 2010 }
透過這樣的設計,我們可以不用自己處理 JSON 格式字串,直接得到程式可操作的物件。若要進一步加上格式驗證或結構限制,也可以考慮使用 StructuredOutputParser
,搭配 schema 定義,確保模型輸出的格式與內容完全符合規範。
CommaSeparatedListOutputParser
:將文字清單轉為陣列當我們希望模型輸出一份清單時,CommaSeparatedListOutputParser
就派上用場了。它能將模型回應中的「逗號分隔字串」自動轉換成陣列,讓輸出結果更方便操作,例如產生關鍵字列表、熱門選項或代辦事項。
以下是一個範例,我們透過 getFormatInstructions()
要求模型輸出三種熱門程式語言,並使用解析器自動轉換成字串陣列:
import { ChatOpenAI } from '@langchain/openai';
import { CommaSeparatedListOutputParser } from '@langchain/core/output_parsers';
import { PromptTemplate } from '@langchain/core/prompts';
const model = new ChatOpenAI({
model: 'gpt-4o-mini',
});
const parser = new CommaSeparatedListOutputParser();
const prompt = new PromptTemplate({
template: `列出三種熱門程式語言。\n{format_instructions}`,
inputVariables: [],
partialVariables: {
format_instructions: parser.getFormatInstructions(),
},
});
const input = await prompt.format({});
const response = await model.invoke(input);
const parsed = await parser.parse(response.content);
console.log(parsed);
Tip:
PromptTemplate
通常需要我們在inputVariables
中傳入使用者輸入,但有些變數(像format_instructions
)是固定的,不需要每次重新指定。這時就能透過partialVariables
先行綁定,讓模板在建立時就包含固定內容。
執行後的輸出結果會是一個陣列,例如:
[ 'JavaScript', 'Python', 'Java' ]
這樣的方式能讓模型輸出更貼近我們需要的資料結構,非常適合處理需要列舉清單或選項的場景。
StructuredOutputParser
:嚴謹結構化輸出的利器如果你需要模型輸出複雜的結構化資料,並且希望對欄位型別和格式進行嚴格驗證,那麼 StructuredOutputParser
就是最佳選擇。它能搭配 zod
schema 來定義每個欄位的名稱、型別與描述,並在解析時自動檢查輸出是否符合規範。
以下範例中,我們定義一個 zod
schema,描述電影資訊的格式,並透過 getFormatInstructions()
要求模型輸出符合結構的內容:
import { ChatOpenAI } from '@langchain/openai';
import { StructuredOutputParser } from '@langchain/core/output_parsers';
import { PromptTemplate } from '@langchain/core/prompts';
import { z } from 'zod';
const model = new ChatOpenAI({
model: 'gpt-4o-mini',
});
const parser = StructuredOutputParser.fromZodSchema(
z.object({
title: z.string().describe("電影名稱"),
genre: z.string().describe("電影類型"),
year: z.number().describe("上映年份"),
})
);
const prompt = new PromptTemplate({
template: `請提供一部知名電影的基本資訊。\n{format_instructions}`,
inputVariables: [],
partialVariables: {
format_instructions: parser.getFormatInstructions(),
},
});
const input = await prompt.format({});
const response = await model.invoke(input);
const parsed = await parser.parse(response.content);
console.log(parsed);
執行後,輸出會是一個完整且符合 schema 驗證的物件,例如:
{ title: 'Interstellar', genre: 'Science Fiction', year: 2014 }
與 JsonOutputParser
相比,StructuredOutputParser
提供更嚴格的驗證機制,它能透過 schema 驗證輸出的完整性與型別正確性。如果模型少了欄位或格式錯誤,解析器會立即拋出例外,避免下游應用因資料異常而出現問題。這種設計特別適合需要欄位完整性與型別一致性的應用場景,例如表單填寫、知識資料庫存取,或需嚴格遵循資料格式的 API 整合。
OutputFixingParser
:自動修正錯誤輸出即使有了格式指令與解析器,LLM 仍有可能產生格式錯誤的輸出,例如漏掉欄位、多了一些描述文字,或 JSON 語法不完整。這時候,我們就可以利用 OutputFixingParser
來自動修正。
它的運作方式是:先嘗試使用原本的解析器(例如 JsonOutputParser
或 StructuredOutputParser
)處理輸出,如果解析失敗,則會再次呼叫模型,要求它依照指定的格式重新生成合格結果。
以下範例示範如何搭配 StructuredOutputParser
與 OutputFixingParser
,即使模型輸出缺少欄位,也能透過修正得到完整物件:
import { ChatOpenAI } from '@langchain/openai';
import { StructuredOutputParser, OutputFixingParser } from '@langchain/core/output_parsers';
import { z } from 'zod';
const model = new ChatOpenAI({
model: 'gpt-4o-mini',
});
const baseParser = StructuredOutputParser.fromZodSchema(
z.object({
title: z.string().describe("電影名稱"),
genre: z.string().describe("電影類型"),
year: z.number().describe("上映年份"),
})
);
const parser = OutputFixingParser.fromLLM(model, baseParser);
const badOutput = `{
"title": "Interstellar",
"genre": "Science Fiction"
}`;
const parsed = await parser.parse(badOutput);
console.log(parsed);
注意:
OutputFixingParser
並非隸屬於@langchain/core/output_parsers
,而是提供在langchain/output_parsers
模組中。使用時請確認已安裝langchain
套件。
在這個例子中,雖然原始輸出缺少了 year
欄位,OutputFixingParser
會請模型自動補齊,最後輸出完整的物件,例如:
{ title: 'Interstellar', genre: 'Science Fiction', year: 2014 }
透過 OutputFixingParser
,我們就能建立一個更穩健的輸出流程:先讓模型依照格式指令生成輸出,再由解析器驗證,若失敗則自動修正,直到產生正確的格式。這讓 LLM 的輸出更結構化、更可靠,適合應用在高可靠度需求的系統中。
今天我們學會了如何運用 LangChain 的 輸出解析器(Output Parsers) 來控管 LLM 的回應格式,讓模型輸出更結構化、穩定且可靠,並能更順利地整合進應用程式流程:
StringOutputParser
:單純取回文字。JsonOutputParser
:將回應轉為 JSON。CommaSeparatedListOutputParser
:自動將逗號分隔字串轉成陣列。StructuredOutputParser
:搭配 schema 嚴格驗證欄位與型別。OutputFixingParser
:當格式錯誤時,可請模型自動修正並輸出合格結果。透過這些解析工具,我們能大幅降低模型輸出不可控的風險,讓 AI 不只是聊天助手,更能成為能穩定融入程式邏輯的可靠元件。