第 10 章:模型下载、后端更新与跨平台 —— 文件只是生命周期的起点¶
10.1 下载管理器的职责¶
Rust downloads 模块接收一组 DownloadItem:URL、保存路径、proxy、sha256、size、model_id。DownloadManagerState 以 task id 保存 CancellationToken 和 paused tasks。
stateDiagram-v2
[*] --> Queued
Queued --> Downloading
Downloading --> Paused: pause / cancel token
Paused --> Downloading: resume partial .tmp
Downloading --> Verifying: bytes complete
Verifying --> Completed: hash / size OK
Verifying --> Failed: mismatch
Downloading --> Failed: network / disk error
Downloading --> Cancelled: cancel
暂停和取消不是同一件事:暂停保留 .tmp/.url 以便恢复;真正取消会清掉临时文件和可能存在的最终文件。这是面向大模型下载的必要语义。
10.2 安全的保存路径¶
下载 command 不应允许任意 save_path 写到用户磁盘任何位置。代码通过 resolve_path_within_jan_data_folder 把目标限定在 Jan data folder 内,再处理删除临时文件。模型、backend 和附件下载都应该共享这个边界。
10.3 ModelManager 与模型来源¶
Core 的 ModelManager 管内存中的模型注册表;完整模型实体还包含 sources、engine、settings、parameters、metadata。模型可能来自 Hugging Face、远程 catalog、用户本地 import 或内置 Jan model。
llamacpp-extension 在 import 时读取 GGUF metadata,检测 embedding、MTP 层和 chat template kwargs,写回模型 settings。这样 UI 的“支持图片/embedding/思考参数”不是手工标签,而是基于模型文件能力生成的。
10.4 Backend 更新为什么复杂¶
llama.cpp backend 可能因 GPU、操作系统、架构不同而不同。更新流程要完成:
- 读取本机已有 backend 与版本。
- 从远程清单挑选适合平台/硬件的构建。
- 下载并校验 checksum。
- 安装到版本目录。
- 原子切换当前选择。
- 必要时重启 router 或使用
reload_router_models热加载。 - 保留最近两个旧版本,以支持 rollback/offline downgrade。
代码中 RELOAD_MIN_BUILD 这类阈值说明:新 router 才支持 diff/reconcile 的 hot reload;旧版本必须完整重启。应用不能只看“版本字符串”,还要看能力版本。
10.5 进程与文件的一致性¶
模型设置变化可能影响三类东西:Web store、model.yml、router preset。llamacpp extension 维护 PRESET_AFFECTING_KEYS,只有影响 preset 的参数才需要 router restart;cosmetic 或只影响 UI 的设置不必重启。
UI setting update
→ classify: preset-affecting / runtime-only / UI-only
→ write model settings
→ regenerate preset if needed
→ reload or restart router based on backend capability
这是桌面应用里常见的“配置编译”问题:用户改一个开关,系统需要决定何时把它变成另一个进程可见的配置。
10.6 跨平台矩阵¶
| 能力 | Desktop | iOS/Android |
|---|---|---|
| Tauri 宿主 | Wry + desktop plugins | mobile entry point |
| Thread storage | JSON files | SQLite pool |
| llama.cpp | router + local binary | 条件能力/移动适配 |
| MLX | 仅 macOS Apple Silicon | 不可用 |
| hardware | desktop plugin | 条件编译 |
| updater | desktop updater commands | 移动端不注册 desktop updater |
| window controls | Windows/Linux/macOS 差异 | safe-area / mobile viewport |
Cargo.toml 中大量 cfg/target dependencies 不是噪声,而是产品能力矩阵的可执行表达。
10.7 删除和 reset 的完整性¶
删除模型不能只删模型文件;还要考虑加载 session、router slot、模型设置、下载历史和可能的 embedding 依赖。删除 thread 不能只删 thread.json;还要清消息、RAG collection、chat session、app transient state。
Jan 的多个清理函数(cleanupVectorDB、useChatSessions.removeSession、useAppState.clearThreadState、Rust factory reset)共同组成数据生命周期。读这部分代码时,建议以“对象创建时产生了哪些副产物”为线索反向检查删除路径。