Doramagic 项目包 · 项目说明书
Localbrain 项目
为本地文件建立索引以进行语义搜索与重排序,可通过 MCP 服务器、CLI 或本地 Web 控制台使用。
概述与系统架构
Localbrain 是一款本地优先(local-first)的个人知识库检索工具,通过在用户机器上完成文件读取、文本分块、向量化与语义检索,让自然语言查询能够直接命中本地的 Markdown、纯文本等文档。README 中明确指出:用户数据始终留在本机,索引与查询均不依赖外部云服务,断网后已索引的内容仍可继续使用 资料来源:[README.md]()。
继续阅读本节完整说明和来源证据。
项目定位与核心能力
Localbrain 是一款本地优先(local-first)的个人知识库检索工具,通过在用户机器上完成文件读取、文本分块、向量化与语义检索,让自然语言查询能够直接命中本地的 Markdown、纯文本等文档。README 中明确指出:用户数据始终留在本机,索引与查询均不依赖外部云服务,断网后已索引的内容仍可继续使用 资料来源:README.md。
围绕这一目标,系统提供三组核心能力:
- 本地语义索引 —— 通过本地嵌入模型将文档切片写入本地向量库;
- 多入口适配 —— 同时面向 MCP(Model Context Protocol)、Web 控制台和 CLI 提供薄入口,让 Claude Code 等外部 AI 工具也能消费本地知识;
- 自反馈回路 —— 通过查询聚类与知识空白报告,为索引的持续优化提供数据支撑。
分层架构
代码以 src/localbrain/ 为根,按 core / services / adapters 三层组织,并由一个组合根(composition root)统一装配:
flowchart TD
A["适配层 Adapters<br/>MCP Server · Web UI · CLI"] --> B["服务层 Services<br/>IndexingService · SearchService · InsightsService"]
B --> C["核心层 Core<br/>Indexer · Searcher · Scanner · Insights"]
C --> D["基础设施<br/>SQLite(file_index/sources/queries) · Chroma(vector store) · Embedding Providers"]
A -.启动.-> E["AppContext (context.py)<br/>composition root"]
E --> B
E --> C
E --> D各层职责:
- 核心层(core/) 承担单一职责的领域逻辑,例如
core/indexer.py只负责"load→chunk→embed→store + file_index 更新"流程,并以yield {"phase":...}形式对外暴露进度事件 资料来源:src/localbrain/core/indexer.py;core/chunking.py只负责段落优先的贪心分块与相邻 overlap 合并 资料来源:src/localbrain/core/chunking.py。 - 服务层(services/) 是面向用例的薄编排,例如
IndexingService.run()负责"扫源 → 生成 ChangeSet → 调用 Indexer → 流式返回进度",并以rebuild=True控制是否全量重建 资料来源:src/localbrain/services/indexing_service.py;InsightsService仅作为Insights.cluster(...)的薄包装,用于查询聚类与知识空白 资料来源:src/localbrain/services/insights_service.py。 - 适配层(adapters/) 是面向协议的入口:
adapters/__init__.py中描述其为"core·services 之上的薄入口" 资料来源:src/localbrain/adapters/__init__.py;mcp_server.py基于 FastMCP 暴露search / add_path / remove_path等工具,让 Claude Code 通过 stdio 直接调用本地知识 资料来源:src/localbrain/adapters/mcp_server.py;adapters/web/__init__.py则声明 Web 端为 FastAPI 后端 + 静态单页架构 资料来源:src/localbrain/adapters/web/__init__.py。
关键数据流:索引与检索
系统通过 AppContext 把所有依赖拼装到一处:构造嵌入 provider、连接 SQLite、初始化 Chroma 向量库、构建 Scanner/Indexer/Searcher/FileIndex/SourceStore,并由各适配器按需取用 资料来源:src/localbrain/context.py。两侧数据流如下:
| 流向 | 触发 | 关键步骤 | 落点 |
|---|---|---|---|
| 写入(索引) | add_path / run(rebuild) | Loader 按扩展名匹配 → chunk_text 分块 → EmbeddingProvider 编码 → Chroma 写入 → file_index 记录 hash/mtime/chunk_ids | 向量库 + SQLite |
| 读取(检索) | MCP search / Web 查询 | Searcher 在 Chroma 上做向量召回 → 可选 Reranker 重排 → 返回带分数的命中片段 | 调用方 |
可插拔扩展点体现在两处 registry:嵌入侧支持 fastembed / ollama / sentence-transformers 三种 provider,按配置名懒加载 资料来源:src/localbrain/core/embed/registry.py;加载器侧通过 _LOADERS: list[Loader] 列表按 supports(path) 选择,当前内置 TextLoader 资料来源:src/localbrain/core/loaders/registry.py。
持久化、配置与可扩展性
SQLite 作为元数据库,core/db.py 中声明了三张表:sources(注册路径与 glob)、file_index(path / hash / mtime / size / chunk_ids / source_id)和 queries(id / text / ts / hit / top_score),并启用 WAL 与 check_same_thread=False 以适配多适配器并发 资料来源:src/localbrain/core/db.py。向量库落盘到 chroma_dir,文件名以 provider.model_id 作为 collection 命名空间,避免不同模型切换时混用 资料来源:src/localbrain/context.py。
扩展建议:
- 新增文件类型:实现
Loader.supports并注册到_LOADERS列表即可被get_loader自动选中 资料来源:src/localbrain/core/loaders/registry.py。 - 新增嵌入后端:在
core/embed/下实现EmbeddingProvider,并在make_provider中追加分支 资料来源:src/localbrain/core/embed/registry.py。 - 新增 AI 客户端:只需在
adapters/下添加薄入口,复用AppContext与服务层,无需触碰 core 资料来源:src/localbrain/adapters/__init__.py。
See Also
- MCP 服务器适配器
- 核心索引器
- 嵌入与检索
来源:https://github.com/Tamariskwhisper962/Localbrain / 项目说明书
核心引擎:索引与数据管道
Localbrain 的核心引擎围绕"扫描 → 加载 → 分块 → 嵌入 → 持久化"五个阶段构建了一条可增量更新的数据管道。该管道的职责是把本地文件系统中的纯文本/结构化文档,转换为 Chroma 向量库中可语义检索的向量记录,并维护一份 SQLite 文件索引以追踪每个路径的哈希与对应分块。引擎本身不直接面向用户,所有调用都通过 AppContext 这一组合根注入到上...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
Localbrain 的核心引擎围绕"扫描 → 加载 → 分块 → 嵌入 → 持久化"五个阶段构建了一条可增量更新的数据管道。该管道的职责是把本地文件系统中的纯文本/结构化文档,转换为 Chroma 向量库中可语义检索的向量记录,并维护一份 SQLite 文件索引以追踪每个路径的哈希与对应分块。引擎本身不直接面向用户,所有调用都通过 AppContext 这一组合根注入到上层服务(IndexingService / SearchService / InsightsService)中,再由 MCP、CLI、Web 三种适配器暴露。
资料来源:src/localbrain/context.py:1-40、CHANGELOG.md:0.1.0
架构总览:组合根
AppContext 在 src/localbrain/context.py 中扮演组合根(composition root)的角色——它一次性装配配置、嵌入 provider、向量库、文件索引、扫描器、索引器等所有依赖。适配层只需要 AppContext() 一行即可获得完整的服务栈,避免在 MCP、CLI、Web 三个入口分别重复拼装。
graph LR
A[适配器 MCP/CLI/Web] --> B[AppContext 组合根]
B --> C[Scanner 扫描]
B --> D[Indexer 索引]
B --> E[VectorStore 向量库]
B --> F[FileIndex SQLite]
B --> G[Insights 洞察]
C -->|ChangeSet| D
D -->|embed + store| E
D -->|update| F资料来源:src/localbrain/context.py:1-40
数据管道:扫描到写入
1. 扫描阶段
Scanner 负责遍历已注册源(文件夹/文件),通过 mtime + 内容哈希 双重比对,产出 ChangeSet(包含 new / modified / deleted 三类路径)。这种"变更即差异"的设计让索引过程天然支持增量更新:未发生变化的文件直接跳过,从而避免重复嵌入。扫描完成后,ChangeSet 被交给 Indexer.apply()。
资料来源:src/localbrain/core/indexer.py:1-40
2. 加载与分块
Indexer 根据路径扩展名从 Loader 注册表中选择合适的加载器,目前内置 TextLoader 用于 .md / .txt 等纯文本。文本随后进入 chunk_text():它首先按双换行切分为段落,再以"段优先 + 字符窗口回退"的贪心策略在 chunk_size(默认 1000)内累积;若某段超出窗口,则按 chunk_size - overlap 步长切分。最后,相邻分块会拼接前一个分块的尾部 overlap(默认 150 字符),形成"重叠上下文",保证检索时不会在块边界丢失语义。
# 摘自 src/localbrain/core/chunking.py
step = max(1, size - overlap)
for i in range(0, len(p), step):
chunks.append(p[i:i + size])
资料来源:src/localbrain/core/loaders/registry.py:1-15、src/localbrain/core/chunking.py:1-40
3. 嵌入与持久化
每个分块经 EmbeddingProvider.embed_texts() 编码为向量。Indexer.apply() 会以流式方式(yield 进度事件)依次处理删除、新增和修改三类目标:先调用 VectorStore.delete_documents() 清理旧向量,再写入新向量与元数据,最后在 FileIndex 中登记新哈希与 chunk_ids。VectorStore 内部按 model_id 命名规则拆分 docs__<tag> 与 queries__<tag> 两个 Chroma 集合,并使用 cosine 距离空间——这样切换嵌入模型时不会出现"新旧向量混合"的数据污染问题。
资料来源:src/localbrain/core/indexer.py:30-50、src/localbrain/core/store.py:1-40
嵌入 Provider 注册表
make_provider() 采用字符串查表 + 懒加载(lazy import)的策略,把 provider 实现与业务解耦。当前内置三种实现:
| Provider 名称 | 后端 | 适用场景 |
|---|---|---|
fastembed | Qdrant 出品的本地 ONNX 推理 | 默认选项,零额外服务 |
ollama | 调用本地 Ollama HTTP /api/embeddings | 已部署 Ollama 的环境 |
sentence-transformers | HuggingFace transformers | 需要自定义/实验性模型 |
例如 OllamaProvider 直接通过 urllib.request 与 http://localhost:11434/api/embeddings 通信,并以 ollama:<model> 作为 model_id 写入向量库标签。注册表还接受 fp16 参数用于推理精度控制。
资料来源:src/localbrain/core/embed/registry.py:1-20、src/localbrain/core/embed/ollama_provider.py:1-30
与上层服务的耦合
核心引擎并不直接处理用户请求——它通过 IndexingService / InsightsService 等服务类与适配器对接。例如,MCP 适配器在 mcp_server.py 中通过 AppContext 拿到 IndexingService 后,将其 add_path() / remove_source() 方法注册为 @mcp.tool() 工具;InsightsService.report() 则把质询日志聚类为 FAQ 与知识空缺报告。这种"core 决定能力边界,adapters 决定暴露方式"的分层让 CLI 与 Web 也能复用同一套索引语义。
资料来源:src/localbrain/adapters/mcp_server.py:1-30、src/localbrain/services/insights_service.py:1-15
常见失败模式
- 嵌入模型未下载:
fastembed首次使用会从 HuggingFace 拉取模型权重,需保持网络可达;CHANGELOG.md指出 0.1.1 已将模型加载改为 lazy,从而保证 MCP 握手不被阻塞。 - 路径 glob 不匹配:
add_path默认*.md,*.txt,若文件夹内全是.pdf等无内置 loader 的类型,is_supported()会返回None,导致整条路径被静默跳过。 - Windows 控制台编码:0.1.1 之前的版本在 cp949 终端输出韩文/em-dash 时会崩溃,升级至 0.1.1 后已强制 UTF-8。
- 向量库分集合未隔离:若手动修改
model_id字符串,建议先备份chroma/目录,避免误把不同维度的向量写入同一集合。
资料来源:CHANGELOG.md:0.1.1、src/localbrain/core/loaders/registry.py:1-15
See Also
- 核心引擎:搜索与重排
- 核心引擎:嵌入与运行时
- 适配器:MCP / CLI / Web
- 数据模型:Source / FileRecord / ChangeSet
搜索、重排序与洞察
Localbrain 的"搜索 · 重排序 · 洞察"三大能力位于 core 层,并由 services 层包装后通过 adapters 暴露给 MCP / CLI / Web 三类入口。组装这一切的是 AppContext——它读取 Config、构造嵌入 provider、向量存储、文件索引以及搜索器、reranker、洞察对象,是唯一的"组合根"。
继续阅读本节完整说明和来源证据。
1. 模块定位与职责切分
Localbrain 的"搜索 · 重排序 · 洞察"三大能力位于 core 层,并由 services 层包装后通过 adapters 暴露给 MCP / CLI / Web 三类入口。组装这一切的是 AppContext——它读取 Config、构造嵌入 provider、向量存储、文件索引以及搜索器、reranker、洞察对象,是唯一的"组合根"。
flowchart LR
A[adapter: MCP/CLI/Web] --> B[services: SearchService / IndexingService / InsightsService]
B --> C[core: Searcher / Indexer / Insights]
C --> D[(VectorStore + SQLite file_index/queries)]
C --> E[EmbeddingProvider]
C --> F[make_reranker → cross-encoder]
style C fill:#eef
style F fill:#fee资料来源:src/localbrain/context.py:1-40
2. 搜索与重排序流程
Searcher 负责从 VectorStore 中拉取候选,再(可选)交给 make_reranker 工厂返回的 reranker 重排。make_reranker 是一个懒加载的注册表,根据配置选择实现(如 cross_encoder),未配置时关闭该阶段以节省资源。CLI 提供 --no-rerank 开关用于对比实验,资料来源:src/localbrain/adapters/cli.py:17;服务侧在 SearchService 中统一封装。
MCP 端 @mcp.tool() search 直接暴露给 LLM,签名仅三参:
| 参数 | 类型 | 作用 | |
|---|---|---|---|
query | str | 自然语言问题 | |
k | int = 5 | 返回条数 | |
path_prefix | `str \ | None` | 限定到某子目录 |
资料来源:src/localbrain/adapters/mcp_server.py:21-24
Searcher 在拉取候选时还会把本次查询写入 queries 表(id / text / ts / hit / top_score),这是后续洞察分析的"原始数据"。资料来源:src/localbrain/core/db.py:21-26
3. 索引与候选的"源头"——增量更新
搜索的候选集合由 Indexer.apply() 维护:它对 ChangeSet.new / modified 跑"加载→分块→嵌入→存储"流水线,对 ChangeSet.deleted 调用 store.delete_documents 同步清理,保证向量库与 file_index 一致。资料来源:src/localbrain/core/indexer.py:36-50
IndexingService 暴露 add_source / remove_source / list_sources / run 四个用例:remove_source 会先把该源下所有 chunk 从向量库中删除,再删除 file_index 记录和 sources 行。资料来源:src/localbrain/services/indexing_service.py:13-29
4. 洞察:FAQ 聚类与知识空缺报告
InsightsService 是 Insights 的薄包装,对外仅暴露 report(min_similarity, gap_score),内部委托给 self._ctx.insights.cluster(...)。资料来源:src/localbrain/services/insights_service.py:9-13
cluster 把 queries 表中的历史问句做相似度聚类:
- FAQ 候选:达到
min_similarity的簇被认为在反复问同一类问题,可整理成标准答案。CLI 默认阈值0.80,资料来源:src/localbrain/adapters/cli.py:21。
这套设计让"知识是否够用"成为可观测信号,而不是凭感觉。资料来源:src/localbrain/core/insights.py、src/localbrain/core/clustering.py
5. 失败模式与排查要点
| 症状 | 根因 | 处置 |
|---|---|---|
| 搜索召回为空 | 嵌入模型已换但未重建 | index --rebuild 重建向量库 |
| 召回相关但顺序差 | 未启用 reranker 或模型缺失 | 检查 make_reranker 配置,或临时 --no-rerank 验证 |
| 洞察报告簇很少 | min_similarity 设得过高 | CLI/服务调低至 0.7 试运行 |
MCP search 报缺工具 | stdio 客户端未指向 mcp_server | 在 Connection 面板核对入口 |
资料来源:src/localbrain/services/indexing_service.py:31-50、src/localbrain/adapters/mcp_server.py:21-30
See Also
- 架构总览与组合根
- 嵌入与运行时
- MCP 接入指南
适配器、配置与部署
Localbrain 采用清晰的三层结构:core (领域核心) → services (业务编排) → adapters (对外接口)。adapters/init.py 中明确说明 "adapters — MCP / CLI / Web. core·services 위의 얇은 진입점",即适配器是位于核心之上的"薄入口"层,仅负责协议转换与参数解析,不承载业务逻辑 资料...
继续阅读本节完整说明和来源证据。
1. 适配器层在整体架构中的位置
Localbrain 采用清晰的三层结构:core (领域核心) → services (业务编排) → adapters (对外接口)。adapters/__init__.py 中明确说明 "adapters — MCP / CLI / Web. core·services 위의 얇은 진입점",即适配器是位于核心之上的"薄入口"层,仅负责协议转换与参数解析,不承载业务逻辑 资料来源:src/localbrain/adapters/__init__.py:1-1。
目前仓库提供三种适配器入口,覆盖了本地知识库与外部 AI 工具的所有典型交互场景:
- MCP 适配器 (src/localbrain/adapters/mcp_server.py):基于
mcp.server.fastmcp.FastMCP实例FastMCP("localbrain"),通过 stdio 与 Claude Code 等兼容客户端直连,对外暴露search、add_path、remove_path等工具函数 资料来源:src/localbrain/adapters/mcp_server.py:1-15。 - CLI 适配器 (src/localbrain/adapters/cli.py):使用
argparse注册子命令,面向脚本化与运维场景。 - Web 适配器 (src/localbrain/adapters/web/__init__.py):FastAPI 后端 + 静态单页,提供可视化控制台。
所有适配器共享同一个 AppContext(定义于 src/localbrain/context.py),构造时即初始化 services,因此各协议层看到的"业务能力"完全一致 资料来源:src/localbrain/context.py:1-15。
flowchart LR
A[MCP stdio 客户端] --> B[adapters/mcp_server.py]
C[终端 / 脚本] --> D[adapters/cli.py]
E[浏览器] --> F[adapters/web]
B --> G[AppContext]
D --> G
F --> G
G --> H[services/*]
H --> I[core/*]2. CLI 命令矩阵
adapters/cli.py 通过 parser.add_subparsers 注册了完整的命令行表面。下表汇总了各子命令的关键参数与用途 资料来源:src/localbrain/adapters/cli.py:1-50:
| 子命令 | 关键参数 | 默认值 | 作用 |
|---|---|---|---|
add-source | path, --globs, --no-recursive | --globs=*.md,*.txt | 注册索引源 |
list-sources | — | — | 列出已注册源 |
index | --source-id, --rebuild | 全量源 | 增量 / 全量索引 |
search | query, -k, --path-prefix, --no-rerank | k 来自 config | 语义检索 |
stats | — | — | 索引状态 |
insights | --min-similarity | 0.80 | 知识图谱 / FAQ 报告 |
index --rebuild 会清空 file_index 中对应源的全部记录并触发全量重建,常用于"模型更换"后向新集合回填数据 资料来源:src/localbrain/services/indexing_service.py:1-30。
3. 配置系统
AppContext.__init__ 是唯一的"组合根"(composition root),它从 Config.load() 读取配置,并据此物化所有依赖 资料来源:src/localbrain/context.py:1-30:
- 嵌入 Provider:
make_provider(config.embedding.provider, model, fp16),通过字符串名路由到具体实现。core/embed/registry.py支持fastembed、ollama、sentence-transformers三家 资料来源:src/localbrain/core/embed/registry.py:1-20。 - 持久层:
connect(config.db_path)创建 SQLite 连接,启用journal_mode=WAL并预建sources、file_index、queries三张表 资料来源:src/localbrain/core/db.py:1-30。 - 向量库:
VectorStore(config.chroma_dir, provider.model_id)将 Chroma 集合与嵌入模型 ID 绑定,便于后续按模型隔离。 - 索引流水线:
scanner与indexer在此装配,indexer.apply(source, cs)是load → chunk → embed → store + file_index 刷新的单职责入口 资料来源:src/localbrain/core/indexer.py:1-20。
4. 部署与典型运行模式
由于三种适配器共享同一 AppContext,部署方式可以按使用场景灵活切换:
- 本地 MCP 模式:
python -m localbrain.adapters.mcp_server启动 stdio 进程,Claude Code 等客户端通过 MCP 协议调用search/add_path工具,从而将本地文档接入大模型 资料来源:src/localbrain/adapters/mcp_server.py:1-30。 - CLI 模式:
python -m localbrain.adapters.cli <subcmd>适合定时任务、CI 中的批量索引与检索。 - Web 模式:
adapters/web暴露 FastAPI + 浏览器控制台,便于人工浏览索引状态、添加源与查看洞察。
README.md 给出的标准流程是:选择文件夹 → 等待进度条 100% → 自然语言搜索 → 在连接面板中管理 MCP 客户端;其强调 "Your data remains on your machine" 与 "It uses local models" 资料来源:README.md:1-50。当 embedding.provider 选择 ollama 或 fastembed 时,整条链路(嵌入、检索、问答)均可在离线环境内完成,符合本地优先的部署哲学。
See Also
- README.md — 项目概览与使用流程
src/localbrain/core/indexer.py— 索引管线的单职责实现src/localbrain/services/insights_service.py— FAQ 聚类与知识图谱入口
来源:https://github.com/Tamariskwhisper962/Localbrain / 项目说明书
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
风险会影响是否适合普通用户安装。
Pitfall Log / 踩坑日志
项目:Tamariskwhisper962/Localbrain
摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:配置坑 - 可能修改宿主 AI 配置。
1. 配置坑 · 可能修改宿主 AI 配置
- 严重度:medium
- 证据强度:source_linked
- 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
- 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
- 证据:capability.host_targets | https://github.com/Tamariskwhisper962/Localbrain | host_targets=mcp_host, claude
2. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 证据:capability.assumptions | https://github.com/Tamariskwhisper962/Localbrain | README/documentation is current enough for a first validation pass.
3. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 证据:evidence.maintainer_signals | https://github.com/Tamariskwhisper962/Localbrain | last_activity_observed missing
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 证据:downstream_validation.risk_items | https://github.com/Tamariskwhisper962/Localbrain | no_demo; severity=medium
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 证据:risks.scoring_risks | https://github.com/Tamariskwhisper962/Localbrain | no_demo; severity=medium
6. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 证据:evidence.maintainer_signals | https://github.com/Tamariskwhisper962/Localbrain | issue_or_pr_quality=unknown
7. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 证据:evidence.maintainer_signals | https://github.com/Tamariskwhisper962/Localbrain | release_recency=unknown
来源:Doramagic 发现、验证与编译记录