
从零构建 LLM Wiki 知识库系统三层降级问答 知识图谱 复利增长实战本文完整记录了一个基于 Karpathy “LLM 即 Wiki” 理念的知识库系统设计与实现过程。从文档摄入到词条生成从三层降级问答到知识图谱从健康检查到 LLM 审计——带你跑通「摄入 → 生成 → 检索 → 问答 → 维护」全链路。零数据库、全异步、支持本地 Ollama 零成本运行。一、为什么需要又一个知识库系统在之前的 KB-MVP 项目中我构建了一个轻量级 RAG 知识库问答系统。它很好地解决了文档上传 → 检索 → 问答 → 溯源的问题但在实践中遇到了一个反复出现的场景用户问了一个通用知识问题如什么是 Transformer 架构 → RAG 系统检索本地知识库 → 知识库中没有相关文档 → 系统回答未找到相关资料 → 但用户知道LLM 本身就知道这个答案更深层的问题是传统 RAG 每次查询都从原始文档重新发现知识没有积累。你问了 100 个问题做了 100 次分析但知识库没有因此变得更聪明——这些探索全部消失在聊天记录中。Andrej Karpathy 的洞察给了答案LLM 本质上是互联网文本的有损压缩它本身就是一部模糊的维基百科。我们不应该只把它当生成引擎而应该把它参数中蕴含的万亿 token 知识当作一座待开采的知识矿藏。于是我设计了LLM Wiki——一个让知识复利增长的知识库系统痛点传统 RAG 的问题LLM Wiki 的解决思路知识无积累每次查询从零开始答案消失在聊天记录词条持久化好答案回填为新页面复利增长通用知识浪费知识库没有的就说未找到参数化兜底——LLM 直接从参数知识回答文档碎片化chunks 相互独立缺乏关联[[]]双向链接构建知识网络维护成本高知识库需要人工维护LLM 自动维护交叉引用、检测矛盾、清理悬空链接质量不可控无质量保障机制健康检查Lint 人工审核 LLM 调用审计二、核心理念三层架构 三大操作2.1 LLM Wiki 三层架构┌──────────────────────────────────────────────────────────────────┐ │ LLM Wiki 三层架构 │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ Layer 1原始资料层Raw Sources │ │ 不可变——LLM 从中读取但永不修改。这是事实来源。 │ │ 系统映射data/docs/上传的文档 data/documents/解析结果 │ │ │ │ Layer 2Wiki 层The Wiki │ │ LLM 生成并维护的结构化词条。LLM 完全拥有这一层。 │ │ 系统映射data/entries/词条 JSON data/store/向量 │ │ │ │ Layer 3Schema 层结构规范 │ │ 告诉 LLM Wiki 如何组织、约定是什么。 │ │ 系统映射data/schema.json页面格式/命名/引用/工作流规范 │ │ │ │ 理念Obsidian 是 IDELLM 是程序员Wiki 是代码库。 │ │ 你策展资料、探索、提问LLM 做所有簿记工作。 │ │ │ └──────────────────────────────────────────────────────────────────┘2.2 三大核心操作操作做什么系统实现Ingest摄入上传文档或输入主题LLM 生成结构化词条自动建立交叉引用从主题生成 从文档生成 增量整合Query查询三层降级问答Wiki 词条 → RAG 文档 → 参数化兜底多信号融合检索 SSE 流式输出 会话上下文Lint健康检查定期检查 Wiki 质量矛盾、孤儿、悬空、过时6 类诊断并行执行 LLM 语义分析三、整体架构设计┌─────────────────────────────────────────────────────────────────┐ │ 浏览器前端单页 │ │ 问答 · 文档 · 词条 · 检查 · 图谱 · 去重 · 日志 · 审计 │ └────────────────────────────┬────────────────────────────────────┘ │ HTTP / SSE ▼ ┌─────────────────────────────────────────────────────────────────┐ │ FastAPI 应用全异步单进程 │ │ │ │ ┌──────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │ │ 静态资源 │ │ API 路由层 │ │ Wiki 引擎 │ │ │ │ 托管前端 │ │ 31 个接口 │ │ 三层降级 增量整合 │ │ │ └──────────┘ └──────┬───────┘ └──────────────────────────┘ │ │ │ │ │ ┌───────────────┼───────────────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌─────────┐ ┌────────────┐ ┌──────────────┐ │ │ │词条生成器│ │ 词条存储 │ │ 会话管理器 │ │ │ │(双模式) │ │ WikiStore │ │ SessionMgr │ │ │ └────┬────┘ └─────┬──────┘ └──────────────┘ │ │ │ ┌─────────┼──────────────────────┐ │ │ │ ▼ ▼ ▼ │ │ │ ┌────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ │Lint│ │Graph │ │Dedup │ │Audit │ │Schema│ │ │ │ └────┘ └──────┘ └──────┘ └──────┘ └──────┘ │ │ ▼ ▼ │ │ ┌──────────┐ ┌──────────────┐ │ │ │ 审计 LLM │ │ Embedding │ │ │ │AuditedLLM│ │ 服务 │ │ │ └────┬─────┘ └──────┬───────┘ │ └───────┼───────────────┼─────────────────────────────────────────┘ ▼ ▼ ┌────────────────┐ ┌────────────────┐ │ 远程模型 API │ │ 本地文件系统 │ │·DashScope │ │·data/entries/ │ │·DeepSeek / GLM │ │·data/store/ │ │·Ollama(可选) │ │·data/sessions/ │ └────────────────┘ └────────────────┘技术栈一览层次选型选型理由后端Python FastAPI全异步SSE 流式支持好向量存储numpy JSON零依赖万级向量瞬时检索文档解析PyMuPDF python-docxPDF/Word 解析为结构化 blocks模型适配AsyncOpenAI DashScope SDK异步多供应商适配审计AuditedLLM 装饰器无侵入记录每次 LLM 调用前端原生 HTML/CSS/JS零构建单文件四、核心实现解析4.1 三层降级问答确保任何情况下都能回答问题传统 RAG 知识库没有相关文档时只能说未找到。但 LLM 本身可能知道答案——如何让它回答方案三层降级链路——Wiki 词条 → RAG 文档 → 参数化兜底。# wiki_engine.py简化展示核心逻辑classWikiEngine:asyncdefask(self,question:str,session_id:strNone):三层降级问答。# Layer 2: 多信号融合检索 Wiki 词条vector_resultsawaitself.store.search(question,top_kconfig.TOP_K*2)kw_resultskeyword_score(question,kw_entries)wiki_resultsrrf_fuse(vector_results,kw_results,top_nconfig.TOP_K)# 阈值判断 逐条过滤防假阳性ifwiki_resultsand(vec_passorkw_pass):filtered[rforrinwiki_resultsifpasses_filter(r)]iffiltered:returnawaitself._answer_from_wiki(question,filtered,...)# Layer 3: RAG 检索如启用ifself.rag:rag_resultsawaitself.rag.search_raw(question,config.TOP_K)ifrag_results:returnawaitself._answer_from_rag(question,rag_results,...)# Layer 1: 参数化兜底——LLM 直接从参数知识回答returnawaitself._parametric_fallback(question,...)参数化兜底是 LLM Wiki 区别于传统 RAG 的核心——传统 RAG 无结果只能说未找到LLM Wiki 兜底回答并提示用户归档为正式词条asyncdef_parametric_fallback(self,question,...):meta{sources:[{title:LLM 参数化知识,source:parametric,confidence:unverified,type_label:参数化兜底有损压缩,}],should_generate_wiki:True,# 提示要不要生成正式词条}# LLM 回答时开头标注「[参数化知识]」...4.2 多信号融合检索比纯向量好得多问题纯向量检索对短查询和缩写词容易漏召如RAG 是什么检索不到标题为检索增强生成的词条。方案向量检索 5 路关键词打分 RRF 融合。向量检索 → 候选集 ↓ 关键词打分5 路信号: ├── 标题精确匹配bypass 级权重 1.0 ├── 标题包含bypass 级权重 0.8 ├── 标题 token 覆盖率bypass 级 ├── curated 关键词匹配bypass 级 └── 正文匹配正文级不可单独 bypass ↓ RRF 融合: score Σ 1/(k rank_i) ↓ 逐条过滤: 杜绝假阳性 纳入条件满足任一: 1. 关键词交集 向量达标双重验证 2. 标题/curated关键词强命中bypass关键设计——bypass 级信号标题或 curated 关键词命中时即使向量相似度不足也可直接放行。但纯正文提及不可单独 bypass——避免某文档 merely 提及关键词如反向链接文本被误判为主题相关。中文分词策略也值得一提英文按单词中文按 2-gram二元组避免单字匹配噪声。问句停用词“什么”、“怎么”、“如何”在计算覆盖率时剔除。4.3 增量整合与交叉引用让知识复利增长问题如何让新词条与已有内容建立关联而不是孤立的信息孤岛方案生成新词条前先搜索已有相关词条将摘要注入 LLM Prompt。# wiki_engine.pyasyncdefgenerate_from_topic(self,topic,depth,on_progress):# 增量整合搜索已有相关词条existing_contextawaitself._gather_existing_context(topic)# 传入已有标题集合避免产生悬空链接self.generator.existing_titlesself.store.all_titles()entryawaitself.generator.generate_from_topic(topic,depth,on_progress,existing_context)awaitself.store.save_entry(entry)# 计算反向链接双向更新awaitself._update_backlinks(entry[title])...交叉链接策略避免了悬空链接的产生# wiki_generator.pyasyncdef_add_cross_links(self,sections,related):已存在的主题 → [[Topic]] 可点击链接 不存在的主题 → 纯文本标注「待创建」existing_links[]pending_mentions[]forrinrelated:ifrinself.existing_titles:existing_links.append(f- [[{r}]])else:pending_mentions.append(f-{r}待创建)...反向链接自动维护——新词条入库后双向更新新词条引用了哪些已有词条 → 给那些词条添加 backlink哪些已有词条引用了新词条 → 给新词条添加 backlink4.4 问答归档好答案回填为新页面问题你在聊天中做了一个精彩的对比分析发现了两个概念的关联——但这些探索消失了下次还要重来。方案将有价值的问答一键归档为新的 Wiki 词条。# wiki_engine.pyasyncdeffile_answer_to_wiki(self,question,answer,session_idNone):好的答案不应该消失在聊天记录中——回填为 Wiki 页面。# 去重检查是否已存在相同内容的归档...# LLM 生成标题titleawaitself._llm_complete(f为以下问答生成标题...)# 构建词条entry{title:title,summary:answer[:200],sections:[{title:问题,content:question},{title:回答,content:answer},],source:filed_answer,...}awaitself.store.save_entry(entry)...这就是复利增长的实现——每次查询不仅获得答案还让 Wiki 更丰富。4.5 Wiki 健康检查6 类并行诊断问题随着 Wiki 增长如何发现矛盾、过时内容、孤儿页面方案6 项检查并行执行asyncio.gatherLLM 辅助语义分析。检查类型说明严重级别孤儿页面没有被其他词条引用的孤立内容low悬空引用related_topics 中提到但不存在的概念medium内容矛盾LLM 检测不同词条间的事实冲突high过时内容超过 30 天未更新的词条low链接拼写错误[[]]目标与已有标题近但不匹配medium语义建议LLM 分析知识覆盖建议缺失概念low# wiki_lint.pyasyncdefrun_full_lint(self)-dict:entriesawaitself.store.list_entries()# 6 项检查并行orphans,dangling,stale,contradictions,broken,suggestionsawaitasyncio.gather(self._find_orphans(entries),self._find_dangling_refs(entries),self._find_stale(entries),self._find_contradictions(entries),# LLM 分批检测self._find_broken_links(entries),self._find_suggestions(entries),# LLM 语义分析)...4.6 知识图谱双向链接构建知识网络基于词条正文中的[[]]交叉链接构建图数据。关键设计只有目标词条真实存在的[[]]才算一条边related_topics仅作为建议关联不创建图边——避免虚假连接。图谱洞察 • 社区检测BFS 连通分量→ 不同颜色表示不同知识社区 • 枢纽节点入度出度最高→ 被大量引用的核心词条 • 孤立节点无入边无出边→ 需要添加交叉引用 • 悬空链接 → 指向不存在词条的引用需创建或清理4.7 AuditedLLM 装饰器无侵入 LLM 调用审计问题LLM 调用消耗 token 即消耗成本如何追踪每次调用方案装饰器模式包装任意BaseLLM自动记录——不改业务代码。# llm_provider.pyclassAuditedLLM(BaseLLM):审计包装器记录每次 LLM 调用不影响主流程。def__init__(self,inner:BaseLLM,audit:LLMAuditLog):self._innerinner self._auditauditasyncdefchat_stream(self,messages):starttime.time()chunks[]try:asyncfortokeninself._inner.chat_stream(messages):chunks.append(token)yieldtokenfinally:# 异步记录失败静默吞掉try:awaitself._audit.log_call(operationself._infer_operation(messages),promptstr(messages)[:2000],response.join(chunks)[:2000],duration_msint((time.time()-start)*1000),...)exceptException:pass# 审计失败不影响主流程使用contextvars.ContextVar传递会话 ID 和问题asyncio 安全。从消息内容自动推断操作类型parametric_qa / rag_qa / wiki_qa / generate / dedup / lint。五、全异步架构每个 I/O 都不阻塞层异步方案LLM 调用AsyncOpenAI原生异步流式 / DashScope SDKrun_in_executor桥接EmbeddingAsyncOpenAI/asyncio.to_threadDashScope文件 I/O大文件asyncio.to_thread小文件直接读取文档解析asyncio.to_threadPyMuPDF / python-docxRAG 检索httpx.AsyncClient原生异步并发保护asyncio.Lock保护向量库写入安全文件 I/O 也不可忽视所有写入通过原子操作tempfile os.replace防止异常时数据损坏。safe_resolve提供路径遍历保护。六、实战零成本本地运行借助 Ollama整套 Wiki 链路可以完全本地运行# 1. 安装 Ollama 并拉取模型ollama pull qwen2.5:7b# 对话模型ollama pull nomic-embed-text# 向量模型# 2. 配置 .envLLM_PROVIDERollamaLLM_MODELqwen2.5:7bEMBEDDING_PROVIDERollamaEMBEDDING_MODELnomic-embed-text# 本地部署无需 API Key# 3. 启动python main.py# 访问 http://127.0.0.1:8889也可以混合使用——DeepSeek 线上对话 Ollama 本地向量化LLM_PROVIDERdeepseekLLM_MODELdeepseek-chatLLM_API_KEYsk-xxxxxxxxEMBEDDING_PROVIDERollamaEMBEDDING_MODELnomic-embed-text如果已有 KB-MVP RAG 系统启用 RAG 桥接即可实现「概念级 原文级」双重保障RAG_BRIDGE_ENABLEDtrueKB_MVP_URLhttp://localhost:8000七、效果展示智能问答三层降级 来源卡片左侧多会话列表右侧消息区展示回答与来源卡片来源卡片包含词条名、置信度颜色标记、相似度参数化兜底场景标注参数化兜底有损压缩并提示归档文档管理上传 生成词条支持 PDF / Word / TXT / Markdown上传后自动解析为结构化 blocks可从文档生成词条状态自动关联知识图谱双向链接网络节点为词条边为[[]]交叉引用社区检测、枢纽节点、孤立节点一目了然悬空链接可视化便于发现知识盲区Wiki 健康检查6 类诊断按高/中/低优先级聚合展示问题每类问题给出修复建议LLM 调用审计成本分析总调用数、错误率、平均耗时、总 Token 数按操作类型分布统计每条记录可展开查看完整 Prompt 与 Response八、设计亮点总结亮点实现方式解决的问题三层降级问答Wiki 词条 → RAG → 参数化兜底传统 RAG 无结果只能说未找到多信号融合检索向量 5 路关键词 RRF 融合纯向量对短查询/缩写词漏召增量整合 交叉引用搜索已有词条注入 Prompt [[]]双向链接词条孤立知识无关联问答归档复利增长好答案一键回填为新词条探索消失在聊天记录知识无积累双向链接知识图谱[[]] 反向链接 社区检测文档碎片化缺乏知识网络Wiki 健康检查6 类并行诊断 LLM 语义分析知识库质量不可控重复检测 一键合并倒排索引粗筛 LLM 精排词条重复膨胀AuditedLLM 装饰器无侵入记录每次 LLM 调用LLM 调用成本不可追踪全异步 零数据库async/await JSON numpy部署重、不支持并发安全文件 I/O原子写入 路径遍历保护异常时数据损坏九、后续展望本项目当前为本地验证版已完整实现核心功能闭环。后续演进方向数据库升级JSON → PostgreSQL 专业向量库支撑大规模知识漂移检测定期重新生成摘要对比自动发现过时内容Agentic 知识生成Agent 自主决定生成什么、补全什么盲区协作审核多人协作 审核工作流 版本控制搜索增强SAG集成搜索引擎补充最新信息多模态词条图表、公式、代码示例写在最后LLM Wiki 不是简单的生成 检索它的核心价值在于知识的复利增长——每次摄入让 Wiki 更丰富每次查询的好答案回填为新页面交叉引用自动建立矛盾自动标记。LLM 承担了人类不愿意做的簿记工作让 Vannevar Bush 80 年前的 Memex 愿景终于落地。如果你也在寻找一种让知识持续积累、自动维护的方案不妨试试。项目已开源欢迎 Star 支持GitHub 仓库https://github.com/MLiueng/wiki-mvpGitee 仓库https://gitee.com/mengl248/wiki-mvp