1. 端侧 Agent 工程化的核心命题1.1 从 Demo 到产品端侧 Agent 的工程化鸿沟很多人在端侧跑通第一个 Agent Demo 的时候都会有一种错觉这东西已经成了。本地模型加载起来Function Calling 调通一两个工具命令行里问一句“帮我查一下明天天气”模型返回一个结构化的 JSON工具执行完把结果塞回去模型再吐出一段自然语言——整个链路跑通了感觉离产品就差一个 UI。但真正把端侧 Agent 往产品方向推的时候问题会成倍地冒出来。模型在 PC 上跑得好好的到了手机端内存直接爆掉Function Calling 在单轮对话里没问题一旦进入多轮、多工具、带状态的场景模型开始胡编参数JSON Schema 写得稍微复杂一点小模型的输出就开始不稳定该填字符串的地方给你填了个对象该用枚举的地方给你编了一个不存在的值。这些问题在 Demo 阶段都可以靠“换个 prompt”糊过去但在工程化阶段每一个都是必须系统性解决的硬骨头。端侧 Agent 工程化要解决的核心矛盾其实就一句话在算力、内存、功耗都受限的端侧环境里让一个能力有限的小模型稳定地完成复杂的工具调用任务。这个矛盾决定了端侧 Agent 的工程化思路和云端 Agent 有本质区别。云端 Agent 可以堆模型参数、堆上下文长度、堆并发端侧不行端侧每一兆内存、每一次推理延迟都要精打细算。我自己的体会是端侧 Agent 的工程化难点集中在三个层面协议层Function Calling 的格式定义与约束、调度层多工具、多轮次的状态管理与编排、运行时层模型加载、内存管理、推理加速。这三个层面里协议层是地基调度层是骨架运行时层是血肉。这一篇主要聊协议层和调度层也就是 Function Calling 和 MCP 相关的工程化实践运行时层的内容留到下一篇展开。1.2 为什么 Function Calling 是端侧 Agent 的命门Function Calling 这个概念本身不复杂就是让模型输出一段结构化的内容告诉外部系统“我要调用哪个函数、传什么参数”。但在端侧环境里这件事的难度会被放大好几倍。原因在于端侧跑的多半是 1B 到 7B 级别的小模型这些模型的指令遵循能力和格式化输出能力远不如云端的大模型。你让 GPT-4 输出一个符合 JSON Schema 的对象它基本不会出错但你让一个 3B 的量化模型做同样的事它可能会在 JSON 外面包一层解释文字可能会把字段名拼错可能会在数值字段里填一个字符串甚至可能直接编造一个 Schema 里不存在的字段。所以端侧 Agent 的 Function Calling 工程化核心不是“怎么让模型调用工具”而是“怎么让模型在能力受限的情况下尽可能稳定地输出符合预期的结构化内容”。这里面涉及到 Schema 设计、Prompt 约束、输出解析、错误恢复等一系列工程手段每一个环节都有很多细节可以抠。我见过不少团队在这个环节踩坑最常见的就是直接把云端 Agent 的那套 Schema 搬到端侧结果小模型根本扛不住那么复杂的结构输出成功率惨不忍睹。正确的做法是反过来先摸清楚端侧模型的能力边界然后在这个边界内设计尽可能简单的 Schema再用工程手段去兜底。1.3 MCP 在端侧 Agent 里的定位MCPModel Context Protocol这两年被讨论得很多它的核心价值是给模型和外部工具之间定义了一套标准化的通信协议。在云端 Agent 场景里MCP 解决的是“工具生态碎片化”的问题——不同的工具提供方各自定义接口Agent 开发者要一个个适配成本很高。有了 MCP工具提供方按协议暴露能力Agent 侧按协议调用双方解耦。但在端侧 Agent 场景里MCP 的定位需要重新思考。端侧 Agent 的工具集通常是固定的、有限的不像云端 Agent 那样需要动态发现和接入大量第三方工具。所以端侧引入 MCP更多是为了统一内部的工具调用抽象让 Agent 的核心逻辑和具体工具实现解耦方便后续替换和扩展。举个例子你在端侧做了一个支持“查天气、设闹钟、发消息”三个工具的 Agent如果不用 MCP你可能在代码里硬编码三个函数的调用逻辑如果用 MCP你可以把这三个工具都封装成 MCP ServerAgent 侧只负责按协议发请求具体工具怎么实现、用什么语言实现、跑在哪个进程里都不影响 Agent 的核心逻辑。这样一来后续要加新工具、要换工具实现改动量会小很多。不过端侧引入 MCP 也有代价主要是协议本身的开销。MCP 的通信基于 JSON-RPC每次调用都有序列化和反序列化的成本在端侧这种资源紧张的环境里这个开销不能忽略。所以我的建议是端侧 Agent 是否引入 MCP要看工具集的规模和变化频率。如果工具就三五个且基本不变直接硬编码可能更划算如果工具有十几个且经常增删那 MCP 带来的解耦收益就值得那点协议开销。2. Function Calling 的 Schema 设计与约束策略2.1 JSON Schema 在端侧的精简原则JSON Schema 是 Function Calling 的基础它定义了模型可以调用的函数长什么样、参数是什么类型、哪些是必填的。在云端场景里Schema 可以写得很详细字段描述可以很长枚举值可以很多因为大模型有足够的上下文窗口和理解能力去消化这些信息。但端侧不行。端侧模型的上下文窗口通常只有 2K 到 8KSchema 本身就要占掉一部分端侧模型的理解能力有限Schema 里的描述文字太长反而会干扰它的判断。所以端侧 Function Calling 的 Schema 设计核心原则就是精简。具体怎么精简我总结了几个实操要点。第一字段描述能短则短不要写“请填写用户想要查询的城市名称支持中文和英文”直接写“城市名”就够了。第二枚举值不要太多超过五个枚举值的字段考虑改成字符串让模型自由填写然后在外部做校验和映射。第三嵌套结构能扁平就扁平端侧模型处理嵌套对象的准确率明显低于扁平结构。第四必填字段尽量少非必要字段都设成可选减少模型漏填导致的调用失败。下面是一个对比示例左边是云端风格的 Schema右边是端侧精简后的 Schema// 云端风格字段描述详细枚举值多 { name: search_flight, description: 搜索符合条件的航班信息返回航班列表, parameters: { type: object, properties: { departure_city: { type: string, description: 出发城市名称支持中文或英文例如北京、上海、Beijing }, arrival_city: { type: string, description: 到达城市名称支持中文或英文 }, date: { type: string, description: 出发日期格式为YYYY-MM-DD }, cabin_class: { type: string, enum: [economy, premium_economy, business, first], description: 舱位等级 } }, required: [departure_city, arrival_city, date] } }// 端侧精简描述短枚举少结构扁平 { name: search_flight, description: 搜索航班, parameters: { type: object, properties: { from: {type: string, description: 出发城市}, to: {type: string, description: 到达城市}, date: {type: string, description: 日期YYYY-MM-DD}, cabin: {type: string, description: 舱位:经济/商务/头等} }, required: [from, to, date] } }精简后的 Schema 在端侧模型上的调用成功率实测下来比云端风格的高出不少。原因很简单模型要处理的信息少了出错的概率自然就低了。2.2 参数类型的选择与陷阱端侧 Function Calling 里参数类型的选择有很多讲究选错了类型会直接导致模型输出不稳定。字符串类型是最安全的端侧模型对字符串的处理能力最强几乎不会出错。所以能用字符串的地方尽量用字符串哪怕这个参数本质上是数字或布尔值。比如“是否开启某功能”这个参数用布尔类型的话模型可能会输出true字符串而不是true布尔值导致解析失败但如果用字符串类型约定yes和no模型输出的稳定性会高很多。数字类型要小心端侧模型经常会把数字输出成字符串或者在数字里混入单位。比如让它填“温度”参数它可能输出25度而不是25。解决办法是在 Schema 里明确说明“只填数字不要带单位”同时在外部解析时做容错处理用正则把数字提取出来。枚举类型在端侧要慎用尤其是枚举值较多的时候。模型可能会输出一个不在枚举列表里的值或者输出枚举值的变体比如大小写不一致、多了空格。如果一定要用枚举建议枚举值用简单的英文单词不要用中文或复杂字符串同时在外部做映射和兜底。数组类型在端侧是最容易出问题的模型经常会把数组输出成字符串或者数组元素类型不一致。如果确实需要数组参数建议限制数组长度并且在 Schema 里明确说明元素类型。比如“标签列表”这个参数可以约定最多三个标签每个标签是字符串。2.3 多工具场景下的 Schema 组织端侧 Agent 通常需要支持多个工具怎么把这些工具的 Schema 组织起来喂给模型也是一个工程化问题。最直接的做法是把所有工具的 Schema 拼成一个大 JSON 数组一次性塞进 system prompt 里。这种做法在工具数量少的时候没问题但工具一多prompt 长度会迅速膨胀端侧模型的上下文窗口根本扛不住。我的做法是分层组织。第一层是工具分类把功能相近的工具归为一组比如“出行类”“通讯类”“设备控制类”。第二层是组内工具每个组内的工具 Schema 放在一起。在对话时先让模型判断用户意图属于哪个分类然后只把该分类下的工具 Schema 加载进上下文。这样每次推理时上下文里只有少量工具的 Schema长度可控。这个思路类似于“路由”用一个轻量的分类步骤换取上下文空间的节省。分类步骤本身也可以用一个很小的模型或者规则引擎来做不一定非要走大模型推理。还有一种做法是动态加载根据对话历史判断当前可能需要哪些工具只加载这些工具的 Schema。这种做法更灵活但实现复杂度也更高需要维护一个工具和意图的映射关系。在端侧资源紧张的环境里我倾向于用分层组织这种简单可靠的方案。2.4 Prompt 约束与输出格式控制Schema 定义好了接下来要解决的是怎么让模型按 Schema 输出。端侧模型的指令遵循能力有限光靠 Schema 本身不够还需要在 prompt 里加约束。约束的核心是明确输出格式。我通常会在 system prompt 里写清楚如果需要调用工具只输出一个 JSON 对象不要输出任何其他文字JSON 对象必须包含name和arguments两个字段arguments必须符合对应工具的 Schema。这些约束要写得直白、具体不要用抽象的描述。除了文字约束还可以用示例约束。在 prompt 里给一两个输入输出的示例让模型模仿。端侧模型对示例的模仿能力比对文字描述的理解能力更强给示例往往比写一堆规则更有效。还有一个技巧是输出前缀。在 prompt 的末尾加上{name:这样的前缀引导模型从这里开始续写。这种做法能显著提高 JSON 输出的成功率因为模型不需要自己决定从哪里开始输出 JSON只需要接着前缀往下写就行。当然这个前缀要在解析时补回去。实测下来这几种约束手段组合使用端侧模型的 Function Calling 成功率能从百分之六七十提升到百分之九十以上。剩下的百分之十靠外部解析和重试来兜底。3. 工具调用链路的工程化实现3.1 从模型输出到工具执行的完整链路一个完整的端侧 Function Calling 链路从模型输出到工具执行再到结果回传中间有很多环节每个环节都可能出问题。链路的第一步是模型推理模型根据当前对话上下文和工具 Schema输出一段文本。这段文本理论上应该是一个 JSON 对象但实际上可能是 JSON 外面包了文字、可能是多个 JSON、可能是格式错误的 JSON。第二步是输出解析从模型输出里提取出 JSON 对象。这一步要做容错比如去掉 JSON 前后的多余文字、修复常见的格式错误比如单引号、尾逗号、处理模型输出的多个 JSON取第一个或最后一个。第三步是参数校验检查解析出来的 JSON 是否符合 Schema。这一步要检查必填字段是否都有、字段类型是否正确、枚举值是否在范围内。校验不通过的话要么重试要么走兜底逻辑。第四步是工具执行根据name找到对应的工具实现把arguments传进去执行。这一步要处理工具执行失败的情况比如网络超时、参数不合法。第五步是结果回传把工具执行的结果塞回对话上下文让模型基于结果生成最终回复。这一步要注意结果的格式最好是结构化的方便模型理解。这五步里第一步和第二步是最容易出问题的也是工程化投入最多的地方。第三步到第五步相对标准化但也不能掉以轻心。3.2 输出解析的容错策略输出解析是端侧 Function Calling 工程化里最脏最累的活因为你要面对模型各种千奇百怪的输出格式。我总结了几种常见的异常输出和对应的处理策略。第一种是JSON 外面包了文字比如模型输出“好的我来帮你查一下天气 {name: get_weather, arguments: {city: 北京}}”。处理策略是用正则找到第一个{和最后一个}把中间的部分提取出来。第二种是JSON 格式错误比如用了单引号、多了尾逗号、少了引号。处理策略是先尝试标准 JSON 解析失败的话用宽松的解析器比如 Python 的json5或者自己写一个简单的修复逻辑。第三种是输出多个 JSON比如模型先输出一个工具调用然后又输出了一段解释解释里又包含了一个 JSON。处理策略是只取第一个完整的 JSON 对象忽略后面的内容。第四种是字段名或类型错误比如把arguments写成了args把字符串写成了数字。处理策略是在解析后做字段映射和类型转换尽量把模型的输出往正确的格式上靠。第五种是完全无法解析模型输出了一段自然语言根本没有 JSON。处理策略是走重试逻辑把模型的输出和错误信息一起塞回上下文让它重新输出。这些容错策略要组合使用形成一个解析管线。我的经验是解析管线要尽量宽松能救则救实在救不回来再重试。因为端侧模型推理一次的成本不低能少重试一次就少一次。3.3 多轮工具调用的状态管理单轮工具调用相对简单模型输出一个工具调用执行完把结果塞回去模型生成最终回复结束。但实际场景里很多任务需要多轮工具调用比如“帮我查一下明天北京的天气如果下雨就提醒我带伞”这需要先查天气再根据天气结果决定是否设置提醒。多轮工具调用的状态管理核心是维护一个清晰的对话状态。每一轮工具调用的输入、输出、模型的中间推理都要记录下来作为下一轮推理的上下文。同时要有一个终止条件判断什么时候任务完成可以生成最终回复了。终止条件通常有两种一种是模型明确表示不再需要调用工具直接输出自然语言回复另一种是达到了预设的最大轮次强制终止。端侧场景里最大轮次要设得小一些比如三轮到五轮因为端侧模型推理慢轮次太多用户体验会很差。状态管理还有一个容易忽略的点是工具调用的去重。模型有时候会重复调用同一个工具传相同的参数这时候要判断是不是真的需要重复调用还是模型陷入了循环。如果是后者要主动打断避免无限循环消耗资源。3.4 工具执行失败的降级处理工具执行失败在端侧是常态网络不稳定、权限不足、参数不合法都可能导致工具执行失败。工程化要做的是在工具失败的时候Agent 能优雅降级而不是直接崩溃。降级策略分几个层次。第一层是重试对于网络超时这类临时性失败可以自动重试一到两次。第二层是参数修正如果失败原因是参数不合法可以尝试修正参数后重新执行比如把城市名从“北京市”改成“北京”。第三层是工具替换如果某个工具不可用可以尝试用功能相近的替代工具。第四层是告知用户如果以上都不行就如实告诉用户工具执行失败让用户决定下一步。这四层降级策略要按顺序尝试能自动解决的就自动解决解决不了的再交给用户。端侧 Agent 的用户体验很大程度上取决于这些降级逻辑做得好不好。4. MCP 在端侧 Agent 中的落地实践4.1 MCP 协议的核心机制与端侧适配MCP 的核心是 JSON-RPC 通信客户端和服务端通过请求-响应模式交互。在端侧 Agent 场景里Agent 本身是客户端工具实现是服务端。客户端发送工具调用请求服务端执行工具并返回结果。MCP 协议定义了三种核心能力Tools可调用的函数、Resources可读取的数据、Prompts预定义的提示模板。端侧 Agent 最常用的是 ToolsResources 和 Prompts 在端侧场景里用得相对少一些。端侧适配 MCP 的关键在于通信方式的选择。MCP 支持多种传输方式包括标准输入输出、HTTP、WebSocket 等。端侧环境里如果工具和 Agent 跑在同一个进程里可以直接用函数调用不需要走 MCP 协议如果工具跑在独立进程里可以用标准输入输出或本地 socket如果工具跑在远端才需要走 HTTP 或 WebSocket。我的建议是端侧 Agent 的工具尽量和 Agent 跑在同一个进程里用函数调用直接交互避免 MCP 协议的开销。只有在工具确实需要独立部署的时候才引入 MCP。这样既能享受 MCP 带来的解耦好处又能避免不必要的性能损耗。4.2 端侧 MCP Server 的实现要点如果确实需要在端侧实现 MCP Server有几个要点需要注意。第一是轻量化。端侧的 MCP Server 不要用重量级的框架尽量用轻量的实现。JSON-RPC 的序列化和反序列化可以用现成的库但不要引入太多依赖端侧的包体积和内存都很宝贵。第二是启动速度。端侧应用的启动速度直接影响用户体验MCP Server 的启动要尽可能快。避免在启动时做耗时的初始化比如加载大模型、建立网络连接这些可以延迟到第一次调用时再做。第三是资源隔离。MCP Server 和 Agent 主进程之间要做好资源隔离避免一个工具的内存泄漏影响整个 Agent。如果工具的执行可能耗时较长要考虑放到独立线程或进程里执行避免阻塞主线程。第四是错误处理。MCP Server 要把工具执行的各种错误都捕获住转换成 MCP 协议定义的错误格式返回给客户端。不要让异常直接抛到协议层导致通信中断。4.3 工具注册与动态发现MCP 的一个好处是支持工具的注册和动态发现。Agent 启动时可以向 MCP Server 查询有哪些工具可用然后把这些工具的 Schema 加载进来。这样新增工具的时候Agent 侧不需要改代码只要 MCP Server 注册了新工具Agent 就能自动发现。在端侧场景里动态发现的价值主要体现在插件化上。你可以把 Agent 的核心逻辑和工具实现分开工具以插件的形式提供用户按需安装。Agent 启动时扫描已安装的插件通过 MCP 协议获取插件的工具列表然后把这些工具纳入可用工具集。这种架构的灵活性很高但实现复杂度也不低。端侧做插件化要考虑插件的加载、卸载、版本管理、权限控制等一系列问题。如果工具集相对固定我建议还是用静态注册的方式简单可靠。4.4 MCP 与 Function Calling 的协同MCP 和 Function Calling 不是替代关系而是协同关系。Function Calling 解决的是“模型怎么表达要调用哪个工具、传什么参数”MCP 解决的是“工具调用请求怎么从 Agent 传到工具实现”。在一个端侧 Agent 里典型的协同流程是这样的模型通过 Function Calling 输出一个工具调用请求Agent 侧解析这个请求转换成 MCP 协议的格式通过 MCP 客户端发送给 MCP ServerMCP Server 执行工具把结果返回给 AgentAgent 再把结果塞回对话上下文让模型生成最终回复。这个流程里Function Calling 和 MCP 各司其职Function Calling 负责模型和 Agent 之间的接口MCP 负责 Agent 和工具之间的接口。两者解耦各自可以独立演进。5. 端侧 Agent 工程化的常见坑与排查5.1 模型输出不稳定的排查思路模型输出不稳定是端侧 Agent 最常见的问题表现是同样的输入有时候能正确调用工具有时候不能。排查这个问题我通常按以下顺序检查。先看prompt 是否太长。端侧模型的上下文窗口有限prompt 太长会导致模型注意力分散输出质量下降。检查方法是把 prompt 打印出来数一下 token 数如果接近模型的上下文窗口上限就要考虑精简。再看Schema 是否太复杂。Schema 里的字段太多、嵌套太深、描述太长都会增加模型的负担。检查方法是把 Schema 单独拿出来看看能不能再精简。然后看示例是否充分。如果 prompt 里没有给示例或者示例太少模型可能不知道该怎么输出。检查方法是加一两个示例看看输出是否稳定。最后看模型本身的能力。如果以上都排查了还是不稳定可能是模型本身的能力不够需要考虑换一个更大的模型或者用量化程度更低的版本。5.2 工具调用参数错误的修复技巧参数错误是另一个高频问题模型输出的参数不符合 Schema导致工具执行失败。修复参数错误我常用的技巧有以下几个。类型转换如果模型把数字输出成了字符串解析时自动转成数字。如果模型把布尔值输出成了字符串解析时自动转成布尔值。枚举映射如果模型输出的枚举值不在列表里尝试做模糊匹配找到最接近的枚举值。比如模型输出“经济舱”枚举列表里是“economy”就做一个中文到英文的映射。默认值填充如果模型漏填了某个可选字段用默认值填充。默认值要在 Schema 里定义好解析时如果发现字段缺失就用默认值。参数修正如果模型输出的参数明显不对比如城市名写错了可以尝试用规则或小模型做修正。比如“北京市”修正为“北京”“上海是”修正为“上海”。这些技巧要组合使用形成一个参数修复管线。修复管线要尽量宽松能修则修修不了再报错。5.3 内存与性能瓶颈的优化方向端侧 Agent 的内存和性能瓶颈主要集中在模型推理和工具执行两个环节。模型推理的优化方向包括量化用 4bit 或 8bit 量化减小模型体积和内存占用、剪枝去掉模型中不重要的参数、蒸馏用大模型教小模型提升小模型的能力、缓存缓存常用的推理结果避免重复计算。工具执行的优化方向包括异步执行工具执行不阻塞主线程、结果缓存缓存工具执行结果避免重复调用、批量执行多个工具调用合并成一次执行、超时控制给工具执行设置超时避免长时间阻塞。这些优化手段要根据具体场景选择不是所有手段都适用。比如量化会损失一定的模型能力如果模型本身能力就不够量化后可能更差。所以优化要在保证功能的前提下进行不能为了性能牺牲功能。5.4 常见问题速查表问题现象可能原因排查方法解决思路模型不调用工具prompt 约束不明确检查 system prompt加明确的输出格式约束和示例模型输出非 JSON模型能力不足换更大模型测试加输出前缀引导或换模型JSON 解析失败格式错误打印原始输出用宽松解析器加修复逻辑参数类型错误Schema 定义不清检查 Schema加类型说明解析时做转换工具执行超时工具实现问题单独测试工具加超时控制异步执行多轮调用死循环终止条件缺失检查轮次控制设最大轮次加去重逻辑内存占用过高模型太大监控内存量化模型优化缓存策略推理速度慢硬件限制测推理耗时用更小模型加推理缓存这张表是我在实际项目里总结出来的覆盖了端侧 Agent 工程化里八成以上的常见问题。遇到问题的时候可以先对照这张表快速定位然后再深入排查。6. 工程化实践中的经验沉淀6.1 Schema 设计的迭代方法Schema 设计不是一次成型的需要反复迭代。我的做法是先设计一个初版 Schema然后在真实场景里跑一批测试用例统计调用成功率。对于成功率低的工具分析失败原因是字段太多、描述不清、还是类型不对然后针对性调整 Schema再跑一批测试看成功率是否提升。这个迭代过程通常要重复三到五轮才能把 Schema 打磨到一个比较稳定的状态。迭代的时候要注意每次只改一个变量这样才能知道是哪个改动带来了提升。如果一次改多个地方成功率变了也不知道是哪个改动起的作用。迭代过程中要积累一个测试用例集覆盖各种典型的用户输入和边界情况。这个用例集是宝贵的资产每次改 Schema 都用它来回归测试确保改动不会引入新的问题。6.2 工具粒度的权衡工具粒度是端侧 Agent 设计里的一个重要决策。粒度太粗一个工具干太多事模型很难正确传参粒度太细工具数量太多上下文装不下模型也容易选错工具。我的经验是一个工具只做一件事但这件事的边界要清晰。比如“查天气”和“查空气质量”可以是一个工具因为它们都是查询环境信息参数也相似但“查天气”和“设闹钟”必须是两个工具因为它们的功能完全不同。工具的数量控制在十个以内比较合适超过十个就要考虑分组或动态加载。端侧模型的上下文窗口有限工具太多会挤占对话历史的空间影响多轮对话的体验。6.3 端侧 Agent 的测试策略端侧 Agent 的测试比云端 Agent 更难因为端侧环境复杂模型行为不确定很难用传统的单元测试覆盖。我的测试策略分三层。第一层是单元测试测试 Schema 解析、参数校验、工具执行这些确定性逻辑用 mock 数据模拟模型输出确保这些环节的正确性。第二层是集成测试用真实的模型跑一批测试用例统计工具调用成功率和最终回复质量这层测试要跑多次因为模型输出有随机性。第三层是端到端测试在真实的端侧设备上跑完整的用户场景测试内存占用、推理延迟、功耗等指标。这三层测试里集成测试是最重要的也是最花时间的。我通常会准备一个包含几十个用例的测试集覆盖各种工具调用场景每次改动后都跑一遍看成功率有没有下降。6.4 从工程化到产品化的最后一公里工程化做完了离产品化还有一段路。产品化要考虑的东西更多比如用户体验、错误提示、隐私保护、版本更新。用户体验方面端侧 Agent 的响应速度是关键。模型推理慢的时候要有 loading 提示工具执行慢的时候要有进度反馈任务完成的时候要有清晰的回复。这些细节直接影响用户对产品的感知。错误提示方面端侧 Agent 出错的时候要给用户友好的提示而不是一堆技术术语。比如工具执行失败不要直接说“HTTP 500”而是说“网络好像不太稳定稍后再试试”。隐私保护方面端侧 Agent 的优势就是数据不出本地这个优势要在产品里体现出来。用户的数据、对话历史、工具调用记录都要存在本地不上传云端。版本更新方面端侧 Agent 的模型和工具都可能需要更新要设计好更新机制支持增量更新和回滚。这一公里的路技术含量可能不如前面的工程化但重要性一点不低。很多端侧 Agent 项目就是死在这一公里上技术做得很漂亮但产品体验一塌糊涂用户用一次就再也不用了。我个人在实际操作中的体会是端侧 Agent 的工程化没有银弹每一个环节都要抠细节每一个问题都要有兜底方案。模型能力不够就用工程手段补工程手段补不了的就用产品设计绕。整个过程就是不断地在能力、资源、体验之间找平衡。这个平衡点每个项目都不一样需要根据具体情况去摸索。但有一点是共通的先把最简单的场景做到极致稳定再逐步扩展复杂度。贪多求快最后往往什么都做不好。
阅读完成 · 觉得有帮助?