Ensu 工作原理深度解析:Ente 端到端本地推理聊天应用的技术内幕
【免费下载链接】ente💚 End-to-end encrypted cloud for everything.项目地址: https://gitcode.com/GitHub_Trending/en/ente
Ensu 是 Ente 开源的本地优先 AI 聊天应用(完整定位可参见介绍页),它把大语言模型的加载、提示词处理与 token 生成全部搬到你的设备本地执行,聊天过程中不依赖任何云端推理服务。本文以 Ensu How it works 文档为主体,结合 monorepo 内 Rust 推理核心与 Web 端推理实现的源码证据,为你讲清 Ensu 的架构形态、模型文件、消息处理流水线、本地存储布局、隐私边界与信任模型,让你能独立审计其"结构性隐私"承诺,并理解各平台实现差异的底层原因。
架构形态:反转主流 AI 聊天应用的结构
几乎所有主流 AI 聊天应用(ChatGPT、Claude、Gemini 等)都遵循同一形态:设备上的瘦客户端与服务器上运行的模型对话。模型太大装不进手机,重活都在别处完成,代价是你输入的一切最终都落在别人的机器上。
Ensu 把这个结构反转过来:
- 模型足够小,可以装进你的设备;
- 聊天 UI 与模型运行在同一个应用、同一台机器上;
- 推理链路中不存在服务器。
当然,小模型的能力不如云端最大型模型,但对日常很多场景已经够用,而且本地模型正在快速进步。Ensu 的职责就是让本地版本的体验与云端一样顺畅。更完整的定位与使用场景(隐私反思与日记、离线使用、书籍与想法讨论等)可以参考Ensu 介绍页。
各平台运行形态:共享 Rust 核心,按平台包装
Ensu 构建在一个共享的Rust 核心之上,负责模型加载、提示与 token 生成,同一个核心被各平台的原生应用包装:
| 平台 | 实现方式 |
|---|---|
| iOS / Android | Rust 核心以原生库形式内置,上层为 Swift / Kotlin UI |
| macOS / Windows / Linux | Tauri 应用:Rust 核心做推理 + 轻量原生外壳 + 内嵌 Ensu Web UI |
| Web | 全部运行在浏览器中,模型以 WebAssembly 运行,模型文件缓存在浏览器的 Origin Private File System(OPFS)中,避免每次访问重复下载 |
底层推理引擎,原生平台基于 llama.cpp,浏览器端则是它的 WebAssembly 构建。Ensu 在这个引擎外面做了一层封装,让聊天 UI、模型下载与设置在各平台表现一致。
这一"双后端"结构在 Web 端代码中有直接体现:inference.ts 中的createInferenceBackend依据运行环境选择后端——Tauri 环境下返回TauriInference,否则返回WasmInference,并抽象出统一的InferenceBackend接口(loadModel/createContext/generateChatStream/cancel等)。Rust 侧则通过llama_cpp_2crate 封装 llama.cpp:LlamaBackend使用OnceLock做进程级单例初始化(见 llm/mod.rs),模型加载走LlamaModel::load_from_file(见 llm/model.rs)。
整个 Ensu 代码库(Rust 推理核心、各平台 UI、Web 应用)都开源在 Ente 的 monorepo 中,与 Photos、Auth、Locker 等应用同仓。
模型文件:GGUF 格式与平台默认模型
模型本身是单个文件,手机上通常 600 MB 到 2 GB,内存充足的桌面上有几 GB。格式为GGUF——与 llama.cpp 同款格式。多模态模型还会附带一个独立的mmproj文件,内含处理图像的视觉投影器(vision projector)。
Ensu 首次启动时会根据你的设备挑选默认模型,并从 Hugging Face 下载:
| 默认模型 | 参数量 | 量化 | 适用设备 | 大小 |
|---|---|---|---|---|
| Gemma 4 E4B(Q4_K_M) | 40 亿(4B)多模态,DeepMind 出品 | Q4_K_M | 桌面端(macOS / Windows / Linux),且内存 ≥ 16 GB | 约 6 GB |
| LFM 2.5 VL 1.6B(Q4_0) | 16 亿(1.6B)多模态,Liquid AI 出品 | Q4_0 | 其余全部:Android、iOS、低内存桌面、Web | 约 700 MB |
这些预设模型在 config.rs(LFM)与 config.rs(Gemma)中以ModelPreset形式硬编码,包含 Hugging Face 下载地址、精确字节大小与 SHA-256 校验值,例如 LFM 2.5 VL 1.6B 主模型 695,752,480 字节、mmproj 583,109,888 字节——下载后会做完整性校验,这也解释了为什么模型文件必须是 GGUF 且校验严格。
设备选择逻辑与内存阈值相关:源码中MOBILE_HIGH_MEMORY_THRESHOLD_BYTES = 7 GB(注释说明移动 OS 报告的内存低于标称值,7 GB 目标对应 8 GB 设备)、DESKTOP_HIGH_MEMORY_THRESHOLD_BYTES = 16 GB(见 config.rs)。
原生平台的下载是可断点续传的:如果下载中断,下次启动应用时会从断点继续。下载在可能的情况下并行进行,并自动重试。这一机制在 Web 端代码里同样成立:inference.ts 的ensureModelCached会把模型写入 OPFS 缓存目录,通过Range: bytes=<downloaded>-请求头实现断点续传(见 inference.ts),并记录 ETag、原始大小等元数据用于校验;isModelAvailable会校验文件头是否为 GGUF 魔数(GGUF四字节,见 inference.ts),且至少 1 MB。
发送消息时发生了什么:一次完整的本地推理流水线
当你按下发送键:
- 输入框把消息、图片附件(如有)和最近的聊天历史交给本地模型;
- Ensu 把系统提示词和仍在上下文中的历史消息前置,然后要求模型继续这段对话;
- 模型把 token 流式返回给应用,你看到的内容逐块出现;
- 模型生成完毕(或被你停止)后,最终消息与其余聊天内容一起保存到本地存储。
整个流程不发任何网络请求。聊天过程中 Ensu 产生的唯一网络流量来自操作系统自身(DNS、系统后台任务),不涉及任何 Ente 端点。你可以在模型下载完成后把设备切到飞行模式验证这一点——Ensu 依然可用。
从 Rust 源码可以还原这条流水线的具体实现(均在 llm/generate.rs):
- 请求模型:
ChatRequest定义了一次生成的全部参数——messages、template_override、add_assistant、image_paths、mmproj_path、max_tokens、temperature、top_p、top_k、repeat_penalty、frequency_penalty、presence_penalty、seed、stop_sequences、grammar(见 generate.rs)。Web 端通过buildGenerateChatRequest做字段映射、buildSamplingConfig做采样参数换算(见 inference.ts)。 - 提示词构造:
build_chat_prompt读取模型自带的 chat template(可被template_override覆盖),对带enable_thinking的模板走 OpenAI 兼容的模板应用路径,普通模型则用apply_chat_template拼出完整提示(见 generate.rs)。默认max_tokens为 8192(DEFAULT_GENERATION_MAX_TOKENS,见 generate.rs)。 - 上下文与 KV 缓存复用:
Context内持有LlamaContext与已缓存 token 列表(见 llm/context.rs);append_only_prefix_len只在提示严格以已缓存前缀开头时复用缓存,避免每次对话都重新 prefill(见 generate.rs,并有对应单元测试only_strict_extensions_reuse_cache)。提示超过上下文窗口会返回PromptTooLong错误(generate.rs)。 - 采样器链:
build_sampler按需组装惩罚(repeat/frequency/presence)、grammar、top-k、top-p、温度与随机种子采样器,temperature ≤ 0时退化为 greedy 解码(见 generate.rs)。 - 流式解码:
StreamDecoder按 token 累积字节并保持 UTF-8 完整性(跨字节边界的中文字符、emoji 不会乱码),同时检测停止序列、在命中时截断输出(见 generate.rs,测试stream_decoder_emits_complete_utf8验证了 emoji 的完整输出)。 - 多模态路径:当携带
image_paths时,要求必须提供mmproj_path,通过缓存的MtmdContext把图像编码为视觉 token 与文本 token 一起送入模型(见 generate.rs)。桌面端还有prewarmMultimodalContext预热机制(见 inference.ts)。 - 取消与停止:每个生成任务注册原子取消标志,UI 上的"停止"按钮通过
cancel(jobId)(jobId ≤ 0 时取消全部)触发,生成循环在每步检查该标志(见 generate.rs)。
Web 端WasmInference走等价路径:formatChat拼提示、tokenize统计 prompt token、createCompletion流式产出 chunk、按job_id管理 abort controller(见 inference.ts)。
什么被存储,存在哪里
Ensu 把所有与聊天相关的东西都存在你的设备上。默认没有 Ente 账号,因此 Ente 服务器上没有任何地方承载这些数据。
本地数据包括:
- 模型文件(多模态模型还有 mmproj 文件)——体积最大的项;
- 语音转写模型(iOS / Android,使用语音输入时);
- 聊天历史:消息、附件、会话标题、分支元数据;
- 设置:系统提示词、模型选择等偏好;
- 日志:用于调试,不含聊天内容,仅在你选择导出时使用。
存储位置:
| 平台 | 路径 |
|---|---|
| macOS | ~/Library/Application Support/io.ente.ensu/ |
| Windows | %APPDATA%\io.ente.ensu\ |
| Linux | ~/.local/share/io.ente.ensu/(或$XDG_DATA_HOME/io.ente.ensu/) |
| iOS | 应用沙盒内,删除应用即清除 |
| Android | 应用内部与外部文件目录,卸载即清除 |
| Web | 模型存浏览器 OPFS,聊天历史存 IndexedDB |
聊天历史在 Web 端由 chat/services/persistence.ts 等模块落盘;移动端上会话与分支的持久化逻辑在 rust/crates/ensu/src/db/chat/ 的 SQLite 后端(含 schema 与迁移)中实现。卸载方式可参考 Uninstall Ensu 文档。
什么不会被存储:隐私边界清单
永远不会离开你设备的数据:
- 你在输入框输入的文字;
- 你为语音输入录制的语音(本地转写);
- 你附加的图片(由多模态投影器本地处理);
- 模型的回答。
Ensu 不会做的事:
- 聊天无需账号——登录流程是为未来的同步功能准备的,完全可选;
- 没有任何分析或遥测追踪你问模型的内容;
- 没有任何后台上传。
所有会走网络的行为,仅此而已:
- 首次启动(或切换模型、Ensu 更新导致模型版本变化)时从 Hugging Face 下载聊天模型;
- iOS / Android 上首次使用语音输入时,从
models.ente.com下载 Parakeet 转写模型与 Silero VAD 模型(除非已缓存); - 软件更新检查,由平台应用商店或桌面自动更新器处理;
- 如果你为未来的同步功能登录,会有一轮标准的认证交互。
在必需模型下载完成后离线运行 Ensu,或直接检查源码,都可以确认以上任何一点。
同步与备份:已构建完成,尚未启用
当前发布版本不会把你的聊天同步到任何地方,每个设备的历史相互独立。
加密同步与备份已经构建完成并可用,但本版本未启用:团队希望在最终确定架构前先收集产品方向上的反馈。同步上线后:
- 使用你现有的 Ente 账号,可随时选择加入或退出;
- 端到端加密,复用 Ente Photos、Auth、Locker 使用的同一套加密库与密钥派生方式——Ente 服务器只能看到密文;
- 与 Ente 其他部分一样支持自托管;
- 你现有的本地聊天会被接管并备份,设备上已有的内容不会丢失。
更多细节见 FAQ 的同步章节(仓库内 FAQ 全文在 faq/index.md)。
信任模型:结构性隐私,而非承诺
Ensu 的隐私是结构性的,而不是口头承诺:
- 模型运行在设备上,明文数据根本不需要离开;
- 默认没有 Ente 账号介入链路,服务器端没有可被攻破的对象;
- 应用开源,你可以独立验证以上任何一点。
Ensu不防御的情形:
- 被攻破的设备:如果手机或电脑上有能读取应用数据的东西,就能读到你的聊天历史。请使用设备级防护(全盘加密、应用锁、屏幕锁);
- 模型自身的缺陷:本地模型同样可能产生幻觉或错误答案,请像对待其他 AI 输出一样看待它;
- 提示词导致的推断风险:如果你把敏感文档粘贴进聊天并要求总结,文档在你的设备上,但它同时也成了本地聊天历史的一部分。防的是第三方,而不是你自己或能接触到同一台设备的人。
关于未来云端同步的隐私保证,见上文"同步与备份"。
延伸阅读
- Ensu 介绍:安装、发送第一条消息与推荐提示词;
- Ensu 功能总览:按功能组织的全平台能力清单;
- Ensu FAQ:隐私、模型、同步与故障排查;
- Rust 推理核心:流式生成、采样器、多模态与 KV 缓存复用实现;
- Web 端推理服务:WASM / Tauri 双后端与 OPFS 断点续传下载;
- 模型预设配置:各平台默认模型的 URL、大小与 SHA-256。
【免费下载链接】ente💚 End-to-end encrypted cloud for everything.项目地址: https://gitcode.com/GitHub_Trending/en/ente
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考