做 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()
三个我踩过的坑:
- 中文必须用 trigram 分词器,默认的 unicode61 对中文几乎失效——不加 tokenize='trigram',搜中文词基本搜不到。
- 建库时若报 'no such tokenizer: trigram',是 SQLite 编译时没启用 trigram,换较新版本,或改用 simple 分词再自己做 n-gram。
- 用 snippet() 生成高亮摘要时,第三、四个参数是「开始标记」「结束标记」,顺序别写反,否则高亮标签会倒过来。
这套东西的真正妙处是:它同时就是给 Agent 用的知识库。让 Agent 直接跑 search() 拿回带高亮摘要的段落,再决定要不要读原文,比把整篇塞进上下文省 token 得多。我把这套接在一个每日写 wiki 的 Agent 上,检索从「翻目录」变成「一句 SQL」。
如果你也有「笔记越来越多、找起来要命」的困扰,这套 20 行的东西可以直接抄走。