端侧 Agent:手机本地多 Agent 协作

目标读者 :要做离线可用、隐私优先、自主可控 Agent 的移动/端侧工程师

预计阅读 :18~22 分钟

主线 :配合 <3B 端侧模型,在手机/PC 本地跑「规划 + 工具 + 记忆」多 Agent;以 onnxruntime-genai 为推理底座,给出可运行骨架,并回应 2026-09-03 前沿模型连环宕机后的可靠性刚需

关键词:端侧 Agent、Edge Multi-Agent、onnxruntime-genai、Phi-mini、离线推理、本地工具


开篇:云端挂了,你的 Agent 还在不在?

2026 年 9 月 3 日 早晨,ChatGPT、Claude、Grok 等在相近窗口相继出现故障(OpenAI 侧公开称路由错误;xAI 侧指向 Memphis 算力中心等)。争议焦点不是「谁背锅」,而是产品侧的冷事实:

只要决策链路绑死云端 API,一次厂商级中断就能让整条 Agent 产品停摆。

于是社区把目光重新压回端侧:配合 <3B 量级模型,在手机 / PC 本地跑「规划 + 工具 + 记忆」的小 Agent------离线可用、数据不出机、自主可控。这不是否定云端大模型,而是补上「可靠性底仓」。

日报卡片里那几行代码,点题很准:

python 复制代码
# pip install onnxruntime-genai
import onnxruntime_genai as og
model = og.Model("phi-mini-onnx")
tok = og.Tokenizer(model)
out = model.generate(tok.encode("本地总结这段文本并调用日历"))
print(tok.decode(out))   # 端侧推理,无云端

本文把它展开成工程可落地的 端侧多 Agent 编排:真实 GenAI 循环、本地工具协议、Planner / Worker / Memory 分工,以及手机上的资源预算。


一、端侧多 Agent 长什么样?

On-device · offline-first · <3B models Planner 拆解 / 路由 Worker Agents 摘要 / 日历 / 检索 Local Tools 日历·文件·通知 Memory SQLite 推理底座:onnxruntime-genai(Phi-mini / Qwen2.5-1.5B / Llama-3.2-1B ONNX INT4) 加速:CPU / DirectML / CUDA / Snapdragon NPU · 数据:不出机 · 网络:可选云端升级

和云端多 Agent(如 OpenAI Agents SDK handoffs)对比:

维度 云端多 Agent 端侧多 Agent
模型 任意大 通常 ≤3B,INT4/INT8
网络 强依赖 离线可跑
工具 HTTP / SaaS 本机日历、通讯录、文件、传感器
记忆 服务端 Session 本地 SQLite / 加密库
失败模式 厂商宕机 = 全挂 能力变弱,但产品仍在线

端侧「多 Agent」往往不是上十个 70B,而是:一个极薄 Planner + 两三个专精 Worker + 确定性工具层------小模型负责意图与槽位,副作用交给代码。


二、为什么卡在 <3B?手机的账要这么算

Rough RAM / UX budget on mid-high phones 0.5--1B 路由/分类 1.5--3B 主对话甜蜜点 3--8B 旗舰机/PC 边 >8B 手机难常驻

经验法则(INT4 ONNX,量级感):

  • 0.5--1B:意图分类、是否调用工具、简单模板填槽
  • 1.5--3B(Phi-mini / Qwen2.5-1.5B / Llama-3.2-1B~3B):端侧主对话 + 浅规划
  • 更大:交给 PC / 云端升级路径,别强行塞进中端机后台

端侧 Agent 的正确姿势是 「小模型编排 + 大能力工具」,而不是「在手机里复刻一个云端 GPT」。


三、推理底座:onnxruntime-genai 实操

3.1 安装与拉模型

bash 复制代码
pip install numpy
pip install --pre onnxruntime-genai          # CPU;GPU/DML 选对应 wheel

# 示例:Phi-3/4 mini 的 CPU+Mobile INT4 包(路径以 HF 卡为准)
huggingface-cli download microsoft/Phi-3-mini-4k-instruct-onnx \
  --include "cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/*" \
  --local-dir ./phi-mini-onnx

Windows GPU 可用 onnxruntime-genai-directml;骁龙机可参考 Snapdragon 教程

3.2 日报「一行 generate」vs 官方循环

卡片里的 model.generate(...) 适合表达「无云端」;生产请用官方 Generator 循环(含 KV cache、采样、流式):

python 复制代码
import onnxruntime_genai as og

MODEL_DIR = "phi-mini-onnx/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4"

model = og.Model(MODEL_DIR)
tokenizer = og.Tokenizer(model)
stream = tokenizer.create_stream()

search_options = {"max_length": 1024, "batch_size": 1}
chat_template = "<|user|>\n{input} <|end|>\n<|assistant|>"

def generate(user_text: str) -> str:
    prompt = chat_template.format(input=user_text)
    tokens = tokenizer.encode(prompt)
    params = og.GeneratorParams(model)
    params.set_search_options(**search_options)
    generator = og.Generator(model, params)
    generator.append_tokens(tokens)
    chunks: list[str] = []
    while not generator.is_done():
        generator.generate_next_token()
        tid = generator.get_next_tokens()[0]
        chunks.append(stream.decode(tid))
    del generator  # 释放捕获图,避免二次推理泄漏
    return "".join(chunks)

print(generate("本地总结这段文本并调用日历"))

这才是「端侧推理,无云端」的可维护写法。


四、从单次生成到多 Agent:规划 + 工具 + 记忆

Deterministic loop · model decides, code executes ① Prompt ② Plan JSON ③ Tools ④ Memory 未完成则回 ①;步数上限 / 拒答策略必须写死 小模型输出严格 JSON schema,工具白名单,禁止自由 shell

核心原则:模型只产结构化计划,副作用只走白名单工具。 小模型胡写命令的风险,用代码兜住。

4.1 可运行骨架(PC 原型,可迁 Android/iOS)

python 复制代码
"""edge_multi_agent.py --- 端侧 Planner + 本地工具 + 记忆(示意可运行)"""
from __future__ import annotations

import json
import re
import sqlite3
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Any, Callable

# --- 可选:有模型时接 onnxruntime_genai;无模型时用规则 stub ---
USE_OG = False
try:
    import onnxruntime_genai as og  # noqa: F401

    USE_OG = Path("phi-mini-onnx").exists()
except ImportError:
    pass


@dataclass
class EdgeMemory:
    db: Path = Path("edge_memory.db")

    def __post_init__(self) -> None:
        with sqlite3.connect(self.db) as conn:
            conn.execute(
                "CREATE TABLE IF NOT EXISTS notes(ts TEXT, role TEXT, content TEXT)"
            )

    def add(self, role: str, content: str) -> None:
        with sqlite3.connect(self.db) as conn:
            conn.execute(
                "INSERT INTO notes VALUES(?,?,?)",
                (datetime.utcnow().isoformat(), role, content),
            )

    def recent(self, n: int = 6) -> list[str]:
        with sqlite3.connect(self.db) as conn:
            rows = conn.execute(
                "SELECT role, content FROM notes ORDER BY ts DESC LIMIT ?", (n,)
            ).fetchall()
        return [f"{r}: {c}" for r, c in reversed(rows)]


# ---------- 本地工具(手机上换成 CalendarContract / EventKit) ----------
def tool_summarize(text: str) -> str:
    text = text.strip()
    return text if len(text) <= 80 else text[:77] + "..."


def tool_add_calendar(title: str, when: str) -> str:
    # 演示:写本地文件;真机写系统日历并申请权限
    Path("local_calendar.log").write_text(
        f"{when}\t{title}\n", encoding="utf-8"
    )
    return f"CAL_OK title={title} when={when}"


TOOLS: dict[str, Callable[..., str]] = {
    "summarize": lambda **kw: tool_summarize(kw["text"]),
    "add_calendar": lambda **kw: tool_add_calendar(kw["title"], kw["when"]),
}


PLANNER_SYS = """你是端侧 Planner。只输出一行 JSON,不要解释:
{"agent":"summarizer|calendar|chat","tool":"summarize|add_calendar|none","args":{...},"reply":"..."}
规则:需要写日历用 calendar+add_calendar;需要压缩文本用 summarizer+summarize;否则 chat+none。
"""


def llm_plan(user: str, memory_snip: str) -> dict[str, Any]:
    """有 OG 则调本地模型;否则用极简规则 stub,保证离线可演示。"""
    if not USE_OG:
        if "日历" in user or "提醒" in user:
            return {
                "agent": "calendar",
                "tool": "add_calendar",
                "args": {"title": "本地提醒", "when": "tonight-20:00"},
                "reply": "已安排本地日历事项。",
            }
        if "总结" in user:
            body = re.sub(r".*总结", "", user).strip() or user
            return {
                "agent": "summarizer",
                "tool": "summarize",
                "args": {"text": body},
                "reply": "摘要如下。",
            }
        return {"agent": "chat", "tool": "none", "args": {}, "reply": "(离线 stub)收到。"}

    # 真实路径:把 PLANNER_SYS + memory + user 喂给 generate()
    from edge_infer import generate  # 你可把上一节 generate 抽成模块

    raw = generate(f"{PLANNER_SYS}\n记忆:{memory_snip}\n用户:{user}\nJSON:")
    m = re.search(r"\{.*\}", raw, re.S)
    return json.loads(m.group(0) if m else '{"agent":"chat","tool":"none","args":{},"reply":"解析失败"}')


def run_turn(user: str, mem: EdgeMemory) -> str:
    mem.add("user", user)
    plan = llm_plan(user, " | ".join(mem.recent()))
    tool_name = plan.get("tool", "none")
    tool_out = ""
    if tool_name in TOOLS:
        tool_out = TOOLS[tool_name](**plan.get("args", {}))
        mem.add("tool", f"{tool_name}:{tool_out}")
    final = plan.get("reply", "")
    if tool_out:
        final = f"{final}\n[{plan.get('agent')}] {tool_out}"
    mem.add("assistant", final)
    return final


if __name__ == "__main__":
    memory = EdgeMemory()
    print(run_turn("请总结:本周完成端侧 Agent POC,并调用日历提醒今晚复盘", memory))

一次运行的期望输出类似:

text 复制代码
摘要如下。
[summarizer] 本周完成端侧 Agent POC,并调用日历提醒今晚复盘
[calendar] CAL_OK title=本地提醒 when=tonight-20:00

Planner 决定「谁上场」,Worker 通过工具名区分;记忆落 SQLite------这就是端侧多 Agent 的最小闭环。


五、手机落地:三条常见技术栈

A. ORT GenAI Phi ONNX · 跨平台 Python/C++/C# 适合 POC→嵌入 B. Android ADK Gemini Nano / 混合 Kotlin 多 Agent 敏感子任务留端 C. 本地 Runtime llama.cpp / EdgeChain GGUF + 工具总线 强离线定制

路线 代表 何时选
A onnxruntime-genai + Phi ONNX 要官方 GenAI 循环、Windows/移动 CPU 友好
B ADK for Android + Gemini Nano 原生 Kotlin、混合云端编排、系统级 on-device
C llama.cpp / EdgeChain / MobAgent 类 任意 GGUF、自研工具沙箱、强离线

产品常见形态是 混合:日常敏感(摘要短信、写日历)走端侧;复杂推理征得用户同意后再上云------正好对冲 9/3 这类「全家桶云端同时抖」的风险。


六、可靠性设计:为宕机日准备的清单

能力 做法
离线路径 首启预下载 INT4 权重;无网仍可 Planner+Tools
降级 无 NPU → CPU;无模型文件 → 规则 stub(仍可写日历)
步数熔断 max_steps=3,防小模型死循环烧电
工具白名单 只开放日历/通知/指定目录;禁止任意 shell
记忆加密 SQLCipher / Keystore;敏感字段不上云日志
观测 本地 trace 文件;可选同步,默认关

9/3 事件的产品翻译就一句话:

云端是加速器,端侧是底仓。 底仓不需要赢过 GPT,只需要「断网那天,核心动作还能做完」。


七、和浏览器本地推理怎么分工?

上一篇 WebLLM(浏览器 WebGPU)解决的是 标签页内隐私推理 ;端侧 Agent 解决的是 OS 级工具权限 + 后台 + 离线常驻

WebLLM 端侧 ORT-GenAI / ADK
载体 浏览器 App / 系统服务
工具 受限 Web API 日历、通知、传感器
模型 可到 4B/8B(高配) 手机常驻更偏 ≤3B
典型 插件摘要 随身助理 / 车机 / 工牌

可以组合:PC 浏览器做重文档,手机端侧做轻行动。


八、踩坑

  1. model.generate 当生产 API → 用 Generator + append_tokens 循环,并 del generator
  2. 让小模型直接「执行自然语言命令」 → 只解析 JSON,工具层写死。
  3. 一个 3B 既当大脑又当百科 → 拆 Planner / Worker,百科交给本地 RAG 或云端。
  4. 忽略权限与电量 → 日历权限弹窗、推理放后台线程、限制 max_length
  5. 以为离线=零下载 → 首次仍要拉 GB 级权重;做差分更新与完整性校验。

九、收束

端侧多 Agent = <3B 本地推理 + 结构化规划 + 白名单工具 + 本地记忆。

onnxruntime-genai 把 Phi-mini 一类模型送进手机/PC;你要补的是编排与可靠性,而不是更大参数。9/3 的连环故障提醒我们:自主可控不是口号,是「云端抖动时产品是否还活着」。

下一步:

  1. 把本文骨架迁到 Android(ORT Mobile / ADK + 系统日历)
  2. 用 30 条真实口语评测「总结 / 建日程 / 闲聊」路由准确率
  3. 设计云端可选升级开关,默认关、用户显式开

参考链接

相关推荐
白猫不黑1 小时前
AI时代如何利用AI学好网络安全
人工智能·安全·web安全·计算机·网络安全·信息安全
码云之上1 小时前
让聊天机器人学会工作方法,星悟接 Agent Skills 的实践
人工智能·架构·全栈
容器魔方1 小时前
议程一览 | 华为云亮相 KubeCon + CloudNativeCon China 2026
人工智能·云原生·容器·开源·华为云·云计算
Csvn1 小时前
第 20 章 质量保障 Harness 与评测体系
人工智能·aigc·agent
4SAPI1 小时前
2026年大模型API接入选型指南:企业与个人用户的架构、稳定性与成本考量
大数据·开发语言·数据库·人工智能·架构·php
paopaokaka_luck1 小时前
非遗文物数字化系统(AI非遗问答、ONNX图像识别、协同过滤推荐、ECharts数据分析、非遗知识浏览与互动、文创商城订单闭环、文化活动报名签到、社区交流)
前端·javascript·vue.js·人工智能·数据分析·echarts
我会飞biubiubiu2 小时前
同一个 AI,为啥有人用出花,有人用出屎?——聊聊上下文工程
人工智能
Csvn2 小时前
评测体系怎么交付?四件套 + 迁移指南——模块一收官(E05)
人工智能
秦先生在广东2 小时前
Anthropic Agent Skills 开源发布:Claude 技能系统的定义与扩展指南
人工智能