Back to blog
    pydantic-ailanggraphai-agentsfine-tuningframework-comparisontool-calling

    Pydantic AI vs LangGraph:微調代理選哪個框架

    Pydantic AI 給你型別安全的線性代理,LangGraph 給你持久化的有狀態圖。一份 2026 年決策矩陣,以及為什麼微調能讓兩者都變得可靠。

    Edward Xi Yang

    更新於 2026-05-10:反映 5 月初 Pydantic AI v1.90.x / v1.93.x 釋出(明確的 tool_choice、專屬的 OutputToolCallEvent / OutputToolResultEvent 串流事件、OpenAI Conversations API 狀態)。下方的決策矩陣不變;新原語主要是收緊 Pydantic AI 已在勝出的型別安全與可觀測性故事。

    到 2026 年,Python 代理框架格局已整合。從任何出貨代理至生產的團隊,手動撰寫的「呼叫 OpenAI 的 while 迴圈」做法已消失。早期 LangChain 那個有四十個可組合抽象的科學怪人堆疊也消失了。兩個框架仍位於認真工作的中心:LangGraph,基於圖的狀態機框架,現在在 Uber、JPMorgan、BlackRock 與 Replit 執行生產代理;以及 Pydantic AI,型別安全的 FastAPI 風格框架,其 2026 年 4 月的 1.0 釋出使其成為新專案的明顯預設。

    兩者都模型無關。兩者都與透過 Ollama、vLLM 或 Ertas Cloud 提供服務的微調開源權重模型乾淨運作。兩者都將工具呼叫視為一級原語。在兩者間選擇不是哪個「更好」的問題——它是關於你的代理該如何結構化的設計哲學選擇。本文誠實地走過取捨,然後展示兩個框架如何因為下面分層微調模型而戲劇性地受益。

    Pydantic AI:型別優先的代理

    Pydantic AI 由 Pydantic 與 Logfire 背後的團隊建構。設計精神直接借鑒自 FastAPI:型別是合約、驗證不可妥協、框架在你宣告形狀後應消失到背景中。Agent 由結果型別參數化。工具是裝飾的函式,Pydantic AI 解析其簽章以建構工具 schema。輸出自動依結果型別驗證。如果模型發出不符合的東西,你獲得 ValidationError,而非沉默的 bug。

    執行期是輕量的。沒有圖引擎、沒有 checkpoint 層、沒有執行排程器。代理作為普通 Python 執行:呼叫 agent.runagent.run_sync,框架處理 LLM 迴圈、工具分派與驗證。整個函式庫採 MIT 授權,相依樹小到你在 pyproject.toml 裡幾乎不會注意到它。

    這使 Pydantic AI 自然契合最常見的生產情境:接收輸入、呼叫幾個工具、回傳結構化輸出的代理。擷取代理、分類器、路由器、輕量助理。如果你的工作流程主要是線性的而你關心輸出 schema,Pydantic AI 比任何可用方案都更快帶你到測試過的生產代理。2026 年 4 月的 1.0 釋出穩定了 API,使在其上建構商業產品變得安全。

    LangGraph:有狀態、耐久、圖編排

    LangGraph 走相反的設計路徑。代理是由邊連接的節點構成的有向圖。每個節點是一個函式(LLM 呼叫、工具執行、條件檢查)。邊描述狀態如何在節點間流動,包括基於中間狀態分支的條件邊。圖引擎執行整個東西,每一步保存狀態。

    從這個設計掉出三件 Pydantic AI 不嘗試做的事。

    耐久 checkpoint。每次狀態轉移都被保存。如果代理在執行中崩潰——程序被殺、伺服器重啟、網路分區——你可以從最後 checkpoint 恢復而非從頭開始。對於執行數小時或數日的代理,這是可行與否的差別。

    並行分支。因為圖引擎排程節點,你可以扇出到多個並行分支並稍後合流。並行呼叫五個不同 API 並彙整其結果的研究代理是一個圖定義,而非手動非同步協調層。

    人類介入中斷。圖可以在指定節點暫停、將狀態呈現給人類審查者,並在決定回來後恢復。對於核可工作流程、升級,以及任何在受監管產業運作的代理,這是必要的。LangGraph 的 interrupt 原語將「人類核可」從事後考量轉成像任何其他圖節點。

    這些能力的代價是複雜性。LangGraph 要求你將代理視為狀態機。圖定義比 Pydantic AI 基於裝飾器的代理更冗長。執行期更重——它帶有圖引擎、checkpoint 層,以及(在生產中)通常為持久化的 Postgres 或 Redis 後端。對於線性擷取代理這太過頭。對於多階段核可工作流程它正是你需要的。

    LangGraph 是 JPMorgan、BlackRock 與 Uber 為觸及金錢、客戶支援與合規相關操作的生產代理選擇的。圖模型給予他們合規團隊要求的稽核軌跡:每次狀態轉移都被記錄、每次工具呼叫都可重現、每個決定都可重播。Pydantic AI 的輕量執行期無法輕易提供該層級的可追溯性。

    兩個框架重疊的地方

    儘管哲學不同,兩個框架在幾個實務點上落在同一處。

    兩者都將 OpenAI 相容 API 作為一級傳輸。兩者都與任何暴露該介面的模型伺服器運作——Ollama、vLLM、llama.cpp 的 llama-server、LM Studio、Ertas Cloud、OpenAI API 本身、透過 OpenAI 相容代理的 Anthropic,或任何自訂服務堆疊。這意味著你在 Ertas Studio 出貨的微調模型對任一框架運作相同,無需程式碼變更。

    兩者都有一級工具呼叫支援。你宣告函式,框架擷取其 schema,LLM 獲得結構化的工具使用格式。兩者都在執行前驗證工具引數;兩者都在下一輪將工具結果呈現回 LLM。

    兩者都有在生產中重要的可觀測性故事。Pydantic AI 與 Logfire 緊密整合(同一團隊)並發出 OpenTelemetry 追蹤。LangGraph 與 LangSmith 整合用於圖執行追蹤,並支援 OpenTelemetry 匯出器。任一個都會在生產中給你每次工具呼叫的延遲、token 使用與錯誤追蹤。

    所以在它們間的選擇不是關於基本能力。它是關於工作流程形狀與營運需求。

    決策矩陣

    情境勝者原因
    線性擷取代理Pydantic AI輕量執行期、schema 經驗證的輸出、無圖開銷
    帶人類審查的多步驟核可工作流程LangGraphInterrupt 原語將核可變成圖節點
    型別安全的工具輸入與輸出至關重要Pydantic AI驗證是框架存在的全部理由
    跨小時暫停與恢復的長時運行代理LangGraph耐久 checkpoint 在程序重啟下存活
    Serverless 或邊緣的輕量執行期Pydantic AI最小相依、無需持久化層
    需要稽核軌跡的受監管產業LangGraph每次狀態轉移皆記錄、可重播、合規就緒
    新創公司從原型到生產的快速Pydantic AI較低的認知負擔、更快迭代
    並行多 API 研究代理LangGraph圖原生扇出與合流

    注意這個模式。當工作流程主要是線性、輸出結構重要,且你想要快速移動時,Pydantic AI 勝出。當工作流程確實是狀態機、耐久性與稽核軌跡不可妥協,且團隊有工程頻寬仔細設計圖時,LangGraph 勝出。

    微調角度:為什麼兩個框架都需要它

    這是 2026 年代理框架的不舒適真相:它們假設模型可以可靠地產生結構化輸出。Pydantic AI 假設它,因為驗證器在每個輸出觸發。LangGraph 假設它,因為每個節點的輸出成為下一節點的輸入。當模型行為不端時,兩個框架都退回重試——而重試耗費延遲、耗費 token,並侵蝕使用者信任。

    對 Claude 或 GPT-5 Pro 等前沿 API,該假設成立得夠好。對通用開源權重模型——直接從 Hugging Face 架上來的 Qwen3-7B、Llama 3.1 8B、Mistral Small——則不然。Schema 違規很常見。錯誤的工具名稱出現。參數型別漂移。框架的驗證層從「防護欄」變成「反覆例外來源」,而你的團隊開始用重試裝飾器包裹每個代理呼叫,粉飾真正的問題。

    微調從源頭修正這點。在你代理使用的確切工具 schema、你程式碼期望的確切輸出格式、來自你領域的數百段代表性對話上訓練模型。模型成為可靠的結構化輸出產生者。Pydantic AI 的驗證器回到防護欄。LangGraph 的節點流入彼此而不需要包裹邏輯。

    經濟模型也以同樣方式傾斜。多步驟代理的前沿 API 呼叫每執行 $0.01 至 $0.05。每天 10,000 次執行就是每天 $100 至 $500、每年 $36,000 至 $180,000。在單 GPU 實例上提供的微調 7B 或 8B 模型成本低數個量級,而微調的 4B 模型可在使用者裝置上免費執行。對於感受到代理成本懸崖在 500 至 5,000 使用者間咬住的行動 app 建構者——當 API 帳單開始消耗利潤的速度比營收成長更快的時刻——微調不是最佳化,而是唯一前進路徑。

    兩個框架的整合相同:在 Ertas Studio 訓練你的模型、匯出為 GGUF、透過 Ollama 或 vLLM 提供服務,並將代理的 base_url 指向 OpenAI 相容端點。從框架角度看,你的微調模型只是另一個 OpenAI 相容模型。從使用者角度看,代理顯著更可靠且帳單顯著更小。

    同一代理,兩個框架

    為了讓比較具體,以下是相同的分流代理——將支援工單對應到正確團隊的理賠路由分類器——以兩個框架實作,對 Ollama 提供的 Ertas 微調 Qwen3-4B 運行。

    Pydantic AI 版本:

    from typing import Literal
    from pydantic import BaseModel
    from pydantic_ai import Agent
    from pydantic_ai.models.openai import OpenAIModel
    
    model = OpenAIModel(
        "ertas-claims-router-4b",
        base_url="http://localhost:11434/v1",
        api_key="not-needed",
    )
    
    class TriageDecision(BaseModel):
        team: Literal["billing", "technical", "fraud", "general"]
        priority: Literal["low", "normal", "high", "urgent"]
        reasoning: str
    
    agent = Agent(
        model,
        result_type=TriageDecision,
        system_prompt="Route incoming support tickets to the right team and priority.",
    )
    
    @agent.tool
    async def lookup_account(ctx, account_id: str) -> dict:
        """Look up account history to inform routing."""
        return await crm.get_account(account_id)
    
    result = agent.run_sync(
        "My card was charged twice for the same order this morning."
    )
    print(result.data)
    # TriageDecision(team='billing', priority='high', reasoning='Duplicate charge')

    LangGraph 版本:

    from typing import TypedDict, Literal
    from langgraph.graph import StateGraph, END
    from langchain_openai import ChatOpenAI
    from langchain_core.messages import HumanMessage
    
    llm = ChatOpenAI(
        model="ertas-claims-router-4b",
        base_url="http://localhost:11434/v1",
        api_key="not-needed",
    ).bind_tools([lookup_account_tool])
    
    class TriageState(TypedDict):
        ticket: str
        account_data: dict | None
        team: str | None
        priority: str | None
    
    def fetch_account(state):
        if account_id := extract_account_id(state["ticket"]):
            return {"account_data": crm.get_account(account_id)}
        return {"account_data": None}
    
    def classify(state):
        msg = llm.invoke([HumanMessage(content=build_prompt(state))])
        parsed = parse_triage_decision(msg.content)
        return {"team": parsed["team"], "priority": parsed["priority"]}
    
    graph = StateGraph(TriageState)
    graph.add_node("fetch", fetch_account)
    graph.add_node("classify", classify)
    graph.set_entry_point("fetch")
    graph.add_edge("fetch", "classify")
    graph.add_edge("classify", END)
    
    app = graph.compile()
    result = app.invoke({"ticket": "My card was charged twice this morning."})

    兩個實作都運作。兩者都使用相同的微調模型。兩者都是大約三十行程式碼。Pydantic AI 版本較短並由構造給你型別化輸出;LangGraph 版本更冗長,但每個狀態轉移都可 checkpoint、圖可透過加入 interrupt 節點暫停以供人類審查,且整個東西自然擴展為——比如說——也通知團隊、開 Jira 工單,並在最終路由前等待人類確認優先順序的工作流程。

    對於純分類器,Pydantic AI 是明顯的選擇。對於是涉及核可與升級之較長工作流程中第一個節點的分類器,LangGraph 開始賺取它的複雜性。

    建議

    對於 2026 年的大多數團隊,正確的答案是從 Pydantic AI 開始。認知負擔較低、執行期較輕、API 較舒適,而型別安全在第一次抓住格式不正確的模型輸出在它觸及生產之前自我支付。九成的代理使用情境是線性或近乎線性,而 Pydantic AI 乾淨地處理它們。

    當圖編排成為瓶頸時——當你發現自己手動建構 checkpoint 層、當你需要真正的人類介入中斷、當合規要求每次狀態轉移的稽核軌跡、當工作流程自然以手動控制流無法乾淨表達的方式分支與重新合流——畢業到 LangGraph。對某些團隊那是真實的時刻。對大多數團隊它不是會抵達的時刻。

    當你看到第二或第三張 API 帳單時,在任一框架下分層微調。微調的 4B 至 8B 模型與真實代理框架的組合是 2026 年讓正式上線代理既可靠又經濟的東西。沒有微調,你的框架花費大部分能量鋪平模型不可靠性。有了微調,框架得以做它被設計來做的工作。

    Ertas Studio 處理微調面。挑你的基底模型——行動端與邊緣的 Qwen3-4B、伺服器端代理的 Qwen3-7B 或 Llama 3.1 8B——在 Data Craft 整理數百個範例、訓練、評估、匯出為 GGUF。Ertas Deployment CLI 在重要時處理行動出貨路徑。OpenAI 相容服務意味著無論你選哪個框架,整合都是一行設定。

    依工作流程形狀挑你的框架。依領域挑你的模型。微調讓模型原生地說你的工具語言。那是 2026 年的生產配方。

    延伸閱讀

    就本文向 AI 提問

    Ship AI that runs on your users' devices.

    Free plan with 30 credits/mo, no card required. Paid plans from $10/mo USD.

    Keep reading