首页
/ OpenViking 资源管理实战指南:add_resource 资源导入管线、增量更新与 Watch 机制全解析

OpenViking 资源管理实战指南:add_resource 资源导入管线、增量更新与 Watch 机制全解析

2026-09-09 21:05:32作者:庞队千Virginia

导读

本指南基于 OpenViking 官方 API 文档,深入剖析资源(Resource)管理模块——这是 OpenViking 面向 Agent 的统一知识底座:外部知识(文档、代码库、网页、云文档)如何被导入、解析、建树、持久化到 AGFS,并经过摘要生成与向量化进入语义检索体系。读完本文,你将掌握 add_resource / temp_upload 两个核心 API 的完整参数语义与调用方式(HTTP / Python / TypeScript / Go SDK 及 CLI),理解递归爬虫、整站(sitemap/RSS)摄取、Git 仓库导入、Feishu 云文档等各类源的接入细节,并能通过 watch_interval 构建自动同步的增量更新机制,让知识库随上游源持续保鲜。

资源类型总览:OpenViking 能摄取哪些外部知识

资源(Resources)是 Agent 可以引用的外部知识。OpenViking 按功能对资源进行分类,覆盖文档、表格与演示文稿、代码、媒体、云文档、网页与整站等七大类别。

文档类(Documents)

类型 扩展名 处理说明
PDF .pdf 支持本地解析与 MinerU API 转换
Markdown .md, .markdown, .mdown, .mkd 原生支持,提取结构并按片段存储
HTML .html, .htm 清理导航/广告后提取正文,转换为 Markdown
Word .doc, .docx, .docm, .odt, .rtf 使用 anydoc 将文本、标题、表格与内嵌图片提取为 Markdown
纯文本 .txt, .text 直接导入与处理
EPUB .epub 使用 anydoc 将电子书正文与内嵌图片转换为 Markdown

表格与演示文稿

类型 扩展名 处理说明
Excel .xlsx, .xls, .xlsm, .xlsb, .ods, .csv 使用 anydoc 将工作表转换为 Markdown 表格
PowerPoint .pptx, .ppt, .pptm, .pps, .ppsx, .ppsm, .pot, .odp 使用 anydoc 提取幻灯片内容与内嵌图片为 Markdown

代码类

类型 资源名 说明
代码文件 *.py, *.js, ... 支持 Python、JavaScript、Go、Rust、Java 等常见编程语言
Git 协议仓库 git://... Git URL、本地目录、.zip 压缩包;遵循 .gitignore,自动过滤 .gitnode_modules 等目录
Git 代码托管平台 https://github.com/{org}/{repo} GitHub、GitLab、Bitbucket 等平台仓库 URL
Git 托管平台的 Raw 文件 https://github.com/{org}/{repo}/raw/{branch}/{path} GitHub、GitLab、Bitbucket 等平台的原始文件下载 URL

代码仓库导入是 OpenViking 的典型场景:本地目录扫描时会以标准 Git 语义尊重根目录及嵌套的 .gitignore,再以 ignore_dirsincludeexclude 进一步精化摄取范围(见下文参数详解)。

媒体类

类型 资源名 说明
图片 *.jpg, *.jpeg, *.png, *.gif ... 多种图片格式,通过 VLM(视觉语言模型)生成描述(实验性)
视频 *.mp4, *.avi, *.mov ... 提取关键帧并用 VLM 分析(规划中)
音频 *.mp3, *.wav, *.m4a ... 执行语音转写(规划中)

云文档

类型 说明
飞书 / Lark 基于 URL 导入,支持 doc/docx、wiki、电子表格、多维表格。默认使用 FEISHU_APP_IDFEISHU_APP_SECRET 的应用凭证;用户态导入可传 args.feishu_access_token;用户态 Watch 还需传 args.feishu_refresh_token,并可选传 args.feishu_app_id / args.feishu_app_secret 应用对

网页(递归爬虫)

类型 资源名 说明
单页 / 递归爬取 https://host/path 默认只抓取入口页。设置 args.depth > 0 后按广度优先爬取同站链接;args.max_pages 仅限制收集的页面总数。每个页面由 trafilatura 提取为 Markdown

递归爬虫支持的 args 包括:depthmax_pagesinclude_pathsexclude_pathsallow_external_linksskip_download_links。页面中发现的下载链接默认被跳过(skip_download_links=true),以避免导入 llms.txt 等 sidecar 文件;将其设为 false 可下载同站文件链接并计入 max_pagesinclude_paths / exclude_paths 采用路径前缀匹配(例如 /docs/ 只匹配以 /docs/ 开头的路径,绝不匹配 /blog/docs-tips 这类子串)。

路由规则:sitemap 风格的 URL(https://host/sitemap.xmlhttps://host/feed.xml*.atom 等)以及显式指定 args.site=true 的请求会被路由到下述整站摄取;而 https://github.com/{org}/{repo} 这类 Git 托管 URL 会被路由到代码类导入。

整站(sitemap / RSS / Atom)

类型 资源名 说明
Sitemap https://host/sitemap.xmlhttps://host/sitemap-index.xml 解析 sitemap 并将每个列出的页面作为单一资源树摄入(每个页面一个子节点)。嵌套的 <sitemapindex> 会被递归跟进。整个站点成为 viking://resources/<host> 下的一个资源
RSS / Atom 订阅 https://host/rss.xmlhttps://host/atom.xmlhttps://host/feed 解析 RSS 2.0 / Atom,将每条条目作为一个树节点;正文从条目链接抓取(当订阅源自带完整内容时直接内联)
整站自动发现 https://host + args.site=true 对裸域名或普通页面强制整站摄取:通过 robots.txt、HTML <link rel="alternate"> 自动发现及常规路径发现站点的 sitemap/RSS 后摄入

爬取是有界的、且不超过所列页面递归:由 parsers.webfeed 配置约束(max_pagesmax_concurrencypoliteness_delaysame_host_onlyrespect_robotsmax_depth),并遵循 robots.txt。在 sitemap/feed URL 上设置 watch_interval 可让整个站点保持同步:每次刷新新增页面、自动移除已删除页面。当添加单个主页(未加 args.site)时,响应可能附带一行提示建议整站摄取——但绝不会自动爬取。

资源处理管线:从源头到语义索引的四阶段

资源在被添加时会经历以下处理阶段:

Source Input -> Parse -> Resource Tree Build -> Persistence -> Semantic Processing
    ↓           ↓            ↓                 ↓               ↓
  URL/File    Parser    TreeBuilder        AGFS       Summarizer/Vector

阶段一:解析(Parse)

  • UnifiedResourceProcessoropenviking/utils/media_processor.py)根据资源类型解析内容;
  • 支持多格式:文档(PDF/Markdown/Word)、表格(Excel/PPT)、代码、媒体文件等;
  • 解析结果写入临时 VikingFS 目录;
  • 媒体文件由 VLM 生成描述。

阶段二:资源树构建(TreeBuilder)

  • TreeBuilder.finalize_from_temp()openviking/parse/tree_builder.py)扫描临时目录结构;
  • 构建资源树节点,处理 URI 冲突(自动重命名);
  • 建立目录与资源之间的关系。

阶段三:持久化

  • 检查目标 URI 是否已存在;
  • 新资源:将临时文件移动到 AGFS 永久位置;
  • 已存在资源:保留临时树以供后续 diff 对比;
  • 获取生命周期锁,防止并发修改;
  • 清理临时目录。

阶段四:语义处理

非等待(wait=false)的 Git 仓库导入

对于 wait=false 的 Git 仓库源,OpenViking 会先校验仓库、解析目标 URI、预留最终 root_uri,然后立即返回;克隆/解析/finalize 在持久化后台任务中继续。立即响应包含 statusroot_uritask_id;可通过 GET /api/v1/tasks/{task_id} 轮询任务状态,Git 资源导入任务使用 queuedfetchingparsingfinalizingprocessing_queue 等阶段。其他资源源在 wait=false 时会在响应前完成抓取/解析/finalize,返回的 task_id 仅追踪语义与嵌入队列的完成情况。

增量更新:Watch 任务机制

资源的增量更新通过 Watch Task 机制实现。

Watch 任务创建

  • 在调用 add_resource 时设置 watch_interval > 0(单位:分钟)且源可重读(如 URL、sitemap、RSS 订阅)即可创建 Watch 任务;
  • 通过 temp_file_id 引用的上传内容属于静态快照,不可被 Watch;本地源变化时需重新添加;
  • 可通过 to 指定目标 URI;若省略,任务绑定到本次导入返回的 root_uri
  • 将 Watch 指向 sitemap/RSS/Atom URL 可保持整站同步:每次刷新重新读取订阅并重建资源树,新发布的页面被添加、被删除的页面自动移除;
  • WatchManageropenviking/resource/watch_manager.py)负责任务持久化;
  • 支持多租户权限控制(ROOT/ADMIN/USER 权限级别)。

目标所有权规则

  • 账户内,原生(native)Watch 独占其解析出的目标,即使暂停期间也保持独占;新建原生 Watch 需要未被占用的目标;Connector Watch 不能与原生 Watch 共享目标;
  • 多个 Connector Watch 可以共享同一目标。对相同源与目标重复导入会创建另一个独立 Watch;重复导入不会更新或重新激活已有 Watch。同一源导入到不同目标同样各自创建 Watch;
  • Connector Watch 在首次导入前创建,并由调度器持有,直到该次导入记录其结果。

任务调度与执行

  • WatchScheduleropenviking/resource/watch_scheduler.py)每 60 秒检查一次到期任务(源码中 DEFAULT_CHECK_INTERVAL = 60.0,默认 max_concurrency = 4task_timeout = 3 * 60 * 60,并通过 asyncio.Semaphore 做并发控制);
  • 默认并发控制防止重复执行;
  • 到期任务自动重新调用 add_resource
  • 更新任务的上次执行时间与下次执行时间。

任务管理操作

  • 创建watch_interval > 0 创建新任务并受上述目标所有权规则约束;目标占用冲突返回 409 Conflict
  • 更新或恢复:使用 PATCH /api/v1/watches/{task_id} 修改参数或将 is_active 设为 true。重复导入不会更新或重新激活任务;
  • 暂停或删除:用 PATCH /api/v1/watches/{task_id} 配合 is_active: false 暂停,或用 DELETE /api/v1/watches/{task_id} 释放目标。原生导入若显式指定 towatch_interval <= 0,会暂停该目标上唯一可访问的 Watch;若有多个可访问 Watch 则返回 409 Conflict。一次性 Connector 导入不触碰已有 Watch;
  • 查询:使用任务 ID,或在目标 URI 唯一标识单个可访问 Watch 时使用目标 URI。URI 查询在多个可访问 Watch 时返回 409 Conflict;请用 task_id 查询、更新或删除单个任务。

API 参考:add_resource

向知识库添加资源。SDK 支持本地文件/目录、URL 及其他源;裸 HTTP 调用通过 path 接收远程 URL、或通过 temp_file_id 接收已上传的本地文件。上传内容属于静态快照,因此不能与 watch_interval > 0 组合使用。

1. 实现概览与入口

该端点(POST /api/v1/resources)是资源管理的核心入口,支持从各种源添加资源,并可选等待语义处理与向量化完成。

处理流程

  1. 识别并校验资源源(URL 或已上传的临时文件);
  2. 解析目标 URI;
  3. 调用对应格式的 Parser;args.parse_mode 控制转换后的 Markdown 正文是否可被拆分;
  4. 构建目录树并写入 AGFS;
  5. processing_mode 执行摄取后处理:semantic_and_vectors 生成语义产物与向量;vectors_only 跳过语义理解、仅入队文件向量化;
  6. wait=true 时等待语义处理/向量化完成;wait=false 时返回 task_id 供队列跟踪;
  7. reason 非空,将其追加到固定资源原因会话,走常规记忆提取管线,使合适的用户记忆可引用该资源 URI;
  8. 若指定了 watch_interval,创建定时更新任务。

代码入口

从源码看,路由层还会调用 resolve_path_variables 展开路径变量(如 {calendar:today})、通过 validate_content_target_uri 校验目标 URI,并在 TempUploadStore.resolve_for_consume 中消费临时上传文件——这些正是 CLI 示例中"路径变量 + 自动建父目录"能力得以实现的底层支撑。

2. 参数详解

参数 类型 必填 默认值 说明
path string - 远程资源 URL(HTTP/HTTPS/Git)。与 temp_file_id 互斥
temp_file_id string - 临时上传文件 ID。与 path 互斥
to string - 本次导入的最终位置。目标已存在则刷新。与 parent 互斥
parent string - 父级 Viking URI(资源置于该目录下)。与 to 互斥
create_parent bool False 父目录不存在时自动创建(服务端标志)
reason string "" 添加资源的理由。非空时 OpenViking 会将其与资源 URI 一起送入常规会话记忆提取管线,在生成的记忆中记录资源引用
instruction string "" 语义提取的处理指令(实验性功能)
wait bool False 返回前是否等待语义处理与向量化完成
timeout float None 超时秒数,仅 wait=True 时生效
strict bool False 是否使用严格模式
ignore_dirs string None 需要忽略的目录名(逗号分隔)
include string None 需要包含的文件模式(glob)
exclude string None 需要排除的文件模式(glob)
directly_upload_media bool True 是否直接上传媒体文件
preserve_structure bool None 是否保留目录结构
args object {} 透传给源解析器/访问器的解析器特定导入选项(详见下文)
watch_interval float 0 定时更新间隔(分钟)。>0 为可重读源创建新 Watch(受目标所有权规则约束);上传的 temp_file_id 快照不可被 Watch。<=0 不创建 Watch:带显式 to 的原生导入会暂停单个可访问任务(不明确时返回 409),Connector 导入则不动已有 Watch。显式 to 优先,否则 Watch 绑定到导入的 root_uri
is_active bool True Watch 初始调度状态。false 要求 watch_interval > 0 且提供 toparentparent 仅原生飞书 URL 导入支持;Connector 导入仍要求精确 to)。初始导入仍执行一次,之后 Watch 保持暂停
processing_mode string semantic_and_vectors 摄取后处理模式。semantic_and_vectors 为常规流程:生成语义产物(.abstract.md.overview.md)与向量;vectors_only 跳过语义理解/VLM 摘要,仅对当前资源文件做向量化
telemetry TelemetryRequest False 是否返回遥测数据

args 细说:原生 HTTPS Git 导入与 Watch 可通过 TLS 传递 HTTP Basic 凭证:args.auth_config={"username":"oauth2","token":"..."}username 默认 oauth2)。Git 的 branchcommit 保持在 args 顶层。要通过 HTTP(S) URL 导入私有 TOS 对象,需且仅需传一个非空字符串:args.tos_signature(作为 X-Tos-Signature 头发送)或 args.tos_access(作为 X-Tos-Access 头发送)。TOS 凭证仅用于当前 HEAD/GET 抓取(以快照方式暂存),不会持久化到资源元数据或队列任务。args.parse_mode 接受 default(既有拆分行为)或 no_split(将每个源文档解析并转换为一个 Markdown 正文)。例如 args.site=true/false 强制/退出整站(sitemap/RSS)摄取;args.max_pages 等覆盖 webfeed 配置;递归爬虫接受 args.depthargs.max_pagesargs.include_pathsargs.exclude_pathsargs.allow_external_linksargs.skip_download_links;飞书用户态导入传 args.feishu_access_token。核心 add_resource 字段如 pathtowatch_intervalincludeexclude 不允许出现在 args 内。

其他重要注意事项

  • toparent 不能同时指定。to 是最终保存位置:目标不存在则创建,已存在则刷新;若目标是目录,当前导入未产生的旧文件或子目录可能被移除。parent 是目标目录,适合在既有目录下新增资源;需要自动建目录时用 create_parent=true 或 CLI 的 --parent-auto-create。当导入的 root_urito 相同时,语义与向量处理会复用未变化的内容,仅处理变更部分;
  • 创建资源需要目标父目录的写权限;更新显式 to 需要该目标的写权限。这些检查在任务入队前执行。自动命名按实际 URI 占用情况,因此不可读的冲突名会依次选择 _1_2 等,而不是尝试覆盖;
  • wait=false 时,status=accepted 表示预检通过且任务已入队,不代表资源处理完成,请用返回的 task_id 查询最终状态;
  • toparent 均省略,服务端可能使用当前用户的 add_targets.resource_uri 覆盖项,再退到 server.user_config_defaults.add_targets.resource_uri;两者均未设置时保持旧的目标解析行为;
  • 资源目标可使用公共 viking://resources/...、home 别名 viking://~/resources/...、显式用户 viking://user/{user_id}/resources/... 或 peer 路径 viking://user/{user_id}/peers/{peer_id}/resources/...。home 别名会按已认证请求身份展开为规范路径;无 uid 的 viking://user/resources/... 拼写会被拒绝,并提示改用 viking://~/resources/...
  • user_idpeer_id 路径段必须是安全的单段标识符(如 aliceweb-visitor-alice),包含路径分隔符、...:+ 的值会被拒绝;
  • pathtemp_file_id 不能同时指定;裸 HTTP 导入本地文件需先经 temp_upload 上传获得 temp_file_id
  • 仅 Git 仓库源在 wait=false 时走完整后台导入;OpenViking 在返回 task_id 前完成仓库预检与目标规划;
  • 原生 HTTPS Git 凭证在 watch_interval <= 0 时仅请求本地有效。当 watch_interval > 0 时,OpenViking 将仓库绑定的用户名/token 存入私有 Watch 状态,仅在后续 Git 抓取时恢复使用。凭证不会出现在常规队列负载及 Watch API/MCP/CLI 响应中。Git PAT 无通用刷新流程;token 过期或被吊销时请重建 Watch。URL 内嵌凭证(如 https://user:token@host/repo.git)仍被接受并原样传递;由于该 URL 同时是源标识,可能被记录在进程参数、日志、队列、资源元数据与 Watch 状态中。新集成建议使用 args.auth_config。明文 HTTP 认证及 args.auth_config 的认证重定向仍被拒绝;
  • token 通过 HTTPS 请求体传输。生产环境应保持诊断请求体转储关闭,因为显式开启可能记录机密;
  • reason 生成的记忆与 session.commit 走同一管线,使用 reason、资源 URI、可用源名与可用目录摘要;不检查或展开完整资源内容。OpenViking 写入 entitieseventspreferences 等既有记忆类型,而非专门的资源记忆目录;
  • 删除资源时,OpenViking 会在删除前扫描当前上下文指向的自有或 peer 记忆,移除由该 reason 引入的匹配资源 URI 与内容,并刷新受影响记忆的语义索引;
  • 其他源在 wait=false 时会在返回前完成源解析、目标解析与 AGFS 写入,仅语义与嵌入队列异步继续;
  • processing_mode=vectors_only 不调用 VLM 语义理解阶段,不生成/刷新 .abstract.md / .overview.md;对既有目标保留已有语义产物与语义向量,仍会更新资源树、在 build_index=true 时对当前非隐藏文件向量化,并移除刷新时被删除文件的细节向量;
  • processing_mode 属于 add_resource;管理员 reindex API/CLI 继续使用 modevectors_onlysemantic_and_vectorsprune_orphans)对已摄取数据做维护操作;
  • watch_interval > 0 时,Watch 任务绑定到 to(若提供),否则绑定到本次导入返回的 root_uri;无稳定 root_uri 时请求失败并要求显式 to
  • Connector 导入的 is_active=false 在提交前创建暂停的 Watch;原生飞书导入通过资源队列携带 is_active,在解析出资源 URI 后创建 Watch。两种情况初始导入都执行一次且定时调度保持禁用;
  • 飞书/Lark 应用凭证导入不传 args.feishu_access_token,OpenViking 沿用既有应用凭证流程,SDK 由 app_idapp_secret 获取 app/tenant token,支持一次性导入与 watch_interval > 0 两种模式;
  • 飞书/Lark 一次性用户态导入传 args={"feishu_access_token": "u-..."}watch_interval <= 0,用户 token 仅用于当前导入、不被存储;
  • 飞书/Lark 用户态 Watch 传 args={"feishu_access_token": "u-...", "feishu_refresh_token": "r-..."}watch_interval > 0,可同时传 feishu_app_idfeishu_app_secret;OpenViking 将该应用对存入私有 Watch 任务状态,用于刷新该 Watch 的用户 token;
  • 若请求省略应用对,用户态 Watch 使用 FEISHU_APP_ID / FEISHU_APP_SECRET,或 ov.conf 中的 feishu.app_id / feishu.app_secret。飞书刷新 token 绑定其签发应用,使用的应用凭证必须与提供的用户 token 匹配;
  • Watch 任务 token 状态与请求提供的应用凭证存储在内部控制文件 viking://resources/.watch_tasks.json 中,对 Watch API/MCP/CLI 响应隐藏;若启用了 VikingFS 文件加密,该控制文件落盘加密,否则服务端控制文件明文包含该私有状态;
  • 本地目录输入按标准 Git 语义尊重 .gitignore(根及嵌套),ignore_dirsincludeexclude 进一步精化摄取内容;
  • 目录摄取在至少一个被选文件成功时是尽力而为:失败文件在 meta.failed_files 中报告、成功文件提交。嵌套 ZIP 的叶子失败以 bundle.zip/path/to/file 这类归档限定路径报告并保留其远程任务 ID。若没有文件成功、或过滤器未选中任何可处理文件,任务失败且不保留空资源目录;
  • args.parse_mode=no_split 仍调用常规格式 Parser:PDF、Word、PowerPoint、HTML 等受支持文档被转换为 Markdown,但跳过基于标题、段落与尺寸的拆分。目录导入对每个受支持文档独立应用该模式,并继续遵循 .gitignore、过滤器与 preserve_structure。该模式下配置了 Understanding 的目录文件回退到原生 Parser;无原生解析支持的文件类型记录在 meta.failed_files,不阻止其他被选文件成功;
  • 单文件输入 + no_split 且省略 to 时,若解析恰好产生一个可见文件,该文件直接存到解析出的父目录下(例如 guide.md 成为 viking://resources/guide.md),不创建包装目录或目录级 .abstract.md / .overview.md;若解析同时产生图片等其他可见文件,则保留包装目录。显式 to 始终作为精确最终 URI 保留;
  • no_split 只改变存储的 Markdown 布局;语义处理、文件向量化及内部嵌入分块保持不变。相对 Markdown 链接按同一 no-split 输出布局解析,因此链接不会指向仅拆分存在的路径。该模式下目录文件不调用 Understanding;
  • 要直接创建或更新纯文本,请使用 content/write 而非 add_resource。资源摄取与内容写入后,语义处理与嵌入会自动刷新。

3. 使用示例

HTTP API

POST /api/v1/resources
Content-Type: application/json
# 从 URL 添加资源
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "path": "https://example.com/guide.md",
    "reason": "User guide documentation",
    "wait": true
  }'

# 导入并 Watch 一个私有 HTTPS Git 仓库
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "path": "https://git.example.com/team/private-repo.git",
    "to": "viking://resources/private-repo",
    "watch_interval": 60,
    "args": {
      "branch": "main",
      "auth_config": {
        "username": "oauth2",
        "token": "replace-with-your-token"
      }
    }
  }'

# 只构建向量、不做 VLM 语义理解
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "path": "https://example.com/guide.md",
    "to": "viking://resources/guide",
    "processing_mode": "vectors_only",
    "wait": true
  }'

# 递归爬取站点:沿同站链接扩展;depth 限制层数,max_pages 限制收集页数
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "path": "https://docs.openviking.ai/getting-started/01-introduction",
    "wait": true,
    "timeout": 60,
    "args": { "depth": 1, "max_pages": 10 }
  }'

# 从本地文件添加(需先 temp_upload)
TEMP_FILE_ID=$(
  curl -s -X POST http://localhost:1933/api/v1/resources/temp_upload \
    -H "X-API-Key: your-key" \
    -F "file=@./documents/guide.md" \
  | jq -r '.result.temp_file_id'
)

curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d "{
    \"temp_file_id\": \"$TEMP_FILE_ID\",
    \"to\": \"viking://resources/guide.md\",
    \"reason\": \"User guide\"
  }"

# 添加到当前用户私有资源根
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d "{
    \"temp_file_id\": \"$TEMP_FILE_ID\",
    \"parent\": \"viking://~/resources/docs\",
    \"create_parent\": true
  }"

# 一次性用户 token 添加飞书文档
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "path": "https://example.feishu.cn/docx/doc_token",
    "args": {
      "feishu_access_token": "u-..."
    }
  }'

# 带定时用户 token 刷新的飞书文档
curl -X POST http://localhost:1933/api/v1/resources \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "path": "https://example.feishu.cn/docx/doc_token",
    "to": "viking://resources/feishu/doc",
    "watch_interval": 1440,
    "args": {
      "feishu_access_token": "u-...",
      "feishu_refresh_token": "r-...",
      "feishu_app_id": "cli_...",
      "feishu_app_secret": "..."
    }
  }'

Python SDK

from openviking_sdk import SyncHTTPClient

client = SyncHTTPClient(url="http://localhost:1933", api_key="your-key")
client.initialize()

# 添加本地文件
result = client.add_resource(
    path="./documents/guide.md",
    options={"reason": "User guide documentation"},
)
print(f"Added: {result['root_uri']}")

# 将每个文档解析为单个 Markdown 正文(不拆分)
result = client.add_resource(
    path="./documents",
    options={"args": {"parse_mode": "no_split"}},
)

# 从 URL 添加到指定位置
result = client.add_resource(
    path="https://example.com/api-docs.md",
    to="viking://resources/external/api-docs.md",
    options={"reason": "External API documentation"},
)

# 递归爬取站点(同站 BFS;depth 层数,max_pages 上限)
result = client.add_resource(
    path="https://docs.openviking.ai/getting-started/01-introduction",
    wait=True,
    timeout=180,
    options={
        "args": {"depth": 1, "max_pages": 10},
    },
)

# 带路径前缀过滤器的递归爬取,同时下载文件链接
result = client.add_resource(
    path="https://docs.openviking.ai/",
    options={
        "args": {
            "depth": 2,
            "max_pages": 50,
            "include_paths": ["/docs/"],
            "exclude_paths": ["/changelog"],
            "skip_download_links": False,
        },
    },
)

# 添加到当前用户私有资源根
result = client.add_resource(
    path="./documents/guide.md",
    parent="viking://~/resources/docs",
    options={
        "create_parent": True,
    },
)

# 等待处理完成
client.wait_processed()

# 启用定时更新
client.add_resource(
    path="./documents/guide.md",
    to="viking://resources/guide.md",
    options={
        "watch_interval": 60,  # 每 60 分钟更新一次
    },
)

# 一次性用户 token 添加飞书文档
client.add_resource(
    path="https://example.feishu.cn/docx/doc_token",
    options={"args": {"feishu_access_token": "u-..."}},
)

# 带定时用户 token 刷新的飞书文档
client.add_resource(
    path="https://example.feishu.cn/docx/doc_token",
    to="viking://resources/feishu/doc",
    options={
        "watch_interval": 1440,
        "args": {
            "feishu_access_token": "u-...",
            "feishu_refresh_token": "r-...",
            "feishu_app_id": "cli_...",
            "feishu_app_secret": "...",
        },
    },
)

从 Python SDK 源码看,add_resource 会做三件事:归一化 to/parent URI(VikingURI.normalize)、通过 _build_options_payload 装配受保护字段的请求体、检测本地路径(目录先压缩为 zip 再上传临时文件),最终 POST /api/v1/resources 并返回 result——本地文件上传因此对调用方完全透明。

TypeScript SDK

const task = await client.addResource("https://example.com/docs", {
  to: "viking://resources/docs/",
  wait: true,
  args: { parse_mode: "no_split" },
});
console.log(task);

Go SDK

result, err := client.AddResource(ctx, "./documents/guide.md", &openviking.AddResourceOptions{
    Reason: "User guide documentation",
    Wait:   true,
    Args:   map[string]any{"parse_mode": "no_split"},
})
if err != nil {
    return err
}
fmt.Println(result["root_uri"])

CLI

# 添加本地文件
ov add-resource ./documents/guide.md --reason "User guide"

# 将每个文档解析为一个 Markdown 正文
ov add-resource ./documents --args parse_mode:no_split

# 从 URL 添加
ov add-resource https://example.com/guide.md --to viking://resources/guide.md

# 递归爬取站点:除非 depth>0,否则只抓取入口页
ov add-resource "https://docs.openviking.ai/getting-started/01-introduction" \
  --args="depth:1,max_pages:10"

# 带路径前缀过滤器的递归爬取(仅 /docs/,排除 changelog)
ov add-resource "https://docs.openviking.ai/" \
  --args='{"depth":2,"max_pages":50,"include_paths":["/docs/"],"exclude_paths":["/changelog"]}'

# 页面下载链接默认跳过;选择接收 PDF/TXT/MD 等文件
ov add-resource "https://example.com/docs" \
  --args="depth:1,max_pages:20,skip_download_links:false"

# 等待处理完成
ov add-resource ./documents/guide.md --wait

# 启用定时更新(每 60 分钟检查一次)
ov add-resource https://github.com/example/repo.git --to viking://resources/guide.md --watch-interval 60

# 启用定时更新并绑定到本次导入创建的 URI
ov add-resource https://github.com/example/repo.git --watch-interval 60

# 通过 PATCH /api/v1/watches/{task_id} 以 {"is_active": false} 暂停 Watch。
# 原生导入使用 --watch-interval 0 也会暂停目标上唯一可访问的 Watch。
# 一次性 Connector 导入不动已有 Watch。

# 一次性用户 token 添加飞书文档
ov add-resource https://example.feishu.cn/docx/doc_token --args feishu_access_token:u-...

# 带定时用户 token 刷新的飞书文档
ov add-resource https://example.feishu.cn/docx/doc_token \
  --to viking://resources/feishu/doc \
  --watch-interval 1440 \
  --args feishu_access_token:u-... \
  --args feishu_refresh_token:r-... \
  --args feishu_app_id:cli_... \
  --args feishu_app_secret:...

# 添加并置于父目录下(父目录必须存在)
ov add-resource ./documents/guide.md --parent viking://resources/docs

# 添加到当前用户私有资源根
ov add-resource ./documents/guide.md --parent viking://~/resources/docs

# 添加到指定 peer 的私有资源根
ov add-resource ./documents/guide.md \
  --parent viking://user/alice/peers/web-visitor-alice/resources/docs

# 父目录不存在时自动创建
ov add-resource ./documents/guide.md -p viking://resources/docs/2026/05/07
# 或使用完整标志
ov add-resource ./documents/guide.md --parent-auto-create viking://resources/docs/2026/05/07

# 使用路径变量 + 自动创建
ov add-resource ./documents/guide.md -p viking://resources/docs/{calendar:today}

响应示例

HTTP API 响应(JSON,wait=true

{
  "status": "ok",
  "result": {
    "status": "success",
    "root_uri": "viking://resources/guide.md",
    "temp_uri": "viking://temp/username/04291108_b62dc7/guide.md",
    "source_path": "./documents/guide.md",
    "meta": {},
    "errors": [],
    "queue_status": {
      "pending": 5,
      "processing": 2,
      "completed": 10
    }
  },
  "telemetry": {
    "operation_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

HTTP API 响应(JSON,非 Git wait=false

{
  "status": "ok",
  "result": {
    "status": "accepted",
    "root_uri": "viking://resources/guide",
    "task_id": "uuid-xxx"
  }
}

使用返回的 task_id 轮询 /api/v1/tasks/{task_id} 获取队列完成状态。Git 仓库源在 wait=false 时,同一端点追踪完整后台导入,任务完成后其 result 包含完整导入结果(含 queue_status)。

CLI 响应(默认表格格式)

Note: Resource is being processed in the background.
Use 'ov wait' to wait for completion, or 'ov observer queue' to check status.
status       accepted
root_uri     viking://resources/01-overview
task_id      uuid-xxx

CLI 响应(JSON 格式,使用 -o json)

{
  "status": "accepted",
  "root_uri": "viking://resources/01-overview",
  "task_id": "uuid-xxx"
}

字段说明

字段 类型 说明
status string 处理状态:accepted 表示已入队,success 表示成功完成,error 表示失败
root_uri string 资源在 OpenViking 中的最终 URI
task_id string (可选,仅 wait=false 时返回)用于轮询 /api/v1/tasks/{task_id} 的任务 ID。非 Git 导入用于队列跟踪;Git 仓库导入用于完整后台导入跟踪
temp_uri string 导入过程中产生的临时 URI
source_path string 原始源文件路径或 URL
meta object 资源解析得到的元数据(文件类型、大小等)
errors array 处理过程中遇到的错误列表
warnings array (可选)警告列表(仅 strict=False 时返回)
queue_status object (可选,仅 wait=true 时返回)队列处理状态,含 pendingprocessingcompleted 计数

add-resource 任务完成结果

对于 wait=false 的 Git 仓库源,后台任务 task_type="add_resource"resource_id 等于返回的 root_uri。运行中的任务记录可能包含 stage。轮询 /api/v1/tasks/{task_id} 直至完成,其嵌套 result 包含最终队列汇总与 context_count

{
  "status": "ok",
  "result": {
    "task_id": "uuid-xxx",
    "task_type": "add_resource",
    "status": "completed",
    "resource_id": "viking://resources/guide",
    "result": {
      "status": "success",
      "root_uri": "viking://resources/guide",
      "queue_status": {
        "Embedding": {
          "processed": 11,
          "requeue_count": 0,
          "error_count": 0,
          "errors": []
        }
      },
      "context_count": 11
    }
  }
}

context_count 是本次上传任务成功生成并建立索引的上下文(context)数量——一条上下文在其嵌入记录成功写入后才被计数。它不是 root_uri 下已存上下文的总数。若服务端在任务持久化最终指标前重启,该字段会被省略而非报告不完整计数。

API 参考:temp_upload

上传临时文件,用于后续通过 add_resource 或 add_skill 导入本地文件。

1. 实现概览与入口

该端点将本地文件上传到服务端管理的临时存储,返回供后续 API 调用使用的 temp_file_id。这是一个辅助端点,通常不经调用方直接调用,而是由 SDK 或 CLI 自动使用。

处理流程

  1. 接收上传文件;
  2. 根据 upload_mode 选择临时上传后端;
  3. 保存文件并记录原始文件名;
  4. 返回临时文件 ID。

代码入口

2. 参数详解

参数 类型 必填 默认值 说明
file UploadFile - 上传文件(multipart/form-data)
telemetry bool False 是否返回遥测数据
upload_mode string "local" 临时上传模式。local 保持既有单节点行为;shared 上传到共享临时存储,供分布式部署使用

补充说明:

  • 默认值为 local,既有客户端除非显式选择 shared,否则保持原行为;
  • 仅在明确需要分布式共享临时上传时才使用 upload_mode=shared
  • shared 模式返回形如 shared_<upload_id>temp_file_id。同一账户在其仍可用期间可重复消费;
  • 新的 shared 上传会创建内部 viking://upload/<created_at_ms>-<uuid>/ 目录,内含 contentmeta。目录名中的 13 位 Unix 毫秒时间戳即上传创建时间;meta 最后写入,标志上传完成。这些对象不属于常规文件系统浏览面;
  • shared 上传保留时长由 server.temp_upload.ttl_seconds 决定(默认 12 小时)。每次新的 shared 上传会列一次内部上传根目录、从每个一级上传目录名解析创建时间戳,并递归移除过期目录(不依赖文件系统修改时间)。

3. 使用示例

HTTP API

POST /api/v1/resources/temp_upload
Content-Type: multipart/form-data
curl -X POST http://localhost:1933/api/v1/resources/temp_upload \
  -H "X-API-Key: your-key" \
  -F "file=@./documents/guide.md"

分布式 / 共享上传:

curl -X POST http://localhost:1933/api/v1/resources/temp_upload \
  -H "X-API-Key: your-key" \
  -F "file=@./documents/guide.md" \
  -F "upload_mode=shared"

Python SDKadd_resourceadd_skill 等端点会自动处理本地文件上传,无需手动调用本端点。若要在 HTTP 客户端模式下启用分布式共享临时上传,在 ovcli.conf 中设置 upload.mode"shared" 即可。

Go SDKclient.AddResourceclient.AddSkillclient.ImportOVPackclient.RestoreOVPack 会自动为本地文件调用 temp_upload。设置 openviking.Config{UploadMode: "shared"} 即可请求共享临时上传。

CLI:CLI 命令同样自动处理本地文件上传,无需手动调用本端点。

响应示例

{
  "status": "ok",
  "result": {
    "temp_file_id": "upload_abc123def456.md"
  },
  "telemetry": {
    "operation_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

shared 模式可能的响应:

{
  "status": "ok",
  "result": {
    "temp_file_id": "shared_7f3c1b8d4f2e4b1bb0f6e8b2d9a4c123"
  }
}

进一步阅读

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525