Karpathy LLM Wiki 实践:用“知识编译“替代 RAG,构建个人知识库

张开发
2026/5/23 8:14:02 15 分钟阅读
Karpathy LLM Wiki 实践:用“知识编译“替代 RAG,构建个人知识库
❝Andrej Karpathy 提出了 LLM Wiki 架构——一种完全不同于 RAG 的知识管理范式。本文将深入解读其核心思想并分享我从零实现一个 LLM Wiki 系统的完整实践。❞一、背景RAG 的繁荣与困境过去两年RAGRetrieval-Augmented Generation几乎成了 LLM 应用的标配。无论是企业知识库、智能客服还是个人笔记系统大家的第一反应都是把文档切块 → 向量化 → 存入向量数据库 → 查询时检索 → 拼进 Prompt。这套流程确实有效但用久了你会发现一些痛点「分块损失」一篇结构化的论文切成 512 token 的碎片后上下文关系全丢了「检索不稳定」Embedding 相似度并不等于语义相关度换个说法就可能检索不到「每次重新理解」同一份文档每次查询时 LLM 都要重新阅读原文浪费算力「知识碎片化」原始文档之间没有显式关联知识只是堆在数据库里这些问题并非 RAG 的 Bug而是其设计哲学决定的——「RAG 本质上是检索时理解」。而 Karpathy 提出了一个反直觉的思路「为什么不在入库时就让 LLM 理解好」二、Karpathy 的核心思想知识编译Karpathy 的 LLM Wiki 架构核心就一句话❝「不要让 LLM 在查询时去理解原始文档而是提前让 LLM 把文档编译成结构化的知识。」❞这跟编程语言的编译器是同一个思路源代码 (.py) → 编译 → 字节码 (已优化) → 执行 → 结果 原始文档 (PDF) → Ingest → Wiki 页面 (结构化) → Query → 答案「编译意味着什么」一篇 20 页的论文核心贡献可能只需 500 字描述格式五花八门的原始资料PDF、网页、笔记统一成 Markdown文档之间隐含的关联同一个概念在不同论文里出现变成显式的双向链接查询时不再需要 LLM 临时抱佛脚而是直接读已经整理好的知识关键洞察在于「如果你的知识库足够精炼你根本不需要复杂的向量检索」。100 个 Wiki 页面每个平均 500 tokens总共才 50,000 tokens——现在的 LLM 动辄 128K 甚至 200K 的上下文窗口完全可以把整个 Wiki 塞进去。三、架构设计三层分离 Schema 契约3.1 三层架构LLM Wiki 采用清晰的三层架构┌─────────────────────────────────────────────┐ │ Layer 3: Wiki已编译的知识图谱 │ │ entities/ concepts/ summaries/ synthesis/ │ │ queries/ index.md │ ├─────────────────────────────────────────────┤ │ Layer 2: Raw Sources原始资料 │ │ IMA API / 本地文件 / 外部数据源 │ ├─────────────────────────────────────────────┤ │ Layer 1: Schema行为契约 │ │ AGENTS.md SCHEMA.md │ └─────────────────────────────────────────────┘「Schema 层」定义 LLM 的工作规则、页面模板、质量标准「Wiki 层」LLM 维护的结构化 Markdown 知识库「Raw Sources 层」只读的原始资料通过 API 访问3.2 Schema最核心的设计在 Karpathy 的设计中「Schema 是整个系统最核心的概念」。它不是数据库 Schema而是一份「给 LLM 看的行为契约」。Schema 分为两个文件AGENTS.md全局行为规范定义工作流Ingest/Query/Lint和通用约定SCHEMA.md实例级约束定义页面模板、标签分类、质量阈值「Schema 解决的核心问题」问题没有 Schema有 Schema格式混乱不统一严格模板、标准结构质量长短不一、详略不同质量稳定、可预测维护知识库逐渐混乱知识库持续整洁更强大的是——「修改 Schema 就能修改 LLM 行为不需要改一行代码」。想让摘要更详细改 SCHEMA.md 里的字数限制就行。想新增一种页面类型在模板里加一个定义即可。3.3 五类页面Wiki 中有五种页面类型各司其职类型目录内容示例「Entities」entities/人物、组织、项目geoffrey-hinton.md「Concepts」concepts/技术概念、理论transformer.md「Summaries」summaries/源文档摘要attention-is-all-you-need.md「Synthesis」synthesis/跨文档综合分析evolution-of-nlp.md「Queries」queries/归档的高质量问答query-20240115-scaling-laws.md每种页面都有严格的模板YAML frontmatter 元数据 标准化的 Markdown 结构 [[双向链接]]交叉引用。四、三大核心操作4.1 Ingest摄入知识的编译过程Ingest 是 LLM Wiki 最关键的操作完整流程如下原始文档 → 内容提取 → LLM 生成摘要 → 创建 Summary 页面 → LLM 提取实体 → 创建/更新 Entity 页面 → LLM 提取概念 → 创建/更新 Concept 页面 → 更新双向链接 → 更新 index.md → 记录 log.md以摄入一篇论文为例代码的核心逻辑是这样的def _ingest_content(self, source_id, source_title, content, source_type, metadata): # 1. LLM 生成摘要 summary self._summarize(content) # 2. 创建摘要页 summary_page self.wiki.create_page( titlesource_title, categorysummaries, contentsummary, frontmatter{source_id: source_id, tags: [summary]}, ) # 3. LLM 提取并创建/更新实体页 for entity in self._extract_entities(content): self._update_entity_page(entity, summary_slug) # 4. LLM 提取并创建/更新概念页 for concept in self._extract_concepts(content): self._update_concept_page(concept, summary_slug) # 5. 更新索引和日志 self.wiki.write_index_file() self.wiki.append_log(ingest, details, sourcesource_id)这里的设计亮点是「LLM 回调机制」所有 LLM 相关功能摘要、提取、问答都通过回调函数注入不提供回调时退化为简单实现如截取前 500 字符做摘要。这让系统可以灵活接入不同的 LLM 服务也方便测试。4.2 Query查询先 Wiki 后原始资料Query 的设计哲学是——「先查已编译的知识Wiki再查原始资料Raw Sources最后综合生成答案」用户提问 → 搜索 WikiBM25 算法→ 搜索 IMA 原始知识库 → 组装上下文 → LLM 综合生成答案 → 判断是否值得归档 → 是创建 Query 页面搜索部分我实现了一个「轻量级 BM25 算法」而非简单的子字符串匹配def search(self, query, categoryNone, top_k20): query_tokens self._tokenize(query) # BM25 参数 k1, b, title_boost 1.5, 0.75, 3.0 # 计算每个查询词的 IDF for token in set(query_tokens): doc_freq sum(1for doc in doc_contents if token in doc) idf_scores[token] math.log( (n_docs - doc_freq 0.5) / (doc_freq 0.5) 1.0 ) # 对每个文档计算 BM25 分数 标题加权 for page in candidate_pages: score sum(idf * tf_norm for each query_token) if token in title_tokens: score idf * title_boost # 标题匹配额外加权BM25 相比简单子字符串匹配的优势支持多关键词分词、TF-IDF 加权、标题匹配加权。同时保持轻量——不需要外部依赖也不需要向量数据库。Query 还有一个精妙的设计「有价值的问答会被自动归档成新的 Wiki 页面」。这意味着 Wiki 会通过使用不断自我增长——你问得越多知识库越丰富。4.3 Lint健康检查维护知识库质量Lint 操作借鉴了代码静态分析的理念定期检查 Wiki 的健康度「孤儿页面」没有任何入链的页面说明知识孤立「断链」指向不存在页面的链接「过时内容」超过 30 天未更新的页面天数从 SCHEMA.md 读取「矛盾信息」跨页面的矛盾内容需要 LLM 检测最终输出一个健康分数和详细报告 Wiki Health Report Health Score: 85.0% | Issue Type | Count | |------------------|-------| | Orphan Pages | 2 | | Broken Links | 1 | | Outdated Pages | 3 | | Contradictions | 0 |五、Schema 驱动 LLM修改文档即修改行为这是整个系统我最欣赏的设计。所有 LLM 调用都会自动注入 Schema 作为 System Promptclass WikiLLMFunctions: def _build_system_prompt(self, task_instruction): parts [ You are an intelligent wiki assistant., You MUST follow the rules and conventions defined below., ] if self._agents_content: parts.append(--- AGENTS.md (Global Behavior Rules) ---) parts.append(self._agents_content) if self._schema_content: parts.append(--- SCHEMA.md (Instance-Specific Constraints) ---) parts.append(self._schema_content) if task_instruction: parts.append(f--- Current Task ---\n{task_instruction}) return\n\n.join(parts)这意味着「提取实体时」LLM 会遵循 SCHEMA.md 中定义的 Entity 页面模板输出符合规范的结构化数据「生成摘要时」LLM 会参考 Schema 里的写作风格指南和字数限制「判断是否归档时」LLM 会根据 Schema 里的归档标准做出判断「想改变 LLM 的行为修改 Markdown 文件即可不需要动一行代码。」这在传统 RAG 系统中是不可想象的——通常你需要改 Prompt、改代码逻辑、重新部署。六、与 RAG 的本质区别维度传统 RAGLLM Wiki「核心思想」原始数据 智能检索预编译 全量上下文「数据处理」分块存储保留原文LLM 预处理提炼精华「检索方式」向量相似度搜索BM25 关键词匹配或全量加载「信息密度」低包含冗余高经过精炼「知识关联」隐式Embedding 空间显式[[双向链接]]「查询时 LLM 负担」重需理解原文轻知识已结构化「更新成本」低增量更新向量高需要重新编译「适合数据量」大规模10GB中小规模 500 页「行为修改」改代码、改 Prompt、部署改 Markdown 文件「它们不是替代关系而是互补」。Karpathy 自己也说❝RAG 是用技术复杂度换取内容量。LLM Wiki 是用前期精炼换取查询时的简单与准确。❞七、适用场景与局限适合「个人研究者」追踪论文、建立知识体系「技术学习者」整理学习笔记、关联概念「内容创作者」管理写作素材、积累领域知识「独立开发者」个人技术文档、项目知识沉淀不适合「企业级知识库」数据量太大编译成本过高「实时问答系统」更新频繁Wiki 的编译开销不划算「多人协作场景」并发编辑 Markdown 文件会有冲突八、总结Karpathy 的 LLM Wiki 并不是要革 RAG 的命而是提出了一种不同的知识管理哲学「编译优于检索」——提前让 LLM 理解文档而不是查询时临时理解「质量优于数量」——500 字精炼摘要 5000 字原文「显式关联优于隐式」——[[双向链接]] Embedding 空间相似度「简单优于复杂」——如果能全量加载就不需要复杂的检索系统「Schema 驱动」——修改文档即修改行为非技术人员也能参与对于个人知识管理来说这种方式有一种独特的魅力你的知识库不再是一个黑盒的向量数据库而是一组精心组织的、人类可读的 Markdown 文件。你可以用 Obsidian 浏览它的知识图谱可以直接阅读任何一个页面可以手动编辑修正 LLM 的输出也可以通过修改 Schema 来调整系统的行为。「知识管理的终极形态或许就是让 AI 帮你维护一个活的 Wiki——持久的、复利增长的知识产物。」❝觉得有用的话「点赞 分享 收藏⭐」一键三连下次找起来方便也能让更多人看到。❞点击 头像关注我一起探索 AI 领域的更多可能 ✌️

更多文章