OpenViking:构建 AI Agent 上下文数据库——Viking URI、L0/L1/L2 三层加载与分层递归检索实战
OpenViking 是面向 AI 智能体的开源上下文数据库,把记忆(memory)、资源(resources)、技能(skills)统一收敛到 viking:// 协议下的虚拟文件系统中,让 Agent 用 ls、tree、find 这类文件操作确定性地定位上下文,而不是查询一个黑盒向量库。本文基于仓库根目录的 README_CN.md 展开,结合 openviking/ 包内源码、examples/ov.conf.example 配置模板和 Rust CLI(crates/ov_cli)实现,完整讲清三层上下文模型、目录递归检索、会话记忆沉淀的落地方式,以及从 pip install 到生产部署的全套操作路径。读完你可以独立部署一个 OpenViking 服务、用 ov 命令行完成资源摄取与语义检索,并为 Claude Code、Codex 等主流 Agent 接入记忆能力。
OpenViking 是什么:一个给上下文用的虚拟文件系统
核心设计一句话概括:所有上下文都是 viking:// 协议下的文件记录,目录本身就是数据。官方文档给出的整体结构如下(继承自 README_CN.md):
viking://
├── resources/ # 资源:项目文档、代码库、网页等
│ └── my_project/
│ ├── docs/
│ │ ├── api/
│ │ └── tutorials/
│ └── src/
└── user/
└── {user_id}/
├── memories/
│ └── preferences/
│ ├── writing_style
│ └── coding_habits
├── resources/
│ └── private_project/
├── skills/
│ ├── search_code
│ └── analyze_data
└── peers/
└── web-visitor-alice/
这套结构不是文档约定,而是由 openviking/core/directories.py 中的 PRESET_DIRECTORIES 在初始化时实际创建的。从源码结构看,每个目录对应一个 DirectoryDefinition 数据类,携带 abstract(L0 摘要)、overview(L1 描述)和 children 三个字段。以 user 作用域下的 memories 为例,预设子目录按记忆类型划分:
memories/preferences:按主题组织的用户偏好(沟通风格、代码规范等),同类偏好可追加;memories/entities:实体记忆(项目、人物、概念),每个实体一个子目录;memories/events:时间无关的历史事件记录,创建后不再更新;memories/cases/patterns:具体案例上下文 vs. 可复用的方法、SOP;memories/tools/skills/trajectories/experiences:工具使用经验、技能执行经验、执行轨迹与从轨迹中蒸馏出的泛化经验。
每个预设目录都自带英文的 abstract/overview 文本,这保证了 Agent 在没有检索命中前,仅靠浏览目录描述就能理解"这个目录放什么、什么时候该来读"。
L0 / L1 / L2 三层加载:按需加载省 token
分层加载是 OpenViking 控制上下文成本的核心机制。每条内容写入时会生成三个层级:
| 层级 | 语义 | 典型规模 | 用途 |
|---|---|---|---|
| L0(摘要) | 一句话总结 | 约 100 tokens | 快速判断相关性 |
| L1(概览) | 核心信息和使用场景 | 约 2k tokens | 规划阶段决策 |
| L2(详情) | 完整原始数据 | 视原文而定 | 确认需要时才读取 |
关键在于目录级也带 L0/L1——读完整文件之前就能判断相关性:
viking://resources/my_project/
├── .abstract # L0:约 100 tokens——快速判断相关性
├── .overview # L1:约 2k tokens——结构和要点
└── docs/
├── .abstract
├── .overview
└── api/
├── auth.md # L2:完整内容,按需加载
└── endpoints.md
源码侧可以印证这套分层是"生成时一次性产出、检索时按档降级":
- 语义产物的生成由 openviking/prompts/templates/semantic/overview_generation.yaml、openviking/prompts/templates/parsing/context_generation.yaml 等提示词模板驱动,L2 原文经过解析管线(openviking/parse/ 下的
parser_router.py、registry.py)拆分分节后生成 L0/L1; - examples/ov.conf.example 中的
auto_generate_l0、auto_generate_l1两个开关(示例值均为true)控制是否自动产出这两层,default_search_mode: "thinking"与default_search_limit: 3则设定了默认检索深度与返回条数; - 检索组装阶段,openviking/retrieve/context_assembler/budget.py 的
plan_entries按 token 预算把候选内容装入 L0/L1/L2 不同档位(Tier),超出预算时自动降级到更浅的层级——这是"任务需要多深就加载多深"的具体实现。
为什么用 OpenViking:四个核心能力
README 归纳了四个差异化能力,每一条都有源码对应物:
- 一个文件系统装下所有上下文。 记忆、资源、技能各有一个
viking://URI,智能体像开发者操作文件一样确定性地定位和操作上下文。命名空间规则见 openviking/core/namespace.py(canonical_user_root、context_type_for_uri、is_session_uri等函数定义了 URI 到上下文类型的映射)。 - 分层加载省 token。 即上文 L0/L1/L2 机制,写入时生成、读取时按预算取档。
- 目录递归检索。 向量检索先定位得分最高的目录,再逐层向下探索,结果连同周边上下文一起返回。
- 检索过程可观察。 每次查询都保留目录浏览轨迹,结果不对时能看到它出自哪条路径。
第 3、4 条的实现落在 openviking/retrieve/hierarchical_retriever.py:HierarchicalRetriever.retrieve() 接收 TypedQuery 和 RequestContext,内部通过 _recursive_search 从起点(起始目录得分最高的条目)递归展开——search_children(current_uri) 负责取当前目录的子节点,逐层向叶子推进;_rerank_scores 在召回后用配置的 rerank 模型(如 doubao-seed-rerank)重排,失败时回退到向量分数;_convert_to_matched_contexts 还会叠加热度因子(hotness,受 openviking/retrieve/memory_lifecycle.py 中 hotness_score 的半衰期逻辑影响,retrieval.hotness_alpha 控制其权重)。检索的统计与轨迹由 openviking/retrieve/retrieval_stats.py(零结果率、平均分、时延)和 context_assembler/ledger.py 中的 RecallLedger 记录,ledger.cooled_uris() 还能按回合对已召回内容做冷却去重,避免同一内容反复注入。
会话沉淀:把对话变成长期记忆
README 中的第 5 条能力——会话提交后,OpenViking 异步提取用户偏好和智能体经验,写入长期记忆——对应的是一条"提交-提取-落盘"的异步链路:
- 配置侧:
examples/ov.conf.example中queue_workers.session_commit.max_concurrent(默认 8)控制会话提交并发,memory段(version: "v2"、extraction_enabled: true、session_skill_extraction_enabled)控制记忆抽取的版本与范围,enable_memory_decay+memory_decay_check_interval: 3600开启按小时检查的记忆衰减; - 服务端侧:会话相关实现集中在 openviking/session/(85 个文件),提取出的偏好、经验按上文
PRESET_DIRECTORIES的类型化目录写入viking://user/{user_id}/memories/,写入即触发 L0/L1 生成与向量索引,下一次检索立刻可用。
这意味着 Agent 的"越用越懂你"不是玄学:偏好进 preferences、可复用做法进 patterns、踩过的坑进 cases/tools,全部是可 ov ls 看到、可 ov find 召回的文件记录。
评测结果:LoCoMo 与 tau2-bench
OpenViking 0.3.22 的评测覆盖两类场景(数据与实验设置以 README 及官方评测报告为准):
- 用户记忆(LoCoMo,长对话记忆问答):接入 OpenViking 后,三种 Agent 集成(OpenClaw、Hermes、Claude Code)准确率均达到 80%–83%,而各自原生记忆仅 24%–57%;同时输入 token 减少 34.3%–91.0%,查询时延降低 58.45%–66.10%。
- 智能体经验(tau2-bench,多轮智能体任务):经验记忆让任务成功率在 Retail 场景提升 6.87pp、Airline 场景提升 11.87pp(对比同一 LLM 无记忆基线)。
实验使用的模型:记忆评测以 Doubao 2.0 Pro 作为 VLM、Doubao-embedding-vision-251215 作为 Embedding 模型。复现脚本全部开源在 benchmark/ 目录下:benchmark/locomo/(按 Agent 分目录:openclaw、hermes、claudecode、mem0、supermemory、vikingbot、openviking)、benchmark/tau2/(含 llm/train/vikingbot 子目录)、benchmark/longmemeval/、benchmark/RAG/ 覆盖知识库问答场景,另有 benchmark/locomo/README.md 等说明各套件运行方式。
快速开始:安装、init、doctor、启动
环境要求:Python 3.10 或更高。
pip install openviking --upgrade
openviking-server init # 交互式向导:提供商、模型、ov.conf
openviking-server doctor # 校验配置
openviking-server # 启动
或后台运行:
nohup openviking-server > /data/log/openviking.log 2>&1 &
init 向导与配置落盘
init 会引导选择模型提供商并写入 ~/.openviking/ov.conf(可用 OPENVIKING_CONFIG_FILE 环境变量覆盖,见 openviking_cli/setup_wizard.py 中的 _config_path / _workspace 辅助函数——workspace 默认与 ov.conf 同目录,保证"一个挂载卷捕获全部状态")。支持的提供商包括:火山引擎、OpenAI、Codex OAuth、Kimi、GLM 和本地 Ollama;选 Ollama 时向导还能检测并安装运行时,按硬件拉取合适的模型。向导也允许"直接手改 ov.conf"(打开 $EDITOR 加载示例配置)。
ov.conf 是 JSON 格式,完整参考模板见 examples/ov.conf.example,关键段摘录:
{
"server": { "host": "0.0.0.0", "port": 1933, "root_api_key": null, "cors_origins": ["*"] },
"storage": {
"workspace": "./data",
"vectordb": { "name": "context", "backend": "local" },
"agfs": { "backend": "local", "cachefs": { "max_file_size_bytes": 1048576 } }
},
"embedding": {
"dense": {
"model": "doubao-embedding-vision-251215",
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"dimension": 1024,
"provider": "volcengine",
"input": "multimodal"
},
"max_input_tokens": 4096
},
"vlm": { "model": "doubao-seed-2-0-lite-260428", "provider": "volcengine", "temperature": 0.0 },
"rerank": { "provider": "vikingdb", "model_name": "doubao-seed-rerank", "threshold": 0.1 },
"auto_generate_l0": true,
"auto_generate_l1": true,
"memory": { "version": "v2", "extraction_enabled": true }
}
模板中还提供多套可替换的示例段:embedding_ollama_example(本地 Ollama,nomic-embed-text,768 维,免 API Key)、embedding_volcengine_plan_example(订阅制 Agent/Coding Plan 的 api_base 差异)、vlm_codex_example(Codex OAuth,token 存 ~/.openviking/codex_auth.json,可从已有 Codex CLI 认证文件引导)、vlm_kimi_example、vlm_glm_example、rerank_openai_example(OpenAI 兼容端点,如 DashScope qwen3-rerank)。此外 parsers 段覆盖 PDF(可选 MinerU 端点)、代码仓库、图片(OCR/VLM)、音频转写、视频抽帧、Markdown、网页抓取等解析器参数;encryption 段支持 local 主密钥、HashiCorp Vault、火山引擎 KMS 三种后端。
doctor:不启动服务器也能体检
doctor 的检查项在 openviking_cli/doctor.py 模块 docstring 中明确列出:配置文件、Python 版本、原生向量引擎、AGFS、Embedding 提供商、VLM 提供商、VikingBot 鉴权、磁盘空间。实现上有两个值得注意的细节:
- 它通过
OpenVikingConfig.from_dict(data)用与服务器启动完全相同的解析器校验ov.conf,因此能提前报出"未知字段/非法取值"这类启动时才会失败的问题; - 检查结果是 pass/warn/fail 三态,失败项附带可执行的修复建议(fix 字段),并区分
ov health(ping 一个运行中的服务器)与doctor(本地前置条件检查)。
ov 命令行:浏览、检索、重建索引
服务器启动后:
ov status
ov add-resource https://github.com/volcengine/OpenViking # 可加 --wait
ov ls viking://resources/
ov tree viking://resources/volcengine -L 2
# 没加 --wait 的话,语义处理需要等一段时间
ov find "what is openviking"
ov grep "openviking" --uri viking://resources/volcengine/OpenViking/docs/zh
add-resource 提交后进入异步摄取队列(queue_workers.add_resource.max_concurrent 默认 4,file_vectorization_concurrency 默认 8),L0/L1 生成与向量写入完成后才能被 ov find 语义命中——这就是"没加 --wait 要等一段时间"的原因。
重建已有索引(Rust CLI 实现见 crates/ov_cli/src/commands/content.rs 中 reindex(uri, mode, wait, dry_run, tags, tag_mode, recursive) 调用链):
| 命令 | 行为 |
|---|---|
ov reindex <uri> --mode vectors_only |
只刷新向量,不重算语义产物 |
ov reindex <uri> --mode semantic_and_vectors |
先重新生成 .abstract.md / .overview.md,再刷新向量 |
追加 --recursive=false |
只刷新目标目录自身的语义产物及 L0/L1 向量 |
--mode prune_orphans |
清理源文件已不存在的向量记录(加 --dry-run 预览,dry_run 参数在 content.rs 中透传) |
注意:不存在 semantic 或 full 这样的模式别名,README 特别强调这一点以避免误用。
客户端侧:ov config 可交互式初始化多服务器配置,ov config switch 在多服务器间切换。Rust CLI 的获取方式为 npm i -g @openviking/cli,或从源码构建 cargo install --git ... ov_cli;构建定义见 crates/ov_cli/Cargo.toml 与 crates/ov_cli/README_CN.md。官方 Docker 镜像也已提供(见 Dockerfile、docker-compose.yml 及 docker/ 目录)。
接入你的 Agent:召回注入 + 会话自动提交
集成层会把 OpenViking 的召回结果注入 Agent 上下文,并在会话结束/关键节点自动提交记忆。README 列出的集成对象与仓库中对应的代码资产:
| 集成对象 | 仓库内对应实现 |
|---|---|
| Claude Code | examples/claude-code-memory-plugin/(commands/hooks/skills/scripts 全套) |
| Codex | examples/codex-memory-plugin/(含 DESIGN.md 与 VERIFICATION.md) |
| OpenClaw | examples/openclaw-plugin/(27 个 TS 插件文件 + 58 个测试文件) |
| Hermes | benchmark/locomo/hermes 下的接入脚本 |
| Cursor | examples/cursor-memory-plugin/ |
| Trae | examples/trae-memory-hooks/ 与 examples/trae-cli-memory-hooks/ |
| OpenCode | examples/opencode-plugin/ |
| pi | examples/pi-coding-agent-extension/ |
| Agent Plugins 1.0 | agent-plugins/(plugin.json、mcp-proxy.mjs) |
| MCP 客户端 | openviking/server/mcp_endpoint.py 提供 MCP 端点 |
| LangChain / LangGraph | integrations/langchain/ 独立可安装包,另见 examples/langchain-langgraph/ |
除了"插件主动接入",服务端还支持反向摄取:ov.conf 的 ingest.harnesses 段可开启 claude_code、codex、opencode、hermes、openclaw 的会话解析(mode: both/backfill/watch),由 openviking/ingest/ 下的 poller/replay/orchestrator 把既有会话转写文件回填成长期记忆。
VikingBot:构建在 OpenViking 之上的 Agent 框架
VikingBot 是仓库内置的完整 Agent 框架(bot/vikingbot/,含 agent/channels/sandbox/skills/openviking_mount 等 20+ 模块),一键启用:
pip install "openviking[bot]"
openviking-server --with-bot
ov chat # 在另一个终端运行
官方 Docker 镜像内置 VikingBot,默认随服务器和控制台 UI 一起启动。配置对应 ov.conf 的 bot 段:bot.gateway(默认 127.0.0.1:18790)是消息网关,bot.ov_server 控制 VikingBot 反向连接 OpenViking 服务的鉴权。部署脚本见 bot/deploy/(docker/ecs/vke 三套),测试覆盖在 bot/tests/ 与 bot/vikingbot/tests/。
生产部署、商业版本与许可证
生产部署建议把 OpenViking 作为独立 HTTP 服务运行(默认端口 1933,server.root_api_key 可启用根密钥),Kubernetes 场景有现成的 Helm Chart(deploy/helm/ 与 examples/k8s-helm/),监控指标内置 Prometheus/OTel 导出器(server.observability.metrics.exporters,Grafana 仪表盘样例见 examples/grafana/)。
商业版本方面 README 明确表态:开源版本不会被削弱——本仓库以 AGPLv3 完整开源,不锁功能、不需要注册账号和激活码,可直接用于生产。火山引擎托管的 SaaS 版(个人版/企业版)与私有化部署版(在线 BYOC / 全内网离线)解决的是"谁来运维、部署在哪"的问题,开源用户可用迁移工具平滑迁入。
许可证按组件划分:
- 主项目:AGPLv3,见 LICENSE
crates/ov_cli:Apache 2.0,见 crates/LICENSEexamples:Apache 2.0,见 examples/LICENSEthird_party:各三方项目(leveldb、rapidjson、spdlog、croaring、krl)保留原有协议
研究背景:OpenViking 开源了 VikingMem 论文(arXiv:2605.29640,VLDB 2026)中描述的部分核心能力,论文题为 "VikingMem: A Memory Base Management System for Stateful LLM-based Applications"。
生态与贡献:已确认的合作伙伴项目包括 deer-flow(长周期 SuperAgent 框架)、NoKV(AI 原生分布式文件系统)、loopx(轻量级循环工程状态内核)、Hermes Agent;贡献指南见 CONTRIBUTING_CN.md,安全漏洞报告方式见 SECURITY.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
