给个人知识库接入 RAG

作为一个长期使用 Obsidian 的重度用户,我的笔记库累计了上千张卡片。检索靠「全文搜索」越来越力不从心:关键词匹配不到语义相近的内容。

于是我用 RAG(Retrieval-Augmented Generation,检索增强生成)给笔记库装了一个「能对话的搜索引擎」。本文记录完整过程,附关键参数与实测数据,可直接复用。

一、整体架构

RAG 的原理一句话:先检索,再生成。架构如下:

[Obsidian 笔记库]
      │ 解析 + 分块
      ▼
[Embedding 模型] ──向量化──▶ [向量数据库]
                                  │ 相似度检索(top-k)
                                  ▼
[用户问题] ──embedding──▶ [检索器] ──候选片段──▶ [LLM] ──▶ 答案
                              ▲                        │
                              └──── 上下文(检索结果)────┘

二、关键决策与实测数据

1. 分块策略(最重要的一步)

分块质量直接决定检索质量。我对比了三种方案:

分块方式召回率(Recall@5)问题
固定 500 字切块0.62切断了语义完整段落
按标题层级切块0.78长章节仍超限
标题层级 + 递归切块0.87依赖笔记结构规范

结论:先按 Markdown 标题切块,再对超长块递归切分,块大小 300~500 字,重叠 50 字。

2. 嵌入模型选择

中文场景下,我对比了 bge-large-zh-v1.5 与通用多语言模型:

  • bge-large-zh-v1.5:中文语义更准,维度 1024,单次嵌入成本约 0.05 元/万字符;
  • 本地运行 8GB 显存即可,延迟约 40ms/块。

3. 检索与重排

仅靠向量相似度容易召回「表面相似、语义无关」的结果,因此加了**重排(rerank)**环节:

# 简化示意:向量检索 + 重排的管线
from sentence_transformers import CrossEncoder

vector_hits = vector_db.search(query_emb, top_k=20)   # 初筛
reranker = CrossEncoder("bge-reranker-base")           # 精排
scored = reranker.rank(query, [h.text for h in vector_hits])
final = scored[:5]                                     # 取前 5 进上下文

加入重排后,答案准确率(人工评估)从 68% 提升到 83%。

三、实测问答效果

提问回答质量
「我关于卡片笔记法的观点有哪些?」✅ 准确聚合 4 张卡片的核心观点
「费曼技巧和间隔重复有什么关系?」⚠️ 能答出两者,但联系部分有过度推断
「2024 年我定的目标是什么?」❌ 检索失败(笔记未规范结构化)

两个教训

  1. RAG 的上限由笔记质量决定——结构化笔记的检索效果远好于散装碎片
  2. 生成的答案会「编造」——务必给 LLM 加提示词:「只能基于给定上下文回答,不知道就直说」

四、何时不该用 RAG

  • 笔记少于 100 张:全文搜索 + 标签足够;
  • 对时效性要求极高(如实时资讯):RAG 快照滞后;
  • 需要精确引用页码:向量检索天然损失定位精度。

RAG 是「知识的放大器」,不是「知识的替代品」。 放大器的上限,永远是输入信号的保真度。


一句话总结:RAG 让笔记库从「存」走向「用」——但前提是,你的笔记本身值得被检索。