Back to blog
    Pydantic AI 裝置端:為型別安全的行動代理微調 Qwen3-4B
    pydantic-aifine-tuningtool-callingqwen3on-devicemobileai-agents

    Pydantic AI 裝置端:為型別安全的行動代理微調 Qwen3-4B

    Pydantic AI 為 LLM 代理帶來型別安全與 FastAPI 人體工學。將其與透過 llama.cpp 在裝置端執行的微調 4B 模型結合,你便能在行動 app 中獲得正式上線等級的代理,享有零 API 成本與構造上經驗證的輸出。

    EErtas Team·

    更新於 2026-05-10 — 反映 5 月初的 Pydantic AI v1.90.x 與 v1.93.x 點版釋出,加入了 Agent 上明確的 tool_choice 設定(讓你可在工作流程要求時將模型固定到特定函式呼叫)以及專屬的 OutputToolCallEventOutputToolResultEvent 串流事件以提供更細粒度的可觀測性。當代理對微調本地模型運行,而你想能精確斷言每一步驟選擇了哪個工具時,兩者都很有用。

    Pydantic AI 是 Python 開發者一直在等待的代理框架。型別提示成為合約。工具定義成為經驗證的函式。輸出 schema 成為保證,而非建議。它是 LLM 代理的 FastAPI——並與微調本地模型異常地契合。

    這個組合很重要,因為 Pydantic AI 的設計假設模型可以可靠地產生結構化輸出。對 Claude 或 GPT-5 等前沿 API 而言,這個假設通常成立。對通用的 7B 開源權重模型而言,則不然——schema 違規很常見、重試是家常便飯,而框架承諾的型別安全開始感覺像是包裹脆弱推論的外殼。

    微調的 4B 模型修正了這點。在你的代理使用的確切工具 schema 與輸出格式上訓練,模型幾乎每次都產生經驗證的輸出。Pydantic AI 的驗證器成為防護欄,而非反覆的例外來源。而由於模型小到足以透過 llama.cpp 在裝置端執行,你獲得 Pydantic AI 承諾的型別安全,卻沒有任何在 500 至 5,000 使用者間打破行動 app 單位經濟學的按 token API 成本。

    本指南將走完完整管線:在 Ertas Studio 為一個範例行動 app 代理微調 Qwen3-4B、透過 Ertas Deployment CLI 在裝置端部署它,並將其接入完全在使用者手機上執行的 Pydantic AI 代理。

    設定:行事曆助理代理

    我們將建構一個讀取自然語言請求並發出經驗證預訂行動的行事曆助理。代理有三個工具:

    • find_availability(start: datetime, end: datetime, duration_min: int) 回傳可用空檔
    • book_meeting(slot: TimeSlot, attendees: list[str], title: str) 建立預訂
    • cancel_meeting(meeting_id: str) 取消既有預訂

    代理的輸出是一個帶結構化欄位的 BookingDecision Pydantic 模型。Pydantic AI 將每個輸出依此 schema 驗證。如果模型發出無效輸出,Pydantic AI 會拋出 ValidationError,主機 app 可捕捉並重試。

    這正是對前沿 API 執行時昂貴、對通用本地模型執行時緩慢的代理。微調並裝置端化後,它既快又免費。

    步驟 1:在 Studio 整理微調資料集

    開啟 Ertas Studio 並建立新專案。使用 Data Craft 定義你的工具 schema——將函式簽章貼到 schema 面板,Studio 會以它們作為訓練資料的結構目標。

    對於行事曆助理,你通常會想要 300–800 個訓練範例,涵蓋:

    • 單工具呼叫:「明天下午 2 點與 john@ 預約 30 分鐘會議」→ 一次 book_meeting 呼叫
    • 多步驟呼叫:「找明天下午 30 分鐘並與設計團隊預約」→ find_availability 接著 book_meeting
    • 驗證邊緣案例:「取消我們剛預訂的那個會議」(需要從先前脈絡取得 meeting_id)
    • 拒絕:「向所有與會者發送追蹤電子郵件」——超出範圍,回傳結構化拒絕

    Data Craft 為此有兩種模式。手動模式讓你在結構化表格中撰寫每個範例。批次模式發出結構化提示範本,你貼到 Claude 或 ChatGPT 對話式地產生數百個範例——Studio 攝取輸出並在加入訓練集前依你的工具 schema 驗證每個範例。

    目標 500 個範例。超過 500 後,資料集品質遠比數量重要。在驗證邊緣案例與拒絕上花時間——這些是通用模型幻覺參數的地方,也是微調產生最大可靠性增益的地方。

    步驟 2:微調 Qwen3-4B

    在 Studio 中選擇 Qwen3-4B-Instruct 作為基底模型。4B 大小是裝置端部署的正確權衡——小到可舒適裝在現代手機上(Q4_K_M 下約 2.5 GB),大到能可靠處理多輪對話與並行工具呼叫。

    Studio 對工具呼叫微調的預設訓練設定是 QLoRA 在 rank 32 下訓練 3 個 epoch。驗證損失曲線通常在 epoch 2.5 附近開始平緩;Studio 的自動評估會標記出現的過擬合。在標準 GPU 階層上,500 個範例的訓練執行在一小時內完成。

    訓練完成後,對你的保留驗證集執行 Studio 的評估套件。對於工具呼叫微調,看三個指標:工具名稱準確率(模型挑了正確的函式嗎?)、參數名稱準確率(它填了正確的參數嗎?)以及參數值準確率(它使用了正確的值嗎?)。正式上線就緒的模型在這三項上得分都超過 95%。

    如果任何指標低於 95%,通常的原因是資料集缺口——在評估報告中找出失敗的範例、為缺失情況加入代表性訓練資料、執行漸進式微調。Studio 支援從 checkpoint 繼續訓練,而不必從頭重新開始。

    步驟 3:匯出為 GGUF 並出貨至行動端

    Studio 的匯出流程在你選擇的量化等級下產生 GGUF 二進位檔。對於行動端的 Qwen3-4B,Q4_K_M 是預設——磁碟上約 2.5 GB、約 3 GB 工作記憶體,在任何現代手機的預算內。

    對你既有的 iOS、Android、Flutter 或 React Native 專案執行 Ertas Deployment CLI:

    ertas deploy mobile \\
      --project ./my-app \\
      --model ertas-calendar-agent-4b.gguf \\
      --framework react-native
    

    CLI 安裝 llama.cpp 的行動 FFI 綁定、將 GGUF 模型放入正確的專案位置,並接通可運作的推論呼叫。對於 React Native 而言,CLI 暴露了一個 useErtasModel hook,回傳一個型別化的推論函式。從執行 CLI 到可運作的裝置端推論呼叫的總耗時:通常在 5 分鐘內。

    步驟 4:將 Pydantic AI 接到裝置端模型

    Pydantic AI 不在裝置端執行——它是 Python 框架。所以架構是後端模式:Pydantic AI 在你的後端執行(Python 服務或 serverless 函式),但它呼叫的模型是 Ertas Deployment CLI 透過本地 HTTP 端點從行動 app 暴露的裝置端推論伺服器。

    開發時,在你的筆記型電腦上透過 Ollama 執行模型,並將 Pydantic AI 指向本地端點:

    from datetime import datetime
    from typing import Literal
    from pydantic import BaseModel
    from pydantic_ai import Agent
    from pydantic_ai.models.openai import OpenAIModel
    
    # Point Pydantic AI at the Ertas-trained Qwen3-4B served via Ollama
    model = OpenAIModel(
        "ertas-calendar-agent-4b",
        base_url="http://localhost:11434/v1",
        api_key="not-needed",
    )
    
    class TimeSlot(BaseModel):
        start: datetime
        end: datetime
    
    class BookingDecision(BaseModel):
        action: Literal["book", "find", "cancel", "reject"]
        slot: TimeSlot | None = None
        meeting_id: str | None = None
        rejection_reason: str | None = None
    
    agent = Agent(
        model,
        result_type=BookingDecision,
        system_prompt="You schedule meetings. Use the available tools to find slots and book.",
    )
    
    @agent.tool
    async def find_availability(ctx, start: datetime, end: datetime, duration_min: int) -> list[TimeSlot]:
        """Find open calendar slots between start and end of at least duration_min."""
        return await calendar_api.search(start, end, duration_min)
    
    @agent.tool
    async def book_meeting(ctx, slot: TimeSlot, attendees: list[str], title: str) -> dict:
        """Create a calendar booking."""
        return await calendar_api.book(slot, attendees, title)
    
    @agent.tool
    async def cancel_meeting(ctx, meeting_id: str) -> dict:
        """Cancel a calendar booking by ID."""
        return await calendar_api.cancel(meeting_id)
    
    # Run the agent with a natural-language request
    result = agent.run_sync(
        "Find me 30 minutes tomorrow afternoon and book it with the design team."
    )
    print(result.data)
    # BookingDecision(action='book', slot=TimeSlot(start=..., end=...), meeting_id='m-abc', ...)
    

    有兩件事在程式碼中看不出來。首先,Pydantic AI 的驗證器已確認模型輸出完全符合 BookingDecision——無遺漏欄位、無幻覺額外項。如果模型發出無效輸出,Pydantic AI 會拋出 ValidationError,你會捕捉到。其次,每次工具呼叫的輸入都依工具的簽章驗證。如果模型傳入錯誤型別,Pydantic AI 會在它觸及你的 CRM 之前拒絕呼叫。

    對於正式上線,將 base_urlhttp://localhost:11434/v1 換成提供你模型服務的端點。如果模型透過 Ertas Deployment CLI 在使用者手機上執行,端點是裝置的本地推論伺服器(通常從裝置自身角度為 http://localhost:8080/v1,或視你的架構透過後端路由)。

    為什麼這個架構有效

    三股力量對齊。

    Pydantic AI 給你型別安全。框架的驗證層將每個模型輸出轉成被檢查的 Python 物件。Schema 違規成為例外,而非沉默的 bug。對於驅動真實行動的代理——預訂、支付、基礎設施變更——這是必要的。

    微調讓型別安全變得穩定。沒有微調,模型是不可靠的結構化輸出產生者,而 Pydantic AI 的驗證器不斷觸發。在代理使用的確切 schema 上微調後,模型成為可靠的產生者,驗證器主要是防護欄而非反覆的失敗點。兩層互補:訓練教模型產生結構化輸出,驗證在執行期強制契約。

    裝置端推論讓經濟模型可行。對於多步驟預訂流程,前沿 API 呼叫依脈絡花費 $0.01–$0.05。1,000 日活躍使用者每人執行 5 次預訂流程,每天就是 $50–$250,即每月 $1,500–$7,500。在裝置端,成本是使用者儲存上的模型大小與每次推論幾百毫秒的 CPU/GPU 時間。帳單不會隨你的使用者基數成長。

    這個組合產出 2026 年罕見的東西:一個既工程設計良好又在規模上經濟的代理系統。Pydantic AI 處理工程。Ertas 訓練模型處理專業化。Ertas Deployment CLI 帶你到行動端。

    從原型到出貨

    這類代理的典型出貨管線看起來像:

    1. 對 API 進行原型(1–2 天)。對 OpenAI 或 Claude 建構 Pydantic AI 代理。把 schema 弄對、把工具流程弄對、證明價值。
    2. 整理資料集(1–2 天)。使用 Data Craft 與來自原型的數百段對話。依 schema 驗證範例。
    3. 在 Studio 微調(訓練時間不到一小時,加上評估)。迭代資料集直到評估指標清過 95%。
    4. 出貨至行動端(用 Deployment CLI 不到一小時)。對你的 iOS、Android、Flutter 或 React Native 專案執行 CLI。將 Pydantic AI 代理中的 API 呼叫換成本地端點。
    5. 對生產追蹤迭代。Pydantic AI 的追蹤(尤其透過 Logfire)成為下一輪訓練資料。Studio 支援從生產追蹤進行漸進式微調,因此模型隨時間改善而從不將使用者資料傳離裝置。

    前三個步驟過去是難處。Pydantic AI 把原型至生產的差距從「數週的提示工程」縮短為「一個下午的資料集整理」。Studio 將資料集至微調的差距從「一個 MLE-月的工作」縮短為「幾小時」。Ertas Deployment CLI 關閉了最後也最頑固的差距:訓練模型是一回事,將其出貨至真實 iOS 或 Android app 是另一回事,而這個步驟歷史上是大多數 app 建構者從未完成的 20–40 小時 llama.cpp 建置設定。

    四件作品一起——Pydantic AI 處理工程、Studio 處理微調、Data Craft 處理資料集、Deployment CLI 處理出貨——將從原型到生產上行動端的時程從「一季的工作」壓縮到「一週的工作」。對於感受到 API 成本懸崖在 500 至 5,000 使用者間咬住的行動 app 建構者,這就是停留在懸崖上與離開懸崖的差別。

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading