Pydantic AI 結構化輸出 (Structured Output)
當你在開發需要與其他系統或資料庫介接的 AI 應用時,只獲得一段非結構化的文字回覆(PlainText)通常是不夠的。你需要 AI 回傳格式正確、型別嚴謹的資料,例如 JSON 格式。
Pydantic AI 最強大的功能之一,就是它無縫整合了 Pydantic 本身的資料驗證機制,能夠確保 AI 模型的回覆百分之百符合你所定義的結構與型別,這也就是所謂的結構化輸出 (Structured Output)。
為什麼需要結構化輸出?
想像你正在打造一個從新聞報導中提取特定資訊的 AI 系統,你需要擷取「標題」、「發生日期」與「相關人物清單」。
如果使用一般的文字輸出,AI 可能有時回覆 Markdown 列表,有時回覆包含敘述性文字的 JSON。當你的程式嘗試解析這些不穩定的格式時,很容易就會發生錯誤(Runtime Error)。結構化輸出可以強制 AI 遵循特定的 Schema,讓下游程式能夠安全地處理資料。
定義回傳型別 (Result Type)
在 Pydantic AI 中,你可以使用 result_type 參數來宣告 Agent 預期的回傳資料結構。這個型別可以是簡單的 Python 內建型別(如 str, int, list[str]),也可以是強大的 Pydantic BaseModel 或 Python dataclass。
範例:回傳 Pydantic BaseModel
這是實務上最推薦的做法。透過定義 Pydantic 的 BaseModel,你不僅定義了資料結構,還能加上驗證規則 (Validation) 與欄位說明 (Descriptions),幫助 AI 更好地理解它該產出什麼。
from pydantic import BaseModel, Field
from pydantic_ai import Agent
# 1. 定義期望的資料結構
class CityInformation(BaseModel):
# 使用 Field 提供說明,這些說明會被當作 prompt 的一部分傳給 AI
city_name: str = Field(description="城市的標準中文名稱")
country: str = Field(description="該城市所屬的國家")
population: int = Field(description="該城市大約的人口數")
is_capital: bool = Field(description="該城市是否為該國的首都")
famous_landmarks: list[str] = Field(description="3個著名的地標景點清單")
# 2. 建立 Agent,並明確指定 result_type 為我們定義的 Model
# 注意:這裡加上了 result_type,框架就能提供型別安全的檢查
agent = Agent(
'gemini-1.5-flash',
result_type=CityInformation,
system_prompt="你是一個地理百科助手,請根據使用者的提問,提取正確的城市資訊。"
)
# 3. 執行 Agent
result = agent.run_sync("請給我關於日本東京的資訊。")
# 4. result.data 此時已經被自動驗證,並轉換為 CityInformation 實例
# IDE 會知道 result.data 有 city_name, population 等屬性
print(f"城市名稱: {result.data.city_name}")
print(f"所屬國家: {result.data.country}")
print(f"是否為首都: {result.data.is_capital}")
print(f"著名景點: {', '.join(result.data.famous_landmarks)}")
發生驗證錯誤時的自動重試
如果 AI 第一次回傳的格式不符合 CityInformation 的結構(例如將人口數 population 填成字串 "一千萬" 而非整數 10000000),Pydantic 驗證會失敗並拋出錯誤。
然而,Pydantic AI 框架具備自動修復的機制。當驗證失敗時,框架會在背後自動發起重試(Retry),並將 Pydantic 產生的錯誤訊息告訴模型,讓模型知道哪裡出錯了並重新生成符合規則的輸出。這個過程對開發者來說是完全透明的,極大程度地減少了應用程式崩潰的機會。
支援的型別
除了 Pydantic BaseModel,result_type 也支援:
- 內建型別:
int,float,str,bool - 集合型別:
list[str],dict[str, int] - 聯合型別 (Union):
Union[str, list[str]]或str | list[str]。這讓 AI 可以根據情況回傳不同的格式。 - Dataclasses:標準 Python 的
@dataclass也可以作為結果型別。
透過宣告結構化輸出,Pydantic AI 把 LLM 充滿不確定性的「自然語言生成」轉變成了「型別安全且可預測的程式函式」,這是構建穩定 AI 應用的關鍵基石。