跳到主要内容

LEANN 全景导览:世界最小的向量索引

30 秒导读: LEANN 是一个跑在你自己笔记本上的个人化 RAG 向量数据库。它的独门绝技是—— 不把 embedding(向量)存下来,而是查询时现算。靠这招,索引体积只有传统向量库的约 3% (省 97% 存储),而搜索精度不掉。你可以用它对邮件、浏览器历史、代码、聊天记录做语义搜索, 全程本地、零云依赖、零隐私外泄。


1. 这是什么(零基础也能懂)

一句话定义: LEANN 是一个低存储的本地向量索引 / RAG 系统——把你的私人文档变成"能用自然语言问答的搜索引擎",且索引小到能装进笔记本。

1.1 它解决谁的什么问题

先说清"向量数据库"这个词:向量数据库是把每段文字先用模型转成一串数字(embedding,语义向量),再靠"向量之间的距离"来找语义相近内容的存储系统。它是 RAG(检索增强生成,先检索资料再喂给大模型作答)的检索底座。

传统做法有个致命的存储痛点,场景化讲:

  • 你想把 6000 万条文本块(邮件 + 浏览器历史 + 论文……)做成可语义搜索的索引。
  • 传统向量库(如 FAISS)要把每一条的 embedding 都存下来——6000 万条要 201 GB,笔记本放不下。
  • LEANN 做同样一份索引,只要 6 GB(见 README:README.md:1281-1285 的存储对比表)。

一句话:LEANN 让"在个人设备上对海量私人数据做语义搜索"这件事,从放不下变成放得下。

1.2 给谁用、能搜什么

LEANN 面向想在本地私密地搜自己数据的人。它自带一批 RAG 应用(apps/ 目录),覆盖:

数据源对应示例应用
PDF / TXT / MD 文档apps/document_rag.py
Apple Mail 邮件apps/email_rag.py
Chrome 浏览器历史apps/browser_rag.py
代码库(AST 感知分块)apps/code_rag.py
微信 / iMessage 聊天apps/wechat_rag.pyapps/imessage_rag.py
ChatGPT / Claude 对话存档apps/chatgpt_rag.pyapps/claude_rag.py
Slack / Twitter(经 MCP 拉实时数据)apps/slack_rag.pyapps/twitter_rag.py

核心卖点(README 提炼):隐私(数据不出本机)、轻量(省 97% 存储)、无精度损失(检索质量对齐重量级方案)。

1.3 用起来什么样

最直观的是 README 里那套 CLI 三连——build 建索引、search 搜、ask 问答:

# ① 从一个目录建索引,my-docs 是索引名
leann build my-docs --docs ./your_documents

# ② 语义搜索
leann search my-docs "machine learning concepts"

# ③ 拿你的文档做问答(单次或 --interactive 连续对话)
leann ask my-docs "Where are prompts configured?"

这三个子命令由 packages/leann-core/src/leann/cli.py 里的 argparse 子命令注册:buildcli.py:267searchcli.py:485askcli.py:618(还有 watch/list/remove/serve 等,见 cli.py:264add_subparsers)。

嫌命令行麻烦?也有声明式 Python API——三个类走完全流程:

# 示意用法,取自 README
from leann import LeannBuilder, LeannSearcher, LeannChat

builder = LeannBuilder(backend_name="hnsw") # 建
builder.add_text("LEANN saves 97% storage ...")
builder.build_index("demo.leann")

searcher = LeannSearcher("demo.leann") # 搜
results = searcher.search("AI creatures", top_k=1)

chat = LeannChat("demo.leann", llm_config={...}) # 问
chat.ask("How much storage does LEANN save?")

这三个类都在 packages/leann-core/src/leann/api.py:LeannBuilder(api.py:378)、LeannSearcher(api.py:1154)、LeannChat(api.py:1672)。

1.4 一句话直觉 / 类比

"不存 embedding,要用时现算。"

打个比方:传统向量库像把每道菜都提前做好冻在冰箱——占地方。LEANN 像只留一份菜谱和食材关系图,谁点单了才现炒那几道——储物间省下来了,炒得又快,味道(精度)还一样。

本节到此不碰任何底层代码——你现在应该已经能对同事讲清楚"LEANN 是干嘛的"了。下面进入全景。


2. 顶层全景(它大概怎么转)

这节讲"大盘":LEANN 由哪些部件拼成、数据怎么流。

2.1 一张结构图

怎么读这张图:上半是用户入口(三种用法都最终落到 leann-core 的三个 API 类);中间是核心引擎;下半是可插拔的两侧——左边喂数据(embedding + 分块),右边选后端(存/查向量的具体算法)。

用户入口
┌───────────────┬───────────────┬───────────────┐
│ leann CLI │ Python API │ MCP 服务 │
│ build/search/ │ LeannBuilder/ │ (Claude Code │
│ ask (cli.py) │ Searcher/Chat │ 语义搜索) │
└───────┬───────┴───────┬───────┴───────┬───────┘
└───────────────┼───────────────┘

┌──────────────────────────┐
│ 核心 API 层 leann-core │
│ api.py:建索引/搜/问答 │
└───┬──────────────────┬────┘
喂数据这一端 │ │ 查/存这一端
┌──────────────▼───┐ ┌─────▼─────────────────┐
│ embedding 计算 │ │ 可插拔后端 registry │
│ + AST 感知分块 │ │ 自动发现 leann-backend-*│
│ (embedding_ │ │ ┌─────┬─────┬───────┐ │
│ compute.py 等) │ │ │HNSW │ IVF │DiskANN│ │
└──────────────────┘ │ └─────┴─────┴───────┘ │
└───────────────────────┘
磁盘上一份索引:pruned 图 + passages.jsonl

2.2 部件一句话职责

部件干什么在哪
核心 API 层对外三件套:建索引、搜、问答packages/leann-core/src/leann/api.py
CLI把三件套包成 leann build/search/askpackages/leann-core/src/leann/cli.py:264
后端注册表leann-backend-* 命名自动发现并注册各后端registry.py:30 autodiscover_backends
HNSW 后端(默认)图索引 + 全量重算,省存储最狠packages/leann-backend-hnsw/
IVF / DiskANN 后端增量更新 / 超内存数据集等不同取舍packages/leann-backend-ivf/-diskann/
embedding 服务建索引时算一次向量;搜索时按需重算embedding_compute.py、各后端 *_embedding_server.py
RAG 应用对邮件/浏览器/代码等各数据源的开箱示例apps/
MCP 集成把 LEANN 语义搜索接进 Claude Codepackages/leann-mcp/

2.3 目录布局(uv workspace)

LEANN 是一个 uv workspace(多包 monorepo):根 pyproject.toml 声明工作区,各子包在 packages/ 下,通过 [tool.uv.sources]editable 方式互相引用。

LEANN/
├── pyproject.toml # 工作区根;[tool.uv.sources] 挂各子包(pyproject.toml:97-103)
├── packages/
│ ├── leann-core/ # 核心:api.py / cli.py / registry.py …
│ ├── leann-backend-hnsw/ # 默认后端
│ ├── leann-backend-ivf/ # 增量增删后端
│ ├── leann-backend-diskann/
│ ├── leann-mcp/ # Claude Code 的 MCP 服务
│ └── leann/ # 元包(把 core + 默认后端凑成 `pip install leann`)
└── apps/ # 各数据源的 RAG 示例

[tool.uv.sources] 逐条把 leann-coreleann-backend-hnswleann-backend-diskann 等指到 packages/ 下的本地路径(pyproject.toml:97-103)。

2.4 主线走一遍(高层,不进代码)

建索引(build,一次性):

  1. 把文档切成文本块(chunk),写进人类可读的 <name>.passages.jsonl,同时存一份"块 ID → 文件偏移"的 .passages.idx 便于快速取回原文(api.py:554-579)。
  2. 对每块算一次 embedding,交给后端建成一张 pruned 图(裁剪过的近邻图),而不落盘每条向量(api.py:580-603builder_instance.build(...))。
  3. <name>.meta.json 记后端、embedding 模型、维度等元信息(api.py:604-642)。

于是磁盘上留下的核心就两样:一张 pruned 图 + passages.jsonl 原文——这正是"小"的来源。

搜索(search,每次查询):

  1. 把 query 也转成向量,在图上做近邻遍历(HNSW/DiskANN 等)。
  2. 遍历途中要比较距离,需要某些节点的 embedding 时——不是从磁盘读,而是当场用 embedding 服务重算(即"selective recomputation":只算搜索路径上碰到的那些节点)。
  3. 命中 top-k 后,靠 .passages.idx 偏移映射回 passages.jsonl 取原文返回(SearchResult,api.py:130)。

ask = 在 search 之上再把命中的原文塞进 prompt 交给某个 LLM 作答(LeannChat,api.py:1672)。


3. 巧妙之处清单(要带走的精华)

一句话点出 LEANN 的几个关键设计,细节各章展开:

  • 图 + 选择性重算(核心)。 存 pruned 图不存向量,搜索路径上碰到谁才现算谁的 embedding——这是省 97% 存储的根。→ 见 01
  • 建/搜两端解耦。 建索引时 use_server=False 直接算(api.py:581-588);搜索时改用常驻 embedding 服务按需重算,用 ZMQ 通信(expected_zmq_port 默认 5557,api.py:1249)。→ 见 02
  • 后端零配置自动发现。 凡叫 leann-backend-* 的已安装包都会被 autodiscover_backends() 扫出并 @register_backend 注册,加新后端不用改核心(registry.py:30registry.py:19)。→ 见 03
  • AST 感知分块。 对代码按函数/类边界切,而非按字数硬切,检索更贴语义(见 README "AST-aware chunking")。→ 见 04
  • 原文人类可读、可移植。 块存成 JSONL 明文 + 偏移索引,整个知识库能低成本在设备间搬运(api.py:554-579)。
  • 一份代码多种入口。 同一套 core 同时喂给 CLI、Python API、MCP、ReAct agent(react_agent.py:26)。→ 见 05

4. 阅读地图(该跳哪一章)

本章(index)只讲"是什么 + 大盘 + 路线"。想深入某个机制,按下面顺序(由浅入深)下钻:

章节一句话讲什么
01-storage-trick.md核心存储魔法:图 + 选择性重算 + 高度保留剪枝,省 97% 的原理讲透。
02-search-recompute.md查询一次的端到端:HNSW 图遍历时如何通过 ZMQ 服务按需重算 embedding。
03-backends-registry.md可插拔后端:HNSW / IVF / DiskANN 的取舍,及 leann-backend-* 自动发现机制。
04-embedding-and-chunking.md喂给索引的两端:多后端 embedding 计算(sentence-transformers / MLX / OpenAI)与 AST 感知分块。
05-apps-cli-agent.md把 RAG 送到用户手里:CLI、MCP 集成、ReAct agent 与各数据连接器。

建议路线: 只想懂"为什么这么省" → 读 01;想看一次查询怎么跑通 → 01 → 02;想加后端或换 embedding → 03、04;想接进自己的应用/Claude Code → 05。


5. 代码地图(导航索引)

给要跳进源码的人/agent 的三列表(符号名抗行号漂移):

主题文件符号
建索引主类packages/leann-core/src/leann/api.py:378LeannBuilder
建索引主流程(写 passages + 建图 + 写 meta)packages/leann-core/src/leann/api.py:520LeannBuilder.build_index
搜索主类packages/leann-core/src/leann/api.py:1154LeannSearcher
搜索入口(含 recompute / ZMQ 端口)packages/leann-core/src/leann/api.py:1240LeannSearcher.search
问答封装packages/leann-core/src/leann/api.py:1672LeannChat
检索结果结构packages/leann-core/src/leann/api.py:130SearchResult
CLI 子命令注册packages/leann-core/src/leann/cli.py:264add_subparsers / build(267)/search(485)/ask(618)
后端自动发现packages/leann-core/src/leann/registry.py:30autodiscover_backends
后端注册装饰器packages/leann-core/src/leann/registry.py:19register_backend
后端契约接口packages/leann-core/src/leann/interface.py:7LeannBackendBuilderInterface / ...SearcherInterface(23)
默认后端实现packages/leann-backend-hnsw/leann_backend_hnsw/hnsw_backend.py:38@register_backend("hnsw")
embedding 服务管理packages/leann-core/src/leann/embedding_server_manager.py:213EmbeddingServerManager
ReAct 多轮推理 agentpackages/leann-core/src/leann/react_agent.py:26ReActAgent
工作区包布局pyproject.toml:97[tool.uv.sources]