OpenViking:LLM Wiki 理念的工程级实践 — L0/L1/L2 分层 + 目录递归检索

lxiol
📝
火山引擎开源 OpenViking 将 Karpathy LLM Wiki 做成完整工程系统:虚拟文件系统、L0/L1/L2 三级上下文分层、目录递归检索、会话后自动记忆提取。

原文链接:https://mp.weixin.qq.com/s/JPUdQDXC8oV9erCJasDIVw
作者:青红皂白

火山引擎开源的 OpenViking 项目,把 Karpathy 的 LLM Wiki 理念做成了一套有文件系统、有分层索引、有递归检索、有自我进化的完整工程系统。我从源码层面拆解了它的两个核心创新:L0/L1/L2 上下文分层和目录递归检索。

从理念到工程的鸿沟

LLM Wiki 理念的核心洞察:RAG 每次查询从零推导,什么都不积累。LLM Wiki 预编译、持续维护,知识随时间复利。

但从「用 LLM 维护一个 wiki」到「让 Agent 真正用上这个 wiki」,中间有一道工程鸿沟:

  • 规模问题 — wiki 膨胀到数百页后,index.md 本身就撑爆 context window
  • 精度问题 — grep + 正则只认字面命中,语义检索能力不足
  • 效率问题 — Agent 每次都要读全量内容,Token 消耗失控
  • 进化问题 — 知识不会自动更新、不会自动发现关联

个人用的 wiki-vault 可以用 index.md + wikilink 解决前 100 页的问题。但当你有几千份文档、几十个 Agent 并发查询时,需要一套完全不同的基础设施。OpenViking 就是这套基础设施的一个工程回答。

OpenViking 是什么

OpenViking 是火山引擎(字节跳动)开源的 Agent 知识操作系统。核心命题:用文件系统的范式替代扁平的向量存储,让 Agent 的上下文像操作文件一样被分层加载、按需检索、持续迭代。

技术栈:Python(服务端 + AI 管线)+ Rust(底层文件系统 AGFS)+ C++(向量索引引擎),提供 FastAPI HTTP 服务。

它在 LLM Wiki 范式的基础上做了四件事:

  1. 虚拟文件系统 — 所有知识通过 viking:// URI 寻址,有目录、有权限、有 ACL
  2. L0/L1/L2 三级上下文 — 每个目录自动生成 100 token 摘要和 2k token 概览,Agent 按需逐层展开
  3. 目录递归检索 — 从目录级定位到文件级精确定位,兼顾全局和局部
  4. 自我进化 — 会话结束后自动提取记忆、更新知识库、重新生成摘要

一、L0/L1/L2:知识的三级分层

当 wiki 有 500 个页面时,Agent 不可能全部读完。它需要一个机制——像 CPU 缓存一样,先看 L1 Cache(小而快),miss 了再看 L2 Cache(中而准),最后才访问 Main Memory(大而全)。

层级 载体 大小 作用 类比
L0 Abstract .abstract.md ~100 tokens 一句话说明这个目录/文件”是什么” CPU L1 Cache
L1 Overview .overview.md ~2k tokens 核心信息 + 导航树 + 文件关系 CPU L2 Cache
L2 Detail 原始文件 不限 完整内容 Main Memory

Agent 的工作流变成:搜索 L0 → 读 L1 → 只在确认需要时才读 L2。Token 消耗从全量降到按需。

生成方式:自底向上的 DAG

L0/L1 不是手写的,而是 LLM 自动生成,关键在自底向上——先处理叶子文件,再逐层汇总到根目录。

OpenViking 用 SemanticDagExecutor(DAG 调度器)编排:文件先按类型用不同 prompt 模板生成摘要(代码文件 >100 行先 AST 提取骨架),子节点完成后触发父目录 overview 生成。L0 是从 L1 输出中自动提取的——一次 LLM 调用产出两层结果。

增量更新

DAG 调度器内置增量检测:文件内容未变则复用已有摘要,目录无变更则复用已有 overview,只有真正变化的路径才触发重新向量化。

二、目录递归检索:从「一袋子 chunk」到「一棵树」

传统 RAG 是扁平的——所有 chunk 平等地躺在向量库里,丢失层级信息,全局与局部矛盾。OpenViking 的解法是目录递归检索,利用 L0/L1 的层级结构先定位再精确搜索。

五步法

  1. 意图分析(可选)
  2. 全局定位 — L0/L1 向量中搜索 top-10 目录
  3. 选择递归入口 — 高分目录 + 预设根目录
  4. 递归搜索 — 优先队列驱动,并行展开子目录
  5. 结果聚合 — 去重、分数融合、热度加权、排序

核心算法:优先队列驱动的并行递归

最大堆驱动目录展开顺序,每轮取最高分 4 个目录并行展开。不是 BFS(平等对待浪费算力)也不是 DFS(可能钻太深错过全局更优),而是 best-first search 的变体——保证每一轮都展开当前全局最高分的目录。

分数传播公式

final_score = α × child_score + (1-α) × parent_score

一个子节点的最终得分不仅取决于自身的相似度,还受到它所在目录相关性的加权——父目录的信誉为子节点背书。

收敛检测

三重机制:top-k 连续 3 轮不变停止 / 结果池连续 3 轮无新结果停止 / visited set 去重。实测大多数查询在 2-4 轮内收敛。

热度加权

借鉴 Hacker News 排序算法,融合语义相似度和热度分。被频繁访问且最近更新的知识排在前面,7 天半衰期——最近的经验优先被召回。

三、自迭代:知识库自己更新自己

每次会话提交时,系统自动执行知识沉淀管线:

1
会话消息 → 归档摘要 → ExtractLoop(ReAct 循环)→ MemoryUpdater → 目录 L0/L1 重建

ExtractLoop 不是简单的 “LLM 提取 → 写入”,而是有工具调用能力的 ReAct 循环——LLM 可以用 read 工具主动查阅现有知识,避免重复或矛盾的记忆写入。支持 upsert+patch(增量合并)、upsert+replace(整体替换)、delete、link 等操作。

写入后触发目录 L0/L1 重新生成,下次查询时新知识已经”编译”好了——这就是 LLM Wiki 理念的工程闭环。

四、回到 LLM Wiki 五范式

维度 LLM Wiki 原版 OpenViking
知识表示 Markdown + wikilink viking:// URI + L0/L1/L2 三层
检索方式 index.md + grep 目录递归检索 + rerank
规模承载 ~100 页 数千页(向量索引 + 分层过滤)
知识更新 手动 ingest 会话后自动提取 + 增量 DAG
权限控制 多租户 + ACL + 路径级权限
可观测性 OpenTelemetry + Prometheus + 事件总线
自进化 ReAct 记忆提取 + RL 训练管线

OpenViking 本质上是 LLM Wiki(范式二)+ GraphRAG(范式四的检索能力)+ 企业级基础设施 的工程融合,核心哲学仍然是 Karpathy 的:知识要被编译、沉淀下来,而不是每次从零检索。L0/L1 就是”编译后的知识”——不是原始文档的 chunk,而是 LLM 理解了整棵目录树后产出的结构化摘要。

五、局限与思考

代价 具体表现
LLM 调用成本高 每个文件都要 LLM 生成摘要,每个目录都要生成 overview
延迟 递归检索需要多轮向量搜索 + 可能的 rerank
系统复杂度 Python + Rust + C++ 三语言栈,部署运维门槛高
摘要质量依赖 LLM L0/L1 质量取决于 LLM 总结能力,弱模型会导致摘要失真

核心判断: OpenViking 证明了 LLM Wiki 理念可以在工程上做到大规模、分层、自进化。但它的价值更多是方向性的验证而非直接可用的产品——它告诉你”上下文分层供给”这条路是走得通的,具体实现可以根据自己的规模选择合适的复杂度。


本文转载自微信公众号,如有侵权请联系删除。

  • 标题: OpenViking:LLM Wiki 理念的工程级实践 — L0/L1/L2 分层 + 目录递归检索
  • 作者: lxiol
  • 创建于 : 2026-07-27 10:00:00
  • 更新于 : 2026-07-27 08:59:38
  • 链接: https://blog.lxiol.cn/2026/07/27/OpenViking-LLM-Wiki工程级实践-L0L1L2分层检索/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。