手搓LLM Wiki知识库(二):文件系统就是数据库 系列第二篇。本篇讲知识库的目录结构设计和文档格式规范。手搓LLM Wiki 知识库一知识库是什么为什么要自己写你是不是也一上来就想选数据库——PostgreSQL、MongoDB、还是直接上向量库你有没有想过这条路其实很容易走偏数据库是实现细节不是起点。在你还没想清楚「知识长什么样」之前就选数据库等于在没有蓝图时先买建材。那么真正的问题来了你的知识放在文件系统里够用吗答案是对于个人知识库完全够用。而且文件有数据库给不了的优势用任何编辑器都能打开、修改Git 天然支持版本控制和协作出了问题直接看文件不需要查询语句数据库挂了知识还在索引只是加速工具这就是 WikiLoop 的核心设计哲学文件是 source of truth数据库只是索引。索引可以随时删除重建但你的知识不能丢。 目录结构设计知识库根目录长这样my-kb/ ├── raw/ ← 原始文件只读source of truth │ ├── articles/ │ ├── papers/ │ └── converted/ ← 二进制文件转换后的文本自动生成 ├── wiki/ ← LLM 蒸馏出的结构化知识自动维护 │ ├── source-notes/ ← 每篇原始文章的知识提炼 │ ├── concepts/ ← 跨文章提炼的核心概念 │ ├── comparisons/ ← 方案对比 │ └── decisions/ ← 选型决策记录 ├── schema/ ← 知识库本地规则可选 └── index/ └── kb.sqlite ← 全文搜索索引自动生成可删除重建三层模型每层职责清晰raw/用户放进来的原始材料。PDF、Word、Markdown、网页存档都可以。这层只有人类在写程序只读不写。wiki/LLM 从 raw/ 里提炼出的结构化知识。这层由程序自动维护也可以人工编辑。wiki/ 里的内容必须引用 raw/ 里的来源不能凭空创造。schema/知识库的本地规则比如「这个知识库专门收集 Go 语言相关内容蒸馏时用中文输出」。可以没有WikiLoop 有合理的默认行为。这个分层的好处raw/ 出问题不影响 wiki/wiki/ 删掉可以重建index/ 随时可以丢弃。三层互相独立各司其职。 四种知识页面类型wiki/ 里的文件不是随便写的 Markdown而是按用途分成四种类型source-note一篇原始文章对应一个 source note。提炼这篇文章的核心观点、关键结论、重要术语。一对一关系。concept跨多篇文章提炼的核心概念。比如「混合检索」这个概念可能在十篇文章里都提到把分散的内容聚合成一个权威定义页。comparison方案对比页。「向量数据库 A vs B」、「方案 X vs 方案 Y」把对比信息从多个来源汇总到一处。decision选型决策记录。「为什么我们选择 SQLite 而不是 PostgreSQL」记录决策背景、考量因素、最终选择和理由。这类页面特别有价值——六个月后你一定会忘记当时为什么这么选。这四种类型不是随意定义的它们对应了知识使用的四种场景查原文source-note、理解概念concept、做选择comparison、回溯决策decision。 OKF frontmatter 规范每个 wiki 页面都有 YAML frontmatter定义了这个页面的元数据。我们遵循OKF v0.1Open Knowledge FormatGoogle Cloud 发布的知识文档格式规范这样知识库可以被任何兼容 OKF 的工具消费。四种页面类型的 frontmatter 模板source-notetype:source-notetitle:description:# 一两句话摘要包含关键技术术语tags:[]# 3-6 个领域分类标签不是随机关键词doc_type:# 技术文章 | 白皮书 | 技术规范 | 开源项目 | ...authority:3# 1-5信息权威度sources:-raw/articles/xxx.mdtimestamp:# ISO 8601文章发布日期不是导入日期key_claims:[]# 5-8 条核心主张包含同义词扩展related_to:[]# 只填已存在的 wiki/ 路径concepttype:concepttitle:description:tags:[]sources:-wiki/source-notes/xxx.mdtimestamp:comparison和decision结构类似type字段对应改成comparison/decision。几个需要特别注意的设计key_claims的 ALIAS RULE每条主张必须把所有已知的同义词、缩写、中英文等价词内联进去。比如不能写「FTS 检索效果好」要写「FTSFull-Text Search全文检索BM25检索配合 RRF倒数排名融合合并结果效果好」。这样无论你用什么词搜索都能命中这条记录。authority权威度1-5 分制。官方文档、论文是 5 分大厂技术博客是 4 分有数据支撑的深度技术文章是 3 分转述他人工作的文章是 2 分纯观点营销文章是 1 分。搜索排序时权威度高的结果会获得加权。related_to只填已存在的路径这是防止 LLM 幻觉的关键约束。蒸馏时 LLM 很容易凭空写出不存在的文档路径。我们在 prompt 里明确要求如果不确定某个路径是否存在就留空。知识图谱的边必须指向真实存在的节点。timestamp用文章发布日期不是文件创建日期不是导入日期是原始文章的发布日期。这样知识库能感知内容的时效性——2022 年的技术文章和 2026 年的技术文章在快速演进的领域里价值是不同的。️ 文件命名约定raw/ 下的文件按来源分目录命名随意保持原始文件名即可。wiki/ 下的文件命名有规范用连字符分隔的英文小写反映内容主题而不是原始文章标题。比如wiki/source-notes/sqlite-fts5-full-text-search-guide.md wiki/concepts/hybrid-search.md wiki/comparisons/sqlite-vs-postgresql-for-local-kb.md wiki/decisions/why-go-not-python.md这个命名方式有个实际好处文件名本身就是一个可搜索的路径related_to字段里的路径一眼就能看出内容。 index.mdOKF 目录页OKF 规范里index.md是保留文件名每个目录下可以有一个index.md作为该目录的导航页。WikiLoop 在每次索引完成后自动生成okf_version: 0.1 # wiki * [concepts](concepts/) — 12 pages * [comparisons](comparisons/) — 8 pages * [decisions](decisions/) — 5 pages * [source-notes](source-notes/) — 47 pages这个文件不需要手动维护重建索引时自动覆盖。它的作用是让你或你的 Agent 快速了解知识库的全貌不需要扫描整个目录树。⚙️ Go 实现思路用 Go 处理这套目录结构核心是两件事解析 frontmatter。Go 生态里处理 YAML frontmatter 的思路是用---分隔符把 frontmatter 和正文分开frontmatter 部分用gopkg.in/yaml.v3解析成结构体正文部分保留原始 Markdown。设计一个Document结构体对应 frontmatter 的字段再加上Path、Content、Layer等运行时字段。解析函数读取文件按---分割分别处理两部分。遍历目录。用filepath.WalkDir扫描 raw/、wiki/、schema/ 三个目录对每个.md文件调用 frontmatter 解析跳过index.md和log.mdOKF 保留文件。这两个操作是整个知识库的基础后续的索引、搜索、蒸馏都建立在这层之上。有一个值得注意的地方frontmatter 解析必须容忍错误。用户手写的文件可能 frontmatter 格式不规范解析失败不应该让整个索引流程崩溃记录警告继续处理下一个文件。 小结文件是 source of truth数据库只是索引索引可以随时重建三层目录raw/原始、wiki/提炼、schema/规则四种页面类型覆盖四种知识使用场景OKF v0.1 frontmatter 规范type、title、description、tags、timestamp、key_claimsALIAS RULE同义词内联到 key_claims让 FTS 搜索覆盖所有查询角度related_to只填已存在路径防止知识图谱出现幻觉边 下篇预告下一篇我们讲如何用 Go 解析 frontmatter、遍历目录树开始动手搓代码。