OpenViking 存储架构详解:VikingFS 抽象层、AGFS/RAGFS 内容存储与向量索引双层设计
【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking
OpenViking 的存储子系统采用“内容存储与索引存储分离”的双层架构:上层 VikingFS 提供统一的 URI 虚拟文件系统抽象,下层由 AGFS(Rust 重写后的 RAGFS)负责 L0/L1/L2 全量内容与多媒体的持久化,向量索引则只保存 URI、向量与元数据。读懂这套架构,你就能理解 OpenViking 中一次rm/mv文件操作如何自动同步向量库记录、多写模式下主备后端如何通过隐藏文件跟踪同步进度,以及上下文目录为何统一呈现.abstract.md/.overview.md/ 明细文件 的三层结构。
双层存储总体架构
OpenViking 的存储架构可以用下图概括:
┌─────────────────────────────────────────┐ │ VikingFS (URI Abstraction) │ │ URI Mapping · Hierarchical Access │ └────────────────┬────────────────────────┘ ┌────────┴────────┐ │ │ ┌───────▼────────┐ ┌─────▼───────────┐ │ Vector Index │ │ AGFS │ │ (Semantic │ │ (Content │ │ Search) │ │ Storage) │ └────────────────┘ └─────────────────┘两层存储的职责划分如下:
| 层 | 职责 | 存放内容 |
|---|---|---|
| AGFS | 内容存储 | L0/L1/L2 全量内容、多媒体文件 |
| Vector Index | 索引存储 | URI、向量、元数据(不存文件内容) |
这一分离设计带来四个直接收益:
- 职责清晰:向量索引负责检索(Retrieval),AGFS 负责存储(Storage);
- 内存优化:向量索引不保存文件内容,显著降低内存占用;
- 单一数据源:所有内容从 AGFS 读取,向量索引只保存引用,避免内容双写导致的不一致;
- 独立扩展:向量索引与 AGFS 可以分别水平扩展。
一个重要的演进事实是:AGFS 已经重写为 Rust 实现,即 RAGFS。仓库中crates/ragfs/目录(含 Cargo.toml 与 ORIGIN.md)承载这一实现,Python 侧配置模型 AGFSConfig 的 docstring 也直接标注为 “Configuration for RAGFS (Rust-based AGFS)”。
VikingFS 虚拟文件系统
VikingFS 是统一 URI 抽象层,它屏蔽底层存储细节,让上层(Python SDK、HTTP API、CLI 文件系统接口)始终面对同一套viking://寻址语义。URI 的完整规范(scope、~家目录别名、路径变量等)见 Viking URI。
URI 映射
VikingFS 将逻辑 URI 映射为物理存储路径:
viking://resources/docs/auth → /local/{account_id}/resources/docs/auth viking://~/memories → /local/{account_id}/user/{user_id}/memories viking://~/skills → /local/{account_id}/user/{user_id}/skills其中{account_id}与{user_id}由服务端根据请求认证身份填充;viking://~展开为当前调用者的用户根目录,因此同一字符串对不同调用者指向不同物理目录。
核心 API
VikingFS 对外暴露的最小操作集合:
| 方法 | 说明 |
|---|---|
read(uri) | 读取文件内容 |
write(uri, data) | 写入文件 |
mkdir(uri) | 创建目录 |
rm(uri) | 删除文件/目录(同步删除向量记录) |
mv(old, new) | 移动/重命名(同步更新向量记录中的 URI) |
abstract(uri) | 读取 L0 摘要 |
overview(uri) | 读取 L1 概览 |
find(query, uri) | 语义搜索 |
源码中的 VikingFS 组织
从源码结构看,VikingFS 实现位于 openviking/storage/viking_fs/,按关注点拆分为多个私有模块:_ops.py(文件操作)、_semantic.py(语义搜索)、_sync.py(向量同步)、_vector.py(向量记录)、_access.py(访问控制)、_grep.py(文本检索)、_snapshot.py(快照)等。
VikingFS 以单例方式初始化,入口函数init_viking_fs的签名(openviking/storage/viking_fs/_base.py)清晰展示了它与下层两个子系统的依赖关系:
def init_viking_fs( agfs: Any, # 预初始化的 AGFS/RAGFS 客户端 query_embedder: Optional[Any] = None, # 查询向量化器 rerank_config: Optional["RerankConfig"] = None, vector_store: Optional["VikingVectorIndexBackend"] = None, # 向量索引后端 acl_manager: Optional["AclManager"] = None, retrieval_config: Optional["RetrievalConfig"] = None, grep_config: Optional["GrepConfig"] = None, timeout: int = 10, enable_recorder: bool = False, encryptor: Optional[Any] = None, ): ...可以看到 VikingFS 的构造直接注入agfs(内容侧)与vector_store(索引侧)两个依赖,这正是“双层存储”在代码层面最直接的体现。
AGFS 后端存储
AGFS 提供 POSIX 风格的文件操作,并支持多种后端。当前配置模型见 openviking_cli/utils/config/agfs_config.py。
单后端与多写模式
默认情况下 AGFS 使用单一后端存储内容。一旦配置了storage.agfs.backups,OpenViking 即进入多写模式:
- 顶层
storage.agfs.backend是主后端,始终是权威的写入目标; storage.agfs.backups.items[]定义备份后端,用于副本、迁移或读加速;- Python SDK、HTTP API、CLI 文件系统接口在多写模式下保持不变;
- 多写内部通过
.redirect.json与.sync_log.json两个隐藏文件跟踪重定向映射和同步进度,这些文件对用户不可见。
配置模型中与此相关的字段(openviking_cli/utils/config/agfs_config.py):
backups: Optional[dict[str, Any]] = Field( default=None, description="Multi-write backups configuration. None = single backend mode." ) redirects: Optional[List[dict[str, Any]]] = Field( default=None, description="Primary redirect policies." )并带有一条一致性校验:redirects只有在配置了backups时才允许存在——单后端模式不支持重定向策略(源码中的校验信息为 “redirects requires backups; single-backend mode does not support redirects”)。多写的完整概念模型(主/备角色、路由、一致性)见 Multi-Write Storage,实操示例见 Multi-Write Storage Guide。
后端类型
文档层面给出的后端一览:
| 后端 | 说明 | 关键配置 |
|---|---|---|
localfs | 本地文件系统 | path |
s3fs | S3 兼容存储 | bucket、endpoint |
memory | 内存存储(测试用) | - |
从当前源码看,RAGFS 迁移后AGFSConfig.backend的取值被校验为'local' | 's3' | 'memory'(openviking_cli/utils/config/agfs_config.py),即文档表格中的localfs/s3fs命名在配置项层面演化为local/s3。选择s3后端时,配置会被展开到S3Config子模型(openviking_cli/utils/config/agfs_config.py),其核心字段包括:
| 字段 | 默认值 | 说明 |
|---|---|---|
bucket | - | S3 桶名(必填) |
region | - | 区域,如us-east-1、cn-beijing(必填) |
access_key/secret_key | - | 访问密钥;未提供时 RAGFS 可尝试环境变量或 IAM 角色(必填校验) |
endpoint | - | 自定义 S3 端点,MinIO/LocalStack 等 S3 兼容服务必填,标准 AWS S3 留空(必填校验) |
prefix | "" | 键前缀,用于命名空间隔离 |
use_ssl | True | 是否启用 HTTPS |
use_path_style | True | MinIO 等用 path-style;TOS 等部分服务用 virtual-host-style |
directory_marker_mode | empty | S3 目录标记持久化方式:none/empty(零字节标记)/nonempty |
disable_batch_delete | False | 禁用 DeleteObjects 批量删除;某些 S3 兼容服务(要求 DeleteObjects 携带 Content-MD5)需要置为True |
normalize_encoding_chars | "?#%+@" | 对象键中需转义为!HH十六进制的字符,置空可关闭键归一化 |
auto_detect_content_type | False | 上传时按扩展名推断 Content-Type(默认关闭以保持向后兼容) |
此外,AGFSConfig还内嵌了三组与文件系统运行相关的子配置:queuefs(任务队列,默认sqlite后端)、cachefs(读缓存,默认 local、单文件缓存上限 1MB)、pathlock(原生路径锁,锁过期时间默认 30 秒),分别对应内容写入队列、读加速与并发路径互斥。AGFSConfig采用extra="forbid"严格模式,port、url、mode、impl、lib_path等旧版 AGFS 字段被标记为废弃并直接忽略(仅打警告),这体现了向 RAGFS 迁移过程中的兼容性策略。
上下文目录的统一结构
每个上下文目录遵循统一的三层文件结构:
viking://resources/docs/auth/ ├── .abstract.md # L0 abstract ├── .overview.md # L1 overview └── *.md # L2 detailed content.abstract.md是 L0 摘要(约 100 token),对应 VikingFS API 中的abstract(uri);.overview.md是 L1 概览(约 2k token),对应overview(uri);- 明细文件(L2)才是完整内容。
这一约定让 L0/L1/L2 上下文分层(见 Context Layers)在物理存储层面有了确定性的落盘位置,而不只是检索时的逻辑概念。
向量索引
向量索引存放语义索引,支持向量搜索与标量过滤,本身不保存文件内容。
上下文集合 Schema
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 主键 |
uri | string | 资源 URI |
parent_uri | string | 父目录 URI |
context_type | string | resource/memory/skill |
is_leaf | bool | 是否叶子节点 |
vector | vector | 稠密向量 |
sparse_vector | sparse_vector | 稀疏向量 |
abstract | string | L0 摘要文本 |
name | string | 名称 |
description | string | 描述 |
created_at | string | 创建时间 |
active_count | int64 | 使用次数 |
其中id是确定性主键:对 L2(普通文件)记录,id = md5(f"{account_id}:{uri}"),由stat()等元数据接口返回,调用方无需额外查找即可在向量记录与文件之间交叉引用;文件移动 URI 后向量记录会随 URI 迁移重新定键。
索引策略
index_meta = { "IndexType": "flat_hybrid", # Hybrid index(稠密+稀疏混合) "Distance": "cosine", # 余弦距离 "Quant": "int8", # 向量量化 }flat_hybrid意味着同时维护稠密向量与稀疏向量索引,配合 int8 量化在精度与内存之间取平衡。
后端支持
| 后端 | 说明 |
|---|---|
local | 本地持久化 |
http | HTTP 远程服务 |
volcengine | 火山引擎 VikingDB |
从源码结构看,三类后端分别对应 openviking/storage/vectordb/collection/ 下的 local_collection.py、http_collection.py、volcengine_collection.py(另有vikingdb_collection.py封装 VikingDB 客户端);索引层位于 openviking/storage/vectordb/index/,除通用index.py外还包含local_index.py与cuvs_index.py(cuVS GPU 索引实验)。集合 Schema 与一致性工具集中在 collection_schemas.py 和 index_consistency.py,向量索引后端的顶层抽象是 viking_vector_index_backend.py 与 vikingdb_manager.py。
向量同步机制
VikingFS 自动维护向量索引与 AGFS 之间的一致性,使“文件系统操作”与“索引状态”永远同进退。
删除同步
viking_fs.rm("viking://resources/docs/auth", recursive=True) # 自动从向量索引中删除所有该 URI 前缀的记录删除文件/目录时,VikingFS 会按 URI 前缀批量清除向量索引中对应的全部记录,避免检索结果中出现指向已删内容的“幽灵引用”。
移动同步
viking_fs.mv( "viking://resources/docs/auth", "viking://resources/docs/authentication" ) # 自动更新向量索引中的 uri 与 parent_uri 字段重命名/移动目录时,向量记录不会“删除后重建”,而是原子地更新uri与parent_uri两个字段,保证层级关系(父目录指针)在移动后依然正确。
实现上,这一同步逻辑从源码结构看落在 openviking/storage/viking_fs/_sync.py 模块中,与_ops.py的文件操作、_vector.py的向量记录读写配合完成。
小结与延伸阅读
OpenViking 的存储架构核心在于三点:VikingFS 作为唯一入口统一了 URI 语义与文件操作;AGFS/RAGFS 以纯内容层的身份承担 L0/L1/L2 与多媒体落盘,并可通过backups进入多写模式;向量索引只保存 URI、向量与元数据,靠rm/mv的同步钩子与内容层保持一致。围绕这套架构,可继续深入以下文档:
- Architecture Overview — 系统整体架构
- Context Layers — L0/L1/L2 上下文模型
- Viking URI — URI 规范、scope 与路径变量
- Multi-Write Storage — 主/备角色、路由与一致性
- Retrieval Mechanism — 检索流程细节
【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考