运行时的真实边界
加载模型只是本地 AI 可见的起点,并不等于运行时本身。一个可用的运行时要决定当前使用哪个模型、如何获取和校验它、该交给哪个后端执行、内存紧张时怎么办、流式生成如何停止,以及其他本地工具如何安全调用它。
LocalEngine 提供了一个具体的参考。它是面向 Apple 平台的原生 Swift 应用,在设备上运行开放权重的语言和视觉模型。它的价值不仅是能离线生成文本,更在于把让本地推理成为可靠子系统的运行环节一并封装起来。
因此,运行时的边界至少包括:
- 模型发现、导入、下载与活动模型选择;
- 推理提供商选择与硬件能力检查;
- 对话状态、流式输出、取消与故障恢复;
- 磁盘、内存和热量资源策略;
- 面向配套应用的、受约束的集成接口。
Local-first 是一项架构约束
“本地”不应只是营销标签。在 LocalEngine 中,提示词、对话和图像输入都在设备上处理;模型安装完成后,应用可以离线工作。这会直接改变系统设计:
| 关注点 | 云端默认 | 本地运行时要求 |
|---|---|---|
| 模型可用性 | 由服务商负责 | 用户需要获取、存储和选择模型 |
| 容量 | 可弹性扩展的远端集群 | 固定的内存、磁盘、电池与散热 |
| 延迟 | 网络与排队占比高 | Prefill、Decode 与 Metal 调度占主导 |
| 隐私边界 | 数据跨越服务边界 | 除非用户主动开启其他服务,输入保留在设备上 |
| 集成方式 | 公网 HTTPS API | 本地、认证、按需启用的接口 |
这也是模型包装器很快就不够用的原因:本地运行时必须承担云端 SDK 可以交给服务商的策略。
一个产品,两个推理后端
LocalEngine 在 macOS 上提供两条互补路径:
- 通过内置 llama.cpp 运行 GGUF。 这条路径兼容广泛的量化 GGUF 模型,并使用 Metal 加速。
- 通过 mlx-swift 运行 MLX。 这条路径面向 Apple Silicon,使用原生、以 Metal 为核心的 MLX 推理栈。
产品应该将它们表达为能力,而不是让应用代码直接绑定其中一个实现。提供商抽象层可以回答“当前模型是否支持图像输入”“Metal 是否可用”“该请求能否流式返回”等问题,而应用始终只需发起一次聊天完成请求。
聊天 / 翻译 / 浏览器扩展
↓
提供商抽象层
↙ ↘
GGUF + llama.cpp MLX + mlx-swift
↘ ↙
Metal / Apple 硬件
重要的契约是请求与流式行为保持稳定,而不是假装两种后端拥有相同的格式、内存占用或性能特征。
模型生命周期属于推理的一部分
LocalEngine 将模型视为受管理的本地资产。用户可以导入 GGUF 文件或 MLX 模型目录、选择活动模型,也可以从目录下载精选模型。下载任务可在后台续传,并显示进度,且可取消。
这是运行时工作,因为一个文件存在并不代表模型可以使用。接受请求前,运行时应能确认:
- 所选路径和格式是否有效;
- 哪个后端可以加载它;
- 视觉能力是否需要额外的多模态投影器;
- 磁盘与工作内存是否足够;
- 下载或模型切换是否仍在进行。
活动模型应是显式状态,并与对话独立持久化。这样可以避免聊天界面、浏览器扩展和后台下载各自悄悄选择不同的模型。
窄而本地的 API,比“仿云端”更有用
配套产品往往需要本地推理,但并不希望各自内置推理引擎。LocalEngine 为此提供可选的 OpenAI 兼容 HTTP 与 WebSocket API:它仅绑定回环地址,默认关闭,启用后使用自动生成并存储在 macOS 钥匙串中的 Bearer Token。
这是一种很好的集成模式:
- 熟悉的
chat/completions请求与流式格式能降低客户端接入成本; - 仅绑定回环地址,使 API 不暴露在公网;
- 按需开启,让用户看见并控制边界;
- 可重新生成的 Token,避免浏览器扩展被永久隐式信任;
- 无需认证的健康与能力端点可以用于发现,而不暴露推理能力。
这里的兼容性是一种产品接口,而非承诺模拟所有云服务特性。运行时必须准确说明支持的角色、图像输入、流式行为与错误响应。
引擎之上,才是运行时策略
可靠的端侧产品需要在 llama.cpp 或 MLX 之上再加一层策略。对于 LocalEngine 一类应用,这一层至少应协调以下事项。
上下文与请求策略
对话历史必须变成长度受控的 Prompt。运行时需要 Token 预算、截断规则,并清楚地区分用户内容、系统指令与本地状态。长上下文失败通常先是内存和延迟问题,之后才是模型质量问题。
资源策略
运行时不能将模型的标称大小等同于实际占用。它需要计算权重、随上下文增长的 KV Cache、多模态资源、临时缓冲区与并行下载。在笔记本上,它应报告有用的失败信息并保留现有会话,而不是让界面失去响应。
流式与取消策略
Token 流式输出是与 UI 的契约。启动、停止、切换模型和关闭对话都必须让引擎处于可预期状态。对交互式工具来说,取消延迟与吞吐同样重要。
可观测性
LocalEngine 会展示活动运行时、所选模型和 Metal 可用性等引擎状态,这是正确的起点。生产级运行时还应在不记录用户提示词的前提下,让模型加载失败、下载状态、请求耗时、首 Token 延迟和停止原因都可被检查。
能揭示真实瓶颈的指标
一个 “tokens/s” 数字掩盖了大部分关键问题。应在用户可感知的边界上衡量运行时:
- 首 Token 时间: Prompt 准备、模型就绪和 Prefill 延迟。
- 解码 tokens/s: 首 Token 后的持续生成速度。
- 峰值常驻内存: 包含模型权重、KV Cache 与临时缓冲区。
- 模型加载与切换时间: 改变活动状态的代价。
- 下载续传与失败率: 模型获取是产品可靠性的一部分。
- 取消延迟: 进行中的回复实际停止需要多久。
- Metal 可用性与回退率: 用于区分配置问题和模型问题。
- 本地 API 成功率与认证失败: 集成边界必须可观测。
这些指标能帮助我们判断问题究竟属于模型、后端、Prompt、设备,还是外围产品逻辑。
本地不保证什么
端侧推理改善了数据流的控制权,但不能让每个模型都适合每台机器或每项任务。用户仍需要为模型预留足够磁盘、为选定上下文提供足够内存,并为偏好的后端准备兼容硬件。MLX 路径尤其依赖 Apple Silicon;模型质量仍取决于模型和 Prompt,而不是推理发生在哪里。
同样,回环 API 也不能替代权限策略。它需要显式开启、妥善处理 Token,并保持狭窄的接口面。隐私、可靠性和互操作性都来自具体的运行时策略。
实用的架构分层
最终,系统可以理解为五层:
产品界面与配套应用
↓
对话、请求与资源策略
↓
模型注册表与提供商抽象
↓
GGUF / llama.cpp 运行时 MLX 运行时
↓
Metal 与本地存储
这套分层使同一个产品可以在 LocalEngine、Ollama、LM Studio 或云端提供商间切换,而不会将产品逻辑绑定到某一个推理框架。但本地提供商应拥有一等的契约:模型所有权、硬件状态、用户可控的隐私,以及本地集成能力,正是它的定义性特征。
Loading discussion…