试过 Obsidian 的标签体系、Notion 的数据库、Logseq 的 graph view,最后发现:知识库的最大敌人不是容量,是维护摩擦。
为什么不做"完美知识库"?
我曾经是一个"知识管理完美主义者"。
尝试 1:Obsidian + 标签体系 + 双向链接
每个笔记文件:
- 标签:#python #async #bug-fix #2026-06
- 链接:[[python-async]] [[common-bugs]]
- 元数据:create_date, last_modified, status, project
结果:三个月后标签体系崩溃了。#python 和 #Python 是两个标签,#bug-fix 和 #bugfix 也是。双向链接变成死链接(文件删了链接还在)。维护成本爆炸,写一条笔记要先想该打什么标签——思考的 friction 超过了记忆的 friction。
尝试 2:Notion 数据库 + 多字段
数据库字段:标题、类型(6 种)、标签(多选)、项目、优先级、状态、来源、日期、附件、笔记
结果:90% 字段闲置。每次新建记录,11 个字段只填 2-3 个,其余空着。Notion 还要求你手动选"类型"、拖"优先级"——录入摩擦太高,最后只记录了 30 条就放弃了。
核心洞察
知识管理的杠杆 = 写入 × 重读,不是字段数。
如果写入摩擦太高,你就不写。如果字段太多、标签太复杂,你就不维护。极简设计 = 更低的维护摩擦 = 更长的生命周期。
QPC 的 4 字段设计哲学
我的 QPC(Question / Practice / Concept)知识库现在有 199 条记录,只用 4 个字段:
| 字段 | 类型 | 作用 |
|---|---|---|
| 个人知识类型 | 枚举 {问题Q, 实践P, 事实C} | 强制你思考这条知识的本质 |
| 标题 | 单行文本(≤50字) | 强制提炼核心结论 |
| 原始记录 | 长文本(Markdown) | Self-contained,不依赖外部 |
| 状态 | 枚举 {已整理, 待整理} | 最简单的进度标记 |
类型(Q/P/C):强制你分类
- 问题Q:有疑问、待研究的话题(如"Azure 免费额度怎么薅?")
- 实践P:具体操作步骤、踩坑经验(如"new-api 改 systemd 绑定 localhost")
- 事实C:客观知识、结论性内容(如"Skill 路由比 ReAct 控制器更适合个人助理")
为什么只有 3 种? 因为 3 种就够了。类型不是给你做分类学的,是在写入那一刻逼你回答:“这条知识到底是什么?” 如果答不上来,说明你还没想清楚,不该存。
标题(≤50字):强制提炼
不能超过 50 字。这是 schema 的限制,也是设计——如果你无法用 50 字说清楚一条知识的核心,说明你还没理解它。
❌ "关于飞书 Bitable API 的 filter 参数不支持中文字段名的那件事"
✅ "飞书 Bitable filter API 不支持中文字段名"
原始记录(Self-contained):不依赖外部
这是一条铁律:每条记录必须独立可读,不依赖任何文件、链接、外部系统。
“QPC is not a knowledge management tool — it is an intellectual identity store / second brain.” “临时文件会被清理,QPC 必须跨机器存活。内容 inline 是唯一永久方案。”
❌ 原始记录 = "详见 /home/caozuohua99/workspace/notes/vps-hardening.md"
❌ 原始记录 = "file:///tmp/idea-035.md"
✅ 原始记录 = "### VPS 三层防御架构\n\n1. GCP Firewall..."
状态(已整理/待整理):最简单的进度
只有两种状态。不是因为不需要更多状态,是因为两种够了——要么你整理完了,要么没有。
为什么不做标签?
这是被问到最多的问题。
标签的熵增问题
标签体系用三个月后就会出现:
- 同义词:
#pythonvs#Pythonvs#py - 层级混乱:
#docker和#docker-compose是平级还是父子? - 定义漂移:
#agent最初指 AI Agent,后来也指 Agent 模式、ReAct Agent… - 密度不均:
#python有 80 条,#obsidian-plugin有 1 条
维护标签体系的认知负担 > 直接全量搜索的负担。
全量 grep < 0.1s
199 条记录全量拉取约 2 秒,内存搜索 < 0.1 秒。不需要索引,不需要标签,grep 就够了。
# 搜索 "所有关于 VPS 的安全实践"
matches = [r for r in all_records
if 'VPS' in r['原始记录'] and r['个人知识类型'] == '实践P']
# 24 条,0.03 秒
如果将来记录数增长到 2000+,可以考虑 SQLite FTS5。我的小样本测试里,中文短文本场景下 FTS5 trigram 相比 LIKE 没有稳定优势;真正需要索引前,应该先用自己的数据重新压测。
为什么不存文件路径?
这是另一个高频问题:“为什么不在 QPC 里存 ‘见 notes/xxx.md’,这样省空间?”
因为 VPS 上的文件会被清理。
我经历过多次:
- VPS 迁移 → 旧路径失效
- 磁盘清理 → 临时笔记被删
- 云服务回收 → 数据库清空
QPC 是 intellectual identity store——它存储的是你的知识身份,必须跨机器、跨 session 永久存活。内容 inline 是唯一方案。
QPC 与 Agent Memory 的分工
这是我设计分层记忆体系时的核心思考:
| 层级 | 存储 | 生命周期 | 容量 |
|---|---|---|---|
| 当前对话 | Context | 单次对话 | ~100K |
| Memory | memory.db | 跨 session | ~200条 |
| QPC | Lark Bitable | 永久 | 无限制 |
类比:
- 当前对话 = 草稿纸(随时擦)
- memory.db = 笔记本(定期整理)
- QPC = 论文笔记(永久保存)
“Agent memory 是短期工作记忆,QPC 是长期 durable knowledge。QPC 不是聊天日志、不是任务列表、不是临时草稿。”
什么该进 QPC?
✅ 有明确结论的技术验证("FTS5 中文性能不优于 LIKE")
✅ 有实测数据支撑的原理性结论
✅ 将来写代码/做决策时会被引用的经验
✅ 自研项目的架构设计(即使项目已停止)
❌ 纯聊天问答("B+Tree 是什么")
❌ 一次性配置参数(临时端口号、测试 IP)
❌ 已经被替代的旧信息("旧的 APP_ID 是 xxx")
实操:如何从零搭建你的 QPC
选择存储介质
我推荐三种方案,按复杂度递增:
方案 A:单 Markdown 文件(适合 < 50 条)
## 实践P | 飞书 Bitable 不支持中文 filter | 已整理
飞书 Bitable API 的 filter 参数对中文字段名完全不...
方案 B:飞书 Bitable(我现在的方案,适合 50-500 条)
- 优点:跨设备、支持多字段、API 可编程
- 缺点:需要飞书机器人凭证
方案 C:自建 SQLite(适合完全离线)
- FTS5 trigram 分词 + LIKE 兜底
- 中文场景 FTS5 和 LIKE 性能差不多
设计你的 4 字段
你可以改字段名,但保持 4 个:
| 我的设计 | 你可以改成的 |
|---|---|
| 个人知识类型 | 类型 / Category / 分类 |
| 标题 | Title / 主题 / 结论 |
| 原始记录 | 内容 / Content / Body |
| 状态 | 进度 / Status |
关键是:不能超过 4 个。 字段越多,写入摩擦越高,放弃越早。
写入第一条
不要等到"设计好了"再写。直接写第一条:
类型:事实C
标题:QPC 知识库只需要 4 个字段
原始记录:QPC 采用极简 4 字段设计(类型/标题/内容/状态),
因为知识管理的主要敌人是维护摩擦而非存储容量...
状态:已整理
定期审计
我每季度做一次审计,按 4 分类处理:
- 删:空标题 / 内容 < 10 字 / 测试残留
- 改:描述已删项目的 → 加归档标记
- 裁:标题 > 50 字 → 重写更短
- 留:没事实错误的不动
最近一次审计(2026-06):199 条中删了 2 条低质量,其余没动。
总结:少即是多
知识管理的杠杆 = 写入 × 重读,不是字段数。
QPC 的核心设计原则:
- 3 种类型(Q/P/C)— 写入时逼你思考本质
- 50 字标题 — 强制提炼核心结论
- Self-contained — 不依赖外部,永久可读
- 2 种状态 — 最简进度追踪
- 不做标签 — grep 全量搜索够用了
- 不存路径 — VPS 文件会消失
这套设计支持我从 0 到 199 条记录,两年内没有经历过任何"标签体系崩溃"或"字段爆炸"。
如果你的知识库总是在 30 条左右就放弃,可能不是你的问题,是字段太多了。