---
id: 6aa43f2c0d91f4fb1191641b
title: LLM Wiki 云端知识库的技术实现
parentId: 6aa43f2c0d91f4fb11916419
rootId: 6aa43f2c0d91f4fb1191640f
author: craboy
createdAt: 2026-08-26T19:26:24.471Z
updatedAt: 2026-10-06T03:01:02.239Z
---

# LLM Wiki 云端知识库的技术实现

### —— 从卡帕西的理念到多租户服务

> 2026 年 4 月，Andrej Karpathy 发布了一个被称为 "LLM Wiki"（或 "LLM Knowledge Bases"）的模式。它不是一个软件，而是一套关于人类与 LLM Agent 如何分工维护知识的**约定**。本文先讲清楚这套理念，再以我们自己的一个云端实现（llm-wiki，部署在多租户 SaaS 平台 2Ryun 上）为主线，展示把「本地 markdown 文件夹」升级成「云端多租户知识库服务」时，工程上会遇到什么、又是怎么解决的。

---

## 一、引言：卡帕西的 LLM Wiki 理念

Karpathy 的核心比喻一句话概括：**「Obsidian 是 IDE，LLM 是程序员，wiki 是代码库。」**

传统上我们让 LLM 帮忙「检索」知识——问一个问题，现场从一堆文档里捞相关的片段拼答案（也就是 RAG）。Karpathy 认为这等于**每次运行程序都重新读一遍源码**。他说：你不会在每次运行程序前重读所有代码，而是**编译一次**，把成本摊到整个生命周期。知识也应该如此：**在入库时就把杂乱材料「编译」成一份结构化、互相链接的 wiki，之后随取随用，而不是每次查询都从头现算。**

这套模式有三层结构、三个操作：

**三层结构**

| 层 | 内容 | 谁写 |
| --- | --- | --- |
| `/raw` | 不可变的原始文档、文章、论文 | 人类（只读，Agent 绝不修改） |
| `/wiki` | LLM 维护的 markdown 页面：实体页、概念页、综合页 | 只有 Agent 写 |
| schema（如 `agents.md` / `CLAUDE.md`） | 用自然语言约定结构、规范、工作流 | 人类设计 |

两个辅助文件让系统可检查：`index.md`（所有页面的一句话目录，Agent 先读它）、`log.md`（只追加的摄入/查询/检查流水账）。

**三个操作**

- **Ingest（摄入）**：读一个新源 → 建摘要页 → 更新 index → 顺手更新 10-15 个相关页 → 自动生成交叉引用。

- **Query（查询）**：回答问题的结果**回填**成新页面——每个问题都在让系统长大，复利增长。

- **Lint（体检）**：周期性检查矛盾、过期声明、孤儿页、缺口。

Karpathy 明确把思想渊源追溯到 Vannevar Bush 1945 年的《As We May Think》和 **Memex**——那台设想中的「知识机器」。Memex 之所以失败，是因为**人工交叉引用不可持续**；而 LLM Wiki 把维护成本降到近乎为零，让 Memex 在 80 年后第一次变得可行。

这套理念很美，但它有两个隐含前提：**单机、单用户**。它假设一个 markdown 文件夹、一个 Obsidian vault、一个 Agent。当一个产品要做成**云端多租户服务**时——多个用户、共享后端、文档实时变化、要求实时图谱——本地约定里的每一件事都要重新设计。本文要讲的，正是把「LLM 当编译器」这件事**服务化**的工程实践。

## 二、系统总览：从本地约定到云服务

我们的 llm-wiki 是 2Ryun 平台的一个插件式能力。2Ryun 是一个文档管理 + 知识库 + 建站的全栈 SaaS：前端 Nuxt，后端 Express + Mongoose，AI 层是一个 LangGraph 编排的 DeerFlow 服务。llm-wiki 的知识提取全部走 DeerFlow。

```
`文档库(原始源)
   │  保存/设置变更 → notify-update
   ▼
wiki-service (:8002) ──调用──> DeerFlow (:8001, LangGraph + LLM)
   │  llm-wiki-extract / llm-wiki-organize / llm-wiki-maintain
   ▼
MongoDB (wiki_entries / wiki_links / wiki_clusters / insights / operation_log)
   │
   ├── 语义检索（嵌入余弦相似度 + 关键词兜底）
   └── 图谱 builder（nodes / edges / clusters）
        │
        ▼
前端插件 @dave/llm-wiki（WikiMain / WikiGraph / WikiEntryCard / Insights）`
```

把卡帕西的本地约定翻译成云端服务，一一对应：

| 卡帕西本地约定 | 云端服务化 |
| --- | --- |
| `/raw` 原始文档 | 主平台的文档库（不可变来源） |
| `/wiki` markdown 页面 | `wiki_entries` 集合（结构化的条目，带溯源和置信度） |
| schema / `agents.md` | 提取与组织的 **skill prompt**（结构、分类、质量规则的唯一来源） |
| `index.md` 目录 | 语义检索（嵌入 + 余弦相似度） |
| `log.md` 流水账 | `operation_log`（每次 create/merge/link/stale 都留痕） |
| Ingest / Query / Lint | `llm-wiki-extract` / 语义搜索 / `llm-wiki-organize` |

**关键差异**：本地约定靠人「手动把新文章丢进 /raw 然后让 Agent 跑一遍」；云端靠**变更时自动触发**——文档一保存，后端就异步通知 wiki-service 提取。这就是「把维护成本降到零」在服务端的落地：不是人记得去 ingest，而是系统自己感知。

## 三、提取管线：LLM 如何「编译」文档

### 3.1 触发：变更即提取

文档在编辑器里保存后，主后端调用 wiki-service 的 `notify-update`。提取是**异步**的——写文档的请求绝不阻塞在 LLM 调用上，用户保存完立刻返回，知识在后台「生长」。每条提取还有去重语义：`skip_if_extracted` 会跳过已处理的文档，幂等。

### 3.2 DeerFlow：三个 skill 对应三种操作

wiki-service 自己不碰 LLM，它通过 HTTP 调用 DeerFlow 的**无状态 run 接口**，由 DeerFlow（LangGraph 编排）去执行 LLM。一共三个 skill，恰好覆盖卡帕西的三个操作：

```
`llm-wiki-extract   → Ingest：从文档内容提取条目
llm-wiki-organize  → Lint：合并、关联、聚簇、标记过期、生成洞察
llm-wiki-maintain  → 新证据出现时增量更新既有条目`
```

这种「编排层 + 无状态接口」的解耦很关键：wiki-service 不关心 LLM 是哪个模型、有没有流式、prompt 怎么拼，它只发内容、收结构化 JSON。换模型、换 skill 都不影响存储层。

### 3.3 提取 prompt：内容的「可信」是设计出来的

提取不是「把文档丢给 LLM 让它总结」，而是**带着严格约束的结构化提取**。看 `_build_extract_prompt` 的核心约定：

```
`For each entity (concept, person, project, event, location, organization,
technology, etc.) found, output:
  - title: Concise descriptive title
  - content: Well-structured markdown — ONLY use info explicitly stated in the document
  - summary: One-sentence description
  - category: concept|person|project|event|location|organization|technology|tool|...
  - confidence_tier: extracted|inferred|ambiguous
  - confidence_score: 0.9+ for explicit, 0.7-0.8 for implied, 0.5-0.6 for tentative
  - text_spans: exact text snippet(s) from the document that this entry is based on
  - tags: 2-5 keywords
  - related_titles: titles of existing entries this relates to (if provided)
  - related_labels: VERY SHORT label (≤15 chars) describing HOW they relate
CRITICAL — Content Rules:
  - The 'content' field must ONLY contain facts, descriptions, and claims
  - that APPEAR IN THE DOCUMENT
  - Do NOT inject your own knowledge, definitions, background, or examples
  - If the doc mentions '冠脉搭桥' without explaining it, do NOT add an explanation
`
```

这里藏着整个知识库可信度的三根支柱：

1. **内容只来自原文 + **`text_spans`** 溯源**。每条内容都被约束为「文档里明确写了的」，并给出原文片段作为证据。这直接回应了卡帕西理念的批评者最担心的问题——「编译」可能把 LLM 自己的幻觉混进知识库。本项目用 prompt 约束 + 溯源字段把这种污染挡在源头。

2. **置信度分档**。`confidence_tier` 区分三种知识：`extracted`（原文直接陈述，0.9+）、`inferred`（模型推理，0.7-0.8）、`ambiguous`（存疑，0.5-0.6）。卡帕西的本地约定靠人肉眼判断页面的可信度；云端把这些判断**内化成了条目的一等字段**，前端图谱、卡片、图例都可以按置信度可视化。

3. **Enrichments 与 content 分离**。LLM 在提取时总会有「文档之外」的知识——背景、术语解释、甚至对文档的质疑。如果塞进 content 就污染了来源；本项目把它们放进独立的 `enrichments` 数组（`detail_supplement`、`correction_challenge`、`timeliness_note`、`data_discrepancy`、`source_gap`……），作为**待审的补充**，不写进内容本体。这是「LLM 编译」和「LLM 创作」的清晰分界：**编译输出忠于源，创作产物单独隔离**。

这三根支柱本质上是把卡帕西 `schema`（agents.md 里「每个人物条目必须包含动机、局限、成就」这类约定）**固化成了 prompt 里的硬规则 + 数据模型里的字段**。Schema 从一份人类可读的约定，变成了提取管线里强制执行的结构。

## 四、组织与关联：让知识长出结构

光有提取，得到的是一堆平铺的条目。知识库的「意义」在于**关系**——这正是 Karpathy 说的交叉引用，也是 Memex 当年死在手工作坊里的地方。本项目把「交叉引用」也交给了 LLM 和向量。

### 4.1 organize：去重、聚簇、过期

`llm-wiki-organize` 一次运行做四件事：

- **重复合并**：同一实体被多次提取出不同条目时，做 canonical selection——先按规则挑候选，必要时让 LLM 选规范名，再智能合并内容（`merge_entries` 保留信息不丢失）。

- **聚簇**：对条目做社区发现，产出 `wiki_clusters`，每个簇有中心条目和成员列表。簇是知识图谱的「骨架」，也是前端分组视图的基础。

- **过期标记**：检测陈旧条目，打 `stale` 标。对应卡帕西 Lint 里的「stale claims」。

- **洞察生成**：在簇/根级别让 LLM 提炼模式、主题、gap——`insights`。这是「编译」之上的一层**综合**，让知识库不只是事实的集合，还有对事实的观察。

organize 同样支持 `organize-by-root`：按文档树范围做，并把 `root_id` 写回条目，让知识图谱能按文档树组织。

### 4.2 三类边：system / llm / semantic

条目之间的关系来自三个来源，前端图谱用不同颜色/线型区分：

- **system**（系统）：同文档、父子、同根、同看板——来自文档本身的结构，无需 LLM。

- **llm**（LLM）：提取时 LLM 给出的语义关系（`related_titles` + `related_labels`，如 `extends`、`contradicts`、`depends_on`、`supersedes`、`works_at`、`member_of`……），关系标签 ≤15 字，可读。

- **semantic**（语义）：嵌入向量的相似度自动连边。

这套「来源可溯的三类边」比 Karpathy 本地约定的交叉引用走得更远：本地靠 Agent 在 markdown 里手动写 `[[链接]]`；云端靠**结构化的关系元数据**，图谱能直接渲染、筛选、按类型着色。

### 4.3 图谱

`graph_builder` 把 entries + links + clusters 组装成前端可直接消费的 `GraphData`（nodes / edges / clusters / insights）。每个节点带 `category`、`confidence_tier`、`confidence_score`、`stale`；每条边带 `link_source`、`link_type`、`strength`。前端基于此做了完整的图谱交互（2D 力导向 + 3D 球形视图，d3-force-3d + three.js）。

## 五、检索：语义搜索

卡帕西的本地方案里，Agent 先读 `index.md` 找到相关页面。云端的规模不允许「把目录塞进上下文」，本项目用**嵌入**做语义检索：

```
`async def search_entries(self, user_id, query, max_results=10):
    # 优先语义：query 向量化，与有条目的向量做余弦相似度
    query_vec = await compute_embedding(query)
    if query_vec:
        results = await self._semantic_search(user_id, query_vec, max_results)
        if results:
            return results
    # 兜底：关键词全文检索
    return await self._keyword_search(user_id, query, max_results)`
```

嵌入默认走 Qwen `text-embedding-v3`（OpenAI 兼容接口），在嵌入服务不可用时降级为「关键词重叠向量」再退到全文搜索——**逐级降级，语义优先，可用性兜底**。这正是 `index.md` 的规模化替代：索引不再是一份人类可读的目录，而是每个条目生成时就写好的向量。

有一个诚实的差异值得写出来：卡帕西的 **Query 会「回填」**——每个问题都会长成新页面，系统复利增长。本项目的检索目前是**只读的**：搜索命中、但不把「这个问题 + 答案」沉淀回知识库。这是理念与实现之间最明显的一条差距，也是未来「maintain」之外值得补的一环。

## 六、前端与质量护栏

前端是一个插件（`@dave/llm-wiki`），挂在 2Ryun 的插件系统上。它不是一个孤立的页面，而是和文档编辑器深度集成：

- **WikiSidebar**：文档侧栏展示提取状态（未提取/提取中/已提取），可一键初始化、重提取。

- **WikiMain**：知识库主界面，Google 风格搜索 + 条目/图谱两个 tab。

- **WikiEntryCard**：条目详情，展示置信度徽标、分类、标签、来源、关联、待审 enrichments。

- **WikiGraph**：2D/3D 知识图谱，按类型/度数/置信度着色，聚焦时邻居高亮、非关联淡出。

- **InsightsPanel / PendingEnrichmentsList**：洞察列表 + AI 补充的**人工审核**队列。

质量护栏贯穿全链路：置信度徽标让「这条是原文说的还是模型推的」一眼可见；`text_spans` 让每条内容都能点回原文；`source_gap` 类 enrichments 主动标注「这条没有出处」；而 AI 的补充一律进**待审**，不自动写进内容。这些护栏合起来，回答了知识库产品最关键的问题：**「这里面的东西，我凭什么信？」**

## 七、理念验证与反思

把卡帕西的三操作对照本项目，大部分对得上：

| 卡帕西操作 | 本项目实现 |
| --- | --- |
| Ingest（摄入新源→建页→交叉引用） | `notify-update` 自动触发 + `llm-wiki-extract` |
| Lint（矛盾/过期/孤儿/缺口） | `llm-wiki-organize`（聚簇/去重/过期/洞察） |
| Query（检索 + 回填） | 语义检索（**缺回填**，见上文） |
| /raw 不可变 | 文档库 + `text_spans` 溯源 |
| log.md | `operation_log` |

**云端化解决了什么**：把「维护成本接近零」从人的自觉变成了系统的自动——文档一保存就提取、图谱实时可看、多租户数据天然隔离（所有查询都带 `user_id`）、嵌入索引入库即生成。

**牺牲了什么**：卡帕西模式最迷人的地方是**产物是纯 markdown**——人可以直接读、直接改、直接 diff。云端落地后，知识变成数据库里的条目 + 嵌入向量，**人失去了对「编译结果」的直接可编辑性**；可控性转移到了「提取 prompt 写得好不好」。这恰好印证了批评者说的「Schema 是瓶颈」——在本项目里，瓶颈就是那三份 skill prompt 和它们产出的 JSON schema。

**局限（与 Karpathy 的批评者共识）**：

- **错误复利**：如果提取阶段产生了一个错误的「事实」，后续 organize、洞察、图谱都会建立在它上面，而检查它的同样是那个会犯错的 LLM。本项目的缓解是置信度分档和 enrichments 待审，但没有根治。

- **规模**：本项目是多租户的条目级知识库，但仍是「提取一批文档→管理条目」的模型，不是卡帕西设想的、能长期积累复利的个人 wiki 那样的生长体。真正到了百万级，图谱和检索还需要新的工程（节点预算、布局后端化、WASM 物理等）。

- **「编译」不等于理解**：一个维护良好的知识库，不等于使用者真的懂了这些知识。卡帕西自己也承认，把整理工作外包给 LLM 的人，可能收获一个自己没消化过的 wiki。

## 八、结语

Karpathy 的 LLM Wiki 把「知识维护」从一种劳动变成了一种**约定**：人做策展（决定读什么、问什么），LLM 做编译（建页、交叉引用、体检），产物是可读、可溯源、复利增长的知识体。本文的 llm-wiki 把这套约定搬上了云端：用自动触发取代手动 ingest，用结构化条目 + 溯源 + 置信度取代自由 markdown，用嵌入检索取代 index.md，用图谱取代手写链接。

两条主线交织出的启示是：**理念是「编译一次」，工程是「让编译可信」**。卡帕西给了方向，而把方向做成一个别人敢用的产品，靠的是 prompt 里的硬约束、数据模型里的置信度、以及「内容忠于源、补充单独隔离」这条把 LLM 当编译器而不是作者的纪律。

---

*参考：Andrej Karpathy「LLM Knowledge Bases」；本项目代码位于 *`packages/extensions/wiki-service/`*（提取/组织/检索/图谱）与 *`packages/frontend/plugins/@dave/llm-wiki/`*（前端插件）。*

#