Mindory 的技术

让 AI 更靠近用户,让数据留在本地

让 AI 更靠近用户,让数据留在本地

Mindory 从一开始就没有把自己设计成一个"连接远程 AI 服务的阅读器"。

我们更希望探索另一种可能:

让 AI 尽可能运行在用户自己的设备上。

对于阅读应用来说,这意味着书籍可以在本地完成解析、文本处理、语义索引和检索,而不需要将整本书上传到服务器,再等待远程服务处理。

因此,Mindory 的技术设计围绕三个目标展开:

这里的"本地 AI"并不意味着所有 AI 能力都必须运行在本地。

Mindory 采用了一种更加务实的方式:

把适合在本地完成的工作留在本地,把真正需要大语言模型的部分交给用户选择的 LLM 服务。

Local RAG:将核心检索链路运行在本地

RAG(Retrieval-Augmented Generation)是 Mindory AI 阅读能力的核心。

传统的 AI 应用通常需要依赖远程服务完成文本 Embedding、向量检索等工作。Mindory 则将 RAG 中适合本地运行的基础设施尽可能放到了用户自己的设备上。

一本书进入 Mindory 后,会经过:

文档解析 → 文本切分 → 本地 Embedding → 本地向量索引 → 语义检索 → LLM

其中,文档解析、文本切分、Embedding 和向量检索都可以在本地完成。

只有在生成回答时,才需要将检索得到的相关内容交给用户配置的 LLM 服务。

这意味着:

书籍不需要为了建立语义索引而上传到远程 Embedding 服务。

本地 Embedding

Mindory 不依赖远程 Embedding API。

Embedding 模型直接运行在用户自己的设备上,即使在 CPU-only 环境下,也可以完成书籍的语义索引。

这带来了几个直接的好处。

更低的成本

不需要为每一本书的索引过程持续调用远程 Embedding API,降低 AI 基础设施的使用成本。

更好的隐私

书籍内容可以在本地完成文本处理和 Embedding,不需要因为建立语义索引而发送到第三方 Embedding 服务。

更强的可控性

Embedding 模型、向量索引和检索过程都由本地应用控制,不依赖某一个远程 Embedding 服务。

Mindory 的目标不是简单地"把 AI 搬到本地",而是:让本地设备真正成为 AI 阅读系统的一部分。

从一本书到语义空间

Mindory 并不是简单地把一本书交给 LLM。

对于一本大部头书籍,系统首先需要将书籍内容转换成适合机器理解和检索的结构。

一本书进入 Mindory 后,会经过完整的文本处理流水线:

Book │ ▼ Document Parser │ ▼ Normalized Text │ ▼ Text Pipeline │ ├── Chunking ├── Overlap └── Text Mapping │ ▼ Local Embedding Model │ ▼ Vector Index │ ▼ Semantic Retrieval │ ▼ LLM

文本首先被切分成适合语义检索的片段,并通过 overlap 保留相邻内容之间的上下文关系。

随后,本地 Embedding 模型将这些文本转换为向量,并建立本地向量索引。

当用户提出问题时,Mindory 不需要把整本书交给 LLM,而是首先从整本书中找到与问题最相关的内容,再将这些内容交给 LLM 进行理解和生成。

这也是 Mindory 能够处理大部头书籍的重要基础。


多格式解析:与应用解耦

电子书的格式非常复杂。

TXT、EPUB、PDF、MOBI、AZW3,它们的数据结构和解析方式完全不同。

如果把文件格式处理直接写进 RAG 系统,随着支持的格式不断增加,整个系统很容易变得复杂而难以维护。

因此,Mindory 在架构上将:

"如何读取一本书""如何理解一本书" 彻底分开。

不同格式分别由独立的 Parser 负责:

TXT ──┐ EPUB ──┤ PDF ──┤ MOBI ──┤──> Unified Text Pipeline AZW3 ──┤ ... ──┘

Parser 负责将不同格式的文档转换为统一的文本表示。

从这一层开始,后续的文本切分、Embedding、向量检索和 RAG Pipeline 都不再关心原始文件是什么格式。

增加一种新的书籍格式,只需要增加对应的 Parser,即可接入现有的阅读和 AI 能力。

这种设计也让文档解析模块与上层应用保持独立,为未来支持更多格式提供了基础。


Rust:本地 AI 应用的核心引擎

Mindory 的核心引擎使用 Rust 实现。

对于运行在本地设备上的应用而言,计算能力、内存和系统资源始终是有限的。Mindory 需要在本地同时处理:

这些工作都发生在用户自己的设备上,因此应用本身需要尽可能高效地利用系统资源。

Rust 强大的类型系统、所有权模型和内存安全机制,为构建高性能、稳定且可靠的本地应用提供了良好的基础。

与此同时,Rust 不依赖垃圾回收机制,可以对内存和资源使用进行更加明确的控制,这对于需要长期运行、同时处理大量本地数据的桌面应用尤其重要。


Async First:让 AI 在后台工作

AI 任务通常涉及大量计算和 I/O 操作。

例如,导入一本书需要经过一系列处理:

读取文件 ↓ 解析 ↓ 文本切分 ↓ Embedding ↓ 建立向量索引 ↓ 完成导入

如果这些耗时操作直接运行在 UI 线程中,很容易造成界面卡顿,影响正常的阅读体验。

因此,Mindory 使用 Tokio 构建异步任务体系,将书籍导入、文本处理、Embedding 和向量索引等耗时操作放到后台执行。

前端无需等待整个任务完成,而是通过事件机制接收后台任务的状态和进度变化:

User │ │ Import Book ▼ Tauri │ ▼ Async Ingest Runner │ ├── Parse ├── Chunk ├── Embed └── Index │ └────── Events ──────> UI

后台任务可以持续运行,而用户无需停下来等待,可以继续阅读和使用应用。

让 AI 在后台工作,让阅读始终保持流畅。

Tauri:更轻量的桌面 AI 应用

Mindory 使用 Tauri 构建桌面应用。

与传统 Electron 应用不同,Tauri 不需要为每个应用打包完整的 Chromium 和 Node.js Runtime,因此可以减少应用体积,让桌面 AI 应用更加轻量。

Mindory 的用户界面使用 React + TypeScript 构建,而本地能力和核心引擎则由 Rust 提供。

这种架构将现代 Web UI 与高性能本地能力结合起来:

Tauri

负责桌面应用容器、窗口管理以及前后端通信,为 Mindory 提供现代化的阅读界面和交互体验。

Rust

负责本地数据管理、文档处理、RAG、Embedding、向量检索以及异步任务等核心能力。

最终,Mindory 将 Web 技术的开发效率与 Rust 的本地性能结合起来,构建一个轻量、高效、更贴近原生体验的桌面 AI 应用


Local AI Architecture

Mindory 的整体架构可以概括为:

┌──────────────────────┐ │ React + TypeScript │ │ UI │ └──────────┬───────────┘ │ Tauri │ ┌──────────▼───────────┐ │ Rust AI Engine │ │ │ │ Async Task Runtime │ │ Document Parser │ │ Text Pipeline │ │ RAG Pipeline │ │ Embedding Engine │ │ Vector Store │ │ SQLite │ └──────────┬───────────┘ │ ┌─────────────┼─────────────┐ ▼ ▼ ▼ Local Book Local Model Local Index │ │ │ └─────────────┴─────────────┘ │ │ Relevant Context ▼ LLM Service │ ▼ Answer

这个架构让本地数据处理与远程 LLM 能力形成清晰的边界:

本地设备负责

LLM Service 负责

Mindory 并不是简单地把所有数据交给云端处理,而是将 AI 工作拆分成适合本地和远程的不同部分。

我们相信的 AI 应用

AI 应用不一定意味着:

上传数据 → 调用 API → 返回结果。

对于阅读这样的个人场景,我们认为还有另一条路:

数据尽可能留在本地,计算尽可能本地化,远程 AI 只承担真正需要它承担的工作。

这也是 Mindory 在技术架构上的核心取舍。

本地 Embedding 减少了对远程 AI 基础设施的依赖,本地 RAG 让书籍的语义索引和检索可以在用户自己的设备上完成,而 Rust + Tauri 则让这些能力能够以轻量、高效的方式运行在桌面环境中。

Mindory 想做的,不只是一个会回答问题的阅读器。

而是一款真正以本地设备为基础构建的 AI 阅读应用

想亲自体验?

立即下载 Mindory,体验全新的阅读方式

下载 macOS 版