news 2026/9/10 7:19:08

OpenViking OVPack:.ovpack 数据包的导入导出与备份恢复完整实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenViking OVPack:.ovpack 数据包的导入导出与备份恢复完整实践

OpenViking OVPack:.ovpack 数据包的导入导出与备份恢复完整实践

【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking

OVPack 是 OpenViking 提供的数据迁移与备份机制,用于将 Viking URI 下的资源树打包为.ovpack文件并在目标环境完整恢复。本文基于 OVPack API 文档 与仓库源码,讲清四个核心接口(export / import / backup / restore)的参数、冲突与向量策略,并深入.ovpack文件的内部格式、完整性校验与源码调用链,读完后可独立完成 OpenViking 数据的迁移、备份与恢复。

一、OVPack API 总览

OVPack API 挂载在/api/v1/pack路由下(见 路由定义),共提供四个接口,覆盖"导出—导入—备份—恢复"完整链路:

接口路径用途权限要求
export_ovpackPOST /api/v1/pack/export将指定 URI 下资源导出为.ovpack文件流ROOT / ADMIN / USER
import_ovpackPOST /api/v1/pack/import.ovpack文件导入到指定父级 URIROOT / ADMIN / USER
backup_ovpackPOST /api/v1/pack/backup将全部公开 scope 备份为 restore-only 包仅 ROOT / ADMIN
restore_ovpackPOST /api/v1/pack/restore恢复 backup 生成的备份包到原始 scope root仅 ROOT / ADMIN

从源码结构看,权限控制在路由层通过装饰器实现:export 和 import 使用@require_auth_role(Role.ROOT, Role.ADMIN, Role.USER),而 backup 与 restore 使用更严格的@require_auth_root_or_admin(见 pack.py 路由 与 backup 路由)。服务层PackService在 backup/restore 时还会通过_account_maintenance_ctx将 ADMIN 上下文的角色提升为 ROOT 执行账号级维护,但保持 URI 归属不变(见 PackService)。

二、.ovpack 文件格式解剖

.ovpack本质是一个 ZIP 压缩包,导出时用户内容原样放在<root>/files/下,内部元数据放在<root>/_ovpack/下。这些目录名在 format.py 中定义为常量:OVPACK_INTERNAL_DIR = "_ovpack"OVPACK_FILES_DIR = "files",包的类型标识为kind: "openviking.ovpack"

包内关键文件:

文件作用
<root>/_ovpack/manifest.json包清单,含format_versionkindrootentriesindex等字段
<root>/_ovpack/index_records.jsonl可迁移的索引标量记录(每行一个 JSON 对象)
<root>/_ovpack/dense.f32仅当include_vectors=true时存在;纯 dense float32 向量快照,little-endian
<root>/files/...用户内容文件,路径相对于导出 root

manifest 的核心语义(来自 manifest.py 与 format.py):

  • entries[].path是相对导出 root 的路径,空字符串""表示 root 目录本身;每个条目kind必须是directoryfile
  • 文件条目包含sizesha256;整体content_sha256是对按路径排序后的文件列表(pathsizesha256)做规范化 JSON 序列化后的 SHA-256,实现见 manifest_content_sha256。
  • iduriaccount_idcreated_atupdated_atactive_count等运行态字段会在目标环境重新生成,不从包内恢复——这是迁移不产生 ID 冲突的关键设计。
  • 当前支持的format_version3OVPACK_FORMAT_VERSION = 3,见 format.py)。导入时版本不匹配会被直接拒绝,错误信息会同时给出包内版本与当前支持版本(见 read_manifest)。
  • OVPack 不额外设置包大小、文件数量或目录深度上限;实际可处理规模由 ZIP、存储后端和运行环境决定。

安全方面,导入时对 ZIP 成员路径做了严格校验:拒绝反斜杠、绝对路径、Windows 盘符、..逃逸段,并要求所有条目位于<base_name>/之下(见 validate_ovpack_member_path),防止恶意构造的包污染存储目录。

三、export_ovpack:导出资源树

处理流程:验证用户权限 → 遍历指定 URI 下的资源 → 写入内容文件和 manifest → 打包成 zip(.ovpack)→ 以文件流形式返回。

参数

参数类型必填默认值说明
uristring-要导出的 Viking URI
include_vectorsbooleanfalse导出纯 dense 向量快照;底层 index type 为 hybrid 时会拒绝

权限要求:ROOT、ADMIN 或 USER,且仍受常规 URI 访问控制约束。

使用示例

HTTP API

curl -X POST http://localhost:1933/api/v1/pack/export \ -H "Content-Type: application/json" \ -H "X-API-Key: your-admin-key" \ -d '{ "uri": "viking://resources/my-project/", "include_vectors": false }' \ --output my-project.ovpack

此接口直接返回文件流(Content-Type: application/zip),不返回 JSON 包装体。从源码看,路由层先把包写入临时文件export_<随机hex>.ovpack,再经FileResponse流式返回,文件名取 URI 末段并补.ovpack后缀,响应完成后通过BackgroundTask清理临时文件(见 export_ovpack 路由)。

CLI

# 导出资源 ov export viking://resources/my-project/ ./exports/my-project.ovpack # 导出 dense 向量快照 ov export viking://resources/my-project/ ./exports/my-project.ovpack --include-vectors

TypeScript SDK

const outputPath = await client.exportOVPack( "viking://resources/docs/", "./exports/docs.ovpack", true, ); console.log(outputPath);

Go SDK

outPath, err := client.ExportOVPack( ctx, "viking://resources/my-project/", "./exports/my-project.ovpack", &openviking.PackOptions{IncludeVectors: false}, ) if err != nil { return err } fmt.Println(outPath)

Python SDK(HTTP SDK 会自动处理下载;导出功能也主要通过 CLI 使用):

import openviking as ov client = ov.SyncHTTPClient(url="http://localhost:1933", api_key="your-admin-key") client.initialize()

CLI 端ov export命令由 handle_export 接收入口,统一转发到 HTTP 客户端的 pack 命令模块。

四、import_ovpack:导入与迁移

处理流程:验证用户权限 → 解析上传的.ovpack文件 → 校验 manifest 元数据、路径、文件和目录集合、文件大小和 checksum → 应用on_conflict→ 导入资源到目标位置并重建向量。

参数

参数类型必填默认值说明
temp_file_idstring-临时上传文件 ID(通过 temp_upload 获取)
parentstring-目标父级 URI(导入到此处)
on_conflictstringfail冲突策略:failoverwriteskip
vector_modestringauto向量处理方式:autorecomputerequire

权限要求:ROOT、ADMIN 或 USER。请求模型对额外字段采用extra="forbid"策略,API 已不再接受旧的vectorizeforce参数(见 ImportRequest)。

向量处理策略 vector_mode

  • auto:存在兼容 dense 快照时直接恢复,否则重新向量化;
  • recompute:总是忽略包内向量,重新计算;
  • require:要求必须存在兼容 dense 快照,否则导入失败。

dense 快照的兼容性会比较 embedding provider、model、input、query/document 参数和维度。从源码看,这些元数据在导出时由 embedding_snapshot_metadata 从当前 embedding 配置中采集(providermodelinputquery_paramdocument_paramdimensions),导入时逐一比对,任何一项不一致都视为不兼容。

完整性与冲突行为

导入校验相当严格,以下情况都会被拒绝:

  • 没有 manifest 的包(无法提供内容完整性校验);
  • 带 manifest entries 的包缺少内容文件或目录、混入额外文件或目录、文件大小不同、单文件sha256不同,或整体content_sha256缺失/不匹配;
  • manifestformat_version不是当前支持版本(3)的包;
  • viking://resources/这类顶级 scope 包必须导入到viking://

冲突策略(root 级):

  • on_conflict=fail(默认):目标 root 已存在时返回结构化的409 CONFLICT
  • on_conflict=overwrite:替换已有目标 root;
  • on_conflict=skip:保留已有目标 root,直接返回该路径,不写入包内容。注意skip是 root 级跳过,不是文件级补齐。

其他行为细节:

  • Session 文件属于 user 命名空间(viking://user/{user_id}/sessions/...),恢复后不触发向量化;
  • .abstract.md.overview.md作为语义侧边文件一并恢复;.relations.json和 OVPack 内部文件(_ovpack/)会被排除;
  • manifest index 标量中的context_type如果存在,必须和最终导入路径语义一致;
  • OVPack 不额外设置导入包大小、文件数量或目录深度上限。

使用示例

HTTP API(两步:先 temp_upload 再 import):

# 第一步:上传 .ovpack 文件 TEMP_FILE_ID=$( curl -s -X POST http://localhost:1933/api/v1/resources/temp_upload \ -H "X-API-Key: your-admin-key" \ -F "file=@./exports/my-project.ovpack" \ | jq -r '.result.temp_file_id' ) # 第二步:导入 curl -X POST http://localhost:1933/api/v1/pack/import \ -H "Content-Type: application/json" \ -H "X-API-Key: your-admin-key" \ -d "{ \"temp_file_id\": \"$TEMP_FILE_ID\", \"parent\": \"viking://resources/imported/\", \"on_conflict\": \"overwrite\", \"vector_mode\": \"auto\" }"

CLI

# 导入 .ovpack 文件 ov import ./exports/my-project.ovpack viking://resources/imported/ # 显式冲突策略 ov import ./exports/my-project.ovpack viking://resources/imported/ --on-conflict overwrite # 要求恢复兼容 dense 向量快照 ov import ./exports/my-project.ovpack viking://resources/imported/ --vector-mode require

TypeScript SDK

const uri = await client.importOVPack( "./exports/docs.ovpack", "viking://resources/", { onConflict: "overwrite", vectorMode: "auto", }, ); console.log(uri);

Go SDK

uri, err := client.ImportOVPack( ctx, "./exports/my-project.ovpack", "viking://resources/imported/", &openviking.ImportPackOptions{ OnConflict: "overwrite", VectorMode: "auto", }, ) if err != nil { return err } fmt.Println(uri)

响应示例

{ "status": "ok", "result": { "uri": "viking://resources/imported/my-project/" }, "telemetry": { "operation_id": "550e8400-e29b-41d4-a716-446655440000" } }

冲突错误示例

{ "status": "error", "error": { "code": "CONFLICT", "message": "Resource already exists at viking://resources/imported/my-project. Use on_conflict='overwrite' to replace it.", "details": { "resource": "viking://resources/imported/my-project" } } }

从源码看,import 路由先用TempUploadStore.resolve_for_consumetemp_file_id解析为本地文件并校验归属,导入完成后在finally中清理临时文件(见 import_ovpack 路由),临时上传本身有独立的 temp_upload 接口 可查。

五、backup_ovpack:账号级全量备份

backup_ovpack将公开 scope root 备份为只能通过 restore 恢复.ovpack文件。备份包含:

  • resources全部公开资源;
  • 当前账号下所有user/{user_id}内容;session 通过 user 命名空间下的user/{user_id}/sessions一起包含。

不包含tempqueue等内部运行态数据,也不包含用户账号或 API Key。该接口仅允许 ROOT 或 ADMIN 调用。

设置include_vectors=true时额外导出兼容的纯 dense 向量快照;底层 index type 为 hybrid 时会拒绝导出向量快照。从源码看,这个限制由 ensure_dense_snapshot_supported 实现:它读取向量索引元数据中的VectorIndex.IndexType,一旦包含hybrid即抛出 "ovpack vector snapshots only support pure dense vector indexes" 错误。

重要限制:备份是在线逐文件读取,不保证同一时刻的原子快照。需要严格一致性时,调用方应在备份窗口暂停写入。

使用示例

HTTP API

curl -X POST http://localhost:1933/api/v1/pack/backup \ -H "Content-Type: application/json" \ -H "X-API-Key: your-admin-key" \ -d '{"include_vectors":false}' \ --output openviking-backup.ovpack

Go SDK

outPath, err := client.BackupOVPack( ctx, "./backups/openviking.ovpack", &openviking.PackOptions{IncludeVectors: true}, ) if err != nil { return err } fmt.Println(outPath)

CLI

ov backup ./backups/openviking.ovpack ov backup ./backups/openviking.ovpack --include-vectors

响应:HTTP 成功时返回application/zip字节流,不使用标准 JSON 响应包:

HTTP/1.1 200 OK Content-Type: application/zip Content-Disposition: attachment; filename="openviking-backup.ovpack" <ovpack binary body>

Go SDK 和 CLI 将字节流写入指定路径,并返回或输出该本地路径。

六、restore_ovpack:备份恢复

restore_ovpack恢复backup_ovpack生成的备份包到原始公开 scope root;普通 import 不接受备份包。该接口仅允许 ROOT 或 ADMIN 调用,并恢复当前账号下包内所有用户路径。向量处理遵循vector_mode;user 命名空间下的 session 文件只恢复文件状态,不触发向量化。

参数

参数类型必填默认值说明
temp_file_idstring-临时上传文件 ID
on_conflictstringfail冲突策略:failoverwriteskip
vector_modestringauto向量处理方式:autorecomputerequire

合并覆盖语义

  • on_conflict=overwrite使用合并覆盖:包内缺失于目标的路径会创建,同路径会覆盖,目标独有路径会保留;不会删除整个viking://resourcesviking://user。向量只更新包内新增或覆盖的内容。
  • skip仍是 scope root 级跳过,但返回前也会完整校验 manifest、内容 checksum 和向量元数据——损坏的备份不会因为skip而返回成功

账号前提

OVPack 不创建用户账号或恢复 API Key。新环境恢复后,需要使用包内相同的user_id创建用户,并使用目标环境新生成的 API Key。

使用示例

HTTP API

TEMP_FILE_ID=$( curl -s -X POST http://localhost:1933/api/v1/resources/temp_upload \ -H "X-API-Key: your-admin-key" \ -F "file=@./backups/openviking.ovpack" \ | jq -r '.result.temp_file_id' ) curl -X POST http://localhost:1933/api/v1/pack/restore \ -H "Content-Type: application/json" \ -H "X-API-Key: your-admin-key" \ -d "{\"temp_file_id\":\"$TEMP_FILE_ID\",\"on_conflict\":\"overwrite\",\"vector_mode\":\"auto\"}"

Go SDK

uri, err := client.RestoreOVPack( ctx, "./backups/openviking.ovpack", &openviking.ImportPackOptions{ OnConflict: "overwrite", VectorMode: "require", }, ) if err != nil { return err } fmt.Println(uri)

CLI

ov restore ./backups/openviking.ovpack --on-conflict overwrite ov restore ./backups/openviking.ovpack --on-conflict overwrite --vector-mode require

响应

{ "status": "ok", "result": { "uri": "viking://" } }

uri是备份恢复到的公开 scope root。

七、源码调用链速览

从源码结构看,OVPack 的完整调用链为三层:

HTTP 路由(openviking/server/routers/pack.py) └─ PackService(openviking/service/pack_service.py) └─ openviking/storage/ovpack/operations.py ├─ format.py # ZIP 路径、checksum、路径安全校验 ├─ manifest.py # manifest 解析与结构校验 ├─ index.py # 索引标量记录 ├─ policy.py # root/scope 策略 ├─ validation.py # 内容完整性校验 └─ vectors.py # dense 快照与兼容性 CLI:crates/ov_cli/src/handlers.rs(handle_export / handle_import / handle_backup / handle_restore)

关键实现细节对应关系:

  • 导出/备份流式返回:路由层生成随机临时文件 →FileResponseapplication/zip流式下发 →BackgroundTask清理(见 pack.py);
  • 备份/恢复提权_account_maintenance_ctx仅允许 ROOT/ADMIN,并将执行上下文角色提升为 ROOT 以覆盖账号下全部 user 命名空间(见 pack_service.py);
  • 格式版本硬约束format_version != 3的包直接拒绝,避免跨版本数据损坏(见 manifest.py);
  • 混合索引保护:hybrid 索引下禁用向量快照导出,防止快照语义失真(见 vectors.py)。

八、相关文档

  • OVPack 指南 - 格式、迁移和操作流程
  • 快照 - 工作区版本管理
  • 临时上传 - 上传待导入的包

【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 7:18:29

连续打卡17天:从新鲜感到惯性,一场关于自律的真实实验

2026年2月4日&#xff0c;Day17&#xff0c;我在打卡表上划掉今天的格子时&#xff0c;突然想把它单独拎出来写一篇。原因很简单&#xff1a;"第17天"这个数字卡在一个相当微妙的位置——比"连续一周"更有说服力&#xff0c;又远没有"满月""…

作者头像 李华
网站建设 2026/9/10 7:16:00

NLTK vs Spacy:自然语言处理实战对比与选型指南

1. 选型先想明白&#xff1a;NLTK和Spacy的设计逻辑决定了你的学习路径如果你今天问一个刚接触NLP的人该从哪套工具开始&#xff0c;十有八九会得到同一个答案&#xff1a;NLTK和Spacy。奇怪的是&#xff0c;这两个库放在一起总是让新人头疼——NLTK像是教科书附赠的瑞士军刀&a…

作者头像 李华
网站建设 2026/9/10 7:15:58

AI文本人性化实战:从机器味到人味的完整改写技能包

如果你最近也在留意“humanizer”这个热词&#xff0c;大概率是因为你开始觉得&#xff1a;AI写的东西越来越像“标准答案”&#xff0c;读着顺&#xff0c;却记不住&#xff0c;改起来更别扭。这个词的字面意思是“人性化”&#xff0c;但在实际使用场景里&#xff0c;它指的往…

作者头像 李华
网站建设 2026/9/10 7:15:36

PLC数字量输出点控制变频器:花式喷泉控制系统实战解析

1. 这个项目到底在做什么&#xff1a;花式喷水池的控制需求拆解先说结论&#xff1a;花式喷水池的核心&#xff0c;不是“喷水”&#xff0c;而是“花式”——也就是说&#xff0c;水型能不能变换、节奏能不能跟上音乐、N个喷头之间能不能协调动作。而这些动作的背后&#xff0…

作者头像 李华
网站建设 2026/9/10 7:15:33

STM32F103RC驱动W5500以太网性能优化实战

简介&#xff1a;本资源是一套面向嵌入式物联网开发者的STM32以太网性能实测工程&#xff0c;聚焦STM32F103RC与W5500芯片的多种通信模式对比验证&#xff0c;适用于单片机初学者进阶实践及工业现场网络速率评估需求。压缩包含458个文件&#xff0c;主体为156个头文件&#xff…

作者头像 李华