Back to blog
    Pydantic AI 设备端:微调 Qwen3-4B 打造类型安全的移动智能体
    pydantic-aifine-tuningtool-callingqwen3on-devicemobileai-agents

    Pydantic AI 设备端:微调 Qwen3-4B 打造类型安全的移动智能体

    Pydantic AI 为 LLM 智能体带来类型安全与 FastAPI 工程美感。把它与一个通过 llama.cpp 在设备端运行的微调 4B 模型组合起来,你将在移动应用中获得生产级智能体——零 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 用户之间打破移动应用单位经济模型的按 token 计费 API 成本。

    本指南走完整条流水线:在 Ertas Studio 中为示例移动应用智能体微调 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,宿主应用可以捕获并重试。

    这正是面对前沿 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 用于工具调用微调的默认训练配置是 rank 32 的 QLoRA,训练 3 个 epoch。验证损失曲线通常在 epoch 2.5 左右趋平;Studio 的自动评估会在出现过拟合时标记。在标准 GPU 等级上,500 个样本的训练运行在一小时内完成。

    训练完成时,在留出验证集上运行 Studio 的评估套件。对于工具调用微调,关注三个指标:工具名称准确率(模型选对函数了吗?)、参数名称准确率(它填对参数了吗?)、参数值准确率(它使用了正确的值吗?)。生产就绪的模型在三项上得分都在 95% 以上。

    如果任何指标低于 95%,通常原因是数据集缺口——在评估报告中找到失败的样本,为缺失的情况添加代表性训练数据,然后运行增量微调。Studio 支持从检查点继续训练,无需从头开始。

    第 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 端点从移动应用暴露的设备端推理服务器。

    在开发中,通过 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 应用是另一回事,而这一步历来是 20–40 小时的 llama.cpp 构建配置,大多数应用开发者从未完成。

    四块拼图合在一起——Pydantic AI 负责工程化、Studio 负责微调、Data Craft 负责数据集、Deployment CLI 负责发货——把从原型到移动端生产的时间线从"一个季度的工作"压缩到"一周的工作"。对于在 500 到 5,000 用户之间感受到 API 成本悬崖咬噬的移动应用开发者,这就是停留在悬崖之上与下到悬崖之外的区别。

    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