# CogVideoX

CogVideoX est un modèle de génération de vidéo à partir de texte, axé sur la création de vidéos plus cohérentes et alignées sur le prompt. Il y parvient à l'aide de plusieurs méthodes.

- un auto-encodeur variationnel 3D qui compresse les vidéos spatialement et temporellement, améliorant le taux de compression et la précision des vidéos.

- un bloc transformer expert pour aider à aligner le texte et la vidéo, et un module d'attention complète 3D pour capturer et créer des vidéos spatialement et temporellement précises.

Le test réel de la dimension des instructions vidéo a révélé que CogVideoX obtient de bons résultats en matière de thème cohérent, d'informations dynamiques, de fond cohérent, d'informations sur les objets, de mouvement fluide, de couleur, de scène, de style d'apparence et de style temporel, mais qu'il ne parvient pas à obtenir de bons résultats pour les actions humaines, les relations spatiales et les objets multiples.

Le fine-tuning avec Diffusers peut aider à compenser ces résultats médiocres.

## Préparation des données

Les scripts d'entraînement acceptent les données dans deux formats.

Le premier format est adapté à l’entraînement à petite échelle, tandis que le second utilise un format CSV, plus approprié pour le flux de données lors d’un entraînement à grande échelle. À l’avenir, Diffusers prendra en charge la balise `<Video>`.

### Petit format

Deux fichiers, l'un contenant des prompts séparés par des lignes et l'autre contenant des chemins vers des données vidéo séparés par des lignes (le chemin vers les fichiers vidéo doit être relatif au chemin que vous transmettez lors de la spécification de `--instance_data_root`). Examinons un exemple pour mieux comprendre !

Supposons que vous ayez spécifié `--instance_data_root` comme `/dataset`, et que ce répertoire contienne les fichiers : `prompts.txt` et `videos.txt`.

Le fichier `prompts.txt` doit contenir des prompts séparés par des lignes :

```
A black and white animated sequence featuring a rabbit, named Rabbity Ribfried, and an anthropomorphic goat in a musical, playful environment, showcasing their evolving interaction.
A black and white animated sequence on a ship's deck features a bulldog character, named Bully Bulldoger, showcasing exaggerated facial expressions and body language. The character progresses from confident to focused, then to strained and distressed, displaying a range of emotions as it navigates challenges. The ship's interior remains static in the background, with minimalistic details such as a bell and open door. The character's dynamic movements and changing expressions drive the narrative, with no camera movement to distract from its evolving reactions and physical gestures.
...
```

Le fichier `videos.txt` doit contenir des chemins vers des fichiers vidéo, séparés par des lignes. Notez que le chemin doit être _relatif_ au répertoire `--instance_data_root`.

```
videos/00000.mp4
videos/00001.mp4
...
```

Dans l'ensemble, voici à quoi ressemblerait votre jeu de données si vous exécutiez la commande `tree` sur le répertoire racine du jeu de données :

```
/dataset
├── prompts.txt
├── videos.txt
├── videos
    ├── videos/00000.mp4
    ├── videos/00001.mp4
    ├── ...
```

Lors de l'utilisation de ce format, `--caption_column` doit être `prompts.txt` et `--video_column` doit être `videos.txt`.

### Format de flux

Vous pouvez utiliser un seul fichier CSV. Pour les besoins de cet exemple, supposez que vous disposez d'un fichier `metadata.csv`. Le format attendu est le suivant :

```
<CAPTION_COLUMN>,<PATH_TO_VIDEO_COLUMN>
"""A black and white animated sequence featuring a rabbit, named Rabbity Ribfried, and an anthropomorphic goat in a musical, playful environment, showcasing their evolving interaction.""","""00000.mp4"""
"""A black and white animated sequence on a ship's deck features a bulldog character, named Bully Bulldoger, showcasing exaggerated facial expressions and body language. The character progresses from confident to focused, then to strained and distressed, displaying a range of emotions as it navigates challenges. The ship's interior remains static in the background, with minimalistic details such as a bell and open door. The character's dynamic movements and changing expressions drive the narrative, with no camera movement to distract from its evolving reactions and physical gestures.""","""00001.mp4"""
...
```

Dans ce cas, `--instance_data_root` doit correspondre à l’emplacement où les vidéos sont stockées et `--dataset_name` doit être soit un chemin vers un dossier local, soit un jeu de données compatible [load_dataset](https://huggingface.co/docs/datasets/main/en/package_reference/loading_methods#datasets.load_dataset) hébergé sur le Hub. En supposant que vous avez des vidéos de gameplay Minecraft sur `https://huggingface.co/datasets/my-awesome-username/minecraft-videos`, vous devez spécifier `my-awesome-username/minecraft-videos`.

Lors de l'utilisation de ce format, `--caption_column` doit être `<CAPTION_COLUMN>` et `--video_column` doit être `<PATH_TO_VIDEO_COLUMN>`.

Vous n’êtes pas strictement limité au format CSV. Tout format fonctionne à condition que la méthode `load_dataset` prenne en charge le format de fichier pour charger une colonne de base `<PATH_TO_VIDEO_COLUMN>` et `<CAPTION_COLUMN>`. La raison pour laquelle il faut passer par ces acrobaties d’organisation de jeu de données pour charger des données vidéo est que `load_dataset` ne prend pas entièrement en charge tous les types de formats vidéo.

> [!NOTE]
> CogVideoX fonctionne de manière optimale avec des prompts longs et descriptifs, enrichis par un LLM, pour la génération de vidéos. Nous recommandons de prétraiter vos vidéos en générant d’abord un résumé à l’aide d’un VLM, puis d’enrichir les prompts avec un LLM. Pour générer les légendes ci-dessus, nous utilisons [MiniCPM-V-26](https://huggingface.co/openbmb/MiniCPM-V-2_6) et [Llama-3.1-8B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct). Un exemple très minimaliste et sans fioritures est disponible [ici](https://gist.github.com/a-r-r-o-w/4dee20250e82f4e44690a02351324a4a). La recommandation officielle pour l’enrichissement des prompts est [ChatGLM](https://huggingface.co/THUDM?search_models=chatglm), et une longueur de 50 à 100 mots est considérée comme appropriée.

>![NOTE] Il est attendu que votre jeu de données soit déjà prétraité. Sinon, un prétraitement de base peut être effectué en jouant avec les paramètres suivants : `--height`, `--width`, `--fps`, `--max_num_frames`, `--skip_frames_start` et `--skip_frames_end`. Actuellement, toutes les vidéos de votre jeu de données doivent contenir le même nombre de frames vidéo lorsque la taille du lot d'entraînement est > 1.

## Entraînement

Vous devez configurer votre environnement de développement en installant les dépendances nécessaires. Les paquets suivants sont requis :
- Torch 2.0 ou supérieur, en fonction des fonctionnalités d'entraînement que vous utilisez (les versions les plus récentes ou les versions nocturnes peuvent être requises pour l'entraînement quantifié/deepspeed)
- `pip install diffusers transformers accelerate peft huggingface_hub` pour tout ce qui concerne la modélisation et l’entraînement
- `pip install datasets decord` pour charger des données d'entraînement vidéo
- `pip install bitsandbytes` pour utiliser les optimiseurs Adam ou AdamW en 8 bits pour un entraînement optimisé en mémoire
- `pip install wandb` en option pour surveiller les journaux d'entraînement
- `pip install deepspeed` éventuellement pour l'entraînement [DeepSpeed](https://github.com/microsoft/DeepSpeed)
- `pip install prodigyopt` si vous souhaitez utiliser l’optimiseur Prodigy pour l’entraînement

Pour vous assurer de pouvoir exécuter avec succès les dernières versions des scripts d'exemple, nous vous recommandons vivement de **l'installer à partir du code source** et de maintenir l'installation à jour, car nous mettons à jour les scripts d'exemple fréquemment et installons certaines dépendances spécifiques aux exemples. Pour ce faire, exécutez les étapes suivantes dans un nouvel environnement virtuel :

Avant d'exécuter le script, assurez-vous d'installer la bibliothèque à partir du code source :
```bash
git clone https://github.com/huggingface/diffusers
cd diffusers
pip install -e .
```

 

Puis accédez au dossier d'exemple contenant le script d'entraînement et installez les dépendances requises pour le script que vous utilisez :

- PyTorch

```bash
cd examples/cogvideo
pip install -r requirements.txt
```

Et initialisez un environnement [🤗 Accelerate](https://github.com/huggingface/accelerate/) avec :

```bash
accelerate config
```

Ou, pour une configuration par défaut d'Accelerate sans répondre à des questions sur votre environnement

```bash
accelerate config default
```

Ou si votre environnement ne prend pas en charge un shell interactif (par exemple, un notebook)

```python
from accelerate.utils import write_basic_config
write_basic_config()
```

Lors de l’exécution de `accelerate config`, l’utilisation de torch.compile peut entraîner des accélérations spectaculaires. La bibliothèque PEFT est utilisée comme backend pour l’entraînement LoRA, assurez-vous donc d’avoir `peft>=0.6.0` installé dans votre environnement.

Si vous souhaitez publier votre modèle sur le Hub après l'entraînement, avec une fiche modèle soignée, assurez-vous d'être connecté :

```bash
hf auth login

# Alternatively, you could upload your model manually using:
# hf upload my-cool-account-name/my-cool-lora-name /path/to/awesome/lora
```

Assurez-vous que vos données sont préparées comme décrit dans [Préparation des données](#data-preparation). Une fois prêt, vous pouvez commencer l'entraînement !

En supposant que vous entraînez sur 50 vidéos d’un concept similaire, nous avons constaté que 1500 à 2000 étapes fonctionnent bien. La recommandation officielle est toutefois de 100 vidéos avec un total de 4000 étapes. En supposant que vous entraînez sur un seul GPU avec un `--train_batch_size` de `1` :
- 1500 étapes sur 50 vidéos correspondraient à `30` époques d'entraînement
- 4000 étapes sur 100 vidéos correspondraient à `40` époques d'entraînement

```bash
#!/bin/bash

GPU_IDS="0"

accelerate launch --gpu_ids $GPU_IDS examples/cogvideo/train_cogvideox_lora.py \
  --pretrained_model_name_or_path THUDM/CogVideoX-2b \
  --cache_dir <CACHE_DIR> \
  --instance_data_root <PATH_TO_WHERE_VIDEO_FILES_ARE_STORED> \
  --dataset_name my-awesome-name/my-awesome-dataset \
  --caption_column <CAPTION_COLUMN> \
  --video_column <PATH_TO_VIDEO_COLUMN> \
  --id_token <ID_TOKEN> \
  --validation_prompt "<ID_TOKEN> Spiderman swinging over buildings:::A panda, dressed in a small, red jacket and a tiny hat, sits on a wooden stool in a serene bamboo forest. The panda's fluffy paws strum a miniature acoustic guitar, producing soft, melodic tunes. Nearby, a few other pandas gather, watching curiously and some clapping in rhythm. Sunlight filters through the tall bamboo, casting a gentle glow on the scene. The panda's face is expressive, showing concentration and joy as it plays. The background includes a small, flowing stream and vibrant green foliage, enhancing the peaceful and magical atmosphere of this unique musical performance" \
  --validation_prompt_separator ::: \
  --num_validation_videos 1 \
  --validation_epochs 10 \
  --seed 42 \
  --rank 64 \
  --lora_alpha 64 \
  --mixed_precision fp16 \
  --output_dir /raid/aryan/cogvideox-lora \
  --height 480 --width 720 --fps 8 --max_num_frames 49 --skip_frames_start 0 --skip_frames_end 0 \
  --train_batch_size 1 \
  --num_train_epochs 30 \
  --checkpointing_steps 1000 \
  --gradient_accumulation_steps 1 \
  --learning_rate 1e-3 \
  --lr_scheduler cosine_with_restarts \
  --lr_warmup_steps 200 \
  --lr_num_cycles 1 \
  --enable_slicing \
  --enable_tiling \
  --optimizer Adam \
  --adam_beta1 0.9 \
  --adam_beta2 0.95 \
  --max_grad_norm 1.0 \
  --report_to wandb
```

Pour mieux suivre nos expériences d'entraînement, nous utilisons les drapeaux suivants dans la commande ci-dessus :
* `--report_to wandb` garantit que les exécutions d’entraînement sont suivies sur Weights and Biases. Pour l’utiliser, assurez-vous d’installer `wandb` avec `pip install wandb`.
* `validation_prompt` et `validation_epochs` pour permettre au script d’effectuer quelques exécutions d’inférence de validation. Cela nous permet de vérifier qualitativement si l’entraînement progresse comme prévu.

Définir le `<ID_TOKEN>` n’est pas obligatoire. D’après quelques expérimentations limitées, nous avons constaté que cela fonctionne mieux (car cela ressemble à l’entraînement [Dreambooth](./dreambooth)) que sans. Lorsqu’il est fourni, le `<ID_TOKEN>` est ajouté au début de chaque invite. Ainsi, si votre `<ID_TOKEN>` était `"DISNEY"` et votre invite `"Spiderman swinging over buildings"`, l’invite effective utilisée lors de l’entraînement serait `"DISNEY Spiderman swinging over buildings"`. S’il n’est pas fourni, vous entraînez soit sans aucun jeton supplémentaire, soit vous pouvez enrichir votre jeu de données pour appliquer le jeton à l’endroit souhaité avant de démarrer l’entraînement.

> [!NOTE]
> Vous pouvez passer `--use_8bit_adam` pour réduire les besoins en mémoire de l'entraînement.

> [!IMPORTANT]
> Les paramètres suivants ont été testés lors de l’ajout de la prise en charge de l’entraînement LoRA pour CogVideoX : - Nos tests ont été effectués principalement sur CogVideoX-2b. Nous travaillerons bientôt sur CogVideoX-5b et CogVideoX-5b-I2V - Un jeu de données composé de 70 vidéos d’entraînement de résolution `200 x 480 x 720` (F x H x W). À partir de celui-ci, en utilisant le saut de frames lors du prétraitement des données, nous avons créé deux jeux de données plus petits de 49 et 16 frames pour des expérimentations plus rapides et parce que la limite maximale recommandée par l’équipe CogVideoX est de 49 frames. Parmi les 70 vidéos, nous avons créé trois groupes de 10, 25 et 50 vidéos. Toutes les vidéos étaient similaires en termes de nature du concept entraîné. - 25 vidéos ou plus ont donné les meilleurs résultats pour l’entraînement de nouveaux concepts et styles. - Nous avons constaté qu’il est préférable d’entraîner avec un jeton d’identifiant qui peut être spécifié via `--id_token`. Cela ressemble à un entraînement de type Dreambooth, mais un ajustement fin normal sans un tel jeton fonctionne également. - Le concept entraîné semblait fonctionner assez bien lorsqu’il était combiné avec des prompts totalement sans rapport. Nous nous attendons à de meilleurs résultats si CogVideoX-5B est ajusté finement. - Le dépôt d’origine utilise un `lora_alpha` de `1`. Nous avons trouvé que ce n’était pas adapté dans de nombreuses exécutions, possiblement en raison de différences dans les backends de modélisation et les paramètres d’entraînement. Notre recommandation est de définir le `lora_alpha` soit sur `rank` soit sur `rank // 2`. - Si vous entraînez sur des données dont les légendes génèrent de mauvais résultats avec le modèle d’origine, un `rank` de 64 ou plus est bon et est également la recommandation de l’équipe derrière CogVideoX. Si les générations sont déjà modérément bonnes sur vos légendes d’entraînement, un `rank` de 16/32 devrait fonctionner. Nous avons constaté que définir le rank trop bas, par exemple `4`, n’est pas idéal et ne produit pas de résultats prometteurs. - Les auteurs de CogVideoX recommandent 4000 étapes d’entraînement et 100 vidéos d’entraînement au total pour obtenir le meilleur résultat. Bien que cela puisse donner les meilleurs résultats, nous avons constaté, à partir de nos expérimentations limitées, que 2000 étapes et 25 vidéos pouvaient également être suffisantes. - Lors de l’utilisation de l’optimiseur Prodigy pour l’entraînement, on peut suivre les recommandations de ce [blog](https://huggingface.co/blog/sdxl_lora_advanced_script). Prodigy a tendance à sur-apprendre rapidement. À partir de mes tests très limités, j’ai trouvé qu’un taux d’apprentissage de `0.5` était adapté en plus de `--prodigy_use_bias_correction`, `prodigy_safeguard_warmup` et `--prodigy_decouple`. - Le taux d’apprentissage recommandé par les auteurs de CogVideoX et de nos expérimentations avec Adam/AdamW se situe entre `1e-3` et `1e-4` pour un jeu de données de 25 vidéos ou plus.
>
> Notez que nos tests ne sont pas exhaustifs en raison du temps limité consacré à l'exploration. Notre recommandation serait de tester les différents paramètres pour trouver les réglages optimaux pour vos données.

## Inférence

Une fois que vous avez entraîné un modèle lora, l’inférence peut être effectuée en chargeant simplement les poids lora dans le `CogVideoXPipeline`.

```python
import torch
from diffusers import CogVideoXPipeline
from diffusers.utils import export_to_video

pipe = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-2b", dtype=torch.float16)
# pipe.load_lora_weights("/path/to/lora/weights", adapter_name="cogvideox-lora") # Or,
pipe.load_lora_weights("my-awesome-hf-username/my-awesome-lora-name", adapter_name="cogvideox-lora") # If loading from the HF Hub
pipe.to("cuda")  # or "mps", "xpu", "cpu"

# Assuming lora_alpha=32 and rank=64 for training. If different, set accordingly
pipe.set_adapters(["cogvideox-lora"], [32 / 64])

prompt = "A vast, shimmering ocean flows gracefully under a twilight sky, its waves undulating in a mesmerizing dance of blues and greens. The surface glints with the last rays of the setting sun, casting golden highlights that ripple across the water. Seagulls soar above, their cries blending with the gentle roar of the waves. The horizon stretches infinitely, where the ocean meets the sky in a seamless blend of hues. Close-ups reveal the intricate patterns of the waves, capturing the fluidity and dynamic beauty of the sea in motion."
frames = pipe(prompt, guidance_scale=6, use_dynamic_cfg=True).frames[0]
export_to_video(frames, "output.mp4", fps=8)
```

## Réduire l'utilisation de la mémoire

Lors des tests effectués avec la bibliothèque diffusers, toutes les optimisations incluses dans la bibliothèque diffusers étaient activées. Ce schéma n'a pas été testé en termes d'utilisation mémoire réelle sur des dispositifs autres que les architectures **NVIDIA A100 / H100**. En général, ce schéma peut être adapté à tous les dispositifs de l'architecture **NVIDIA Ampere** et supérieure. Si les optimisations sont désactivées, la consommation mémoire sera multipliée, l'utilisation mémoire de pointe étant environ 3 fois la valeur indiquée dans le tableau. Cependant, la vitesse augmentera d'environ 3 à 4 fois. Vous pouvez désactiver sélectivement certaines optimisations, notamment :

```
pipe.enable_sequential_cpu_offload()
pipe.vae.enable_slicing()
pipe.vae.enable_tiling()
```

+ Pour l'inférence multi-GPU, l'optimisation `enable_sequential_cpu_offload()` doit être désactivée.
+ L’utilisation de modèles INT8 ralentit l’inférence, ce qui est fait pour prendre en charge des GPU à faible mémoire tout en maintenant une perte de qualité vidéo minimale, bien que la vitesse d’inférence diminue considérablement.
+ Le modèle CogVideoX-2B a été entraîné en précision `FP16`, et tous les modèles CogVideoX-5B ont été entraînés en précision `BF16`. Nous recommandons d'utiliser la précision dans laquelle le modèle a été entraîné pour l'inférence.
+ [PytorchAO](https://github.com/pytorch/ao) et [Optimum-quanto](https://github.com/huggingface/optimum-quanto/) peuvent être utilisés pour quantiser les modules encodeur de texte, transformer et VAE afin de réduire les besoins en mémoire de CogVideoX. Cela permet d’exécuter le modèle sur des Colabs T4 gratuits ou sur des GPU dotés d’une mémoire plus faible ! Notez également que la quantisation TorchAO est entièrement compatible avec `torch.compile`, ce qui peut améliorer considérablement la vitesse d’inférence. La précision FP8 doit être utilisée sur des équipements NVIDIA H100 et supérieurs, nécessitant l’installation depuis le code source des paquets Python `torch`, `torchao`, `diffusers` et `accelerate`. CUDA 12.4 est recommandé.
+ Les tests de vitesse d’inférence ont également utilisé le schéma d’optimisation de la mémoire décrit ci-dessus. Sans optimisation de la mémoire, la vitesse d’inférence augmente d’environ 10 %. Seule la version `diffusers` du modèle prend en charge la quantification.
+ Le modèle ne prend en charge que les entrées en anglais ; les autres langues peuvent être traduites en anglais pour être utilisées via un raffinement par un grand modèle.
+ La consommation mémoire de l’ajustement fin des modèles est testée dans un environnement `8 * H100`, et le programme utilise automatiquement l’optimisation `Zero 2`. Si un nombre spécifique de GPU est indiqué dans le tableau, il faut utiliser ce nombre de GPU ou plus pour l’ajustement fin.

 | **Attribut**                        | **CogVideoX-2B**                                                       | **CogVideoX-5B**                                                       |
| ------------------------------------ | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **Nom du modèle**                       | CogVideoX-2B                                                           | CogVideoX-5B                                                           |
| **Précision d'inférence**              | FP16* (Recommandé), BF16, FP32, FP8*, INT8, INT4 non pris en charge         | BF16 (Recommandé), FP16, FP32, FP8*, INT8, INT4 non pris en charge         |
| **VRAM d'inférence sur GPU unique**        | FP16 : Utilisation de diffusers 12,5 Go* INT8 : Utilisation de diffusers avec torchao 7,8 Go* | BF16 : Utilisation de diffusers 20,7 Go* INT8 : Utilisation de diffusers avec torchao 11,4 Go* |
| **VRAM pour l'inférence multi-GPU**         | FP16 : Utilisation de diffusers 10 Go*                                             | BF16 : Utilisation de diffusers 15 Go*                                             |
| **Vitesse d'inférence**                  | A100 unique : ~90 secondes, H100 unique : ~45 secondes                      | A100 unique : ~180 secondes, H100 unique : ~90 secondes                     |
| **Précision de l'ajustement fin**            | FP16                                                                   | BF16                                                                   |
| **Consommation de VRAM lors de l'ajustement fin**     | 47 Go (bs=1, LORA) 61 Go (bs=2, LORA) 62 Go (bs=1, SFT)                 | 63 Go (bs=1, LORA) 80 Go (bs=2, LORA) 75 Go (bs=1, SFT)                 |

