OpenViking 资源接入实战:深入解析ov add-resource导入管线与语义化处理
【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking
ov add-resource是 OpenViking 上下文数据库的核心入口命令,负责把本地文件、目录、ZIP 压缩包、URL 与 Git 仓库等外部资源导入统一的viking://resources/命名空间,并触发后台的解析、语义抽取与向量化处理。本文以官方技能文档 add-resource.md 为骨架,结合仓库中 Rust CLI(commands/resources.rs)、HTTP 路由(resources.py)、资源服务(resource_service.py)与 URI 校验(uri_validation.py)等源码实现,完整讲解该命令的全部参数、目标定位规则、异步处理模型与定时刷新机制,读完即可在真实项目中熟练导入并管理自己的资源库。
一、ov add-resource是什么:从外部世界到上下文数据库的入口
OpenViking 将 Agent 的记忆、知识库(RAG)与技能统一收敛到一个自演进式的上下文数据库(Self-evolving Context Database)中。其中"知识"的进入通道就是资源导入:ov add-resource把各类外部来源转换成以viking://resources/为根的上下文资源,并交由后台完成文件解析、语义抽取(semantic extraction)与向量化。
从代码结构看,这条命令是一个"CLI 前站 + 服务端管线"的两段式实现:
- CLI 侧:Rust 编写的 ov_cli 负责参数组装与请求发送;当
path指向本地已存在的文件或目录时,客户端会优先走临时上传(temp upload)通道,把内容上传到服务端再触发导入,而不是让服务端直接读本地磁盘。 - 服务端侧:FastAPI 路由
POST /api/v1/resources(见 resources.py)接收AddResourceRequest请求模型,经 URI 解析与权限校验后,转交给 ResourceService.add_resource 进入异步处理队列。
官方技能包 ov-resources 就是围绕这组命令组织的,add-resource是其中的第一个核心操作,配套的ov ls、ov tree、ov search等命令则负责浏览与检索已导入的资源。
二、支持的资源来源(Source Types)
ov add-resource支持五类来源,官方文档中的对照表如下:
| 类型 | 示例 |
|---|---|
| 本地文件 | ./docs/api.md、./team_building.jpg、/User/volcengine/Documents/profile.pdf |
| 本地目录 | /User/volcengine/Photo/Travels/2026/ |
| ZIP 压缩包 | ./docs-of-project.zip(由服务端解压) |
| URL | https://example.com/guide.md、https://arxiv.org/pdf/2602.09540 |
| Git 仓库 | https://github.com/volcengine/OpenViking、git@code.xxxx.org:viking/viking.git |
关于来源还有两个值得注意的实现细节:
- HTTP 场景下的本地路径限制:服务端在 local_input_guard.py 中通过
require_remote_resource_source明确拒绝"直接在 HTTP 请求里携带主机本地文件路径"的行为,只接受远程 URL 或经/api/v1/resources/temp_upload上传得到的temp_file_id。CLI 之所以能导入本地文件,正是因为它在客户端完成了"本地文件 → 临时上传 →temp_file_id"的转换。 add_type显式 Connector 路由:请求模型支持add_type(如tos、git),一旦显式声明,请求会路由到 Connector 集成,要求必须有精确的to目标,且不能与temp_file_id、parent组合(校验逻辑见 resources.py)。
三、基本用法:五种来源的实操命令
# 从 URL 导入 ov add-resource https://github.com/volcengine/OpenViking ov add-resource https://arxiv.org/pdf/2602.09540 # 从本地文件导入 ov add-resource ./docs/api-spec.md ov add-resource ./team_building.jpg ov add-resource /User/volcengine/Documents/project.docx # 从本地目录导入(可配合过滤规则) ov add-resource /User/volcengine/Photo/Travels/2026/ --include "*.jpg,*.jpeg,*.png" # 从 ZIP 压缩包导入 ov add-resource ./docs-of-project.zip默认情况下,资源会落在共享的viking://resources/根下,并由服务端自动生成目标 URI。如果需要精确控制落点,请参考下一节的目标定位参数。
四、目标位置:--to、--parent与--parent-auto-create
资源导入到哪个viking://URI 由三个互斥参数决定。CLI 侧在 handlers.rs 中强制校验"--to、--parent、--parent-auto-create三者只能选一个";Rust 客户端在组装请求时,会把--parent-auto-create映射为请求体里的create_parent=true(见 client.rs),这样对不支持该字段的旧服务端也能保持兼容。
# 精确目标(目标 URI 必须不存在,否则视为增量更新) ov add-resource ./docs --to "viking://resources/2026/2026-01-01/" # 放到已存在的父目录下 ov add-resource ./docs --parent "viking://resources/docs/" # 放到当前用户的私有资源根下 ov add-resource ./docs --parent "viking://~/resources/docs/" # 放到某个特定 peer 的私有资源根下 ov add-resource ./docs --parent "viking://user/alice/peers/web-visitor-alice/resources/docs/" # 父目录不存在时自动创建 ov add-resource ./docs --parent-auto-create "viking://resources/docs/2026/05/07" # 使用 URI 模板(-p 是 --parent 的简写),自动填充今天的日期 ov add-resource ./docs -p "viking://resources/docs/{calendar:today}"4.1 URI 模板变量:{calendar:today}等路径变量
--parent-auto-create/-p支持由 path_variables.py 提供的 URI 模板解析。服务端路由在进入资源服务前,会先调用resolve_path_variables展开变量,再交给validate_content_target_uri做格式校验(见 resources.py)。可用变量包括:
| 变量 | 示例输出 |
|---|---|
{calendar:today} | 2026/05/07 |
{calendar:yesterday} | 2026/05/06 |
{calendar:tomorrow} | 2026/05/08 |
{calendar:year} | 2026 |
{calendar:month} | 05(带前导零) |
{calendar:day} | 07(带前导零) |
{calendar:ym} | 2026/05 |
{calendar:quarter} | Q1、Q2、Q3、Q4 |
{calendar:yq} | 2026/Q2 |
{calendar:week} | ISO 周号,如18(带前导零) |
{calendar:yw} | 2026/w18 |
4.2viking://命名空间语义与校验规则
目标 URI 的合法性由 uri_validation.py 的validate_content_target_uri把关:先做形式校验(validate_request_viking_uri),再确认 URI 指向的是 resource 类内容(matches_content_kind),最后做访问权限检查(is_accessible)。命名空间的解析集中在 namespace.py:
- home 别名:
viking://~/resources/...是当前认证调用者的 home 别名,会被展开为viking://user/{user_id}/resources/...。 - 旧写法废弃:不带 uid 的
viking://user/resources/...不再被接受,会返回错误并提示改用viking://~/...形式(相关说明见 config.py)。 - peer_id 段约束:
peers之后的段必须是安全单段标识符(如web-visitor-alice);包含:、+、.、..或路径分隔符的值会被拒绝。底层由 identifiers.py 的validate_identifier_part统一校验为字母数字字符串(alpha_numeric),并经 peer_id.py 的normalize_peer_id归一化。
五、异步处理控制:--wait与--timeout
语义化处理(解析、语义抽取、向量化)默认在后台异步执行,CLI 立即返回。官方文档给出的三种模式:
# 阻塞直到处理完成 ov add-resource ./docs --wait # 带超时的等待(单位:秒) ov add-resource ./docs --wait --timeout 60 # 默认:fire-and-forget ov add-resource ./docs关键行为说明:
- 当
wait=false时,CLI 在"上传 / 解析 / finalize"完成(非 Git 来源)或"预检 preflight"完成(Git 来源)后即返回。Git 仓库场景下,服务端会先校验仓库、解析目标 URI、预占root_uri,然后立刻返回;克隆、解析与 finalize 继续在后台进行(对应服务端_preflight_git_source与execute_add_resource_job的实现,见 resource_service.py)。 - 返回结果中的
task_id是追踪进度的关键:可以调用GET /api/v1/tasks/{task_id}查询任务状态,也可以用 CLI 侧的任务命令(如ov task status <task_id>、ov task list)查看进度。在部分版本中,CLI 输出也会直接提示Use 'ov task status <task_id>' to check progress(见 commands/resources.rs)。 - 请求模型中的
timeout字段只有在wait=true时才生效,None表示不设超时(见 resources.py)。
六、定时刷新:--watch-interval与 Watch 任务
--watch-interval(单位:分钟)可以把一次导入升级为周期性刷新任务(Watch):
# 每 60 分钟刷新一次,并绑定到固定 URI ov add-resource https://github.com/volcengine/OpenViking \ --to "viking://resources/repos/OpenViking" \ --watch-interval 60 # 每 30 分钟刷新一次,绑定到导入后的 root_uri ov add-resource https://example.com/spec.md --watch-interval 30 # 取消同一目标的 watch(间隔设为 0 或负数) ov add-resource https://github.com/volcengine/OpenViking \ --to "viking://resources/repos/OpenViking" \ --watch-interval 0使用要点:
> 0表示创建/更新 watch;<= 0表示取消。长期稳定的定时任务建议始终配合--to使用固定 URI,避免依赖自动生成的root_uri造成绑定漂移。- 长期 watch 的凭据(如 Git 私有仓库的
auth_config)会保存在私有的 watch 状态中;带--to的重复导入不会更新或恢复已有 watch,需通过PATCH /api/v1/watches/{task_id}或删除后重建(见 resources.py 的注释说明)。 - 服务端由 watch_scheduler.py 中的
WatchScheduler负责调度:默认每 60 秒检查一次到期任务(DEFAULT_CHECK_INTERVAL = 60.0),默认最大并发 4(max_concurrency),单任务默认超时 3 小时(DEFAULT_TASK_TIMEOUT),并通过信号量控制并发、跳过正在执行的任务,执行失败不会影响下一次调度。 - 上传内容(
temp_file_id)不支持watch_interval > 0:上传是静态快照,周期性重处理旧内容没有意义,服务端会直接报错,建议改为 watch URL / sitemap / RSS 源(见 resources.py)。
6.1 Watch 的日常管理:ov task watch
创建之后,watch 任务的控制面由ov task watch子命令提供(详见配套文档 watch-management.md):
| 动作 | 命令 |
|---|---|
| 创建/更新 | ov add-resource <source> --to <uri> --watch-interval <minutes> |
| 列出 | ov task watch ls [--active-only] |
| 查看详情 | ov task watch show <key> |
| 暂停(保留节奏) | ov task watch pause <key> |
| 恢复 | ov task watch resume <key> |
| 更新周期 | ov task watch update <key> --interval <minutes> |
| 立即刷新 | ov task watch trigger <key> |
| 删除 | ov task watch rm <key> |
| 通过 add-resource 取消 | ov add-resource <source> --to <uri> --watch-interval 0 |
其中key既可以是viking://URI,也可以是任务 ID。暂停(is_active=false)与watch_interval相互独立:暂停不会丢失刷新节奏,恢复后按原周期继续。
七、过滤选项:--include、--exclude、--ignore-dirs与--preserve-structure
导入本地目录时,可以用过滤规则精确控制哪些文件进入上下文数据库:
# 只包含匹配的文件 ov add-resource ./project --include "*.py,*.md" # 排除匹配的文件 ov add-resource ./project --exclude "*.tmp,*.log" # 忽略指定目录名 ov add-resource ./project --ignore-dirs "node_modules,target,.git" # 保留目录结构 ov add-resource ./project --preserve-structure行为细节:
- 本地目录扫描会以标准 Git 语义遵守
.gitignore;ignore_dirs、include、exclude在此基础上进一步收窄入库范围。 - 请求模型中这些字段均为字符串:
ignore_dirs是逗号分隔的目录名列表,include/exclude是 glob 模式(见 resources.py)。 directly_upload_media(默认true)控制媒体文件是否直接上传;preserve_structure控制目录导入时是否保留原有目录层级(默认由服务端决定,显式传入时生效)。
八、CLI 输出格式:表格与 JSON
默认输出为表格:
Note: Resource is being processed in the background. Use 'ov wait' to wait for completion, or 'ov observer queue' to check status. status success root_uri viking://resources/01-overview task_id uuid-xxx使用-o json输出 JSON 结构:
{ "status": "success", "root_uri": "viking://resources/01-overview", "task_id": "uuid-xxx" }注意:当配合--wait使用时,响应中会额外携带queue_status字段,包含pending、processing、completed三类任务的计数,便于判断队列整体消化情况。
九、关键参数速查表
| 参数 | 说明 |
|---|---|
--to | 精确目标 URI(与--parent互斥) |
--parent/-p | 父目录 URI(与--to互斥) |
--parent-auto-create | 父目录不存在时自动创建 |
--reason | 添加原因(实验性,用于文档化与监控) |
--instruction | 处理指令(实验性,为语义抽取提供提示) |
--wait | 阻塞直到语义处理完成 |
--timeout | 配合--wait使用的超时秒数 |
--strict | 使用严格模式处理 |
--ignore-dirs | 要忽略的目录名(逗号分隔) |
--include | 要包含的文件模式(glob) |
--exclude | 要排除的文件模式(glob) |
--watch-interval | 定时刷新间隔(分钟) |
请求模型(resources.py)中还包含几个 CLI 参数未直接暴露、但 API 层支持的字段:temp_file_id(临时上传 ID)、add_type(Connector 类型)、internal_task(是否从默认任务列表隐藏)、source_name、tags/tag_mode(标签管理,replace为默认替换模式)、processing_mode、is_active(初始 Watch 状态)以及args(解析器专属参数,如 Git 认证{"auth_config": {"username": "oauth2", "token": "..."}}、飞书一次性 user-token{"feishu_access_token": "..."}等)。
十、底层原理:一次导入的完整调用链
综合上述源码,一次ov add-resource的完整生命周期可以归纳为:
- 客户端参数解析与互斥校验:Rust CLI 校验
--to/--parent/--parent-auto-create互斥,并把--parent-auto-create映射为create_parent;远程来源与watch_interval的合法性由validate_watch_source把关(watch 只对远程来源有意义)。 - 来源判定与上传:
path若指向本地文件/目录,则经/api/v1/resources/temp_upload上传换取temp_file_id;若为 URL / Git,则原样透传。 - URI 规范化与校验:服务端路由调用
resolve_path_variables展开{calendar:...}模板,再经validate_content_target_uri完成格式、类型与权限三重校验。 - 入队与异步执行:
ResourceService.add_resource归一化参数、规划来源计划(_plan_source_job_target、_enqueue_source_plan),非 Git 来源在 upload/parse/finalize 后返回;Git 来源先做 preflight 预检并预占root_uri,克隆与解析在后台继续。最终由 queuefs 的AddResourceProcessor消费任务。 - Watch 管理:若
watch_interval > 0,_manage_watch_if_needed创建或更新绑定任务,此后由WatchScheduler周期性检查并重新导入。
这条链路与官方技能包 commands.md 中整理的常用命令模式一一对应,也与 LangChain 集成中暴露的viking_add_resource工具共享同一套服务端实现(相关测试见 test_langchain_integration.py),意味着 Agent 既可以通过 CLI 手动导入,也可以在代码中以工具调用的方式完成同样的资源入库。
十一、重要注意事项与最佳实践
path与temp_file_id二选一,不可同时提供。to与parent互斥;to指向已存在资源时,会触发增量更新而不是覆盖重建。- Git 仓库在
wait=false时:OpenViking 会先校验仓库、解析目标 URI、预占root_uri并立即返回;克隆/解析/finalize 在后台完成,务必用task_id追踪结果。 - 直接创建或更新纯文本内容,应优先使用
ov write而不是add_resource——后者面向外部资源导入,前者才是文本内容的一等公民通道。 - 长期 watch 建议固定
--to;重复导入不会静默更新既有 Watch,需要显式通过 watch 管理命令处理。 - 服务端只接受远程 URL 与临时上传内容,禁止在 HTTP 请求中直接提交主机文件系统路径,这是刻意设计的边界,用于避免服务器本地文件被任意读取。
结合 SKILL.md 与 watch-management.md,ov add-resource构成了"导入 → 浏览(ov ls/ov tree)→ 定时刷新(Watch)→ 检索(ov search)"完整知识管理闭环的第一环,是 OpenViking 语境化(context compilation)与 Agent 记忆统一的最重要入口之一。
【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考