跳到主要内容

OpenViking — Agent 上下文数据库:架构与原理

30 秒导读: OpenViking 是给 AI Agent 用的上下文数据库。它不把资料切成一堆零散向量丢进 RAG,而是把 Agent 需要的三样东西——记忆、资源、技能——统一成一棵可以 ls/find/grep 的虚拟文件系统树(根是 viking://)。每个节点在写入时就被自动切成三层摘要(L0 一句话 / L1 概览 / L2 全文),检索时先锁定高分目录、再逐层往里细化,只把真正相关的那几片全文喂给模型。会话结束还能自动抽取记忆回写,让 Agent 越用越聪明。


1. 这是什么(零基础也能懂)

一句话定义: OpenViking 把"Agent 的大脑"做成一个能像文件系统一样操作的数据库——记忆、资源、技能都是这棵树上的"文件/目录",每个都有唯一地址(URI)。

它想解决的痛点。 传统 Agent 的上下文有几个老毛病,OpenViking 一条条对着治:

老毛病传统做法OpenViking 的解法
上下文散落各处记忆写死在代码、资源塞进向量库、技能到处放统一成一棵 viking:// 虚拟文件系统树
上下文越滚越大简单截断/压缩,信息丢失L0/L1/L2 三层,按需加载
检索效果差扁平存储、只做一次向量召回目录递归检索,兼顾语义与全局结构
检索过程是黑盒隐式召回链,出错难查目录浏览轨迹全程留痕、可视化
记忆只会记用户缺 Agent 自身的任务经验会话结束抽取用户记忆 + Agent 经验

给谁用。 写 AI Agent 的开发者。把 OpenViking 当成一个独立 HTTP 服务跑起来,Agent 通过 CLI / SDK 往里存资料、取上下文,不用再自己管一堆向量库和记忆逻辑。

用起来什么样。 一段最小的命令行交互,直观感受"上下文即文件":

ov add-resource https://github.com/volcengine/OpenViking # 把一个仓库塞进上下文库
ov ls viking://resources/ # 像列目录一样看有什么
ov tree viking://resources/volcengine -L 2 # 看目录树
ov find "what is openviking" # 语义检索,按需取相关片段
ov grep "openviking" --uri viking://resources/volcengine/OpenViking/docs/zh

一句话直觉。 把它想成 Agent 的一块"带语义索引的磁盘":目录结构给你全局视野和精确寻址(像真文件系统),向量索引给你模糊语义召回(像 RAG),两者长在同一棵树上。


2. 顶层全景(它大概怎么转)

先看两条主线:资料怎么进来(写)、上下文怎么出去(读)。中间夹着一个"每个节点切三层"的关键动作。

怎么读这张图: 上半是写入路径(左→右),下半是检索路径(右→左往回取),中间的 VikingFS 是所有操作的统一门面,底下是两套存储引擎。

┌───────────────────────────────────────────────┐
写入 (add-resource) │ ① 解析 parse/ ② 建树 core/building_tree │
原始文件/网页/仓库 ───▶ │ 抽文本·识别类型 ───▶ 一个节点一个 Context │
│ 每个节点切 L0/L1/L2 │
└───────────────────────┬───────────────────────┘
│ 写 .abstract.md/.overview.md
│ + 三层各自向量化

┌────────────────────────── VikingFS(统一门面 / viking:// 寻址) ──────────────────────────┐
│ ls · tree · read · write · find · grep · 权限 · 加密 · 命名空间路由 │
└───────────────┬───────────────────────────────────────────────┬──────────────────────────┘
│ │
文件内容/目录树 向量与标量索引
▼ ▼
┌────────────────────────┐ ┌────────────────────────────┐
│ RAGFS(Rust 聚合文件系统)│ │ 向量库 vectordb(C++ 引擎) │
│ 真实落盘 / 加密 / 多后端 │ │ ANN 召回 + 稀疏检索 + KV 存储 │
└────────────────────────┘ └────────────────────────────┘
▲ ▲
检索 (find/search) │ ④ 目录递归:先锁高分目录 → 逐层 search_children → 分数传播 │
查询 ────────────▶│ ③ 意图分析 intent_analyzer → 生成多路检索条件 │
└────────────── retrieve/hierarchical_retriever ─────────────┘

会话结束 (commit) ──▶ ⑤ session 抽取:压缩对话 → 抽用户记忆 + Agent 经验 → 回写 viking://user/...

部件一句话职责:

部件干什么关键位置(符号)
VikingFS所有上下文操作的统一门面,负责 viking:// 寻址、权限、加密、命名空间路由openviking/storage/viking_fs.py:253(VikingFS)
解析层 parse把文件/网页/仓库抽成文本、识别资源类型openviking/parse/parser_router.pyunderstanding_api.py:35(UnderstandingAPI)
建树 building_tree把解析结果组织成一棵 Context 节点树openviking/core/building_tree.py:11(BuildingTree)
分层写入每个节点生成 L0/L1/L2 并各自向量化openviking/storage/content_write.py:47(ContentWriteCoordinator)
意图分析把用户查询拆成多路检索条件openviking/retrieve/intent_analyzer.py:38(IntentAnalyzer)
目录递归检索先锁高分目录、逐层细化的核心算法openviking/retrieve/hierarchical_retriever.py:350(_recursive_search)
RAGFSRust 写的聚合文件系统,真实存文件、管加密与多后端crates/ragfs/src/core/filesystem.rs:97(FileSystem trait)
向量库引擎C++ 写的 ANN 索引 + 稀疏检索 + KV 存储src/index/index_engine.h:14(IndexEngine)、src/store/kv_store.h:10(KVStore)
会话记忆会话结束抽取用户记忆与 Agent 经验并回写openviking/session/memory/extract_loop.py:82(ExtractLoop)

主线走一遍(高层,不进代码):

  • 写: add-resource → 解析层抽文本、识别类型 → BuildingTree 建成节点树 → 每个节点由 ContentWriteCoordinator 生成 .abstract.md(L0)/.overview.md(L1),三层分别向量化 → 文件落进 RAGFS、向量落进 C++ 向量库。
  • 读: find "…"IntentAnalyzer 把查询拆成多路条件 → 向量召回先定位到高分目录_recursive_search 进入该目录 search_children、把子节点分数与父目录分数传播融合,若还有子目录就递归下钻 → 汇总最相关的若干片段返回。
  • 自迭代: 会话 commit → 压缩对话与工具调用 → 抽取"用户偏好"和"Agent 经验/轨迹" → 回写到 viking://user/{id}/memories 等目录,下次直接可检索。

三条主线的细节各有一章,见下方阅读地图。


3. 阅读地图(建议按顺序读)

六章由浅入深,前三章讲"范式与两条主线",后三章往存储与底层引擎钻:

  1. 文件系统范式:viking:// URI 与三类上下文 —— 为什么用"文件系统"而不是扁平向量;viking:// 地址怎么分 resources / user / skills / peers;三类上下文(SKILL / MEMORY / RESOURCE)如何统一寻址。
  2. 写入路径:解析 → 建树 → L0/L1/L2 分层 —— 一份资料从原始文件到"三层摘要节点树"的完整流水:解析、识别类型、建 Context 树、生成 L0/L1、三层各自向量化落库。
  3. 目录递归检索:先锁高分目录再逐层细化 —— 核心算法:意图分析拆多路条件 → 目录优先队列 → search_children 逐层下钻 → 父子分数传播融合 → 收敛与聚合;以及检索轨迹为何可观测。
  4. 存储层:VikingFS 门面、RAGFS 虚拟文件系统与向量库 —— VikingFS 如何做统一门面(寻址/权限/加密/命名空间);Rust 的 RAGFS 怎么真实落盘、支持加密与多后端;向量库如何按目录组织索引。
  5. 会话记忆自迭代:v3 抽取、用户记忆与 Agent 经验 —— 会话压缩、commit 触发抽取、ExtractLoop 如何产出"用户记忆"与"Agent 经验/轨迹",以及回写与合并策略。
  6. 底层引擎:C++ ANN 索引 + KV 存储(及 Rust 绑定) —— 最底层:C++ 的 IndexEngine(向量召回 + 稀疏检索 + 标量过滤)与 KVStore,通过 abi3 PyCapsule 暴露给 Python;RAGFS 的 Rust→Python 绑定。

4. 巧妙之处(读者要带走的精华)

① 用"文件系统"当上下文的统一抽象,一举解决三个问题。 把记忆/资源/技能都映射成 viking:// 下的目录节点,于是 Agent 可以用 ls/find/grep 这类确定性命令精确寻址,而不只是"模糊语义匹配"。同一套抽象顺带解决了"碎片化"和"黑盒不可观测"——因为每一步都是可见的文件操作。三类上下文用同一个枚举收口(openviking/core/context.py:26,ContextType = SKILL/MEMORY/RESOURCE)。

② 分层在"写入时"就做好,把省 token 前置。 传统 RAG 是查询时才压缩;OpenViking 在写入时就把每个节点切成 L0/L1/L2(openviking/core/context.py:34,ContextLevel ABSTRACT=0 / OVERVIEW=1 / DETAIL=2),派生出 .abstract.md.overview.md 两个小文件(openviking/storage/content_write.py:41,_DERIVED_FILENAMES)。检索时先用 L0/L1 判断相关性,只有真需要才加载 L2 全文——渐进式披露落到了存储结构上。

③ 目录递归 + 分数传播,让召回带上"全局上下文"。 不是一次性向量召回 top-k,而是把命中先归到目录,进入目录再对子节点二次检索,并把父目录分数按 final = α·子分数 + (1-α)·父分数 融合传播(openviking/retrieve/hierarchical_retriever.py:350,_recursive_search)。好处:既找到语义最像的片段,又保留了"它在整棵树哪个位置"的全局信息;用优先队列 + 并发子目录搜索控制成本。

④ Python 编排、Rust 存文件、C++ 管索引——各用所长。 上层业务用 Python 写(灵活、好接模型);真实文件系统用 Rust 的 RAGFS(内存安全、并发、可插拔多后端与加密,crates/ragfs/src/core/filesystem.rs:97);向量/标量索引这种性能热点用 C++ 引擎,通过 abi3 稳定 ABI 的 PyCapsule 暴露给 Python(src/abi3_engine_backend.cpp:24,kIndexCapsuleName / kStoreCapsuleName)。三层语言边界清晰。

⑤ 记忆会"自迭代",还分用户与 Agent 两类。 会话 commit 时不仅抽"用户偏好",还抽"Agent 的操作经验/轨迹"(openviking/session/memory/agent_experience_context_provider.pyagent_trajectory_context_provider.py),回写成可检索的记忆节点——这正是它宣称"越用越聪明"的机制,也补上了传统记忆"只记用户不记 Agent"的缺口。


5. 代码地图(导航索引)

按"想看哪块就跳哪"组织。行号 as-of sourceCommit;行号漂移时用符号名 grep 更稳。

主题文件路径关键符号
viking:// 命名空间与路由openviking/core/namespace.pyclassify_uricanonical_user_root_CONTENT_TYPES_BY_SCOPE(:13)
三类上下文 / 三层枚举openviking/core/context.pyContextType(:26)、ContextLevel(:34)、Context(:61)
建树openviking/core/building_tree.pyBuildingTree(:11)、to_directory_structure(:77)
解析层(建 Context 树)openviking/parse/tree_builder.pyTreeBuilder(:39)
解析层(理解 API / VLM)openviking/parse/understanding_api.pyUnderstandingAPI(:35)
分层写入 / 生成 L0·L1openviking/storage/content_write.pyContentWriteCoordinator(:47)、_DERIVED_FILENAMES(:41)
统一门面 VikingFSopenviking/storage/viking_fs.pyVikingFS(:253)、init_viking_fs(:166)
意图分析openviking/retrieve/intent_analyzer.pyIntentAnalyzer(:38)
目录递归检索openviking/retrieve/hierarchical_retriever.pyHierarchicalRetriever(:45)、_recursive_search(:350)、search_children(:413)
向量后端(Python 侧)openviking/storage/viking_vector_index_backend.pyVikingVectorIndexBackend(:644)、_SingleAccountBackend(:93)
C++ 引擎的 Python 封装openviking/storage/vectordb/engine/_python_api.pybuild_abi3_exports(:414)、IndexEngine(:420)
会话与压缩openviking/session/session.pycompressor_v3.pySessionCompression(:214)
会话服务(commit 触发抽取)openviking/service/session_service.pySessionService(:33)、commit(:249)、commit_async(:272)
记忆抽取主循环openviking/session/memory/extract_loop.pyExtractLoop(:82)
Agent 经验 / 轨迹记忆openviking/session/memory/agent_experience_context_provider.pyAgentExperienceContextProvider(:42)
C++ 向量索引引擎src/index/index_engine.hIndexEngine(:14)、add_data(:21)、search(:25)
C++ KV 存储src/store/kv_store.hKVStore(:10)、exec_op(:14)、seek_range(:26)
C++↔Python abi3 桥src/abi3_engine_backend.cppkIndexCapsuleName(:24)、kStoreCapsuleName(:25)
RAGFS 文件系统抽象(Rust)crates/ragfs/src/core/filesystem.rsFileSystem trait(:97)
RAGFS 装配(Rust)crates/ragfs/src/core/builder.rsRagfsStack(:41)、RagfsConfig(:27)
RAGFS 的 Python 绑定crates/ragfs-python/src/lib.rsCacheProviderFactory、缓存/后端配置

说明:repo 取自克隆内 README.md 声明的 volcengine/OpenViking;其余结论均以 sourceCommit 处真实源码为准。上游若未改动本页所引文件,结论仍成立,仅需重盖 sourceCommit