在前面幾天,我們探討了Prompt的邊界設定,以及如何透過Context Engineering(Write、Select、Compress、Isolate)精準調配模型的輸入
當輸入端的工程做好後,系統工程師馬上會撞到下一個致命痛點:輸出端的不可控性。
在傳統軟體工程中,模組與模組之間的溝通依賴嚴格的API契約(API Contracts)與型別系統(Type Systems)。然而,LLM天生是個自由文字生成器。如果你對模型說「請以 JSON 輸出」,它可能在今天回傳標準 JSON,明天卻在外面包了一層 json ... ,後天甚至漏掉某個關鍵欄位
只要輸出格式一破裂,下游的Python程式碼就會直接噴出 JSONDecodeError 或 KeyError,整個自動化工作流隨之崩潰
這正是為什麼我們需要 Structured Output Engineering(結構化輸出工程)
今天我們就來拆解它的底層原理與演進歷程
在軟體架構中,Structured Output Engineering的核心定義是:
透過確定性約束機制,強制 LLM 產生的 Token 序列嚴格遵循預先定義的資料結構(如 JSON Schema 或 Pydantic Model),確保輸出 100% 可被下游程式碼安全反序列化。
早期工程師常用的方式是在Prompt裡寫:「請輸出JSON,不要加多餘文字」。這種方法的致命缺陷在於:
"true"、空值可能變成 "None" 而非 null、數字可能帶有單位(如 "100元")。為了讓LLM穩定輸出結構化資料,社群與模型供應商經歷了三個階段的演進:
階段 1: Prompt + Regex / Output Parsers (重試與修補)
│
▼
階段 2: Function / Tool Calling 模式 (參數引導)
│
▼
階段 3: Constrained Decoding & JSON Schema Enforcement (底層語法引導生成)
json_schema 嚴格模式、Outlines、Instructor、SGLang), 或右大括號 },模型就絕對不可能生成英文字母。這在數學與邏輯上保證了輸出 100% 符合 JSON Schema
一個健全的結構化輸出定義,通常由以下三層資訊構成:
from pydantic import BaseModel, Field
from typing import Literal, Optional
class CustomerIntentOutput(BaseModel):
# 1. 欄位型別與枚舉限制 (Enums)
intent: Literal["REFUND", "EXCHANGE", "TRACKING", "OTHER"] = Field(
description="用戶的核心業務意圖"
)
# 2. 邊界約束與預設值
confidence_score: float = Field(
ge=0.0, le=1.0,
description="模型對此分類判定的置信度 (0.0 到 1.0 之間)"
)
# 3. 可選欄位與詳細定義
order_id: Optional[str] = Field(
default=None,
description="提取出的訂單編號,若對話未提及則為 null"
)
str、int、float、bool。Field(description=...) 指引模型該欄位的提取邏輯,兼具 Prompt 的導引效果。| 比較維度 | 非結構化輸出 (Free Text) | 結構化輸出 (Structured Output) |
|---|---|---|
| 資料型態 | 自然語言字串 (String) | 型別安全物件 (Pydantic / TypedDict) |
| 下游串接 | 需人工撰寫複雜 Parser 拆解字串 | 直接對接 API Payload、ORM、資料庫 |
| 錯誤處理 | 執行期遭遇 Parse Error 導致當機 | 在進入業務邏輯前即完成驗證與型別轉換 |
| 工作流相容性 | 難以在條件分支(Routing)中作為判斷依據 | 屬性可直接作為 if-else 或狀態機判斷條件 |
| 確定性 | 低(機率漂移) | 極高(語法級約束保證) |
Structured Output Engineering是將LLM從「聊天助理」轉化為「標準微服務節點」的關鍵轉換器
它抹平了生成式AI的隨機性,賦予輸出與傳統程式碼無縫相容的確定性
理解了結構化輸出的本質與底層機制後,在實戰中我們該如何使用Pydantic與主流LLM SDK(OpenAI, LangChain, Instructor)寫出零容錯的解析管線?
明天 【Day 7】怎麼應用 Structured Output Engineering,我們將進入實戰篇,透過具體程式碼展示如何使用 Pydantic 定義資料契約、處理驗證失敗回退機制,並將 LLM 輸出無縫寫入資料庫!