去年我在做一个端侧 Agent 的 PoC 时,最崩溃的不是 Agent 架构设计,而是怎么把模型真正塞进那块巴掌大的板子里。跑起来只是及格线,还要让它在掉电、过热、内存不够的环境里稳定响应。这篇是“深入理解端侧 Agent”系列的第二篇,聊端侧 LLM 部署,覆盖模型选型、量化策略、推理引擎、硬件平台和实际踩坑经验。内容围绕部署这条主线展开,适合正在做端侧 AI 硬件落地、Agent 开发、或者在 Jetson、RK3588 这类平台上折腾本地大模型的工程师。
1. 端侧 Agent 的部署蓝图:先想清楚再动手
1.1 为什么端侧部署值得折腾
端侧 Agent 和云端 Agent 的核心差别,不在“智能”而在“边界”。云端方案计算力充足,模型可以无限大,但每次请求都依赖网络往返,延迟高、隐私风险大、离线场景直接不可用。端侧部署 LLM 最直接的价值就是三件事:数据不出设备、响应不受网络抖动拖累、在没有基站的地方也能跑。这在智能家居、工业巡检、车载语音、医疗终端这类场景里几乎是刚需。
但端侧的代价同样明显,模型参数量被硬件严格约束,7B 级别基本就是常规设备的甜点区,超过这个级别,内存和算力都会崩。另一个容易被忽视的点是开发成本:云端只要调用 API,端侧却要自己处理量化、推理引擎、算子适配、内存复用、温度策略,一个环节不对,效果就是断崖式下降。
我的建议是,动手部署之前先画两张图:一张是“数据流图”,明确传感器输入、意图识别、工具调用、知识检索各环节在哪一步需要 LLM;另一张是“资源预算表”,把内存带宽、算力、闪存空间、功耗线列清楚。刚才提到的那次 PoC,就是因为在资源预算表上少算了一栏“GPU 共享带宽”,导致摄像头推理和 LLM 推理抢带宽,整个 Agent 的响应延迟直接翻倍。这个教训后面在排查部分会展开。
1.2 四条路线怎么选
端侧 LLM 部署目前没有统一标准,主流路线可以归纳为四类:
| 路线 | 代表工具 | 适用人群 | 优点 | 痛点 |
|---|---|---|---|---|
| 开箱即用派 | Ollama | 想快速验证 Agent 流程的人 | 命令简单、模型管理方便、集成度高 | 定制化弱,难以细粒度控制算子 |
| 精度派 | llama.cpp | 需要嵌入自有 C/C++ 工程的团队 | 量化格式丰富、内存控制精细 | 二次开发成本高,生态偏底层 |
| 移动端派 | MLC-LLM | iOS/Android/浏览器端开发 | 编译优化好,硬件适配广 | 构建流程复杂,debug 难受 |
| 平台专用派 | TensorRT-LLM、RKNN | 固定硬件、追求极限性能 | 算子级优化,性能最强 | 绑定特定芯片,换板子基本重来 |
选择路线时我的判断标准只有一个:你的开发周期里,哪个环节最不可控。如果是快速原型验证,Ollama 会节省大量时间;如果是产品化部署且主控板已经锁定,尽早切到平台专用工具链。最怕的是先用高自由度方案跑通,又要在最后一刻切到专用方案,那相当于把推理引擎整个重写一遍。端侧 Agent 的部署复杂度和“路线切换时间点”强相关,越晚切换越痛苦。
2. 模型选型与量化级别:跑得动只是及格线
2.1 榜单、分数和实测滤镜
第一次接触端侧部署的开发者,通常第一件事就是打开公开榜单看排名,然后选一个得分最高的模型。这个思路不能说错,但很容易踩坑。公开榜单上的分数是在大规模 GPU 集群上、以特定数据集跑出来的,那些评估集和端侧真实场景相差甚远。例如一个模型在通用知识问答上表现优秀,但你要它做工业设备的故障日志格式化,效果可能一塌糊涂。
我在选模型时有三层筛选逻辑:
- 第一层,看基准测试的“同规模”对比,而不是跨规模比绝对分。7B 模型和 70B 模型比分数没有意义。
- 第二层,看任务相关性。直接构造 20 条你项目里真实会发生的 prompt(比如指令理解、工具调用、链路抽取、长文本摘要),分别在候选模型上跑,然后人工比对输出质量。
- 第三层,看运行时的稳定性。同一段 prompt 跑三次,输出差异大的模型,在家里尽力别用,端侧环境里这种不确定性会被放大成灾难。
现在公开榜单已经逐渐从“谁聪明”转向“谁能效比最高”,比如每瓦特完成的 token 数、每 GB 内存能承载的上下文长度。这反而是端侧更需要的指标。一个模型效率再高,如果硬件吃不住,也谈不上下一步的 Agent 编排。
2.2 量化不是无脑压精度
量化级别直接决定模型能不能在端侧跑起来。部署前先做一个基础换算:7B 参数模型以 FP16 精度存储,大约是 14GB,光是权重就已经超过大多数端侧设备的内存上限。INT8 降到 7GB,INT4 降到 3.5GB 左右,加上 KV cache、临时激活、输入输出缓冲区,内存预算才会显得可接受。
量化的选择普遍遵循两个原则:
- 第一原则:能跑到所需速度的前提下,精度越高越好。
- 第二原则:优先量化权重,损失模型容量而非能力。权重量化(如 AWQ、GPTQ)对能力的破坏通常小于激活量化(如 SmoothQuant 处理不当)。
我用 llama.cpp 的量化等级时,保守操作是在 Q4_K_M 和 Q5_K_M 之间做实测。Q8_0 跑大文件效果稳定,但体积上涨明显;Q2 系列文件大小诱人,但输出质量很多时候已经不能用。量化等级不是越新越好,而是越适配你的“token 吞吐目标”越好。端侧 Agent 每轮对话往往需要生成 300 到 800 个 token,如果每秒只能出 5 个 token,用户会觉得这机器“脑子生锈了”。
2.3 Token 的三点模型怎么用
很多人刚接触大模型时,都听过“Token 是模型处理文本的最小单位”这句话,但真正做 Agent 时,理解更重要的其实是 Token 的语义分工。我习惯把它概括成“三点模型”:Key 是“我是谁”,对应系统提示词里定义的 Agent 角色和能力边界;Query 是“我在找什么”,对应当前用户意图和目标拆解;Value 是“我能提供什么”,对应工具列表、知识库索引、可执行动作清单。每次一次 Agent 循环,模型接收一个 Key-Query-Value 三元组,输出的是下一步动作的决策。
布置端侧 LLM 时,这三点直接决定了模型的输入工程:系统提示词(Key)要写清 Agent 的边界,别让一个 7B 模型去做 70B 模型才做得好的开放式创作;用户输入(Query)要经过意图精简,减少无效 token 输入;工具描述(Value)要压缩到只有必要参数和调用格式,避免把工具文档全塞给模型。端侧上下文本就有限,省出的空间可以留给多轮对话的 KV cache,能明显减少历史遗忘问题。这也是为什么我后面提到的 RAG 本地强化如此重要。
3. 主流硬件平台与推理引擎实战
3.1 Jetson Orin 部署 DeepSeek 本地版
NVIDIA Jetson Orin 系列是端侧 AI 硬件里综合实力最稳的选手之一,从 Orin Nano 到 Orin AGX,覆盖从 7B 到 13B 模型的基本运行需求。我以 Jetson Orin 部署 DeepSeek 本地版为例,给出可复现的路径。
第一步,准备 JetPack 5.1+ 环境,确认 JetPack 6 与 Ollama、llama.cpp 的兼容性。JetPack 6 的底层库升级幅度较大,部分 ONNX Runtime 和 TensorRT 插件需要重新编译适配,没有充分测试前不要贸然迁移。
第二步,安装 Ollama,官方脚本一条命令即可。Ollama 对 Jetson 生态支持很成熟,能自动识别 CUDA 版本并将模型分配到 GPU。
第三步,选择模型文件并拉取:
ollama pull deepseek-r1:7b这是 CPU+GPU 混合推理的典型例子,Ollama 会把一部分算子和权重放到 GPU,超出显存的部分自动切到内存。Orin 8GB 内存跑 7B 比较吃紧,建议把上下文窗口调低到 2048。不必追求 8192,原因有两个:一是端侧模型本身对长上下文的有效利用能力有限,二是 KV cache 占用的显存会随窗口长度成倍增长,2048 在多数 Agent 任务里够用。
第四步,性能校准。我在 Orin Nano 上实测,7B Q4 版本稳定出词速度约在每秒 20 到 30 token,延迟在交互场景下稍显笨拙,但用于后台流水线任务完全没问题。如果对速度敏感,可以升级到 Orin NX 16GB,速度提升显著。
3.2 RK3588 上跑视觉 Agent 的组合思路
RK3588 是另一块出现频率极高的端侧主板,特点是 CPU 强、NPU 算力约 6 TOPS,且对 INT8 和 INT16 支持不错,非常适合跑“视觉 + 轻量 LLM”的组合型 Agent。比如在工业质检场景里,RK3588 上部署 YOLOv8 做目标检测,结合一个 1.5B 到 3B 的语言模型做缺陷描述和决策建议,整体功耗还能控制在 15W 以内。
RNKK 工具链是 RK3588 上跑视觉模型的主流方式,YOLOv8 在 RKNN 上的部署流程已经比较成熟,导出、量化、模拟器验证、板端推理一步接一步。要注意 RKNN 对某些算子的支持优先于另一些,ONNX 模型里如果含有自定义算子,需要先做算子替换或用 CPU fallback,否则在模拟器上可以跑,上板后却出现 NaN。
端侧视觉 Agent 的架构和纯文本 Agent 的区别在于模态融合。视觉模型输出的不是文本 token,而是目标框、分类概率、特征向量;LLM 要理解这些结果,需要把检测结果转为结构化文本,再作为 Value 注入 Agent 的上下文。比如“detected_defect: scratch, confidence: 0.87, location: upper_left”这样清晰的键值文本,比直接把特征数组丢给 LLM 输出更容易被理解。这里的诀窍是:视觉模型只负责“看到什么”,LLM 负责“该怎么判断和表达”,两边解耦,出错时也好排查。
3.3 Ollama 配置中的几个关键参数
很多人用过 Ollama,但几乎不碰它的环境变量,默认参数只在普通桌面环境合理,放到端侧 Agent 场景就会出问题。下面几个是我觉得部署前必须过一遍的配置:
| 参数 | 作用 | 推荐设置 |
|---|---|---|
| OLLAMA_HOST | 服务监听地址 | 局域网设备设为 0.0.0.0,方便 Agent 调用 |
| OLLAMA_NUM_PARALLEL | 并发请求数 | 端侧建议 1 到 2,别贪多 |
| OLLAMA_KEEP_ALIVE | 模型驻留时间 | 高频任务设 5m 以上,省去每次加载 |
| OLLAMA_MAX_LOADED_MODELS | 同时驻留模型数量 | 1,防止多个模型把内存打爆 |
其中 OLLAMA_NUM_PARALLEL 是最容易让人误解的。理想情况当然是并发越高、吞吐越大,但端侧的内存和算力摆在那里,多路并发的结果是相互拖慢,单个请求的响应延迟变得不可控。对于 Agent 场景,我更倾向保持单并发,把并发控制放在 Agent 调度层实现。Agent 内部本来就有多步工具调用,每一步之间天然串行,强行并发反而会让记忆同步复杂化。
除此之外还有 Flash Attention、mmap 等开关,不同版本默认值不同,实测为准。环境变量改完记得systemctl restart ollama,配置才算真正生效。
4. 给 Agent 装上本地大脑:RAG、本体与记忆
4.1 本体与 llm wiki 的关系
端侧部署 LLM 不是终点,Agent 真正要解决的是“在给定知识范围内做到准确决策”。模型权重里固化的通用知识不足以支撑垂直场景,因此知识增强成了标准动作。RAG 是最常见的方案,而 llm wiki 这类词汇里提到的本体(Ontology)则解决了一个更深层的问题——检索到的东西如何组织成 LLM 能理解的逻辑结构。
本体定义的是领域内的概念层级和关系约束,比如“缺陷”包含“划痕”“凹陷”“色差”,而“划痕”有属性“长度”“位置”“深度”。如果没有本体,RAG 检索出来的结果是碎片化文本,模型需要自行推断这些片段之间的关系;有了本体,检索结果可以按概念关系组织成结构化的三元组,模型在理解时不需要做无根据的补全,幻觉率会显著下降。
这本质上还是在说 LLM 的 Token 三点模型。本体就是 Value 部分的结构化骨架,让你知道“我能提供什么”之前,先想清楚“我能关联什么”。在端侧部署中尤其明显,上下文窗口小,模型每秒可编码的 token 量有限,结构化的知识注入能帮它在更少的信息里做出同样准确的判断。
4.2 GraphRAG 与本体 RAG 的实际切入点
经常被提到的 GraphRAG 并不是完全独立的思路,它是把实体之间的关系显式建图,在检索阶段沿图结构做多跳展开。这适合关系复杂、跨越多个实体的查询,例如“这条生产线最近是否因为设备老化导致良率下降”。先定位“生产线 A”,再关联“设备 B”,然后沿“老化”属性找到“良率下降”的证据链。
端侧做 GraphRAG 需要克制,不要在设备上维护庞大图库,更合理的做法是:
- 离线在服务器或开发机上构建知识图谱,导出与当前设备强相关的子图。
- 端侧只加载子图,并压缩为紧凑的结构化文本。
- LLM 推理时,沿子图做局部检索,不试图全库遍历。
我给一个粗略的评估:一个 20MB 子图能被压缩为 2 万 token 以内的结构化文段,按 Q4 量化后的 7B 模型上下文窗口,这个量级是完全可以承担的。GraphRAG 的材质不在于图多大多全,而在于子图裁剪得准不准、周边信息是否收敛,这对端侧效果影响非常大。
4.3 Agent 编排、沙盒与安全护栏
聊到 Agent 框架,吴恩达的 Agent 教程是一个很好的入门参考,它把规划、记忆、工具使用拆得很清楚。端侧 Agent 的编排更需要轻量,常见的思路是 LangGraph 这类状态机方案,把每一步调用显式定义为状态节点,这样方便跟踪工具调用链、也方便失败后重试。轻量不只是为了代码简洁,更是为了减少端侧 CPU 的额外负担。编排层每多一层抽象,每一次 Agent 循环的固定开销都会增加几十毫秒,在端侧这类延迟敏感场景里是实质成本。
另一件常被忽略的事是 Agent 的“工作环境”和工具权限控制。近期出现的一些无头 Agent 部署方式(比如类似 Clawdbot 的无人值守模式)很有参考价值,但注意一定要把 Agent 放进沙盒。Agent 在端侧往往能直接访问系统命令、文件、硬件接口,一旦提示词注入或工具调用出错,影响范围会从“输出一段坏文本”扩散成“设备执行了危险动作”。
Agent 安全至少有四道闸门:
- 工具调用白名单:只暴露目标场景必需的几个函数。
- 动作审批点:高风险操作必须二次确认(人工智能或人工)。
- 日志审计:每次工具调用的入参和返回值都留痕。
- 记忆保护:对长期记忆模块做写保护,类似 a-memguard 这样的防御框架专门防操纵 Agent 记忆的投毒攻击,这个方向值得跟进。
在端侧条件有限的情况下,优先做好前两道闸门。开发期图省事,后面生产环境迟早要加倍还。
5. 端侧落地的坑与调优实录
5.1 内存不足与速度瓶颈排查
端侧部署最常出现的问题是“模型能加载但会话一深就崩”,通常都是内存被吃光的信号。排查顺序是:先看模型文件大小与量化等级,再看 KV cache 设置,最后检查是否有多个模型驻留。有一个真实的案例,设备上同时驻留了两个模型文件,一个做对话,一个做视觉描述,平时相安无事,一旦两个 Agent 任务并行,内存立刻见底,系统触发 OOM,模型进程直接被杀。
解决方式是给内存划定硬边界。Ollama 里限制模型数量、降低上下文窗口,并调节 OLLAMA_KEEP_ALIVE 减少驻留时间。另一个通行的做法是把不常用工具切到独立进程,用的时候才拉起,用完后立即释放。端侧的内存管理讲究“及时回收”,不要让后台进程懒洋洋地占着位。
速度瓶颈通常不是算力而是内存带宽。模型每生成一个 token,都要把全部权重从内存搬到计算单元,推理速度的上限基本被内存总线速度焊死。所以数据上看,同级别模型在 8GB 内存的 Orin Nano 上跑,和 16GB 内存的 Orin NX 上跑,速度差距未必和算力差距成正比,真正拉开的还是带宽和显存占用导致的缓存策略。别只看 TOPS,内存带宽同样是硬指标。
5.2 并发、长上下文与 token 管理
写 Agent 时总会遇到“需求一会 2 个请求,过一会变 10 个请求”的场景。端侧 LLM 扛并发的思路不是把它们对着模型,而是要在上游做队列和合并。我常用一个简单的令牌桶机制:模型每秒最多出 N 个 token,Agent 调度层根据此设置请求速率上限,超出后等待或合并相似请求。对于相似度高的查询(同一设备的同一类请求),可以做结果缓存;知识问答类的请求,检测到命中缓存直接秒回,完全不用挨模型一下。
长上下文是端侧的另一个坑。很多主流模型声称支持 128K 上下文,但在端侧设备上,光 KV cache 就可能占用数 GB。如果业务场景确实需要长上下文,用外置记忆模块来补,而不是把全部历史都塞进上下文窗口:
- 短期记忆:最近一轮多轮对话,保留 2 到 3 轮即可。
- 工作记忆:当前任务的结果队列,动态更新。
- 长期记忆:定期从对话历史中用 LLM 抽取关键事实,压缩后存入外部文件或知识库。
这种分层记忆把 Token 的消耗降一个量级,也规避了端侧上下文窗口的硬性制约。
5.3 稳定性与电源发热
端侧部署在真实场景里的敌人不是性能,是高温和电压跌落。我见过一块板子在无风扇机箱里连续运行 4 小时后,NPU 频率主动下降到初始值的 60%,出词速度肉眼可见地变慢。对策是提前做好降频策略,将 CPU/GPU/NPU 的最大工作频率限制到名义值的 85% 左右,并结合温度传感器做动态调节。温度超过 70 摄氏度就把 Agent 任务排队,而不是一股脑塞给模型。
电源方面,量产设备用适配器供电尚可,但如果是电池供电,要把 LLM 推理的高瞬态功耗考虑进电池选型。7B 模型在 Jetson 上推理时的瞬时功耗可以达到整机功耗的两倍,电池要预留足够的峰值电流能力,否则会出现推理一半系统复位的故障。这类问题在开发板上基本测不出来,但量产阶段必现,提前做功耗预算测试很重要。
5.4 经验总结与后续扩展
端侧 LLM 部署是一项系统工程,微观上是量化、推理引擎、算子适配,宏观上是模型选型、Agent 框架、知识增强、安全护栏。作为已经在生产环境跑过一版端侧 Agent 的人,我的切身体会是:第一版不要追求完美,先把一个最小闭环跑通,包括设备端模型推理、Agent 决策、工具调用、异常处理,然后再逐步优化。第二版再引入 RAG 和本体,第三版再做并发和记忆分层。
这篇文章只是系列的第二篇,重点放在了部署和模型落地上,后面还可以继续展开 Agent 编排细节、知识库构建、工具调用协议、部署监控体系等主题。端侧 Agent 是有趣且注定会持续被需要的方向,希望这些实战记录,能帮你少走几步弯路。