# CogVideoX

CogVideoX é um modelo de geração de vídeo a partir de texto focado em criar vídeos mais coerentes alinhados a um prompt. Ele alcança isso usando vários métodos.

- um autoencoder variacional 3D que comprime vídeos espacialmente e temporalmente, melhorando a taxa de compressão e a precisão do vídeo.

- um bloco transformer especializado para ajudar a alinhar texto e vídeo, e um módulo de atenção total 3D para capturar e criar vídeos espacial e temporalmente precisos.

O teste real da dimensão de instrução de vídeo constatou que o CogVideoX apresenta bons efeitos em tema consistente, informações dinâmicas, fundo consistente, informações de objetos, movimento suave, cor, cena, estilo de aparência e estilo temporal, mas não consegue alcançar bons resultados com ação humana, relação espacial e múltiplos objetos.

O ajuste fino com Diffusers pode ajudar a compensar esses resultados ruins.

## Preparação de Dados

Os scripts de treinamento aceitam dados em dois formatos.

O primeiro formato é adequado para treinamento em pequena escala, e o segundo formato usa o formato CSV, que é mais apropriado para streaming de dados para treinamento em larga escala. No futuro, o Diffusers suportará a tag `<Video>`.

### Formato pequeno

Dois arquivos, em que um contém prompts separados por linha e o outro contém caminhos separados por linha para os dados de vídeo (o caminho para os arquivos de vídeo deve ser relativo ao caminho que você passa ao especificar `--instance_data_root`). Vamos dar uma olhada em um exemplo para entender melhor!

Suponha que você tenha especificado `--instance_data_root` como `/dataset` e que este diretório contenha os arquivos: `prompts.txt` e `videos.txt`.

O arquivo `prompts.txt` deve conter prompts separados por linha:

```
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.
...
```

O arquivo `videos.txt` deve conter caminhos para arquivos de vídeo separados por linha. Observe que o caminho deve ser _relativo_ ao diretório `--instance_data_root`.

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

No geral, é assim que o seu conjunto de dados se pareceria se você executasse o comando `tree` no diretório raiz do conjunto de dados:

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

Ao usar este formato, o `--caption_column` deve ser `prompts.txt` e o `--video_column` deve ser `videos.txt`.

### Formato de stream

Você pode usar um único arquivo CSV. Para fins deste exemplo, assuma que você tem um arquivo `metadata.csv`. O formato esperado é:

```
<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"""
...
```

Nesse caso, o `--instance_data_root` deve ser o local onde os vídeos estão armazenados e o `--dataset_name` deve ser um caminho para uma pasta local ou um dataset compatível com [load_dataset](https://huggingface.co/docs/datasets/v5.2.0/en/package_reference/loading_methods#datasets.load_dataset) hospedado no Hub. Supondo que você tenha vídeos de gameplay de Minecraft em `https://huggingface.co/datasets/my-awesome-username/minecraft-videos`, você precisaria especificar `my-awesome-username/minecraft-videos`.

Ao usar este formato, o `--caption_column` deve ser `<CAPTION_COLUMN>` e o `--video_column` deve ser `<PATH_TO_VIDEO_COLUMN>`.

Você não é estritamente limitado ao formato CSV. Qualquer formato funciona, desde que o método `load_dataset` suporte o formato de arquivo para carregar uma coluna básica `<PATH_TO_VIDEO_COLUMN>` e `<CAPTION_COLUMN>`. A razão para passar por essas acrobacias de organização de dataset para carregar dados de vídeo é que o `load_dataset` não suporta totalmente todos os tipos de formatos de vídeo.

> [!NOTE]
> CogVideoX funciona melhor com prompts longos e descritivos, aprimorados por LLMs, para a geração de vídeos. Recomendamos pré-processar seus vídeos gerando primeiro um resumo usando um VLM e, em seguida, aprimorando os prompts com um LLM. Para gerar as legendas acima, usamos [MiniCPM-V-26](https://huggingface.co/openbmb/MiniCPM-V-2_6) e [Llama-3.1-8B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct). Um exemplo muito básico e sem complicações para isso está disponível [aqui](https://gist.github.com/a-r-r-o-w/4dee20250e82f4e44690a02351324a4a). A recomendação oficial para aprimorar prompts é [ChatGLM](https://huggingface.co/THUDM?search_models=chatglm) e um comprimento de 50 a 100 palavras é considerado adequado.

>![NOTE] Espera-se que seu conjunto de dados já esteja pré-processado. Caso contrário, alguns pré-processamentos básicos podem ser realizados ajustando os seguintes parâmetros: `--height`, `--width`, `--fps`, `--max_num_frames`, `--skip_frames_start` e `--skip_frames_end`. Atualmente, todos os vídeos do seu conjunto de dados devem conter o mesmo número de quadros de vídeo ao usar um tamanho de lote de treinamento > 1.

## Treinamento

Você precisa configurar seu ambiente de desenvolvimento instalando os requisitos necessários. Os seguintes pacotes são obrigatórios:
- Torch 2.0 ou superior, com base nos recursos de treinamento que você está utilizando (pode exigir versões mais recentes ou noturnas para treinamento quantizado/deepspeed)
- `pip install diffusers transformers accelerate peft huggingface_hub` para tudo relacionado a modelagem e treinamento
- `pip install datasets decord` para carregar dados de treinamento de vídeo
- `pip install bitsandbytes` para usar os otimizadores Adam ou AdamW de 8 bits para treinamento otimizado em memória
- `pip install wandb` opcionalmente para monitorar os logs de treinamento
- `pip install deepspeed` opcionalmente para treinamento com [DeepSpeed](https://github.com/microsoft/DeepSpeed)
- `pip install prodigyopt` opcionalmente, caso você queira usar o otimizador Prodigy para o treinamento

Para garantir que você consiga executar com sucesso as versões mais recentes dos scripts de exemplo, recomendamos fortemente **instalar a partir do código-fonte** e manter a instalação atualizada, pois atualizamos os scripts de exemplo com frequência e instalamos alguns requisitos específicos de exemplo. Para isso, execute as etapas a seguir em um novo ambiente virtual:

Antes de executar o script, certifique-se de instalar a biblioteca a partir do código-fonte:
```bash
git clone https://github.com/huggingface/diffusers
cd diffusers
pip install -e .
```

 

Em seguida, navegue até a pasta de exemplo que contém o script de treinamento e instale as dependências necessárias para o script que você está usando:

- PyTorch

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

E inicialize um ambiente [🤗 Accelerate](https://github.com/huggingface/accelerate/) com:

```bash
accelerate config
```

Ou para uma configuração padrão do Accelerate sem responder perguntas sobre seu ambiente

```bash
accelerate config default
```

Ou, se o seu ambiente não suporta um shell interativo (por exemplo, um notebook)

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

Ao executar `accelerate config`, se você usar torch.compile, é possível obter aumentos de velocidade significativos. A biblioteca PEFT é usada como backend para o treinamento LoRA, portanto, certifique-se de ter `peft>=0.6.0` instalado no seu ambiente.

Se você deseja enviar seu modelo para o Hub após a conclusão do treinamento, com um cartão de modelo bem organizado, certifique-se de que você está conectado:

```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
```

Certifique-se de que seus dados estejam preparados conforme descrito em [Preparação de dados](#data-preparation). Quando estiver pronto, você pode começar o treinamento!

Assumindo que você está treinando com 50 vídeos de um conceito semelhante, descobrimos que 1500-2000 passos funcionam bem. A recomendação oficial, no entanto, é de 100 vídeos com um total de 4000 passos. Assumindo que você está treinando em uma única GPU com um `--train_batch_size` de `1`:
- 1500 passos em 50 vídeos corresponderiam a `30` épocas de treinamento
- 4000 passos em 100 vídeos corresponderiam a `40` épocas de treinamento

```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
```

Para acompanhar melhor nossos experimentos de treinamento, estamos usando as seguintes flags no comando acima:
* `--report_to wandb` garante que as execuções de treinamento sejam rastreadas no Weights and Biases. Para usá-lo, certifique-se de instalar o `wandb` com `pip install wandb`.
* `validation_prompt` e `validation_epochs` para permitir que o script execute algumas inferências de validação. Isso nos permite verificar qualitativamente se o treinamento está progredindo como esperado.

Definir o `<ID_TOKEN>` não é necessário. A partir de algumas experimentações limitadas, descobrimos que funciona melhor (pois se assemelha ao treinamento de [Dreambooth](https://huggingface.co/docs/diffusers/en/training/dreambooth)) do que sem ele. Quando fornecido, o `<ID_TOKEN>` é adicionado ao início de cada prompt. Portanto, se o seu `<ID_TOKEN>` fosse `"DISNEY"` e o seu prompt fosse `"Spiderman swinging over buildings"`, o prompt efetivo usado no treinamento seria `"DISNEY Spiderman swinging over buildings"`. Quando não fornecido, você estaria treinando sem nenhum token adicional ou poderia aumentar seu conjunto de dados para aplicar o token onde desejar antes de iniciar o treinamento.

> [!NOTE]
> Você pode passar `--use_8bit_adam` para reduzir os requisitos de memória do treinamento.

> [!IMPORTANT]
> As seguintes configurações foram testadas no momento da adição do suporte ao treinamento de LoRA para CogVideoX: - Nossos testes foram realizados principalmente no CogVideoX-2b. Trabalharemos com CogVideoX-5b e CogVideoX-5b-I2V em breve - Um conjunto de dados composto por 70 vídeos de treinamento com resoluções de `200 x 480 x 720` (F x H x W). A partir disso, usando o salto de quadros no pré-processamento de dados, criamos dois conjuntos de dados menores, de 49 e 16 quadros, para experimentação mais rápida e porque o limite máximo recomendado pela equipe do CogVideoX é de 49 quadros. Dos 70 vídeos, criamos três grupos de 10, 25 e 50 vídeos. Todos os vídeos eram semelhantes em termos da natureza do conceito sendo treinado. - 25+ vídeos funcionaram melhor para treinar novos conceitos e estilos. - Descobrimos que é melhor treinar com um token de identificador que pode ser especificado como `--id_token`. Isso é semelhante ao treinamento estilo Dreambooth, mas o ajuste fino normal sem tal token também funciona. - O conceito treinado pareceu funcionar razoavelmente bem quando combinado com prompts completamente não relacionados. Esperamos resultados ainda melhores se o CogVideoX-5B for ajustado. - O repositório original usa um `lora_alpha` de `1`. Encontramos isso inadequado em muitas execuções, possivelmente devido a diferenças nos backends de modelagem e nas configurações de treinamento. Nossa recomendação é definir o `lora_alpha` para `rank` ou `rank // 2`. - Se você estiver treinando com dados cujas legendas geram resultados ruins com o modelo original, um `rank` de 64 ou superior é bom e também é a recomendação da equipe por trás do CogVideoX. Se as gerações já forem moderadamente boas nas suas legendas de treinamento, um `rank` de 16/32 deve funcionar. Encontramos que definir o rank muito baixo, por exemplo `4`, não é ideal e não produz resultados promissores. - Os autores do CogVideoX recomendam 4000 passos de treinamento e 100 vídeos de treinamento no total para alcançar o melhor resultado. Embora isso possa render os melhores resultados, descobrimos, em nossa experimentação limitada, que 2000 passos e 25 vídeos também podem ser suficientes. - Ao usar o otimizador Prodigy para treinamento, pode-se seguir as recomendações deste [blog](https://huggingface.co/blog/sdxl_lora_advanced_script). O Prodigy tende a sofrer overfitting rapidamente. Em meus testes muito limitados, encontrei uma taxa de aprendizado de `0.5` como adequada, além de `--prodigy_use_bias_correction`, `prodigy_safeguard_warmup` e `--prodigy_decouple`. - A taxa de aprendizado recomendada pelos autores do CogVideoX e da nossa experimentação com Adam/AdamW está entre `1e-3` e `1e-4` para um conjunto de dados de 25+ vídeos.
>
> Observe que nossos testes não são exaustivos devido ao tempo limitado para exploração. Nossa recomendação seria experimentar diferentes parâmetros para encontrar as melhores configurações para seus dados.

## Inferência

Depois de treinar um modelo lora, a inferência pode ser feita simplesmente carregando os pesos do lora no `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)
```

## Reduzir o uso de memória

Durante os testes com a biblioteca diffusers, todas as otimizações incluídas na biblioteca diffusers foram habilitadas. Esse esquema não foi testado para uso real de memória em dispositivos fora das arquiteturas **NVIDIA A100 / H100**. Em geral, esse esquema pode ser adaptado a todos os dispositivos com **NVIDIA Ampere architecture** ou superior. Se as otimizações forem desabilitadas, o consumo de memória será multiplicado, com o uso de memória de pico sendo cerca de 3 vezes o valor na tabela. No entanto, a velocidade aumentará cerca de 3-4 vezes. Você pode desabilitar seletivamente algumas otimizações, incluindo:

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

+ Para inferência em múltiplas GPUs, a otimização `enable_sequential_cpu_offload()` precisa ser desativada.
+ O uso de modelos INT8 reduzirá a velocidade de inferência, o que é feito para acomodar GPUs com menos memória, mantendo uma perda mínima na qualidade do vídeo, embora a velocidade de inferência diminua significativamente.
+ O modelo CogVideoX-2B foi treinado em precisão `FP16`, e todos os modelos CogVideoX-5B foram treinados em precisão `BF16`. Recomendamos usar a precisão em que o modelo foi treinado para inferência.
+ [PytorchAO](https://github.com/pytorch/ao) e [Optimum-quanto](https://github.com/huggingface/optimum-quanto/) podem ser usados para quantizar os módulos de text encoder, transformer e VAE, reduzindo os requisitos de memória do CogVideoX. Isso permite que o modelo rode em Colabs T4 gratuitos ou em GPUs com memória menor! Além disso, observe que a quantização TorchAO é totalmente compatível com `torch.compile`, o que pode melhorar significativamente a velocidade de inferência. A precisão FP8 deve ser usada em dispositivos com NVIDIA H100 ou superior, exigindo a instalação a partir do código-fonte dos pacotes Python `torch`, `torchao`, `diffusers` e `accelerate`. O CUDA 12.4 é recomendado.
+ Os testes de velocidade de inferência também utilizaram o esquema de otimização de memória descrito acima. Sem a otimização de memória, a velocidade de inferência aumenta em cerca de 10%. Apenas a versão do modelo do `diffusers` suporta quantização.
+ O modelo suporta apenas entrada em inglês; outros idiomas podem ser traduzidos para inglês para uso por meio de refinamento por modelos de grande escala.
+ O uso de memória no ajuste fino de modelos é testado em um ambiente `8 * H100`, e o programa utiliza automaticamente a otimização `Zero 2`. Se um número específico de GPUs for indicado na tabela, é necessário usar esse número ou mais GPUs para o ajuste fino.

 | **Atributo**                        | **CogVideoX-2B**                                                       | **CogVideoX-5B**                                                       |
| ------------------------------------ | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **Nome do Modelo**                       | CogVideoX-2B                                                           | CogVideoX-5B                                                           |
| **Precisão de Inferência**              | FP16* (Recomendado), BF16, FP32, FP8*, INT8, Não suportado INT4         | BF16 (Recomendado), FP16, FP32, FP8*, INT8, Não suportado INT4         |
| **VRAM para inferência em GPU única**        | FP16: Usando diffusers 12,5GB* INT8: Usando diffusers com torchao 7,8GB* | BF16: Usando diffusers 20.7GB* INT8: Usando diffusers com torchao 11.4GB* |
| **VRAM para inferência em múltiplas GPUs**         | FP16: Usando diffusers 10GB*                                             | BF16: Usando diffusers 15GB*                                             |
| **Velocidade de Inferência**                  | A100 único: ~90 segundos, H100 único: ~45 segundos                      | A100 único: ~180 segundos, H100 único: ~90 segundos                     |
| **Precisão do ajuste fino**            | FP16                                                                   | BF16                                                                   |
| **Consumo de VRAM no fine-tuning**     | 47 GB (bs=1, LORA) 61 GB (bs=2, LORA) 62GB (bs=1, SFT)                 | 63 GB (bs=1, LORA) 80 GB (bs=2, LORA) 75GB (bs=1, SFT)                 |

