| 名称 | vss-deploy-profile |
| 描述 | ‘用于选择、配置、部署、验证、调试或拆除VSS配置文件(base、search、lvs、warehouse、edge)。不适用于独立微服务——请使用vss-deploy-*技能。’ |
| 开源协议 | Apache-2.0 metadata: |
| 版本 | ‘3.2.0’ github-url: ‘https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization’ tags: ‘nvidia blueprint deployment’ |
VSS 部署
可用脚本
| 脚本 | 用途 | 参数 |
|---|---|---|
scripts/normalize_resolved_yml.py |
在部署前,为从resolved.yml中过滤掉的服务剔除可选的depends_on条目。 |
resolved.yml的路径 |
scripts/probe_remote_models.sh |
探测兼容OpenAI的远程LLM/VLM端点并验证所选模型ID。 | Base URL,可选预期模型ID |
配置文件路由
将用户请求匹配到对应的配置文件,然后加载该配置文件的参考文档,以获取规模、服务、环境配置和调试信息。
| 用户说的内容 | 配置文件 | 参考文档 |
|---|---|---|
| “部署vss” / “部署base” | base |
references/base.md |
| “部署alerts” / “告警验证” / “实时告警” / “为事件报告部署” | alerts |
references/alerts.md |
| “部署lvs” / “视频摘要” | lvs |
references/lvs-profile.md |
| “部署search” / “视频搜索” | search |
references/search.md |
| “部署warehouse” / “warehouse蓝本” / “vss warehouse” | warehouse |
references/warehouse.md |
| “调试warehouse” / “warehouse不工作” / “warehouse FPS低” / “warehouse BEV不同步” | warehouse(调试) |
references/warehouse-debug.md |
边缘硬件路由(DGX Spark、AGX/IGX Thor):参见references/edge.md。DGX Spark在端口30081上使用Spark Nano 9B独立本地LLM;AGX/IGX Thor使用Edge 4B独立vLLM作为后备。
每个配置文件的参考文档都拥有自己的规模表。 不要从这个文件选择部署形态——打开配置文件参考文档,对照主机硬件,在该参考文档的(模式×平台)矩阵中检查最低GPU数量。
说明
部署流程始终是:将.env复制到generated.env,应用覆盖项,将compose dry-run到resolved.yml,审查、规范化、部署,然后等待就绪。
# 1. cp dev-profile-<profile>/.env dev-profile-<profile>/generated.env (干净副本)
# 2. 将环境变量覆盖项应用到 generated.env(源 .env 保持原样)
# 3. docker compose --env-file generated.env config > resolved.yml (dry-run)
# 4. 审查 resolved.yml
# 5. docker compose --env-file generated.env -f resolved.yml up -d
.env是只读的、已检入的默认文件;generated.env是每次部署的工作副本。第1c步会完整说明这一点。
前提条件
- 仓库路径 — 在询问用户之前自动检测
video-search-and-summarization/。将检测到的路径用作所有后续命令的$REPO。 - 凭据门槛 — 参见
references/credentials.md:NGC_CLI_API_KEY用于本地/local_shared NIM拉取,NVIDIA_API_KEY用于远程NIM端点,HF_TOKEN用于使用受限HF模型的边缘方案。 - 系统前提条件(GPU驱动、Docker、NVIDIA容器工具包、内核sysctl参数,以及——如果
ufw处于活动状态——Docker网桥→宿主机防火墙允许,以便网桥NIM能从主机模式的VST获取视频片段) — 完整检查见references/prerequisites.md。规范硬件/驱动矩阵见VSS前提条件页面。
自动检测片段(git根目录,然后是基于deploy/docker/compose.yml + dev-profile.sh + skills/vss-deploy-profile的通用路径探测)位于references/prerequisites.md。导出解析后的$REPO;如果检测失败,询问用户获取检出路径。
飞行前检查
每次部署前运行。完整的系统检查清单和修复步骤见references/prerequisites.md。对于DGX Spark / IGX Thor / AGX Thor,还需运行references/edge.md中的缓存清理程序检查。
首先检测sudo模式。 一些飞行前修复和边缘缓存清理程序安装器会调用sudo。如果主机需要sudo密码,这些步骤在sudo -n下会静默无效,使部署处于半准备状态。
if sudo -n true 2>/dev/null; then
echo 'passwordless sudo — pre-flight will auto-install missing pieces'
else
echo 'sudo requires password — pre-flight will NOT auto-install; hand commands to the user'
fi
当sudo需要密码时,技能不得自行运行特权安装程序。要向用户提供来自references/prerequisites.md的可复制粘贴命令块,并带有*“运行一次并确认”*的交接提示,然后在用户回复后继续。
最小冒烟测试(必须成功):
nvidia-smi --query-gpu=index,name --format=csv,noheader
docker info 2>/dev/null | grep -qi runtimes \
&& docker run --rm --gpus all ubuntu:22.04 nvidia-smi >/dev/null 2>&1 \
&& echo 'nvidia runtime OK'
如果冒烟测试失败,请勿继续;打开references/prerequisites.md查看修复树。
模型选择
$LLM_REMOTE_URL/$VLM_REMOTE_URL(如果用户要求远程)$NGC_CLI_API_KEY(本地NIM)或$NVIDIA_API_KEY(远程)
端点意图门槛。 不要根据杂散的环境变量推断远程放置(LLM_ENDPOINT_URL、VLM_ENDPOINT_URL、LLM_BASE_URL、VLM_BASE_URL可能是遗留变量)。仅在以下情况使用远程LLM/VLM:(1) 用户要求/提供了远程端点;(2) 本地规模无法容纳所选模型且用户同意;或(3) 边缘方案需要VSS视为remote的独立本地服务(例如localhost:30081上的DGX Spark Nano 9B)。如果端点变量已设置但用户未要求远程,在第1步中提出并询问——绝不要因为某个变量碰巧存在就静默部署远程。
如果此主机上没有组合满足配置文件的规模要求,停止并报告阻塞点——不要静默选择其他形态。
边缘共享模式特定于平台。 完整方案见
references/edge.md。
部署流程
始终遵循此顺序。切勿跳过dry-run。
步骤 0 — 拆除任何现有部署 + 清理数据卷
如果已存在部署,请在重新部署前拆除它并清理过期的数据卷。
完整程序见references/teardown.md。
步骤 0a — 凭据门槛(在任何环境变量变更之前运行)
在第1c步将.env复制到generated.env之前,验证所选配置文件需要的每个凭据和选定的远程端点。这里的401是30秒的失败;同样的401在NIM冷启动中则是10–20分钟的失败。运行references/credentials.md中的发现和探测流程,包括为计划写入generated.env的任何LLM/VLM端点运行scripts/probe_remote_models.sh。将结果与所选模式对照:缺失或无效的必需凭据/端点是阻塞项,可选凭据不是。
步骤 1 — 收集上下文
在构建环境变量覆盖项之前,请确认:
| 值 | 如何确定 |
|---|---|
| 配置文件 | 将用户意图匹配到上面的路由表。默认:base |
| 仓库路径 | 使用在前提条件中自动检测到的$REPO值。如果自动检测失败,在继续前询问用户的检出路径。 |
| 硬件 | nvidia-smi --query-gpu=name,memory.total --format=csv,noheader |
| LLM/VLM放置 | 明确决定本地/local_shared/远程。将可用GPU与所选配置文件的最低GPU数量表交叉对照。如果端点环境变量存在但用户未请求远程,询问是使用还是忽略它们。 |
| API密钥 | NGC_CLI_API_KEY用于本地NIM,NVIDIA_API_KEY用于远程 |
HOST_IP |
集群内拨号地址:ip route get 1.1.1.1 src(与dev-profile.sh相同;在局域网和云上正确)。如果该接口是VPN/隧道,则回退到局域网IP并提示用户 — 网络寻址。 |
EXTERNAL_IP |
面向浏览器的地址;默认值为${HOST_IP}。当浏览器路径不同时覆盖——云公共IP、Brev安全链接(第1d步)或隧道;如果不确定,请询问用户从哪里浏览。网络寻址。 |
HAPROXY_PORT |
面向浏览器的入口端口。默认7777;确保它空闲。 |
在docker compose up之前,验证EXTERNAL_IP、HAPROXY_PORT、VSS_PUBLIC_HOST和VSS_PUBLIC_PORT已填充浏览器可访问的值。否则,堆栈可能看起来健康,而UI/API/VST链接却404或通过Cloudflare Access循环。
步骤 1b — 准备数据目录
布局(资产路径、所有权、挂载点、配置文件专属子目录)记录在references/data-directory.md。在主机上首次部署或切换配置文件前,请阅读该文件。
步骤 1c — 初始化generated.env
这是技能每次部署的工作副本。始终从源.env的全新副本开始,绝不修改源文件。
PROFILE=base
ENV_SRC=$REPO/deploy/docker/developer-profiles/dev-profile-$PROFILE/.env
ENV_GEN=$REPO/deploy/docker/developer-profiles/dev-profile-$PROFILE/generated.env
cp "$ENV_SRC" "$ENV_GEN"
所有后续写入(Brev EXTERNAL_IP、第2步的env_overrides字典)都写入$ENV_GEN。从这里开始,$ENV_SRC只读。
步骤 1d — 仅适用于Brev:先检测,然后将EXTERNAL_IP设置为安全链接域名
首先检测Brev — Brev配置的实例会在/etc/environment中设置BREV_ENV_ID;没有其他方式:
grep -qE '^BREV_ENV_ID=' /etc/environment && echo 'on Brev' || echo 'not Brev'
- 不是Brev → 跳过此步骤的其余部分,不要阅读
references/brev.md;保留基于${HOST_IP}的正常EXTERNAL_IP。 - 是Brev → 将
references/brev.md§ 设置流程中的Brev安全链接覆盖项应用到generated.env(而不是.env)。这些项将EXTERNAL_IP/VSS_PUBLIC_HOST设置为安全链接域,并设置VSS_PUBLIC_HTTP_PROTOCOL=https/VSS_PUBLIC_WS_PROTOCOL=wss/VSS_PUBLIC_PORT=443— 仅设置EXTERNAL_IP会使UI/API/WS链接保持http://…:7777,浏览器会将其作为混合内容阻止。
步骤 2 — 构建env_overrides
根据用户请求和收集的上下文生成env_overrides字典:明确选择远程/本地LLM/VLM,设置凭据,指定端点,设置平台特定标志。不要让现有的shell环境变量静默选择放置方式;将选定的LLM_MODE / VLM_MODE及匹配的端点/模型字段写入generated.env。完整映射(每个覆盖键、适用时机、默认值、配置文件特定差异)见references/env-overrides.md。每个配置文件参考文档都包含该配置文件常见场景的工作示例。
步骤 3 — 应用覆盖项 + dry-run
工作环境文件: <repo>/deploy/docker/developer-profiles/dev-profile-<profile>/generated.env(在第1c步创建)。
提醒(参见第1c步): 将所有覆盖项(第2步字典 + Brev
EXTERNAL_IP)应用到generated.env;--env-file始终指向它,部署后验证器读取它以获取实际部署的值。
# (第1c步已执行:cp $ENV_SRC $ENV_GEN)
# 将第2步的env_overrides字典应用到generated.env
# (读取行,更新匹配的键,追加新键,写入)
# 示例:
# sed -i "s|^LLM_MODE=.*|LLM_MODE=remote|" "$ENV_GEN"
# sed -i "s|^LLM_BASE_URL=.*|LLM_BASE_URL=http://localhost:30081|" "$ENV_GEN"
# 解析compose
cd $REPO/deploy/docker
docker compose --env-file $ENV_GEN config > resolved.yml
解析后的YAML保存到<repo>/deploy/docker/resolved.yml。
步骤 3b — 验证resolved.yml没有未展开的${…}标记
如果resolved.yml中存在未展开的${VAR}标记,说明compose没有看到这些环境变量值。诊断过程和常见原因见references/troubleshooting.md。
步骤 3c — 验证对所选NGC工件的访问权限
在resolved.yml存在且docker compose up之前执行此操作。第0a步的NGC令牌探测只能证明密钥能验证身份;它不能证明密钥所属的组织/团队能访问所选的镜像或模型仓库。
从实际选定的部署构建工件列表:
resolved.yml:nvcr.io/...下Compose将要拉取的每个image:。$ENV_GEN:NGC支持的模型/资源路径,例如RTVI_VLM_MODEL_PATH=ngc:nim/nvidia/cosmos3-nano-reasoner:bf16-final。跳过none、git:...、本地路径和远程端点URL。- 配置文件分阶段步骤:配置文件参考文档中记录的任何NGC模型/资源下载,如告警/搜索感知模型分阶段。
继续前,使用规范化的NGC密钥探测每个选定的工件:
- 容器镜像:在
docker login nvcr.io之后,运行docker manifest inspect <nvcr.io/...>— 对于受限的nvcr.io仓库,此处返回401/403明确表示没有权限(manifest读取与层拉取需要相同的组织/团队授权);或者当工件能干净映射到NGC镜像路径时,使用匹配的ngc registry image info ...命令。 - NGC模型/资源路径(例如RT-VLM运行时下载的Cosmos检查点):为配置文件将要加载或下载的确切仓库/标签运行匹配的
ngc registry model info ...或ngc registry resource info ...;这些使用NGC的作用域认证。不要使用docker manifest inspect探测模型(会返回“no such manifest”,因为模型不是OCI镜像),也不要使用裸的Authorization: Bearer <key>REST调用(会返回403,因为那不是NGC的认证流程);两者都是预期的假阴性,而非权限失败。如果ngcCLI不可用,则将上面的容器镜像探测视为权限信号,因为NGC授予组织/团队对镜像和模型的联合访问权限。 - 配置文件分阶段的TAO/感知模型:在分阶段块下载文件之前,为每个仓库/标签运行相应
ngc registry model info .../resource info ...。
如果任何探测返回401、403、permission、not being a member of the organization that owns the repo、缺少org/repo或类似的访问错误,停止并向用户索要有权访问这些工件的组织/团队的NGC密钥。不要在Compose启动NIM冷启动时才发现失败。
步骤 3d — 从resolved.yml中剔除悬挂的可选depends_on依赖
必须在第3步之后、第5步之前运行。 跳过此步骤会中止部署:
规范化 - 为从resolved.yml中过滤掉的服务丢弃可选依赖。
# 从仓库根目录运行
uv run skills/vss-deploy-profile/scripts/normalize_resolved_yml.py "$REPO/deploy/docker/resolved.yml"
如果主机上没有uv,用curl -LsSf https://astral.sh/uv/install.sh | sh安装一次(无需root权限)。
在up -d之前重新验证:
docker compose -f "$REPO/deploy/docker/resolved.yml" config --quiet && echo 'resolved.yml OK'
如果规范化器运行后验证仍然失败,捕获错误并检查——那是另一个bug(非可选依赖,或其他模式冲突),而不是悬空depends_on的情况。
步骤 4 — 审查
向用户展示将要部署的内容摘要:
- 配置文件名称和硬件
- LLM/VLM模型和模式(本地/远程/local_shared)
- 将要启动的服务
- GPU设备分配
- 关键端点(UI端口、代理端口)
询问:“看起来没问题——现在部署吗?” 并在第5步前等待确认。
例外情况 — 自主模式。 如果用户的请求已经要求自主运行(例如“自主部署X”、“无需确认运行”、“非交互式”),则跳过确认提示直接进入第5步。此路径的存在是为了自动化评估/CI调用不会挂起等待永远不会得到的人工回复。在所有其他情况下,必须由人工批准。
步骤 5 — 部署
cd $REPO/deploy/docker
docker compose --env-file $ENV_GEN -f resolved.yml up -d
--env-file是必需的。 如果没有使用第3步中相同的generated.env,COMPOSE_PROFILES可能未设置,up -d可能以选中服务为零而退出0。
普通重试时避免使用宽泛的
--force-recreate— 它会销毁已热身的NIM容器(每个再需要3–5分钟的torch.compile + CUDA图捕获)。修复根本原因(通常是权限或环境变量拼写错误)后重新运行up -d;仅当配置文件参考文档将定向--force-recreate --no-deps <service...>记录为恢复路径时才使用。
docker compose up -d只创建容器;它不会等待内部服务完成预热。在所有就绪门禁通过之前,绝不宣布部署成功。
步骤 5b — 等待堆栈真正健康
门禁0 — 容器数量必须大于0。 在启动数量(docker compose -f resolved.yml ps -q | wc -l)非零且≥预期数量(config --services | wc -l)之前,拒绝越过up -d继续;零个或数量不足几乎总是意味着第5步缺少--env-file。确切门禁以及完整就绪程序见references/readiness.md。
冷部署可能需要10–20分钟,每个配置文件参考文档列出了所需端点。绝不要在第up -d后宣布部署完成;只有在每个记录的端点成功后才可以。
拆除
要拆除部署 — 完全回收主机或保留缓存的重新部署/配置文件切换 — 请遵循references/teardown.md。始终使用带-v --remove-orphans的mdx项目进行拆除;普通的docker compose down会遗留卷和网络。
调试部署
当用户要求“调试部署”、“验证其是否正常工作”、“为什么代理没有响应”或类似请求时,使用此工作流。目标是确认完整的视频摄取到智能体回答路径,而不仅仅是容器“正在运行”。
每个配置文件参考文档都有一个调试部分,列出该配置文件的具体命令和故障模式表。
快速检查(所有配置文件)
# 1. 所有预期容器正在运行
docker ps --format 'table {{.Names}}\t{{.Status}}'
# 2. 代理API + UI响应
curl -sf http://localhost:8000/health >/dev/null && echo 'agent OK'
curl -sf http://localhost:3000/ >/dev/null && echo 'ui OK'
LLM/VLM NIM探测 — 包括跳过localhost:3008x(预期会连接被拒绝)的*_MODE=remote处理,并通过scripts/probe_remote_models.sh探测所选*_BASE_URL/v1/models — 位于references/troubleshooting.md。
局限性
- 此技能仅部署基于compose的VSS配置文件;独立微服务部署属于对应的
vss-deploy-*技能。 - 硬件规模、模型放置和配置文件特定就绪由配置文件参考文档负责;不要凭记忆推断。
- 当无密码sudo不可用时,需要用户批准才能进行特权主机修复。
故障排除
常见错误快速参考、完整症状→原因→修复表、未展开${...}诊断以及NIM端点探测都集中在references/troubleshooting.md中 — 对于任何部署、运行时或探测失败都先从那里开始,然后在匹配的每配置文件参考文档的调试部分继续。