OpenViking 深度技术解析:AI Agent 上下文数据库的设计哲学与实践

Cosolar 59 阅读 AI Agent

本文是一篇面向新手 / 初中级开发者的系统性教程,结合 OpenViking 官方文档(https://docs.openviking.ai/zh)与源码实现视角,从「概念直觉 → 核心概念 → 实现原理 → 动手实操 → 横向对比」四个层次,把 OpenViking 讲透。

阅读建议:如果你刚接触 AI Agent,请重点读第 1–5 章(概念);如果你已经会写 Agent 但想理解内部机制,请直接跳到第 6–11 章(原理);如果你想立刻跑起来,请跳到第 12 章(5 分钟上手)。

写在前面:用一句话建立直觉

传统 RAG(检索增强生成)把文档切碎、塞进向量数据库,Agent 提问时「按相似度翻找碎片」——这就像你把所有书撕成纸条扔进一个箱子,要用时只能靠关键词碰运气。

OpenViking 的做法完全不同:它把 Agent 需要的所有知识(记忆、文档、技能)组织成一个「虚拟硬盘」(viking:// 文件系统),让 Agent 像人浏览文件夹一样去定位、理解、按需读取上下文。 这个「虚拟硬盘」还会自动写摘要、自动从对话里学经验、并且把每次检索路径都记录下来供你审查。

一句话:OpenViking 是「专为 AI Agent 设计的上下文数据库(The Context Database for AI Agents)」,用文件系统范式统一管理三类上下文,用分层加载省 Token,用目录递归搞检索,用可视化轨迹消除黑箱,用会话自演化让 Agent 越用越聪明。

第一部分:概念直觉(新手必读)

第 1 章 OpenViking 是什么?为什么需要它?

1.1 一个真实的痛点场景

设想你做了一个「客服 Agent」。第一天用户告诉你「我姓张,公司用深色主题」。第二周用户再问问题,Agent 却说「您好,请问怎么称呼您?」——它失忆了

你尝试用传统 RAG 把聊天记录存进向量库。但很快发现:

  • 记录散落各处(用户偏好在 A 库、产品文档在 B 库、工具定义在 C 库),碎片化
  • 长对话越攒越多,全塞进上下文窗口会爆,所需上下文猛增
  • 向量检索只匹配「相似句子」,却不知道「张先生的偏好」其实在三个月前那条消息里,检索效果不佳
  • 为什么 Agent 这次答错了?你翻遍日志也找不到它「看了哪些资料」,上下文不可观测
  • 最致命的:传统 RAG 只会「记用户」,却不会「记自己怎么把事干成的」,记忆迭代有限

这五大问题,正是官方文档明确定义的「构建 AI Agent 的五大挑战」,也是 OpenViking 所有设计的出发点。

1.2 五大挑战 ↔ 五大特性

官方定义的挑战 OpenViking 的对应解法
上下文碎片化 文件系统范式,统一三类上下文
所需上下文猛增 L0/L1/L2 分层加载,按需取用
检索效果不佳 目录递归检索(结构 + 语义)
上下文不可观测 可视化检索轨迹
记忆迭代有限 会话自动管理与自演化记忆

1.3 OpenViking 的本质定位

  • 开源:Apache-2.0 许可证,由字节跳动火山引擎 Viking 团队开源,背后有 VLDB 2026 论文 VikingMem 的理论支撑。
  • 上下文数据库:它不是又一个向量库(那是它的底层之一),而是在存储之上构建了意图分析、层次化检索、记忆提取、会话管理的一套完整上下文操作系统
  • Agent 无关:通过 Python SDK、HTTP API、Rust CLI(ov)、Go SDK、MCP 协议,可以接入任何 Agent 框架(LangChain、Claude Code、Cursor、TRAE 等)。

第二部分:四大核心概念

第 2 章 核心概念一:一切皆文件(Viking URI 与虚拟文件系统)

2.1 为什么用「文件系统范式」?

人类理解知识的方式天然是「分门别类」的:先看目录名,大概知道这块讲什么;再看 README,了解结构;最后才打开具体文件读细节。传统的向量 RAG 把这种结构彻底摧毁了——所有文档被切成等长片段,扁平地躺在向量空间里,上下文的「位置感」和「从属关系」全部丢失。

OpenViking 把这种「人类浏览知识」的直觉,映射成了一套虚拟文件系统

  • 每一段上下文(一个文档、一条记忆、一个技能)都有唯一地址:viking://resources/docs/api.md
  • Agent 可以用标准文件操作去探索它:ls(列目录)、tree(看树)、read(读内容)、write(写)、find(找)、grep(搜文本)、glob(按通配符匹配)
  • 每个目录自动附带隐藏的「元信息文件」:.abstract.md(L0 摘要)、.overview.md(L1 概览)、.relations.json(关联),见第 4 章

新手理解:你可以把 viking:// 想象成电脑里的 C:/~/。只不过这个盘里装的不是你的电影和文档,而是「给 AI 看的知识」。

2.2 URI 语法

viking://{scope}/{path}
  • scheme:固定为 viking
  • scope:顶级命名空间(官方公开支持 resourcesuseragenttempqueueupload 为内部临时作用域)
  • path:作用域内的路径

三大公开作用域说明:

作用域 存放什么 生命周期 可见性
resources 客观知识(文档、代码、规范) 长期 account 全局
user 用户级数据(记忆、私有资源、技能、会话) 长期 / 会话生命周期 当前用户
agent Agent 能力与配置(技能、端点、工具、支付) 长期 account 全局

⚠️ 约束:resources 作用域只放客观知识,禁止存放工具配置、技能定义等非知识类数据(那些要放 agent 作用域)。这是新手常踩的坑。

📊 如图:一切皆文件 —— 三大公开作用域

一切皆文件·虚拟文件系统概念图

2.3 目录树长什么样?

viking://
├── resources/                    # 独立资源(客观知识)
│   └── {project}/
│       ├── .abstract.md          # L0 摘要
│       ├── .overview.md          # L1 概览
│       └── {files...}
│
├── user/{user_id}/               # 当前用户的数据
│   ├── profile.md                # 用户画像
│   ├── memories/                 # 记忆空间
│   │   ├── preferences/          # 按主题
│   │   ├── entities/             # 每条独立
│   │   └── events/               # 每条独立
│   ├── resources/                # 用户私有资源
│   ├── skills/                   # 用户技能
│   ├── peers/{peer_id}/          # 关于某个交互对象的隔离空间
│   │   ├── memories/
│   │   └── resources/
│   └── sessions/{session_id}/    # 会话
│
└── agent/                        # Agent 能力与配置(全局共享)
    ├── skills/
    ├── endpoints/                # 通信端点(规划中)
    ├── tools/                    # 工具配置(规划中)
    └── payments/                 # 支付配置(规划中)

短路径约定(新手友好):你在代码里写 viking://user/memories/,服务端会按当前登录身份自动展开成 viking://user/{user_id}/memories/{user_id}{peer_id} 必须是安全的单段标识(如 aliceweb-visitor-alice)。

2.4 变量路径:按时间自动归档

这是 OpenViking 一个很巧妙的设计。URI 支持路径变量,特别适合按时间序列组织数据(邮件、日志、日报):

{namespace:key}

calendar 命名空间提供了一整套日期变量:

变量 含义 示例(2026-05-07)
{calendar:today} 完整日期路径 2026/05/07
{calendar:yesterday} 昨天 2026/05/06
{calendar:ym} 年/月 2026/05
{calendar:quarter} 季度 Q2
{calendar:yw} 年/ISO 周 2026/w18
# 写法(模板原样传,服务端渲染)
viking://resources/emails/{calendar:today}/inbox
# 渲染为:viking://resources/emails/2026/05/07/inbox
# CLI 中也一样(--parent-auto-create 可简写为 -p)
ov add-resource -p "viking://resources/emails/{calendar:today}/inbox" ./emails/*.eml
ov read "viking://resources/logs/{calendar:yesterday}/app.log"

第 3 章 核心概念二:三类上下文(Resource / Memory / Skill)

OpenViking 把 Agent 需要的所有信息抽象成三种基本类型,对应人类认知的三个侧面:外部知识、自身认知、行动能力

类型 用途 生命周期 谁往里写
Resource(资源) 知识和规则 长期,相对静态 用户添加
Memory(记忆) Agent 的认知 长期,动态更新 Agent 自动记录
Skill(技能) 可声明的能力配置 长期,静态 用户/系统添加

3.1 Resource:Agent 可以引用的外部知识

  • 特点:用户主动添加(如产品手册、代码仓库);添加后内容很少变;按项目/主题以目录组织,并自动抽取多层信息(L0/L1)。
  • 示例:API 文档、FAQ、代码仓库、研究论文、技术规范。
  • URIviking://resources/{project}/...
  • 代码
# 添加资源(支持 URL / 本地文件 / 目录)
client.add_resource("https://docs.example.com/api.pdf", reason="API 文档")

# 在资源范围内检索
results = client.find("认证方法", target_uri="viking://resources/")

3.2 Memory:Agent 从交互中「学」到的持久知识

  • 特点:由 Agent 主动提取和记录;随交互持续更新;针对特定用户/Peer 个性化。
  • 关键认知:Memory 存在独立的 viking://agent/memories 目录——它写在当前用户或 Peer 的命名空间下(viking://user/{user_id}/memories/...viking://user/{user_id}/peers/{peer_id}/memories/...)。

官方内置的 11 种记忆类型(这是理解 OpenViking「记忆观」的关键):

类型 默认位置 说明
profile user/memories/profile.md 用户基本信息
preferences user/memories/preferences/ 按主题组织的用户偏好
entities user/memories/entities/ 人物、项目、组织等实体知识
events user/memories/events/ 决策、里程碑等事件记录
identity user/memories/identity.md 助手的名称、形象、气质、自我介绍
soul user/memories/soul.md 助手的核心原则、边界、风格、连续性
cases user/memories/cases/ 用于训练和评估的任务案例
trajectories user/memories/trajectories/ 可复用的任务执行轨迹
experiences user/memories/experiences/ 从执行结果中提炼的可复用经验
tools user/memories/tools/ 工具使用经验与最佳实践
skills user/memories/skills/ 技能执行经验与工作流策略

新手理解三个维度

  • 「用户与环境」= 它知道用户是谁profile/preferences/entities/events
  • 「助手身份」= 它知道自己是谁identity/soul)——这是很多框架缺失的
  • 「任务执行与学习」= 它知道自己怎么把事干成cases/trajectories/experiences/tools/skills

记忆从会话中自动提取,开发者不需要手写:

session = client.session()
await session.add_message("user", [{"type": "text", "text": "我喜欢深色模式"}])
commit = await session.commit()           # 启动后台记忆提取
task = await client.get_task(job_id)      # 轮询直到 status == "completed"

# 搜索记忆
results = await client.find("用户界面偏好", target_uri="viking://user/memories/")

3.3 Skill:Agent 可以调用的能力

  • 定义:Skill 是 Agent 可以调用的能力,属于 AgentDefinedContextType。包括传统工作流(如搜索、代码生成)、通信端点、工具配置、支付能力等。运行时定义相对静态,但「用得好不好」的经验会进 Memory。
  • 存储位置
    • 用户私有的:viking://user/skills/{skill-name}/
    • 通过 --uri 覆盖为全局共享的:viking://agent/skills/{skill-name}/
  • 目录结构(自身也遵循 L0/L1/L2)
viking://user/skills/search-web/
├── .abstract.md   # L0: 简短描述
├── SKILL.md       # L1: 详细概览
└── scripts        # L2: 完整定义
  • 代码
await client.add_skill({
    "name": "search-web",
    "description": "搜索网络获取信息",
    "content": "# search-web\n..."
})
# 全局共享:ov skills add search-web -p viking://agent/skills

3.4 统一检索:三类一起搜

Agent 常常需要同时找「用户偏好 + 相关文档 + 可用技能」,OpenViking 支持跨类型统一检索:

results = await client.find("用户认证")   # 不指定 target_uri,全量搜
for ctx in results.memories:   print(f"记忆: {ctx.uri}")
for ctx in results.resources:  print(f"资源: {ctx.uri}")
for ctx in results.skills:     print(f"技能: {ctx.uri}")

第 4 章 核心概念三:L0/L1/L2 三层信息模型(省 Token 的核心)

这是 OpenViking 最优雅、也最值得理解的设计。本质问题是:上下文窗口(Token 上限)有限,但知识无限,怎么办?

人类看书不会把整本书背下来——先看目录(L0),再看章节导言(L1),只有真要细读才翻到正文(L2)。OpenViking 把这套行为工程化了。

4.1 三层定义

层级 文件 Token 用途
L0 摘要 .abstract.md ~100 tokens 向量搜索、快速过滤
L1 概览 .overview.md ~2k tokens Rerank 精排、内容导航
L2 详情 原始文件/子目录 无限制 完整内容、按需加载

L0 示例(超短,让 Agent 一眼感知主题):

API 认证指南,涵盖 OAuth 2.0、JWT 令牌和 API 密钥的安全访问方式。

L1 示例(适中,告诉 Agent 内容结构和「去哪读详细」):

# 认证指南概览
本指南涵盖 API 的三种认证方式:
## 章节
- **OAuth 2.0** (L2: oauth.md): 完整 OAuth 流程和代码示例
- **JWT 令牌** (L2: jwt.md): 令牌生成和验证
- **API 密钥** (L2: api-keys.md): 简单的密钥认证
## 要点
- OAuth 2.0 推荐用于面向用户的应用
- JWT 用于服务间通信
## 访问
使用 read("viking://resources/docs/auth/oauth.md") 获取完整文档。

L2:完整原文,只在确认需要时才 read() 加载。

📊 图示:L0/L1/L2 自底向上聚合

L0/L1/L2 自底向上聚合

4.2 它们是怎么自动生成的?

  • 何时生成:① 添加资源时,Parser 解析后由 SemanticQueue 异步生成;② 会话归档压缩旧消息时,生成历史片段的 L0/L1。
  • 生成方向:叶子节点 → 父目录 → 根目录(自底向上)。子目录的 L0 会被聚合进父目录的 L1,形成层级导航。
  • 由谁生成SemanticProcessor(资源/技能语义生成)、SessionCompressor(会话历史语义生成)。

统一目录结构:

viking://resources/docs/auth/
├── .abstract.md      # L0: ~100 tokens
├── .overview.md      # L1: ~1k tokens
├── .relations.json   # 相关资源
├── oauth.md          # L2: 完整内容
├── jwt.md            # L2
└── api-keys.md       # L2

4.3 多模态支持

  • L0/L1 永远是文本(Markdown),方便检索和阅读;
  • L2 可以是任何格式(文本、图片、视频、音频);
  • 二进制内容的 L0/L1 用文本描述(如「一张工作室布局图,包含……」),让 Agent 即使不加载原图也能感知它。

4.4 怎么省 Token?——给新手的策略

# 先用 L1 概览判断,只在确实不够时才读 L2
overview = client.overview(uri)
if needs_more_detail(overview):
    content = client.read(uri)
场景 推荐层级
快速相关性检查 L0
理解内容范围 L1
详细信息提取 L2
为 LLM 构建上下文 L1 通常就够

原理总结:L0 超短用于「粗筛」避免加载大文件;L1 提供导航,多数情况下替代完整 L2;L2 无限制但严格按需。通过「轻量筛选 → 中等导航 → 精准加载」的递进,在保住信息完整的同时最大化省 Token。官方在 LoCoMo 等基准上报告了 63%–91% 的 Token 消耗下降。

第 5 章 核心概念四:会话与记忆自演化

Session(会话)是 Agent 与用户一次完整交互的载体。OpenViking 的会话管理不止「存聊天记录」,而是构成记忆自演化闭环

5.1 生命周期:创建 → 交互 → 提交

session = client.session(session_id="chat_001")
session.add_message("user", [TextPart("怎么配置 embedding?")])
session.commit()

小贴士:用 client.get_session(..., auto_create=True) 可在会话不存在时自动创建。

消息结构(新手了解有四种 Part)

  • TextPart:文本
  • ImagePart:图片 URL(记忆提取时可用 VLM 转成文字描述)
  • ContextPart:引用某个上下文(URI + 摘要)
  • ToolPart:工具调用(输入 + 输出)

📊 图示:会话生命周期与 commit 两阶段提交

会话生命周期与两阶段提交

5.2 使用追踪 used()

告诉系统「这次回答用了哪些上下文 / 技能」,这对后续记忆提取和重要性统计很重要:

session.used(contexts=["viking://user/memories/profile.md"])
session.used(skill={"uri": "viking://user/skills/code-search",
                    "input": "search config", "output": "found 3 files", "success": True})

5.3 commit() 两阶段提交(关键!)

commit() 分两阶段,同步立即返回,重活后台异步做

Phase 1(同步,立即完成)

  1. 递增 compression_index
  2. 把消息写入归档目录 messages.jsonl
  3. 清空当前消息列表
  4. 返回 task_id

Phase 2(异步后台)
5. 生成结构化摘要(LLM)→ 写入 .abstract.md / .overview.md
6. 提取长期记忆
7. 写入 memory_diff.json(记忆变更审计日志)
8. 更新 active_count(使用次数)
9. 写入 .done 完成标记

result = session.commit()
# {"status": "accepted", "task_id": "uuid-xxx", "archive_uri": "...", "archived": True}
task = client.get_task(result["task_id"])
# task["status"]: pending | running | completed | failed

5.4 记忆提取与去重闭环

消息 → LLM 提取 → 候选记忆
   → 向量预过滤(找相似旧记忆)
   → LLM 去重决策(candidate: skip/create/none + item: merge/delete)
   → 写入 AGFS → 向量化
层级 决策 说明
Candidate skip 候选重复,跳过
Candidate create 创建;必要时先删冲突旧记忆
Candidate none 不创建,只处理已有记忆
Existing item merge 合并到已有记忆
Existing item delete 删除冲突的已有记忆

memory_diff.json 审计日志(每次 commit 都会写,便于回溯):

{
  "archive_uri": "viking://user/{user_id}/sessions/{sid}/history/archive_001",
  "extracted_at": "2026-04-21T10:00:00Z",
  "operations": {
    "adds":    [{"uri": ".../identity.md", "memory_type": "identity", "after": "..."}],
    "updates": [{"uri": ".../project.md",  "memory_type": "context", "before": "...", "after": "..."}],
    "deletes": [{"uri": ".../old.md",      "memory_type": "context", "deleted_content": "..."}]
  },
  "summary": {"total_adds": 1, "total_updates": 1, "total_deletes": 1}
}

即使这次没有记忆变动,也会写入一个全 0 的空结构,保证可审计。

5.5 Peer Memory:为多对象隔离记忆

当 Agent 同时服务多个交互对象(比如一个助手同时对接多个客户/子系统),可以为每个 Peer 维护独立记忆空间:

viking://user/{user_id}/peers/{peer_id}/memories/
viking://user/{user_id}/peers/{peer_id}/resources/

提交会话时,若对话涉及稳定的 Peer,相关记忆会落入对应 Peer 空间,实现记忆隔离 + 共享

5.6 会话与记忆的存储结构(一图总览)

viking://user/{user_id}/sessions/{session_id}/
├── messages.jsonl        # 当前消息
├── .abstract.md          # 当前摘要
├── .overview.md          # 当前概览
├── history/
│   └── archive_001/
│       ├── messages.jsonl
│       ├── .abstract.md
│       ├── .overview.md
│       ├── memory_diff.json   # 记忆变更审计
│       └── .done
└── tools/{tool_id}/tool.json

viking://user/memories/   # 11 类记忆目录
├── profile.md  identity.md  soul.md
├── preferences/ entities/ events/
├── cases/ trajectories/ experiences/ tools/ skills/

第三部分:实现原理(深入引擎内部)

第 6 章 系统架构总览

6.1 四层架构

📊 图示:四层架构与数据流(彩色可视化)

四层架构与数据流

┌──────────────────────────────────────────────────────────────┐
│                          Client 层                            │
│   AsyncOpenViking / SyncOpenViking / HTTPClient / ov CLI / Go │
└───────────────────────────────┬──────────────────────────────┘
                                 │ 委托
┌───────────────────────────────▼──────────────────────────────┐
│                       Service 层(业务逻辑)                   │
│  FSService / SearchService / SessionService / ResourceService │
│  RelationService / PackService / DebugService                 │
└───────────────────────────────┬──────────────────────────────┘
            ┌────────────────────┼────────────────────┐
            ▼                    ▼                    ▼
     ┌─────────────┐     ┌─────────────┐      ┌─────────────┐
     │  Retrieve   │     │   Session   │      │    Parse    │
     │ (上下文检索) │     │ (会话管理)   │      │ (上下文提取) │
     │ search/find │     │ add/used    │      │ 文档解析     │
     │ 意图分析    │     │ commit      │      │ L0/L1/L2    │
     │ Rerank      │     │ 压缩/去重    │      │ 树构建       │
     └──────┬──────┘     └──────┬──────┘      └──────┬──────┘
            │                   │ 记忆提取            │
            │                   ▼                     │
            │            ┌─────────────┐              │
            │            │ Compressor  │              │
            │            │ 压缩/去重     │              │
            │            └──────┬──────┘              │
            └───────────────────┼────────────────────┘
                                ▼
                    ┌───────────────────────────┐
                    │       Storage 层           │
                    │   AGFS(内容) + 向量库(索引) │
                    └───────────────────────────┘

核心模块职责表:

模块 职责 关键能力
Client 统一入口 所有操作接口,委托 Service
Service 业务逻辑 7 个 Service(见下)
Retrieve 上下文检索 意图分析、层级检索、Rerank
Session 会话管理 消息记录、使用追踪、压缩、记忆提交
Parse 上下文提取 文档解析、树构建、异步语义生成
Compressor 记忆压缩 Schema 驱动提取、LLM 去重
Storage 存储 VikingFS、向量索引、AGFS

Service 层方法(解耦传输层,HTTP/CLI 复用):

Service 职责 主要方法
FSService 文件系统操作 ls mkdir rm mv tree stat read abstract overview grep glob
SearchService 语义搜索 search find
SessionService 会话管理 session sessions commit delete
ResourceService 资源导入 add_resource add_skill wait_processed
RelationService 关联管理 relations link unlink
PackService 导入导出 export_ovpack import_ovpack backup restore
DebugService 调试 observer(观测检索轨迹)

6.2 三条数据流

① 添加上下文(写路径):

输入 → Parser → TreeBuilder → AGFS → SemanticQueue → 向量库
  1. Parser:解析文档、建文件/目录结构(无 LLM 调用
  2. TreeBuilder:把临时目录移入 AGFS,入队语义处理
  3. SemanticQueue:异步自底向上生成 L0/L1
  4. 向量库:建索引用于语义搜索

② 检索上下文(读路径):

查询 → 意图分析 → 层级检索 → Rerank → 结果

③ 会话提交(记忆路径):

消息 → 压缩 → 归档 → 记忆提取 → 存储

6.3 设计原则(官方提炼)

原则 说明
存储层纯粹 存储层只做 AGFS 操作和基础向量搜索,Rerank 在检索层
三层信息 L0/L1/L2 渐进式加载,省 Token
两阶段检索 向量召回候选 + Rerank 精排
单一数据源 内容只从 AGFS 读,向量库仅存引用和索引

第 7 章 双层存储:内容-索引分离

7.1 为什么要分离?

传统做法把「文件内容」和「向量索引」混在一起,导致:向量库内存被大文件撑爆、内容与索引耦合难扩展、改一份要两处同步。

OpenViking 用双层存储彻底解耦:

┌─────────────────────────────────────────┐
│            VikingFS (URI 抽象层)         │
│    URI 映射 · 层级访问 · 关联管理        │
└────────────────┬────────────────────────┘
        ┌────────┴────────┐
        │                 │
┌───────▼────────┐  ┌─────▼───────────┐
│   向量库索引    │  │      AGFS       │
│   (语义搜索)    │  │   (内容存储)    │
└────────────────┘  └─────────────────┘
存储层 职责 存储内容
AGFS 内容存储 L0/L1/L2 完整内容、多媒体、关联关系
向量库 索引存储 URI、向量、元数据(不存文件内容

分离的好处:① 职责清晰;② 内存优化(向量库不存正文);③ 单一数据源(内容都从 AGFS 读);④ 可独立扩展(向量库和 AGFS 分别扩容)。

注:AGFS 已用 Rust 重写为 RAGFS,性能更强。

7.2 AGFS 内容存储

提供 POSIX 风格文件操作,支持多种后端:

后端 说明 配置
localfs 本地文件系统 path
s3fs S3 兼容存储 bucket, endpoint
memory 内存(测试用) -

多写模式:配置 storage.agfs.backups 后,顶层 backend 是 primary(权威写入),backups.items[] 是副本/迁移/读加速。用户接口不变,内部用 .redirect.json.sync_log.json 维护映射(对用户不可见)。

7.3 向量库索引

向量库只存「索引」,Context 集合 Schema 如下:

字段 类型 说明
id / uri / parent_uri string 主键、资源 URI、父目录 URI
context_type string resource/memory/skill
is_leaf bool 是否叶子(文件)
vector / sparse_vector vector 密集 / 稀疏向量(混合检索)
abstract string L0 摘要文本
name / description string 名称 / 描述
created_at / active_count - 创建时间 / 使用次数

索引策略flat_hybrid 混合索引 + cosine 距离 + int8 量化。
后端支持:local(本地持久化)、http(远程)、volcengine(火山引擎 VikingDB)。

一致性由 VikingFS 自动维护(新手不用操心同步):

viking_fs.rm("viking://resources/docs/auth", recursive=True)
# 自动递归删除向量库中 uri 以此开头的所有记录

viking_fs.mv("viking://resources/docs/auth",
             "viking://resources/docs/authentication")
# 自动更新向量库中的 uri 和 parent_uri

7.4 VikingFS 虚拟文件系统

VikingFS 是统一 URI 抽象层,屏蔽底层存储:

📊 图示:VikingFS → AGFS + 向量库 双层存储

VikingFS 双层存储

viking://resources/docs/auth  →  /local/{account_id}/resources/docs/auth
viking://user/memories        →  /local/{account_id}/user/{user_id}/memories

核心 API:read write mkdir rm mv abstract overview relations find
关联管理通过 .relations.json

viking_fs.link(from_uri="viking://resources/docs/auth",
               uris=["viking://resources/docs/security"], reason="相关安全文档")
relations = viking_fs.relations("viking://resources/docs/auth")

第 8 章 上下文提取流水线(Parser → TreeBuilder → SemanticQueue)

这是「往 OpenViking 里加一份文档」时,引擎内部发生的事。

8.1 总体流水线

输入文件 → Parser → TreeBuilder → SemanticQueue → 向量库
           ↓           ↓              ↓
         解析转换    文件移动     L0/L1 生成
         (无 LLM)   入队语义      (LLM 异步)

设计原则:解析与语义分离——Parser 不调 LLM(快、省),语义生成异步进行。

📊 图示:上下文提取流水线时序(Parser → TreeBuilder → SemanticQueue → 向量库)

上下文提取流水线时序

8.2 Parser(解析器)

负责格式转换与结构化,在临时目录建文件结构。

支持格式:

格式 解析器 扩展名 状态
Markdown MarkdownParser .md .markdown 已支持
纯文本 TextParser .txt 已支持
PDF PDFParser .pdf 已支持
HTML HTMLParser .html .htm 已支持
代码 CodeRepositoryParser 遵循 .gitignore 已支持
图片/视频/音频 Image/Video/AudioParser png/jpg/mp4/… 规划/部分

智能分割

if document_tokens <= 1024:   → 保存为单文件
else:
    → 按标题分割
    → 小节 < 512 tokens 合并
    → 大节 > 1024 tokens 创建子目录

8.3 TreeBuilder(树构建器)

把临时目录移动到 AGFS,并入队语义处理。5 个阶段:① 找文档根目录;② 确定目标 URI(按 scope 映射);③ 递归移动目录树;④ 清理临时目录;⑤ 入队语义生成。

scope 基础 URI
resources viking://resources
user viking://user

8.4 SemanticQueue(语义处理队列)

异步生成 L0/L1 并向量化。处理顺序:叶子 → 父 → 根(自底向上)。单目录步骤:

  1. 并发生成文件摘要(并发上限 max_concurrent_llm=10
  2. 收集子目录摘要
  3. 生成 .overview.md(L1)
  4. 从 overview 提取 .abstract.md(L0)
  5. 写入 AGFS
  6. 向量化,入队 EmbeddingQueue

代码文件的 AST 骨架提取(省钱妙招)
对 ≥100 行的代码文件,OpenViking 可用 tree-sitter 抽取结构骨架(模块 docstring、import、类继承与方法签名、顶层函数签名),跳过 LLM 调用。通过 ov.confcode_summary_mode 控制:

  • "ast":只抽 AST 骨架(默认,最省)
  • "llm":全走 LLM
  • "ast_llm":先抽骨架再辅助 LLM

支持 Python/JS/TS/Java/C/C++/Rust/Go/C#/PHP/Lua,其余 fallback 到 LLM。

8.5 三类上下文的提取差异

环节 Resource Memory Skill
基础 URI viking://resources viking://user/memories viking://user/skills
TreeBuilder scope resources user user
SemanticMsg type resource memory skill

记忆提取走:SessionCompressorV2 → ExtractLoop → MemoryUpdater → SemanticQueue

第 9 章 检索机制:目录递归检索

这是 OpenViking 取代「扁平向量 RAG」的核心算法,也是「检索效果不佳」挑战的解法。

9.1 两阶段检索总览

查询 → 意图分析 → 层级检索 → Rerank → 结果
         ↓           ↓          ↓
     TypedQuery  目录递归    精排评分

📊 图示:检索机制流程(意图分析 → 层级检索 → Rerank)

检索机制流程

9.2 find() vs search()

特性 find() search()
会话上下文 不需要 需要
意图分析 不使用 使用 LLM 分析
查询数量 单一查询 0–5 个 TypedQuery
延迟 较高
适用 简单查询 复杂任务
# 简单查询
results = await client.find("OAuth 认证", target_uri="viking://resources/")

# 复杂任务(需要会话上下文)
results = await client.search("帮我创建一个 RFC 文档", session_info=session)

9.3 意图分析(IntentAnalyzer)

用 LLM 把用户查询「翻译」成结构化的检索计划,生成 0–5 个 TypedQuery

@dataclass
class TypedQuery:
    query: str               # 重写后的查询
    context_type: ContextType  # MEMORY/RESOURCE/SKILL
    intent: str              # 查询目的
    priority: int            # 1-5 优先级
  • 输入:会话压缩摘要 + 最近 5 条消息 + 当前查询
  • 查询风格:skill 以动词开头(“创建 RFC 文档”)、resource 是名词短语(“RFC 模板”)、memory 是"用户XX"(“用户的代码规范偏好”)
  • 特殊情况:0 个查询 = 闲聊/问候;多个查询 = 复杂任务需技能+资源+记忆

9.4 层级检索(HierarchicalRetriever)

优先队列递归搜索目录结构,关键在「先定位好目录,再深度钻取」:

Step1: 按 context_type 确定根目录
Step2: 全局向量搜索定位起始目录
Step3: 合并起始点 + Rerank 评分
Step4: 递归搜索(优先队列)
Step5: 转为 MatchedContext

根目录映射:MEMORY→viking://user/memoriesRESOURCE→viking://resourcesSKILL→viking://user/skills

递归算法(含分数传播 + 收敛检测):

while dir_queue:
    current_uri, parent_score = heapq.heappop(dir_queue)

    results = await search(parent_uri=current_uri)
    for r in results:
        # 分数传播:子节点分数 = α*自身 + (1-α)*父分数
        final_score = alpha * embedding_score + (1-alpha) * parent_score

        if final_score > threshold:
            collected.append(r)
            if not r.is_leaf:                # 目录则继续递归
                heapq.heappush(dir_queue, (r.uri, final_score))

    if topk_unchanged_for_3_rounds:          # 收敛检测,提前停止
        break
参数 说明
score_propagation_alpha 1.0 子节点自身分数权重;1.0 表示仅用子节点自身分数
MAX_CONVERGENCE_ROUNDS 3 收敛检测轮数
GLOBAL_SEARCH_TOPK 10 全局搜索候选数
MAX_RELATIONS 5 每资源最大关联数

9.5 Rerank 精排

THINKING 模式(search 默认)下,对候选做精排:

  • 触发:配置了 Rerank AK/SK 且使用 THINKING 模式
  • 失败回退:Rerank 无效或 API 失败 → 回退向量分数
  • 后端:火山引擎 doubao-seed-rerank
  • 使用位置:起始点评估 + 每层递归子节点评估

9.6 检索结果与可视化轨迹

返回结构:

@dataclass
class MatchedContext:
    uri: str; context_type; is_leaf; abstract  # L0 摘要
    score: float; relations: List[RelatedContext]

@dataclass
class FindResult:
    memories; resources; skills; query_plan; query_results; total

可视化检索轨迹:由于检索是确定性的「目录浏览 + 文件定位」过程,OpenViking 能完整记录「走过哪些目录、选中哪些片段、为何选中」,并通过 Web Studio(React + Vite 构建)可视化。这直接解决了「上下文不可观测」的挑战——调试不再是黑箱猜测。

第 10 章 会话提交与记忆闭环(原理视角)

把第 5 章的机制串起来看,OpenViking 的「自演化」本质是这条异步流水线:

对话消息
  → SessionCompressorV2 压缩(保留最近 N 轮,旧消息归档 + 生成 L0/L1)
  → ExtractLoop 用 LLM 抽取候选记忆
  → 向量预过滤找相似旧记忆
  → LLM 去重决策(skip/create/merge/delete)
  → MemoryUpdater 写 AGFS + 向量化
  → 写 memory_diff.json 审计

整个过程对开发者透明且异步——你只需 session.commit(),剩下的 OpenViking 在后台把 Agent「养」得越来越懂用户、越来越会干活。

第 11 章 部署模式

11.1 嵌入式模式(类似 SQLite)

client = OpenViking(path="./data")

自动启动 AGFS 子进程、用本地向量索引、单例模式。适合本地开发、单进程应用。

11.2 HTTP 模式(类似 PostgreSQL)

client = SyncHTTPClient(url="http://localhost:1933", api_key="xxx")
curl http://localhost:1933/api/v1/search/find \
  -H "X-API-Key: xxx" -d '{"query": "how to use openviking"}'

Server 独立进程(openviking-server),支持任何能发 HTTP 的语言。适合团队共享、生产环境。

11.3 多语言架构(Polyglot)

语言 职责
Python 3.10+ 服务端、SDK、客户端、会话/检索/解析
Rust CLI(ov)、RAGFS 核心、高性能组件
Go AGFS 原始文件系统、Go SDK
TypeScript/React Web Studio 前端

11.4 安全与加密

信封加密:主密钥 → 账户密钥 → 文件密钥,对上层透明;每账户独立密钥,多租户强隔离。

第四部分:动手实操 + 选型

第 12 章 5 分钟上手(新手逐行教程)

12.1 前置要求

  • Python ≥ 3.10(Linux / macOS / Windows 均可)
  • 稳定网络(下载依赖 + 访问模型服务)

12.2 安装

# 推荐 uv
uv tool install openviking --upgrade
# 或 pip
pip install openviking --upgrade --force-reinstall
# 或 pipx
pipx install openviking && pipx upgrade openviking

装完会有 ov(别名 openviking)命令和 openviking-server 服务。

12.3 准备模型

OpenViking 需要两类模型:

  • VLM 模型:图像/内容理解(火山引擎豆包 / OpenAI GPT-4V / Codex 等)
  • Embedding 模型:向量化与语义检索

12.4 配置环境

首次推荐用向导生成配置:

openviking-server init
openviking-server doctor

或手动写 ~/.openviking/ov.conf

{
  "embedding": {
    "dense": {"api_base": "<endpoint>", "api_key": "<key>",
              "provider": "<provider>", "dimension": 1024, "model": "<model>"}
  },
  "vlm": {
    "api_base": "<endpoint>", "api_key": "<key>",
    "provider": "<provider>", "model": "<model>"
  }
}

配置在默认路径时自动加载;否则用 export OPENVIKING_CONFIG_FILE=/path/to/ov.conf

12.5 运行第一个示例(逐行讲解)

创建 example.py

import openviking as ov

client = ov.OpenViking(path="./data")     # 1. 创建嵌入式客户端,数据存 ./data

try:
    client.initialize()                    # 2. 初始化(启动 AGFS 子进程)

    # 3. 添加资源:支持 URL / 文件 / 目录;本地目录默认遵循 .gitignore
    #    wait=True 会阻塞到语义处理(L0/L1 生成)完成
    print("Wait for semantic processing...")
    add_result = client.add_resource(
        path="https://raw.githubusercontent.com/volcengine/OpenViking/refs/heads/main/README.md",
        wait=True,
    )
    root_uri = add_result['root_uri']

    # 4. 像用文件系统一样探索结构
    ls_result = client.ls(root_uri)
    print(f"Directory structure:\n{ls_result}\n")

    # 5. glob 找所有 markdown 文件,read 读取第一个的前 200 字
    glob_result = client.glob(pattern="**/*.md", uri=root_uri)
    if glob_result['matches']:
        content = client.read(glob_result['matches'][0])
        print(f"Content preview: {content[:200]}...\n")

    # 6. 获取 L0 摘要和 L1 概览(省 Token 的关键)
    abstract = client.abstract(root_uri)
    overview = client.overview(root_uri)
    print(f"Abstract:\n{abstract}\n\nOverview:\n{overview}\n")

    # 7. 语义检索
    results = client.find("what is openviking", target_uri=root_uri)
    print("Search results:")
    for r in results.resources:
        print(f"  {r.uri} (score: {r.score:.4f})")

    client.close()                        # 8. 关闭
except Exception as e:
    print(f"Error: {e}")

运行 python example.py,预期看到目录结构、内容预览、摘要/概览、带分数的检索结果。🎉 你已跑通 OpenViking。

想跑服务端模式?用 Docker:docker-compose up -d(镜像 ghcr.io/volcengine/openviking:latest,默认 1933 端口 + /studio Web 前端 + 内置 vikingbot)。

第 13 章 横向对比(选型参考)

📊 图示:扁平向量 RAG vs OpenViking 层级文件系统

扁平向量 RAG vs OpenViking 层级文件系统

为了看清 OpenViking 的定位,与主流开源方案对比:

维度 OpenViking Mem0 Letta Zep/Graphiti LangMem
架构范式 文件系统 + 层次化检索 向量 + 事实提取 OS 式分层自编辑 时序知识图谱 模块化记忆原语
产品形态 可插拔基础设施 可插拔记忆层 完整 Agent 运行时 可插拔记忆层 框架组件
上下文范围 记忆+资源+技能 仅记忆 记忆+对话状态 仅记忆 仅记忆
结构化管理 虚拟文件系统(强) 扁平向量(弱) 分层(中) 图谱(强)
Token 优化 L0/L1/L2 三层 分页
时间推理 元数据级 元数据级 隐式 一等公民(强) 情景记忆
自演化 多类记忆自动提取+去重 事实提取+去重 Agent 自编辑 事实+过期 热/后台路径
可观测性 完整轨迹可视化
集成复杂度 中等 极低 中(需图库) 中(LangChain 绑定)

结论性判断

  • 想要最简 API 上手 → Mem0;
  • 想要完整 Agent 运行时 → Letta;
  • 需要强时间推理(医疗/金融/合规) → Zep/Graphiti;
  • 想要框架无关、统一治理三类上下文、强 Token 优化与可观测 → OpenViking。

第 14 章 核心优势与局限(客观总结)

优势

  1. 统一治理:记忆/资源/技能一套 URI + API,天然可关联。
  2. 极致 Token 效率:L0/L1/L2 分层,不靠压缩/截断做减法,而是按需加载。
  3. 确定性可调试:文件系统范式让检索路径可追溯、可视化。
  4. 自演化记忆闭环:11 类记忆自动提取、去重、合并、审计。
  5. 灵活部署:嵌入式 ↔ HTTP,Python/Rust/Go/TS 多语言,MCP + VikingBot 多端。

局限

  1. 时间推理较弱:相比 Zep 双时间线图谱,时间维度主要依赖元数据。
  2. 学习曲线偏陡:L0/L1/L2、目录分类、两阶段提交、Peer Memory 需一定投入。
  3. 生态早期:社区集成、教程、第三方贡献仍在成长中。

第 15 章 学习路线图(给新手的下一步)

建议顺序(与官方文档导航一致):

  1. 概念建立:本文第 1–5 章(或官方「简介」)。
  2. 动手跑通:官方「5 分钟上手」+ 本文第 12 章。
  3. 深入原理:官方「架构详解 / 上下文类型 / 上下文层级 / Viking URI / 存储架构 / 上下文提取 / 检索机制 / 会话管理」——即本文第 6–10 章。
  4. 进阶集成:MCP 接入、VikingBot(Telegram/飞书/钉钉/Slack/QQ)、Web Studio、ov CLI、Pack 导入导出、多写存储、数据加密、多租户。

官方文档导航(权威、随版本更新)

  • 快速开始:简介 / 5 分钟上手 / 服务端模式 / 安装 SOP / CLI 配置
  • 核心概念:架构概述 / 上下文类型 / 上下文层级 / Viking URI / 存储架构 / 上下文提取 / 检索机制 / 会话管理
  • Agent 集成:Claude Code / Codex / Cursor / TRAE / LangChain 等
  • API 参考 / 常见问题 / 关于

本文概念、特性、API 与代码示例均以 OpenViking 官方文档(https://docs.openviking.ai/zh)为准,结合源码实现视角整理。官方文档持续更新,请以最新版本为权威来源。示例代码均为说明性片段,实际运行时请参照官方「配置指南」填入有效的模型服务地址与密钥。