mcpField
V
vss-search-archive

vss-search-archive

github.com/promptingcompany数据与数据库039 次安装17 周前更新
代码仓库

关于 vss-search-archive

vss-search-archive 是用于 NVIDIA VSS 视频档案自然语言检索的技能,可搜索已归档视频,也可接入文件或 RTSP 流并管理检索来源。它通过属性检索与 Cosmos Embed1 向量检索组合查找片段;该功能处于 Alpha 阶段,不建议用于生产环境。

主要功能

  1. 01自然语言搜索视频档案
  2. 02接入视频文件与 RTSP 流
  3. 03生成并索引视频向量嵌入
  4. 04融合属性与向量检索
  5. 05删除来源及其搜索数据

适用场景

  1. 01查找档案中的特定对象或活动
  2. 02按时间与地点筛选视频片段
  3. 03将新视频或 RTSP 源加入搜索
  4. 04移除来源及相关嵌入数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/promptingcompany/nv-skills --skill vss-search-archive

安装后在 Claude Code 中输入/vss-search-archive确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

BENCHMARK.md
skill-card.md
skill.oms.sig
evals/
evals.json
search.json
references/
discovery_modes.md
troubleshooting.md

详细介绍

目的

在已归档视频中运行顶层 VSS 融合搜索,摄取新的视频片段 / RTSP 流以供搜索,并删除已摄取用于搜索的源。

前置条件

  • 可通过 $HOST_IP 访问正在运行的 VSS 部署(参见 vss-deploy-profile 和 references/)。
  • 已安装 vss-manage-video-io-storage 技能(用于在搜索前列出和管理视频源)。
  • 如需拉取任何镜像,需在 $NGC_CLI_API_KEY 和 $NVIDIA_API_KEY 中提供 NGC 凭据。
  • 调用方可使用 curl、jq 和 Docker。

说明

按照以下路由表和分步工作流操作。每个以 workflow、quick start 或 flow 结尾的部分都应从上到下执行。详细参考资料位于 references/ 中。

示例

端到端示例保存在 evals/ 下(每个 *.json 清单都包含一个可运行场景),也以内联形式列在下方各工作流的 curl 代码块中。运行 nv-base validate <this-skill-dir> --agent-eval 可重放这些示例并进行 Tier-3 评估。

限制

  • 需要部署与之匹配且可从调用方访问的 VSS 配置文件 / 微服务。
  • NGC 托管的模型和 NIM 可能受速率限制、GPU 内存要求和许可证限制。
  • 并发、GPU 内存和存储限制取决于主机硬件和配置文件的 compose 文件。

故障排除

  • 错误:REST 调用返回连接被拒绝。原因:目标微服务未运行。解决方案:检查 /docs 或 /health;通过 vss-deploy-profile 或匹配的 vss-deploy-* 技能重新部署。
  • 错误:从 NGC 拉取时收到 HTTP 401/403。原因:缺少或已过期的 NGC_CLI_API_KEY。解决方案:运行 docker login nvcr.io,然后重新导出密钥再试。
  • 错误:容器发生 OOM,或模型加载失败。原因:所选配置文件的 GPU 内存不足。解决方案:切换到较小的变体,或通过 docker compose down 释放 GPU。

视频搜索工作流

Alpha Feature — 不建议用于生产环境。

使用 Cosmos Embed1 嵌入向量,通过自然语言搜索视频档案。需要搜索配置文件 — 使用 vss-deploy-profile 技能(-p search)进行部署。这些视频源可以是已摄取的文件或 RTSP 流。

适用场景

  • “查找所有出现叉车的实例”
  • “有人是什么时候进入限制区域的?”
  • “显示装卸区附近的人员”
  • “搜索上午 8 点到中午之间的车辆”
  • 对视频档案进行任何自然语言搜索
  • “摄取 <file> 以供搜索” / “上传此视频以供搜索”
  • “添加此 RTSP 流以供搜索” / “注册 <rtsp_url> 以供搜索”
  • “从搜索中删除 <file>” / “移除此视频及其嵌入向量”

部署前提条件

此技能需要在 $HOST_IP 上运行 VSS search 配置文件。执行任何请求前:

  1. 检查服务栈:

    curl -sf --max-time 5 "http://${HOST_IP}:8000/docs" >/dev/null \
      && curl -sf --max-time 5 "http://${HOST_IP}:9200/" >/dev/null
    

    (第二项检查用于确认 Elasticsearch 已启动,这是搜索配置文件独有的检查。)

  2. 如果检查失败,请询问用户:

    “VSS search 配置文件未在 $HOST_IP 上运行。是否要使用 /vss-deploy-profile 技能和 -p search 立即部署?”

    • 如果是 → 转交给 /vss-deploy-profile 技能。部署成功后返回此处。
    • 如果否 → 停止。不要在缺少服务栈或配置文件错误的情况下运行此技能。

    (如果调用方已明确预先授权你自主部署 — 例如请求中写明“已预先授权部署前置条件”,或你正在具有该权限的非交互式评估环境中运行 — 则跳过确认,直接调用 /vss-deploy-profile。)

  3. 如果检查通过,则继续。


摄取前提条件(任何 /generate 调用前均为必需)

要使来源可供搜索,必须通过 VSS Agent 后端摄取,而不能仅通过 VIOS 摄取。Agent 的摄取路由将 VIOS 上传、RTVI-CV 注册和 RTVI-embed 管道作为一个事务处理;单独执行 VIOS PUT 只会存储字节,不会将其接入 Elasticsearch。

请先确认来源存在于 VIOS 中(必需工作流第 2 步)。如果来源不存在,请在调用 /generate 前使用以下任一方案摄取。摄取成功后,来源会以你提供的名称显示在 sensor/list 中,并可在 Agent 转发给搜索工具分解器的自然语言查询中引用——你无需自行构造结构化的 video_sources 负载。

文件上传——通用三步流程

使用下面带时间戳的上传表单。VSS Agent/搜索配置使用 2025-01-01T00:00:00.000Z 作为上传的 video_file 基础时间戳; VIOS 存储和嵌入必须使用相同的时间线,否则 截图 URL 和 critic 帧获取可能会失败。

FILENAME="<filename.mp4>"
FILE_PATH="/path/to/${FILENAME}"

# 1. Ask the agent for the chunked-upload URL
UPLOAD_URL=$(curl -s -X POST "http://${HOST_IP}:8000/api/v1/videos" \
  -H "Content-Type: application/json" \
  -d "{\"filename\":\"${FILENAME}\"}" | jq -r .url)

# 2. Chunked POST the file to that VST URL (nvstreamer protocol).
#    The final-chunk response carries sensorId.
IDENTIFIER=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid)
UPLOAD_RESPONSE=$(curl -s -X POST "${UPLOAD_URL}" \
  -H "nvstreamer-chunk-number: 1" \
  -H "nvstreamer-total-chunks: 1" \
  -H "nvstreamer-is-last-chunk: true" \
  -H "nvstreamer-identifier: ${IDENTIFIER}" \
  -H "nvstreamer-file-name: ${FILENAME}" \
  -F "mediaFile=@${FILE_PATH};filename=${FILENAME}" \
  -F "filename=${FILENAME}" \
  -F 'metadata={"timestamp":"2025-01-01T00:00:00"}')

# 3. Tell the agent the upload finished — this fans out to RTVI-CV + RTVI-embed
SENSOR=$(printf '%s' "${UPLOAD_RESPONSE}" | jq -r .sensorId)
[ -z "${SENSOR}" ] || [ "${SENSOR}" = "null" ] \
  && { echo "Upload failed: no sensorId in response: ${UPLOAD_RESPONSE}"; exit 1; }
printf '%s' "${UPLOAD_RESPONSE}" \
  | jq --arg filename "${FILENAME}" '. + {filename: $filename}' \
  | curl -s -X POST "http://${HOST_IP}:8000/api/v1/videos/${SENSOR}/complete" \
      -H "Content-Type: application/json" \
      -d @- | jq .

等待 /complete 响应(嵌入写入后会返回 chunks_processed > 0)。只有在此之后,视频才可供搜索。

已弃用的 PUT /api/v1/videos-for-search/{filename} 路由也已接入,供旧版调用方使用(单次请求,由 Agent 驱动),但其 OpenAPI 条目标记为 deprecated。新工作请优先使用上述三步流程。

RTSP 流——单个端点
curl -s -X POST "http://${HOST_IP}:8000/api/v1/rtsp-streams/add" \
  -H "Content-Type: application/json" \
  -d '{
    "sensorUrl": "rtsp://<host>:<port>/<path>",
    "name": "<sensor-name>",
    "username": "",
    "password": "",
    "location": "",
    "tags": ""
  }' | jq .

响应格式为 {status, message, error}——不包含 sensorId(Agent 使用你提供的 name 作为流的键)。任何步骤失败时,之前的步骤都会回滚。start_embedding_generation 步骤采用触发后验证的方式:2xx 表示请求已被接受且嵌入管道正在后台运行,并不表示流已可供搜索。只有在足够多的分块写入 Elasticsearch 后,搜索结果才会开始出现——如果需要确认是否就绪,可以在几秒后使用较小的 top_k 值轮询查询。

删除来源——通过 Agent 清理

请通过 Agent 后端删除,而不要直接通过 VIOS 删除,以便同时清理 VIOS 存储和搜索嵌入。

# For video files: video_id is the VIOS sensor/video UUID
curl -s -X DELETE "http://${HOST_IP}:8000/api/v1/videos/<video_id>" | jq .

# For RTSP streams: name is the registered source name
curl -s -X DELETE "http://${HOST_IP}:8000/api/v1/rtsp-streams/delete/<name>" | jq .

搜索原理

  1. 摄取——文件通过 Agent 的通用三步流程接入;RTSP 流通过 /api/v1/rtsp-streams/add 接入。两种路由都会将来源交给 RTVI-CV(属性检测)和 RTVI-Embed(Cosmos Embed1),后者会为视频片段生成向量嵌入。
  2. 索引——嵌入通过 Kafka 管道存储在 Elasticsearch 中。
  3. 查询——自然语言查询会被转换为嵌入,并通过相似度与已存储的向量进行匹配。
  4. 结果——按相关性排序的带时间戳视频片段,并附带片段播放链接。

VSS Agent 编排的这种搜索可以产生 3 种行为:

  • 仅属性搜索:当 LLM 分解查询后,只找到外观属性而没有动作时(例如“穿红色夹克的人”)
  • 仅嵌入搜索:当查询没有可提取的属性时(例如“给我看看叉车”)
  • 融合搜索:当查询同时包含动作和属性时(例如“穿红色夹克跑步的人”),先运行嵌入搜索,再使用属性搜索重新排序

强制工作流程

使用此技能时,始终遵循以下高级工作流程:

  1. 根据用户指示解析输入——如果未明确提供 $HOST_IP,则立即停止。 请参阅下方的 § 输入解析。不要默认使用 localhost、127.0.0.1、Agent 自身运行所在的主机或任何其他猜测值。在用户提供端点之前,不要发送 POST http://.../generate 请求。向用户只提出一个问题,询问 HOST_IP / VSS Agent 端点,然后等待。

  2. 解析来源——在调用 /generate 之前立即停止。 如果用户的查询提到特定视频 / 传感器名称(例如“机场视频”“warehouse_cam_3”“sample warehouse”),请在发送 POST .../generate 之前,确认它确实已在 VIOS 中注册。使用 vss-manage-video-io-storage 技能列出来源。

    然后:

    • 如果命名的来源(或明显包含该名称的来源)在列表中 → 继续执行第 3 步。逐字转发用户的自然语言查询——Agent 自带的搜索工具分解器(services/agent/src/vss_agents/tools/search.py)会根据提供的可用来源从文本中提取 video_sources,因此此技能无需构造结构化的 video sources 载荷。
    • 如果命名的来源不在列表中 → 停止。不要调用 /generate 进行探测。向用户回复已注册的来源名称,并询问他们指的是其中某个来源、想要摄取缺失来源(指引他们参阅摄取前提条件,并通过Agent 后端而非直接调用 VIOS 来运行匹配的文件或 RTSP 方案),还是想要放弃此查询。等待澄清。
    • 如果查询未命名特定来源(“在已摄取的视频中查找叉车”“搜索所有来源”)→ 跳过子字符串检查,但 sensor/list 仍必须返回非空结果(否则没有摄取任何来源 → 立即停止)。
  3. 使用选定的方法运行搜索

  4. 根据用户的查询向用户呈现结果。将回复格式设为专业的检查报告,标题命名为 Video Search Results: — 使用清晰的章节标题

    • 逐项整理发现,并提供支持细节,最后以摘要收尾
    • 在比较有帮助时使用表格。采用技术报告的写法,而非聊天消息的语气。
    • 如果 criteria 结果非空,除包含“Critic result”(“confirmed” | “rejected” | “skipped”)列外,还要包含“Criteria”列,其中列出此搜索结果的全部标准({criteria_n}: ✓ | ✗)
  5. 关键:验证结果并简明地向用户说明验证情况。 如果搜索失败,或返回意外结果(即与用户查询不匹配的视频、零条匹配结果、返回零个视频、出错等),请停止。必须先阅读 troubleshooting.md,通过反馈循环反复处理,直到找到并呈现正确结果,且格式符合专业检查报告的要求。

  6. 最终验证:

    • 始终告知用户可以运行最终验证和后续验证。将此内容作为 Verification Step 呈现
    • 仅当用户同意时,才使用搜索命中项(JSON 结果)中最佳候选项(相似度得分最高)的 screenshot_url,将截图下载到 /tmp。读取截图并验证其是否符合用户查询

输入解析

仅根据对话或用户查询推断这些输入(除非用户提供,否则不要使用其他文件)。如果无法推断其中某些输入,请立即询问用户:

  • $HOST_IP:VSS Agent 后端的运行位置

注意事项

  • 一旦发生任何意外情况,立即进入工作流中的故障排查步骤,并阅读 troubleshooting.md
  • 使用具体的视觉描述(物体、动作、位置)查询效果最佳。必要时补充用户查询,以提升问题质量并拓展可能的细节
  • 此技能假设视频源已通过 Agent 后端完成摄取(请参阅 摄取前提)。用户明确提出请求时(“为搜索摄取 <file>”、“添加 <rtsp_url> 以供搜索”),可以运行由 Agent 支持的摄取配方;但不会搜索用户未指定的本地文件系统文件,也不会使用裸 VIOS PUT 路径(不会生成嵌入向量)。工作流第 2 步仍将确认“此源存在于 VIOS 中”作为执行 /generate 的硬性前提。
  • 使用 vss-query-analytics 技能,将搜索结果与事件/警报数据交叉对照

通过 REST API 搜索

除非用户另有指定,否则默认使用此 REST API 方式。

# Consider only ingested video file sources by default
curl -s -X POST http://${HOST_IP}:8000/generate \
  -H "Content-Type: application/json" \
  -d '{"input_message": "find all instances of forklifts"}' | jq .
更多示例
# Search by object
curl -s -X POST http://${HOST_IP}:8000/generate \
  -H "Content-Type: application/json" \
  -d '{"input_message": "find vehicles in the parking lot"}' | jq .

# Search by action
curl -s -X POST http://${HOST_IP}:8000/generate \
  -H "Content-Type: application/json" \
  -d '{"input_message": "show me people running"}' | jq .

# Search by time context
curl -s -X POST http://${HOST_IP}:8000/generate \
  -H "Content-Type: application/json" \
  -d '{"input_message": "what happened at the entrance between 2pm and 3pm?"}' | jq .

# Consider only RTSP sources with `search_source_type` filter i.e. live camera streams
curl -s -X POST http://${HOST_IP}:8000/generate \
  -H "Content-Type: application/json" \
  -d '{"input_message": "find all instances of forklifts", "search_source_type": "rtsp"}' | jq .
高级控制选项

如果用户的查询有歧义、用户需要更多指导,或需要精细控制,请通过纯文本明确指出特定选项,补充用户的 input_message,并引导 Agent 按期望方向执行。可用的控制维度:

维度类型默认值说明
video sourcesstring[]null限定特定摄像头或传感器名称
top kint10最大结果数
minimum similarityfloat0.0最低相似度阈值;提高阈值(例如 0.3)可过滤噪声
critic usagebooltrueVLM 验证每个结果并移除误报
descriptionstringnull如果元数据可用,则按摄像头元数据(例如位置、类别)筛选

选择部分调优选项,并根据用户的情况和查询进行调整。 有关使用这些选项的发现模式示例,请参阅 discovery_modes.md。


通过 Agent UI 搜索

打开 http://${HOST_IP}:3000/ 并输入自然语言查询:

find all instances of forklifts
show me people near the loading dock
when did a truck arrive at the gate?
find someone wearing a red jacket

结果包括带时间戳的片段及其相似度分数。

bump:2

评论

支持 Markdown