tao-finetune-video-clip

Par nvidia · skills

InternVideo2-CLIP L14 (TAO video_clip) pour la récupération vidéo-texte, la classification zero-shot, l'extraction d'embeddings, le fine-tuning LoRA, l'export ONNX et le déploiement TensorRT. À utiliser lorsque l'utilisateur demande à « fine-tuner IV2CLIP », « exécuter video_clip train/evaluate/inference/export », « construire un moteur TensorRT Video-CLIP », « InternVideo2-CLIP sur des chunks KPI », ou « TAO video_clip sur du JSON vadr1_chunks ».

npx skills add https://github.com/nvidia/skills --skill tao-finetune-video-clip

InternVideo2-CLIP (TAO video_clip)

Installation autonome ? Si cette session n'a pas été initialisée par le plugin TAO skill bank, exécutez d'abord la skill tao-setup (preflight hôte, credentials, cross-skill discovery).

La task TAO video_clip enveloppe InternVideo2-CLIP L14 d'OpenGVLab. L'image PyTorch fournit train, evaluate, inference, export, et default_specs. TAO Deploy fournit gen_trt_engine, TensorRT evaluate, et TensorRT inference.

Les images de conteneur et les commandes par action sont dans references/skill_info.yaml et references/tao-deploy-video-clip.skill_info.yaml. Les specs de démarrage sont dans references/spec_template_*.yaml.

Note de version : L'image PyTorch épinglée est la version release-candidate TAO 7.2 validée pour Video-CLIP. Elle inclut PyAV 17.1.0 comme décodeur principal et ONNXScript 0.7.1 pour l'export, sans decord. L'image TAO Deploy est épinglée indépendamment car gen_trt_engine et les actions TensorRT n'exécutent pas dans l'image PyTorch.

Images défectueuses connues : les builds intermédiaires coupés avant le commit tao-pytorch 0cc31de4 livrent un package video_clip sans le sous-module model.backbones, ainsi train/evaluate/inference échouent à l'import tandis que video_clip --help quitte toujours avec le code 0. Les images sans PyAV échouent aussi au chargement des données. Exécutez les deux vérifications d'import dans le preflight ci-dessous avant de récupérer les données ou de lancer une exécution.

Train Action Policy

AutoML n'est pas fourni avec cette model skill. Utilisez toujours les actions video_clip directes même quand une demande de haut niveau mentionne AutoML. Les actions non-train restent dans cette skill.

Quick Start (local Docker)

Utilisez le conteneur TAO épinglé déclaré dans references/skill_info.yaml. Tirez avec NGC_KEY quand l'image n'est pas en cache localement.

VIDEO_CLIP_IMAGE_DEFAULT="nvcr.io/nvidia/tao/tao-toolkit:7.2.0-pyt"  # versions-key: images.tao_toolkit.pyt
VIDEO_CLIP_IMAGE="${VIDEO_CLIP_IMAGE:-$VIDEO_CLIP_IMAGE_DEFAULT}"
docker pull "$VIDEO_CLIP_IMAGE"

Disposition attendue de l'espace de travail (chemins hôte montés en bind dans le conteneur) :

workspace/
├── data/
│   ├── train.json              # métadonnées vadr1_chunks ; video_path = /data/videos/<name>.mp4
│   ├── val.json
│   ├── prompts.txt             # une invite textuelle par ligne (inference)
│   └── videos/                 # clips mp4 référencés par train.json / val.json
├── model/
│   ├── mobileclip_blt.pt       # poids MobileCLIP pour model.text_encoder
│   └── hf/                     # snapshot offline InternVideo2_distillation_models (HF_HUB_OFFLINE=1)
├── specs/
│   ├── train.yaml
│   ├── evaluate.yaml
│   ├── inference.yaml
│   └── export.yaml
├── deploy_specs/
│   ├── gen_trt_engine.yaml
│   ├── evaluate.yaml
│   └── inference.yaml
└── results/

Options Docker pour toutes les actions (l'IC skill-eval utilise le même motif de montage $WORKSPACE_DIR) :

VIDEO_CLIP_IMAGE_DEFAULT="nvcr.io/nvidia/tao/tao-toolkit:7.2.0-pyt"  # versions-key: images.tao_toolkit.pyt
VIDEO_CLIP_IMAGE="${VIDEO_CLIP_IMAGE:-$VIDEO_CLIP_IMAGE_DEFAULT}"
RUN_ROOT="${RUN_ROOT:-$PWD}"
DOCKER_COMMON=(
  --rm --gpus all --shm-size=8g --network=host
  --shm-size=64g
  --ulimit memlock=-1
  --ulimit stack=67108864
  -e WANDB_DISABLED=true
  -e WANDB_MODE=disabled
  -e HF_HUB_OFFLINE=1
  -e HUGGINGFACE_HUB_CACHE=/model/hf
  -e TRANSFORMERS_OFFLINE=1
  -e TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD=1
  -v "$RUN_ROOT/data:/data:ro"
  -v "$RUN_ROOT/model:/model:ro"
  -v "$RUN_ROOT/specs:/specs:ro"
  -v "$RUN_ROOT/results:/results"
)

Preflight (hôte) :

[ -f "$RUN_ROOT/model/mobileclip_blt.pt" ] || echo "MISSING: MobileCLIP weights"
[ -f "$RUN_ROOT/data/train.json" ] || echo "MISSING: train metadata"
[ -d "$RUN_ROOT/model/hf" ] || echo "MISSING: offline HF snapshot under model/hf"
docker run --rm "$VIDEO_CLIP_IMAGE" video_clip --help >/dev/null || echo "MISSING: video_clip in container"
docker run --rm "$VIDEO_CLIP_IMAGE" \
  python -c "import nvidia_tao_pytorch.multimodal.video_clip.model.adapters.internvideo2clip" \
  >/dev/null 2>&1 || echo "BROKEN IMAGE: video_clip package is incomplete (missing model.backbones) — stop, see Release note"
docker run --rm "$VIDEO_CLIP_IMAGE" python -c "import av; print(av.__version__)" \
  >/dev/null 2>&1 || echo "BROKEN IMAGE: PyAV is missing — use the pinned FC image; do not install decord"
nvidia-smi >/dev/null 2>&1 || echo "note: no GPU visible"

Train :

docker run "${DOCKER_COMMON[@]}" "$VIDEO_CLIP_IMAGE" \
  video_clip train -e /specs/train.yaml results_dir=/results

Evaluate :

docker run "${DOCKER_COMMON[@]}" "$VIDEO_CLIP_IMAGE" \
  video_clip evaluate -e /specs/evaluate.yaml results_dir=/results

Inference :

docker run "${DOCKER_COMMON[@]}" "$VIDEO_CLIP_IMAGE" \
  video_clip inference -e /specs/inference.yaml results_dir=/results

Export :

docker run "${DOCKER_COMMON[@]}" "$VIDEO_CLIP_IMAGE" \
  video_clip export -e /specs/export.yaml results_dir=/results

TensorRT Deploy

Utilisez l'image TAO Deploy épinglée indépendamment après l'export PyTorch. Lisez references/tao-deploy-video-clip.md avant d'exécuter les actions de déploiement ; ses templates couvrent la construction du moteur, l'évaluation de retrieval, et les contrats de text inference.

VIDEO_CLIP_DEPLOY_IMAGE_DEFAULT="nvcr.io/nvidia/tao/tao-toolkit:7.2.0-deploy"  # versions-key: images.tao_toolkit.deploy
VIDEO_CLIP_DEPLOY_IMAGE="${VIDEO_CLIP_DEPLOY_IMAGE:-$VIDEO_CLIP_DEPLOY_IMAGE_DEFAULT}"

# Vérifiez l'image épinglée indépendamment avant de préparer les artefacts ou d'utiliser un GPU.
docker run --rm "$VIDEO_CLIP_DEPLOY_IMAGE" video_clip gen_trt_engine --help >/dev/null || \
  { echo "BROKEN IMAGE: Video-CLIP deploy entrypoint is unavailable" >&2; exit 1; }

docker run --gpus all --rm --shm-size=16g \
  -v "$RUN_ROOT/deploy_specs:/specs:ro" \
  -v "$RUN_ROOT/results/export:/models:ro" \
  -v "$RUN_ROOT/data:/data:ro" \
  -v "$RUN_ROOT/results/deploy:/results" \
  "$VIDEO_CLIP_DEPLOY_IMAGE" \
  video_clip gen_trt_engine -e /specs/gen_trt_engine.yaml

Gardez ensemble le fichier ONNX exporté, son *_config.yaml correspondant, et son répertoire *_tokenizer/ correspondant. gen_trt_engine copie les sidecars à côté du moteur pour que TensorRT evaluate et inference puissent reconstruire le preprocessing et la tokenization.

Quick Start (virtualenv — local dev hosts)

Sur les hôtes avec un checkout tao-pytorch et une venv tao-cli (par exemple rtdetr-pytorch), exécutez via tao-run-on-virtualenv au lieu de Docker :

export VENV="${VENV:?set to your tao-cli virtualenv (must contain bin/video_clip)}"
export TAO_PYTORCH_ROOT="${TAO_PYTORCH_ROOT:?set to your tao-pytorch checkout with multimodal/video_clip}"
export PATH="$VENV/bin:$PATH"
export PYTHONPATH="$TAO_PYTORCH_ROOT:$TAO_PYTORCH_ROOT/tao-core:$PYTHONPATH"
export HF_HOME="${HF_HOME:-$PWD/hf_cache}"
export HF_HUB_OFFLINE="${HF_HUB_OFFLINE:-1}"
export WANDB_DISABLED=true
export WANDB_MODE=disabled

Copiez un template spec de references/spec_template_*.yaml, remplissez les chemins de checkpoint et les métadonnées, puis exécutez :

video_clip train -e /path/to/train.yaml
video_clip evaluate -e /path/to/evaluate.yaml
video_clip inference -e /path/to/inference.yaml
video_clip export -e /path/to/export.yaml

Credentials

  • NGC_KEY — tirez le conteneur TAO épinglé de nvcr.io quand il n'est pas en cache localement.
  • HF_TOKEN (téléchargement Hugging Face en ligne uniquement) : token de lecture Hugging Face utilisé quand model.vision_encoder et model.clip_head sont null et le resolver télécharge le snapshot InternVideo2 nommé par model.internvideo2clip_hf_id. Pour l'IC/eval offline, préparez le snapshot S3/local complet et pointez les deux champs aux fichiers locaux ; aucun token Hugging Face n'est alors requis.

Traitez les tokens comme des secrets. Exportez-les dans l'environnement ou passez-les via un --env-file de lignes KEY=value nues, plutôt que d'intégrer les valeurs dans le YAML spec généré, les lignes de commande, ou quoi que ce soit écrit sous results_dir.

Data format (vadr1_chunks)

Les métadonnées sont une liste JSON de haut niveau d'enregistrements vidéo. Chaque enregistrement a video_path, split, et des chunks[] imbriqués avec des champs caption (queries, action_queries, anomaly_queries, dense_caption, scene_caption).

Pointez dataset.*.video_text.metadata vers les fichiers JSON de l'utilisateur (par exemple /data/train.json et /data/val.json dans les templates). Chaque video_path doit être un chemin absolu résolvable à l'exécution — pour Docker, remappez les clips hôte aux chemins de conteneur comme /data/videos/<name>.mp4 et réglez data_root: null sauf si vous utilisez path_prefix_mapping.

Smoke overrides

Pour une vérification fonctionnelle rapide (par exemple 2 epochs, 1 GPU, petit batch) :

train.num_epochs: 2
train.num_gpus: 1
train.gpu_ids: [0]
train.optim.warmup_steps: 10
dataset.train.batch_size: 2
dataset.val.batch_size: 2
dataset.train.num_workers: 4
dataset.val.num_workers: 4
dataset.train.video_text.caption_fields: [queries, action_queries, anomaly_queries]
dataset.train.video_text.caption_mode: first
dataset.metrics.mode: classification

Utilisez dataset.metrics.mode: retrieval uniquement quand dataset.val.video_text.relevance_file est fourni.

Inference

  • inference.mode: embeddings écrit video_embeddings.h5 et text_embeddings.h5 sous results_dir.
  • Fournissez inference.query.text_file (une invite par ligne) et/ou inference.query.input_texts.
  • Les vidéos de galerie viennent de dataset.inference.video_text.metadata.

Export

export.encoder_type: combined produit l'ONNX image-et-texte consommé par le workflow de déploiement Video-CLIP. Gardez export.batch_size: -1 pour les dimensions de batch symboliques/dynamiques ; une valeur positive produit un ONNX batch fixe. Export écrit aussi les sidecars *_config.yaml et *_tokenizer/ correspondants ; préservez les trois artefacts. L'opset par défaut est 23 sur la branche vendor. Export requiert un .pth entraîné à export.checkpoint.

LoRA

Pour les runs vision-LoRA, partez de tao-pytorch experiment_spec_lora.yaml ou ajoutez un bloc peft: de haut niveau (voir les commentaires de spec livrés). Fusionnez LoRA avant l'export quand les checkpoints contiennent des clés lora_*.

Common pitfalls

  • PATH doit préférer $VENV/bin sur les hôtes virtualenv pour que les processus enfants résolvent le Python venv.
  • evaluate utilise dataset.val, pas un split de test séparé — l'étape Lightning "test" charge toujours les métadonnées val.
  • Eval precision : correspondez à train.precision (typiquement bf16) ou les chemins flash-attn peuvent échouer sous eval fp32.
  • Les action_queries vides sur les chunks normaux deviennent des positifs littéraux "Normal" pendant l'entraînement ; excluez Normal/Abnormal dans dataset.metrics.exclude_categories pour l'eval classification.
  • Pas de training dur-négatif / explicit-neg sur la branche vendor sauf si la spec et la branche l'activent explicitement.
  • video_clip --help n'est pas une vérification de santé. Il quitte avec le code 0 sur une image dont le package video_clip manque model.backbones ; seule la vérification de smoke d'import dans le preflight l'attrape.
  • PyAV est le décodeur Video-CLIP principal dans TAO 7.2. Le loader peut revenir au support CLI FFmpeg et OpenCV de l'image. Un import av manquant est un défaut d'image : utilisez l'image FC épinglée. N'ajoutez pas et ne forcez pas l'installation de decord, car il ne fait pas partie du contrat de décode TAO 7.2 supporté.
  • Les actions TensorRT utilisent TAO Deploy. gen_trt_engine, TensorRT evaluate, et TensorRT inference doivent utiliser l'image deploy épinglée indépendamment et les templates deploy, pas l'image/specs PyTorch.
  • Les sidecars de déploiement sont requis. TensorRT evaluation et text inference ont besoin du *_config.yaml exporté et du répertoire *_tokenizer/ à côté du moteur. Gardez-les avec l'entrée ONNX pour que la génération du moteur puisse les copier automatiquement.
  • PyTorch ≥ 2.6 utilise par défaut torch.load(weights_only=True) et rejette les objets dtype numpy du checkpoint TAO avec _pickle.UnpicklingError. TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD=1 est défini dans DOCKER_COMMON ci-dessus ; gardez-le pour evaluate, inference, et export.
  • model/hf/ est un snapshot, pas un cache hub HF. Les packs offline préparent les poids InternVideo2 aux chemins relatifs au repo (stage1/L14/L14_dist_1B_stage2/pytorch_model.bin, clip/L14/pytorch_model.bin), tandis que HUGGINGFACE_HUB_CACHE attend un arbre models--<org>--<repo>/snapshots/<sha>/. Laisser model.vision_encoder / model.clip_head à null envoie la résolution d'asset à hf_hub_download et échoue sous HF_HUB_OFFLINE=1 — pointez les deux directement aux fichiers.
  • IC / skill-eval : préparez les poids + JSON remappé sous $WORKSPACE_DIR depuis S3 ; ne comptez pas sur les téléchargements Hugging Face LFS au moment de l'eval.

References

  • Defaults livrés : tao-pytorch nvidia_tao_pytorch/multimodal/video_clip/experiment_specs/ (quand on développe depuis la source)
  • Workflow TAO Deploy : references/tao-deploy-video-clip.md

Skills similaires