From 7c8aab0930d29e34d231a381d6fe5b843bfc885b Mon Sep 17 00:00:00 2001 From: Adam Lee Date: Fri, 26 Jun 2026 00:10:13 +0900 Subject: [PATCH] Fix validation fps from 1 to 16 --- .../train/configs/rl/wan/diffusion_nft_videoalign.yaml | 1 + fastvideo/train/methods/rl/common/validation.py | 2 ++ fastvideo/train/methods/rl/diffusion_nft.py | 3 ++- tests/local_tests/test_train_rl_sampling.py | 8 ++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/train/configs/rl/wan/diffusion_nft_videoalign.yaml b/examples/train/configs/rl/wan/diffusion_nft_videoalign.yaml index 24af91b3c..71baec2b3 100644 --- a/examples/train/configs/rl/wan/diffusion_nft_videoalign.yaml +++ b/examples/train/configs/rl/wan/diffusion_nft_videoalign.yaml @@ -41,6 +41,7 @@ method: num_prompts: 16 batch_size: 4 log_samples: true + fps: 16 seed: 42 data_path: diff --git a/fastvideo/train/methods/rl/common/validation.py b/fastvideo/train/methods/rl/common/validation.py index 1cf42a682..315d8f7dc 100644 --- a/fastvideo/train/methods/rl/common/validation.py +++ b/fastvideo/train/methods/rl/common/validation.py @@ -17,6 +17,7 @@ class RLValidationConfig: num_prompts: int = 16 batch_size: int = 16 log_samples: bool = True + fps: int = 1 seed: int = 42 data_path: str | None = None sampling: dict[str, Any] | None = None @@ -37,6 +38,7 @@ class RLValidationConfig: num_prompts=max(1, int(raw.get("num_prompts", 16) or 16)), batch_size=max(1, int(raw.get("batch_size", 16) or 16)), log_samples=bool(raw.get("log_samples", True)), + fps=max(1, int(raw.get("fps", 1) or 1)), seed=int(raw.get("seed", 42) or 42), data_path=(None if data_path in (None, "") else str(data_path)), sampling=(dict(sampling) if sampling is not None else None), diff --git a/fastvideo/train/methods/rl/diffusion_nft.py b/fastvideo/train/methods/rl/diffusion_nft.py index 6b447db6a..ed66e2794 100644 --- a/fastvideo/train/methods/rl/diffusion_nft.py +++ b/fastvideo/train/methods/rl/diffusion_nft.py @@ -491,11 +491,12 @@ class DiffusionNFTMethod(TrainingMethod): return artifacts = [] + fps = int(self._validation_config.fps) for item in sorted(logs, key=lambda x: int(x["index"])): artifact = tracker.video( media_to_video_array(item["media"]), caption=validation_caption(str(item["prompt"]), item["rewards"]), - fps=1, + fps=fps, ) if artifact is not None: artifacts.append(artifact) diff --git a/tests/local_tests/test_train_rl_sampling.py b/tests/local_tests/test_train_rl_sampling.py index aa7d9e9d6..744d6b0ff 100644 --- a/tests/local_tests/test_train_rl_sampling.py +++ b/tests/local_tests/test_train_rl_sampling.py @@ -4,6 +4,7 @@ import pytest from fastvideo.pipelines import TrainingBatch from fastvideo.train.methods.rl.common import ( DiffusionSampler, + RLValidationConfig, SamplingConfig, distributed_k_repeat_indices, media_to_video_array, @@ -236,6 +237,7 @@ def test_diffusion_nft_video_config_uses_genrl_rewards_in_clean_layout(): assert cfg.method["validation"]["num_steps"] == 50 assert cfg.method["validation"]["num_prompts"] == 16 assert cfg.method["validation"]["batch_size"] == 4 + assert cfg.method["validation"]["fps"] == 16 assert cfg.method["beta"] == 0.1 assert cfg.method["kl_beta"] == 0.0001 assert cfg.training.loop.gradient_accumulation_steps == 24 @@ -254,6 +256,12 @@ def test_validation_shard_indices_are_stable_and_padded(): assert rank1 == [(1, True), (3, True), (0, False)] +def test_rl_validation_config_parses_video_fps(): + config = RLValidationConfig.from_mapping({"fps": 16}) + + assert config.fps == 16 + + def test_distributed_k_repeat_indices_repeats_prompts_globally(): rank0 = distributed_k_repeat_indices( dataset_length=100,