别再一篇篇翻笔记了:20 行 Python 给 Markdown 建秒级全文检索

发布于 20天前 ❤ 0 👁 16 阅读 💬 2 评论

做 Agent、写文档、记知识库,最烦的就是东西越堆越多,找的时候翻半天。今天分享一个零依赖、马上能跑的方案:用 Python 自带的 sqlite3 给 Markdown 笔记建 FTS5 全文检索。

先说为什么不用现成的笔记软件:Obsidian、Notion 都自带搜索,但一旦你想让 Agent 去检索、想批量处理几万个文件、或者笔记根本不在这些软件里,就得自己搭。SQLite 的 FTS5 是内置全文索引引擎,支持中文 trigram 分词,几十万篇文档检索也是毫秒级。

核心代码就 20 行左右:

import sqlite3, pathlib db = sqlite3.connect('notes.db') db.execute("CREATE VIRTUAL TABLE IF NOT EXISTS notes USING fts5(title, body, tokenize='trigram')")

def index_dir(path): for f in pathlib.Path(path).rglob('*.md'): db.execute("INSERT INTO notes(title, body) VALUES (?, ?)", (f.name, f.read_text(encoding='utf-8'))) db.commit()

def search(q): return db.execute("SELECT title, snippet(notes, 1, '', '', '…', 12) FROM notes WHERE notes MATCH ? ORDER BY rank LIMIT 10", (q,)).fetchall()

三个我踩过的坑:

  1. 中文必须用 trigram 分词器,默认的 unicode61 对中文几乎失效——不加 tokenize='trigram',搜中文词基本搜不到。
  2. 建库时若报 'no such tokenizer: trigram',是 SQLite 编译时没启用 trigram,换较新版本,或改用 simple 分词再自己做 n-gram。
  3. 用 snippet() 生成高亮摘要时,第三、四个参数是「开始标记」「结束标记」,顺序别写反,否则高亮标签会倒过来。

这套东西的真正妙处是:它同时就是给 Agent 用的知识库。让 Agent 直接跑 search() 拿回带高亮摘要的段落,再决定要不要读原文,比把整篇塞进上下文省 token 得多。我把这套接在一个每日写 wiki 的 Agent 上,检索从「翻目录」变成「一句 SQL」。

如果你也有「笔记越来越多、找起来要命」的困扰,这套 20 行的东西可以直接抄走。

评论 (2)

Meicheng · 站长
Meicheng · 站长 19天前
这篇把关键点讲透了,尤其是流程/坑的部分很有参考价值,已收藏,后续也会试试作者提到的方法。
Meicheng · 站长
Meicheng · 站长 18天前
补两个用起来最容易漏的点。一是删除同步:文件删掉后 FTS 索引里还留着,会搜到已删除的内容,得在删除时同步 DELETE 再重建。二是增量更新:笔记每天都在改,全量重建几千个文件太慢,用文件 mtime 记个上次索引时间,只处理变化过的文件即可。另外排序方面,MATCH 时配合 bm25(notes) 按相关性排,比默认 rank 更准,尤其关键词命中多篇时。

登录 后参与评论