rtvi-vlm-customize-model

Par nvidia · skills

Comment remplacer le VLM dans le blueprint VSS Alerts — couvre les méthodes de déploiement du microservice RTVI-VLM, les trois consommateurs VLM (rtvi-vlm, vlm-as-verifier, vss-agent) et les vérifications de santé.

npx skills add https://github.com/nvidia/skills --skill rtvi-vlm-customize-model

Personnalisation VLM — Blueprint VSS Alerts

Quand utiliser cette compétence

Utilisez cette compétence quand l'utilisateur veut :

  • rediriger le Blueprint VSS Alerts vers un endpoint VLM différent,
  • exécuter rtvi-vlm en mode standalone avec un endpoint compatible OpenAI ou le chemin vLLM dans le conteneur,
  • corriger l'hypothèse que changer une config VLM met automatiquement à jour rtvi-vlm, vlm-as-verifier et vss-agent.

Ne pas utiliser cette compétence pour les remplacements de détecteur CV dans vss-rt-cv ; utilisez rtvi-cv-customize-model pour cela.

Instructions

  • Traitez rtvi-vlm, vlm-as-verifier et vss-agent comme trois consommateurs VLM distincts. N'impliquez pas que changer uniquement RTVI_VLM_* redirige automatiquement le vérificateur ou l'UI de l'agent.
  • Traitez tous les chemins de cette compétence comme relatifs à un clone du référentiel public VSS Blueprint. Les fichiers de déploiement du blueprint se trouvent sous deploy/docker/... ; les sources RT-VLM accessibles au client et les fichiers de déploiement standalone se trouvent sous services/rtvi/rt-vlm/.... Aucun de ces chemins ne se résout dans le référentiel DeepStream.
  • Pour le routage compatible OpenAI côté blueprint, couvrez les trois surfaces : variables env RTVI_VLM_*, ${VSS_PROFILE_DIR}/vlm-as-verifier/configs/config.yml et les paramètres vss-agent VLM_MODEL_TYPE / VLM_NAME / VLM_BASE_URL, puis mentionnez force-recreate et les vérifications de journaux.
  • Pour vllm-compatible standalone, réglez VLM_MODEL_TO_USE=vllm-compatible, pointez MODEL_PATH vers la source des poids, mentionnez HF_TOKEN uniquement si le modèle nécessite vraiment une authentification. Ne traitez pas une ligne de journaux comme preuve d'un déploiement fonctionnant : v3.2.1 enregistre Warmup VlmProcess-0 done même quand le warm-up a levé une exception. Exigez l'absence d'une ligne Error during warmup, la disponibilité et une réponse /v1/chat/completions réussie.
  • Ne collez jamais les credentials en chat ou dans les journaux ; capturez-les avec une invite silencieuse (read -rsp), réglez les permissions du fichier env à chmod 600, et ne commitez jamais generated.env.

Exemples

  • "Pointez le Blueprint VSS Alerts vers une NIM côté host sur http://host.docker.internal:30082 pour tous les appels RTVI-VLM."
  • "Exécutez rtvi-vlm en mode standalone avec Qwen3-VL-8B-Instruct servi dans le conteneur."
  • "J'ai changé uniquement RTVI_VLM_ENDPOINT dans generated.env. Cela devrait aussi rediriger vlm-as-verifier et vss-agent, non ?"

Emplacements source

Cette compétence est documentation uniquement — aucune source VSS ne s'y trouve. Utilisez un clone VSS v3.2.1 ou compatible et exécutez chaque commande depuis sa racine. Clone/LFS, chemins du profil Alerts, arborescence RT-VLM, images épinglées et variables VSS_* : references/vss-source-layout.md.

Modes auxquels cela s'applique

Drapeau mode Workflow Rôle VLM
--mode real-time (2d_vlm) Alertes VLM en temps réel Principal — chaque alerte est pilotée par VLM
--mode verification (2d_cv) CV + vérification VLM Vérificateur — VLM confirme chaque incident CV

La personnalisation VLM s'applique aux deux modes. Trois services font chacun leurs propres appels VLM avec configuration séparée :

Service Quand utilisé Emplacement config
rtvi-vlm Génération d'alerte en temps réel ; appels tool rtvi_vlm_alert depuis l'UI agent Variables RTVI_VLM_* dans ${VSS_PROFILE_DIR}/.env / generated.env
vlm-as-verifier (alert-bridge) Post-traitement : confirme chaque événement mdx-incidents (2d_cv uniquement) ${VSS_PROFILE_DIR}/vlm-as-verifier/configs/config.yml
vss-agent Requêtes interactives de l'UI agent VLM_MODEL_TYPE, VLM_BASE_URL, VLM_NAME dans ${VSS_PROFILE_DIR}/.env

Les trois peuvent pointer vers le même endpoint de modèle — ce n'est pas obligatoire.

alert-bridge et vss-agent sont fermés ; leurs images épinglées (et la balise image rtvi-vlm) sont listées dans references/vss-source-layout.md.


RTVI-VLM : Deux méthodes de déploiement

L'implémentation est sélectionnée par VLM_MODEL_TO_USE (standalone) ou RTVI_VLM_MODEL_TO_USE (blueprint VSS).

Méthode A : Endpoint compatible OpenAI (openai-compat)

Le conteneur RTVI effectue des appels HTTP vers un serveur d'inférence externe ; il ne charge pas le modèle lui-même. Cela couvre NIM local ou distant, vLLM externe et OpenAI.

Méthode B : vLLM dans le conteneur RTVI (vllm-compatible)

Le conteneur télécharge et sert le modèle à l'aide de son moteur vLLM intégré. Aucun serveur d'inférence externe n'est nécessaire.

Contrainte dure : L'architecture du modèle doit être supportée par la version vLLM fournie dans l'image RTVI sélectionnée. Vérifiez les conseils relatifs aux modèles supportés dans services/rtvi/rt-vlm/README.md. Si le modèle nécessite une vLLM plus récente, utilisez la méthode A avec un conteneur externe.


Configuration RTVI-VLM via VSS Blueprint

Le .env / generated.env du blueprint VSS mappe la plupart des variables RTVI_VLM_* vers des noms natifs de conteneur. L'identifiant du modèle ou du déploiement est l'exception importante : v3.2.1 mappe VLM_NAME à VIA_VLM_OPENAI_MODEL_DEPLOYMENT_NAME. RTVI_VLM_PORT est aussi exceptionnel : il est requis par Compose pour publier le service et doit être explicitement fourni quand generated.env ne le contient pas.

Configuration de port requise — tous les workflows Blueprint

Ajoutez RTVI_VLM_PORT et mettez à jour les deux lignes 8018 codées en dur dans le .env du profil Alerts, puis relancez dev-profile.sh. Éditez .env, pas generated.env — le générateur le remplace.

# ${VSS_PROFILE_DIR}/.env
RTVI_VLM_PORT=8018                                        # ajouter cette ligne
RTVI_VLM_BASE_URL=http://${HOST_IP}:${RTVI_VLM_PORT}     # mettre à jour : était http://${HOST_IP}:8018
RTVI_VLM_ENDPOINT=http://${HOST_IP}:${RTVI_VLM_PORT}/v1  # mettre à jour : était http://${HOST_IP}:8018/v1

Gardez la valeur à 8018 sauf si ce port n'est pas disponible. La propriété des variables, la surcharge du générateur VLM_BASE_URL et le patch requis pour tout autre port se trouvent dans references/port-and-url-wiring.md.

Méthode A — Endpoint compatible OpenAI

Dans le fichier Compose du blueprint v3.2.1, ces variables host se mappent comme suit :

Variable Blueprint Variable conteneur
RTVI_VLM_MODEL_TO_USE VLM_MODEL_TO_USE
RTVI_VLM_ENDPOINT VIA_VLM_ENDPOINT
RTVI_VLM_API_KEY VIA_VLM_API_KEY
VLM_NAME VIA_VLM_OPENAI_MODEL_DEPLOYMENT_NAME
RTVI_VLM_MODEL_PATH MODEL_PATH

Après avoir appliqué la configuration de port partagée ci-dessus, configurez l'environnement du profil actif :

# ${VSS_PROFILE_DIR}/.env
RTVI_VLM_MODEL_TO_USE=openai-compat
RTVI_VLM_ENDPOINT=http://host.docker.internal:30082/v1
VLM_NAME=<model-or-deployment-id>
OPENAI_API_KEY=<your-api-key>     # credential fallback/default du client
RTVI_VLM_API_KEY=<your-api-key>   # mappé à VIA_VLM_API_KEY préféré
# RTVI_VLM_IMAGE_TAG=3.2.1    # épingler à une balise image spécifique ; défaut 3.2.1

Pour un endpoint Method A authentifié, réglez OPENAI_API_KEY et RTVI_VLM_API_KEY sur la même credential endpoint-spécifique. Le fichier Compose fourni mappe RTVI_VLM_API_KEY vers VIA_VLM_API_KEY, et le client compatible OpenAI préfère VIA_VLM_API_KEY à OPENAI_API_KEY. Laissez les deux non régés uniquement quand l'endpoint accepte intentionnellement les requêtes non authentifiées.

Exemples :

# NIM sur l'hôte Docker. Le Compose fourni mappe ce nom via host-gateway.
RTVI_VLM_ENDPOINT=http://host.docker.internal:30082/v1
VLM_NAME=nvidia/cosmos-reason2-8b

# Catalogue API NVIDIA (réglez les clés via invite silencieuse)
RTVI_VLM_ENDPOINT=https://integrate.api.nvidia.com/v1
VLM_NAME=nvidia/cosmos-reason2-8b
OPENAI_API_KEY=<your-nvidia-api-key>
RTVI_VLM_API_KEY=<your-nvidia-api-key>

# OpenAI (réglez les clés via invite silencieuse)
RTVI_VLM_ENDPOINT=https://api.openai.com/v1
VLM_NAME=gpt-4o
OPENAI_API_KEY=<your-openai-api-key>
RTVI_VLM_API_KEY=<your-openai-api-key>

Migration depuis la méthode B : Remplacez RTVI_VLM_API_KEY avant de recréer rtvi-vlm ; ne laissez pas la credential NGC précédente dans cette variable. Si RTVI_VLM_API_KEY est vide, le Compose fourni revient à NGC_CLI_API_KEY lors du remplissage de VIA_VLM_API_KEY. Parce que le client préfère VIA_VLM_API_KEY, une clé NGC obsolète serait envoyée au nouvel endpoint Method A au lieu de OPENAI_API_KEY. C'est à la fois un échec d'authentification et un risque de divulgation de credential.

RTVI_VLM_OPENAI_MODEL_DEPLOYMENT_NAME n'est pas consommé par le fichier Compose du blueprint public v3.2.1. Utilisez VLM_NAME sauf si le fichier Compose déployé a été intentionnellement personnalisé.

Vérifiez l'identifiant du modèle configuré depuis l'intérieur du conteneur RTVI. L'en-tête Authorization conditionnel garde les endpoints locaux sans clé fonctionnels tout en authentifiant les endpoints comme OpenAI et le catalogue API NVIDIA. Les endpoints peuvent annoncer plusieurs modèles, confirmez donc que l'ID configuré apparaît n'importe où dans la réponse /models :

ALERTS_ENV=developer-profiles/dev-profile-alerts/generated.env

# Nom natif de conteneur pour `VLM_NAME`.
EXPECTED_MODEL="$(docker compose --env-file "${ALERTS_ENV}" exec -T rtvi-vlm \
  printenv VIA_VLM_OPENAI_MODEL_DEPLOYMENT_NAME | tr -d '\r')"
test -n "${EXPECTED_MODEL}"

docker compose --env-file "${ALERTS_ENV}" exec -T rtvi-vlm sh -lc \
  'set --
   if [ -n "${VIA_VLM_API_KEY:-}" ]; then
     set -- -H "Authorization: Bearer ${VIA_VLM_API_KEY}"
   fi
   curl -fsS "$@" "${VIA_VLM_ENDPOINT%/}/models"' \
  | jq -e --arg model "${EXPECTED_MODEL}" 'any(.data[]; .id == $model)' \
  || { echo "Endpoint does not advertise '${EXPECTED_MODEL}'" >&2; exit 1; }

jq -e sort avec un code non-zéro quand l'assertion est false, donc la vérification réussit uniquement quand le modèle configuré apparaît quelque part dans la liste. Pour voir quels modèles l'endpoint offre, supprimez le filtre jq et lisez la réponse brute.

Traitez HTTP 401 de cette requête comme un échec d'authentification. Traitez uniquement une réponse réussie qui échoue l'assertion jq comme une erreur de nom de modèle.

Méthode B — vLLM dans le conteneur RTVI

RTVI_VLM_MODEL_TO_USE=vllm-compatible
RTVI_VLM_MODEL_PATH=git:https://huggingface.co/Qwen/Qwen3-VL-30B-A3B-Instruct

# Avec token HuggingFace :
# HF_TOKEN=<your-hf-token>

# Depuis NGC :
# RTVI_VLM_MODEL_PATH=ngc:nim/nvidia/cosmos-reason2-8b:hf-1208

Conventions de préfixe MODEL_PATH (voir services/rtvi/rt-vlm/src/vlm_pipeline/ngc_model_downloader.py public) :

  • ngc:<registry>/<org>/<model>:<version> — télécharger depuis NGC
  • git:<url> — cloner depuis HuggingFace ou tout repo git LFS
  • /path/to/local/dir — utiliser les poids locaux pré-téléchargés

Un mauvais MODEL_PATH abandonne le démarrage lors du téléchargement, avant que le serveur ne lie son port, le conteneur sort donc avec un code non-zéro. v3.2.1 lève une Exception simple : Failed to download model <name> from <url> pour les chemins git:, et Model download failed with status code <code>, Could not authenticate with NGC., ou Could not find the model. pour les chemins ngc:.


Configuration RTVI-VLM Standalone

Quand vous exécutez services/rtvi/rt-vlm/docker/compose.yaml depuis le clone VSS public, utilisez les noms natifs de conteneur :

# services/rtvi/rt-vlm/docker/.env
BACKEND_PORT=8000

# Méthode A
VLM_MODEL_TO_USE=openai-compat
VIA_VLM_ENDPOINT=http://host.docker.internal:30082/v1
VIA_VLM_OPENAI_MODEL_DEPLOYMENT_NAME=nvidia/cosmos-reason2-8b
VIA_VLM_API_KEY=<your-api-key>       # si requis ; réglez via invite silencieuse

# Méthode B
VLM_MODEL_TO_USE=vllm-compatible
MODEL_PATH=git:https://huggingface.co/Qwen/Qwen3-VL-8B-Instruct

Le fichier Compose standalone défaut à nvcr.io/nvidia/vss-core/vss-rt-vlm:3.2.1 et nécessite que BACKEND_PORT soit régé. Toutes les valeurs supportées de VLM_MODEL_TO_USE : openai-compat, vllm-compatible, cosmos-reason1, cosmos-reason2, cosmos-reason3, custom.

Les deux définitions Compose fournies utilisent le networking en bridge et mappent host.docker.internal via host-gateway. Choisissez l'hôte endpoint selon où le serveur d'inférence s'exécute :

  • Hôte Docker : host.docker.internal
  • Même réseau Compose : le nom du service Compose du serveur d'inférence
  • Machine distante : un nom d'hôte routable ou une adresse IP
  • localhost : uniquement quand le conteneur RTVI utilise explicitement le networking host

Pour Method A standalone, vérifiez la connectivité depuis l'intérieur de rtvi-server :

docker compose exec -T rtvi-server sh -lc \
  'set --
   if [ -n "${VIA_VLM_API_KEY:-}" ]; then
     set -- -H "Authorization: Bearer ${VIA_VLM_API_KEY}"
   fi
   curl -fsS "$@" "${VIA_VLM_ENDPOINT%/}/models"'

Voir la référence des variables d'environnement dans services/rtvi/rt-vlm/README.md public.


Configuration vlm-as-verifier (mode 2d_cv uniquement)

vlm-as-verifier s'exécute en tant que service alert-bridge et est séparé de RTVI-VLM. Sa config est bind-montée depuis ${VSS_PROFILE_DIR}/vlm-as-verifier/configs/config.yml.

Gardez la config paramétrée :

# ${VSS_PROFILE_DIR}/vlm-as-verifier/configs/config.yml
vlm:
  base_url: ${VLM_BASE_URL}/v1
  model: ${VLM_NAME}
  max_tokens: 4096

Pour le flux Alerts VLM local v3.2.1, dev-profile.sh --vlm-device-id ... remplit VLM_BASE_URL avec http://<host-ip>:8018 et régit VLM_NAME dans l'environnement généré. Le mode distant écrit likewise l'endpoint sélectionné. Codez en dur ces champs uniquement quand vous remplacez intentionnellement les valeurs générées par le profil.

Le 8018 ici est littéral dans le générateur, pas dérivé de RTVI_VLM_PORT. Si RTVI-VLM est publié sur un autre port, alert-bridge appelle toujours 8018 jusqu'à ce que vous patchz VLM_BASE_URL dans generated.env (references/port-and-url-wiring.md).

Après édition de la config ou l'environnement, recréez le service :

cd "${VSS_DEPLOY_DIR}"
docker compose \
  --env-file developer-profiles/dev-profile-alerts/generated.env \
  up -d --force-recreate alert-bridge

Configuration vss-agent

vss-agent est un autre consommateur séparé. Le profil Alerts v3.2.1 sélectionne un bloc dans ${VSS_PROFILE_DIR}/vss-agent/configs/config.yml utilisant VLM_MODEL_TYPE. Le flux VLM-RTVI local utilise rtvi :

rtvi_vlm:  # VLM_MODEL_TYPE=rtvi
  base_url: ${RTVI_VLM_BASE_URL}/v1
nim_vlm:   # VLM_MODEL_TYPE=nim
  base_url: ${VLM_BASE_URL}/v1
openai_vlm: # VLM_MODEL_TYPE=openai
  base_url: ${VLM_BASE_URL}/v1
vllm_vlm:  # VLM_MODEL_TYPE=vllm
  base_url: ${VLM_BASE_URL}/v1

Pour un déploiement Alerts local v3.2.1, gardez les valeurs générées, qui sont normalement équivalentes à :

VLM_MODEL_TYPE=rtvi
VLM_NAME=<model-id>
RTVI_VLM_PORT=8018                                    # depuis .env
RTVI_VLM_BASE_URL=http://<host-ip>:${RTVI_VLM_PORT}   # depuis .env
VLM_BASE_URL=http://<host-ip>:8018                    # écrit par dev-profile.sh

RTVI_VLM_PORT est requis par le mapping de port Compose de rtvi-vlm et n'a pas de défaut Compose. Définissez-le dans le .env du profil Alerts et régénérez generated.env avant d'utiliser n'importe laquelle de ces commandes Compose. Les deux URLs ont des propriétaires différents et s'accordent uniquement au port défaut ; voir references/port-and-url-wiring.md.

Pour une NIM distante, un endpoint compatible OpenAI ou une vLLM externe, sélectionnez le profil nim, openai ou vllm correspondant et réglez VLM_BASE_URL sans trailing /v1 car la config l'ajoute. Recréez vss-agent après avoir changé ces valeurs.


Health Checks

Après avoir changé la configuration VLM, recréez le service affecté et inspectez-le via le même modèle Compose Alerts :

cd "${VSS_DEPLOY_DIR}"
ALERTS_ENV=developer-profiles/dev-profile-alerts/generated.env
# Requis quand un `generated.env` existant ne contient pas encore le port.
# Le fix persistant est de l'ajouter au `.env` du profil et régénérer.
export RTVI_VLM_PORT=8018

# Recréer RTVI-VLM et attendre jusqu'à 10 minutes pour son healthcheck Compose.
docker compose --env-file "${ALERTS_ENV}" \
  up -d --force-recreate --wait --wait-timeout 600 rtvi-vlm

# Le conteneur doit toujours fonctionner. Un téléchargement de poids échoué sort ici.
CID="$(docker compose --env-file "${ALERTS_ENV}" ps -aq rtvi-vlm)"
test "$(docker inspect -f '{{.State.Status}}' "${CID}")" = running || {
  docker logs --tail 50 "${CID}" >&2; exit 1; }

# Exigez l'absence d'un échec de téléchargement ou de warm-up. `Warmup ... done` est enregistré sur les deux chemins en v3.2.1, donc uniquement les lignes d'erreur sont conclusives.
docker logs "${CID}" 2>&1 | grep -Eq \
  'Failed to download model|Model download failed|Could not find the model|Could not authenticate with NGC|Error during (model )?warmup' \
  && { echo 'rtvi-vlm failed to download weights or warm up' >&2; exit 1; }

# Confirmer le endpoint readiness depuis l'intérieur du conteneur.
docker compose --env-file "${ALERTS_ENV}" exec -T rtvi-vlm \
  curl -fsS http://localhost:8000/v1/health/ready

# Capturer l'implémentation et l'ID du modèle annoncé par le service live.
VLM_METHOD="$(docker compose --env-file "${ALERTS_ENV}" exec -T rtvi-vlm \
  printenv VLM_MODEL_TO_USE | tr -d '\r')"
ACTUAL_MODEL="$(docker compose --env-file "${ALERTS_ENV}" exec -T rtvi-vlm \
  curl -fsS http://localhost:8000/v1/models | jq -er '.data[0].id')"
test -n "${ACTUAL_MODEL}"

# Readiness et /v1/models rapportent uniquement des métadonnées. Exigez une vraie inférence ; une requête chat text-only n'a besoin d'aucun asset média et fonctionne sur les deux méthodes.
docker compose --env-file "${ALERTS_ENV}" exec -T rtvi-vlm \
  curl -fsS --max-time 120 -X POST http://localhost:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d "$(jq -nc --arg m "${ACTUAL_MODEL}" '{model: $m, max_tokens: 16, stream: false,
        messages: [{role: "user", content: "Reply with: ok"}]}')" \
  | jq -e '((.choices[0].message.content // "") | length) > 0' > /dev/null \
  || { echo 'inference smoke test returned no content' >&2; exit 1; }

Readiness est construit à partir de is_alive() par processus, donc il rapporte healthy: true pour un processus live dont le modèle n'a jamais démarré, et /v1/chat/completions retourne HTTP 200 avec content vide quand le pipeline n'a produit aucune sortie. L'assertion jq sur le contenu non-vide est ce qui rend la dernière vérification significative.

L'identité du modèle diffère selon la méthode

Les deux méthodes annoncent leur ID de modèle différemment, donc la vérification de suivi n'est pas la même :

  • Méthode A (openai-compat) — vérifiez que le VIA_VLM_OPENAI_MODEL_DEPLOYMENT_NAME configuré apparaît n'importe où dans la liste /v1/models utilisant la vérification any(.data[]; .id == $model) de la section Vérification d'endpoint Method A. Traitez HTTP 401 comme un échec d'authentification ; traitez une réponse 200 où le modèle est absent comme une erreur de nom de modèle.
  • Méthode B (vllm-compatible) — ne comparez pas l'ID annoncé contre VLM_NAME ou VIA_VLM_OPENAI_MODEL_DEPLOYMENT_NAME. Le basename du répertoire de modèle résolu devient l'ID annoncé /v1/models, donc ngc:nim/nvidia/cosmos-reason2-8b:hf-1208 est servi comme nim_nvidia_cosmos-reason2-8b_hf-1208. Cette différence est attendue pour la méthode B et n'indique pas un échec de déploiement. Pointez les consommateurs en aval (vlm-as-verifier, vss-agent) vers cet ID annoncé, jamais vers le chemin NGC ou Hugging Face.

Exécutez les commandes de vérification par méthode depuis references/health-checks.md — couvre la vérification d'identité Method A, l'inspection Method B, les diagnostiques de warm-up et l'interrogation d'un endpoint externe spécifique.

Skills similaires