benchmark-vlm-qa

Par nvidia-ai-blueprints · video-search-and-summarization

Évalue la précision et la latence de questions-réponses vidéo d'un RT-VLM déployé (Cosmos Reason 3) via `vss vlm run`, en utilisant des questions et des vidéos issues du dataset DSS `vss-devx-base`. Remplace le chemin d'évaluation obsolète `nat eval` / `vss-agent` QA. Non applicable aux évaluations de tool-calling ou de trajectoire, ni à la mesure de débit de résumé LVS.

npx skills add https://github.com/nvidia-ai-blueprints/video-search-and-summarization --skill benchmark-vlm-qa

Benchmark video Q&A via vss vlm

Mesurez la précision (LLM-as-judge vs vérité de base) et la latence de la réponse à des questions vidéo de bout en bout en appelant vss vlm run contre un Cosmos Reason 3 RT-VLM déployé. Les questions et clips proviennent du dataset DSS vss-devx-base (nvdataset).

Ceci remplace docker exec vss-agent nat eval pour la slice QA. Cela ne note pas les appels d'outils ou les trajectoires.

Quand utiliser

  • L'utilisateur demande d'évaluer / benchmarker le video Q&A VLM après la suppression de vss-agent / NAT eval.
  • L'utilisateur veut la latence et la précision des réponses sur vss-devx-base.

Quand ne pas utiliser

  • Évaluation des appels d'outils ou des trajectoires — hors de portée.
  • Débit de summarization LVS — utilisez benchmark-video-summarization.
  • Questions ad-hoc uniques — utilisez /vss-ask-video.

Prérequis

  • Une stack VSS avec RT-VLM servant Cosmos Reason 3, et vss configure déjà exécuté de sorte que vss configure check liste rt_vlm comme ok et vst comme ok.

    Configurez avec une adresse routable, pas localhost. Les clips sont adressés en tant que capteurs VIOS, donc RT-VLM les récupère par URL ; l'URL que VIOS génère est construite à partir de l'origine configurée. Une origine loopback génère une URL loopback, qui ne signifie rien à l'intérieur du conteneur RT-VLM, donc le CLI revient à l'inline du clip en base64 et le VLM rejette tout ce qui est volumineux avec HTTP 422 ... content ... valid string. vss configure --base-url http://<host-ip>:7777 évite cela — --base-url est un flag vss configure, pas un flag benchmark. --inline-media est un flag benchmark ; il force l'ancien comportement inline et n'est sûr que pour les clips de moins de ~10 MB.

  • uv et ce checkout (CLI via uv run --project services/agent --no-dev --extra cli vss).

  • Le CLI nvdataset. Il n'est pas sur PyPI, et l'index utilisé par l'ancien deep-search eval (urm.nvidia.com/.../sw-ngc-data-platform-pypi) retourne 403. Installez depuis l'index en lecture seule documenté à la place — aucune credential requise :

    uv tool install --index https://artifactory.pdx.nvidia.com/artifactory/api/pypi/sw-ngc-data-platform-pypi-local/simple nvdataset
  • Accès DSS, l'un des éléments suivants :

    • NVDATASET_API_KEY — une Personal Key depuis org.ngc.nvidia.com/setup/personal-keys restreinte au service NVIDIA Dataset Service, avec l'org NGC basculée vers celle possédant le dataset. Ce n'est pas la clé NGC globale utilisée par le NGC CLI ; une clé globale retourne 403. NVDATASET_NGC_API_KEY et NGC_API_KEY sont aussi lues, dans cet ordre, pour la rétrocompatibilité uniquement — la run affiche la variable qu'elle a choisie comme dss credential: <name>, vérifiez donc cette ligne si un 403 vous surprend.
    • nvdataset auth login (Starfleet SSO), qui n'a besoin d'aucune clé. Ajoutez --flow device sur une machine distante sans navigateur. L'accès au groupe nécessite l'appartenance à ngc-datasetservice-viewer-<tenant>-<group> (lecteur) ou ...-user-... (écrivain).

    Plus tenancy, que SSO ne fournit pas — après auth login, nvdataset auth status rapporte toujours "tenant_id": null et chaque appel échoue avec Did not find tenant_id. Le script ne nomme aucun tenant, donc définez-en un vous-même : exportez NVDATASET_TENANTID et NVDATASET_GROUPID, ou enregistrez-les une fois avec nvdataset auth context add. Demandez ses coordonnées à l'équipe possédant le dataset. Un autre dataset ne nécessite aucune modification du script.

  • Un LLM judge compatible OpenAI : EVAL_LLM_JUDGE_BASE_URL et EVAL_LLM_JUDGE_NAME, authentifiés avec EVAL_LLM_JUDGE_API_KEY. NGC_API_KEY est intentionnellement pas envoyé aux hôtes judge non-NVIDIA — il est défini pour le téléchargement du dataset et ne doit pas atteindre une tierce partie. N'importe quel endpoint chat-completions fera l'affaire ; le judge déplace les scores absolus de son côté, donc tenez-le fixe entre les runs que vous voulez comparer, et lisez judge_model dans summary.json avant de comparer deux nombres. --skip-judge donne la latence uniquement.

Le bootstrap se trouve dans AGENTS.md à la racine du repo. Ne construisez pas les URLs RT-VLM ; vss vlm run lit la config enregistrée.

Exécution

export NVDATASET_API_KEY=<personal-key>            # ou : nvdataset auth login [--flow device]
export NVDATASET_TENANTID=<tenant>                 # SSO ne définit pas ceci ; voir Prérequis
export NVDATASET_GROUPID=<group>
export EVAL_LLM_JUDGE_BASE_URL="${LLM_BASE_URL}"   # Origine compatible OpenAI, ex. http://127.0.0.1:8000
export EVAL_LLM_JUDGE_NAME="${LLM_NAME}"

# Optionnel : dataset déjà extrait
# export VSS_EVAL_DATASET=/path/to/vss-devx-base

<repo>/skills/benchmarking/benchmark-vlm-qa/scripts/run_vlm_qa_benchmark.sh \
  --dataset-name vss-devx-base \
  --dataset-file dataset_single_turn.json

Les deux flags dataset sont requis — le script ne porte aucun dataset par défaut, donc il ne suppose jamais les coordonnées DSS d'une équipe.

Flags utiles (transmis à benchmark_vlm_qa.py) :

Flag Objectif
--dry-run Résolvez les items QA et fichiers vidéo ; pas d'appels VLM
--limit N Les N premiers items QA (smoke)
--skip-judge Latence uniquement
--skip-download Utilisez un vss-devx-base déjà téléchargé
--timeout SEC Transmis comme vss vlm run --timeout (par défaut 300)
--num-frames N Budget de frames (par défaut 20, correspondant à l'ancienne config de l'agent RT-VLM)
--model ID Remplacez le modèle RT-VLM que vss configure a enregistré

Sorties sous <dataset>/../../results/vlm_qa/ (ou --output-dir) :

  • summary.json — précision moyenne, latence moyenne / p50 / p90 / p95 / p99, et le modèle que le déploiement a rapporté servir, pour qu'un nombre ne soit jamais laissé sans attribution
  • qa_evaluator_output.json — scores judge par item (même forme que la sortie QA NAT)
  • latency_summary.json — wall-clock par item autour de vss vlm run
  • workflow_output.json — réponses brutes
  • summary.csv

Règles

  • Piloter le VLM uniquement via vss vlm run. Jamais POST /generate ou /v1/chat/completions construits à la main.
  • N'enveloppez pas vss dans des retries. --timeout est la limite ; le script n'ajoute qu'un hard kill 60 s après, donc un CLI qui ne retourne jamais ne peut pas coûter la whole run. Un item tué est enregistré comme une erreur nommant le watchdog, jamais comme un score faible.
  • Les items doivent déclarer evaluation_method contenant qa et porter une ground_truth texte. Les items de report, trajectoire uniquement, et non marqués sont ignorés.

Échecs

Branchez sur le code de sortie ; ne scrapiez jamais stdout pour le mot "error".

Sortie Signification Quoi faire
0 Chaque item répondu Lisez summary.json
2 Précondition mauvaise — un flag dataset manquant, pas de credential DSS, pas de judge configuré, dataset ou vidéos non trouvés, pas d'items QA Fixez la configuration. Relancer sans changement échoue identiquement
3 Le téléchargement a échoué, ou au moins un item a vu une erreur Lisez l'error de chaque item dans summary.json

Un appel vss qui quitte 4 (service manquant de la config enregistrée) remonte comme une erreur d'item, donc la run se termine à la sortie 3 — la correction est vss configure, pas un flag.

Défaillances dignes d'être reconnues par leur message :

  • HTTP 422 ... content ... valid string sur les gros clips — l'origine enregistrée est loopback, donc les clips sont inlinés en base64. Reconfigurez avec une adresse routable.
  • Did not find tenant_id — SSO vous a connecté mais n'a sélectionné aucun tenant. Exportez NVDATASET_TENANTID, ou nvdataset auth context use.
  • LLM judge HTTP 403 ... key_model_access_denied ou 400 Invalid model name sur chaque item — l'id judge n'est pas ce que cette gateway appelle le modèle. Les gateways qui font de la façade pour plusieurs providers veulent généralement un id complètement qualifié et rejettent le nom brut. GET <judge-base-url>/models liste les ids que la clé peut utiliser ; copiez-en un verbatim dans EVAL_LLM_JUDGE_NAME. Les réponses VLM ne sont pas affectées, donc seul le scoring est perdu.
  • Une erreur d'item nommant le watchdog — le CLI n'a jamais retourné et a été tué à --timeout + 60 s. Cela est enregistré comme une erreur, jamais comme un score faible. Ne retraitez pas.
  • La précision loin de la baseline ~0.465 n'est pas une défaillance du harness. Le modèle judge et --num-frames la déplacent tous deux ; vérifiez judge_model et model_served avant de déposer un rapport.

Implémentation : scripts/benchmark_vlm_qa.py, testé par scripts/tests/. Contrat de téléchargement du dataset : README_eval.md.

Skills similaires