[bugfix]: document the NVFP4 decoder through the commands that actually parse it

`fastvideo generate` takes a run config plus dotted overrides and never reads FastVideoArgs.add_cli_args, so the
documented `--h3-vae-nvfp4-decoder` flag failed before the model loaded. The flag is removed; the guide uses
`--generator.pipeline.experimental.h3_vae_nvfp4_decoder`, and a test drives that override through the generate parser
to FastVideoArgs. Also drops two narrating test docstrings.
This commit is contained in:
Aryan Kumar
2026-10-30 11:39:42 -07:00
parent 3fb5059e8e
commit a7da439f87
4 changed files with 25 additions and 21 deletions
+7 -6
View File
@@ -107,16 +107,17 @@ hf download FastVideo/FastH3-NVFP4-VAE-Decoder --include 'quality-36L/decoder-nv
'fast-8L/decoder-nvfp4.safetensors' --local-dir fasth3-nvfp4-vae
```
Select it through the surface you drive the pipeline with; the field, the CLI flag and the environment variable all
set `fastvideo_args.h3_vae_nvfp4_decoder`, and the serve-config field wins over the environment.
Select it through the surface you drive the pipeline with. The config field (also a dotted override of
`fastvideo generate`), the example's `--vae-decoder` and the environment variable all set
`fastvideo_args.h3_vae_nvfp4_decoder`, and the config field wins over the environment.
```bash
# example script
python examples/inference/basic/basic_open_h3_regenerate_2k.py --video draft.mp4 --prompt "..." \
--vae-decoder fasth3-nvfp4-vae/quality-36L/decoder-nvfp4.safetensors
# `fastvideo generate` and the serve config use the same field
fastvideo generate --model-path Efficient-Large-Model/Open-H3-Regenerate-2K --video draft.mp4 --prompt "..." \
--h3-vae-nvfp4-decoder fasth3-nvfp4-vae/quality-36L/decoder-nvfp4.safetensors
# `fastvideo generate`: a run config, with the decoder as a dotted override
fastvideo generate --config regen2k_run.yaml \
--generator.pipeline.experimental.h3_vae_nvfp4_decoder fasth3-nvfp4-vae/quality-36L/decoder-nvfp4.safetensors
```
```yaml
@@ -126,7 +127,7 @@ generator:
h3_vae_nvfp4_decoder: ./fasth3-nvfp4-vae/quality-36L/decoder-nvfp4.safetensors
```
`FASTVIDEO_H3_VAE_NVFP4_DECODER` stays as the fallback when neither the serve config nor the CLI sets the field. The
`FASTVIDEO_H3_VAE_NVFP4_DECODER` stays as the fallback when the config does not set the field. The
swap happens in the VAE loader, so the dense decoder never reaches the GPU: it is replaced on the CPU by the exported
checkpoint (2.0 GiB of packed weights instead of 9.7 GiB of FP32), moved to the device, and decoded under bf16 autocast.
The decoder keeps the pipeline's tiling (at 2560x1440: 8x13 tiles of 256 px with 64 px overlap) and the fused Triton
-7
View File
@@ -881,13 +881,6 @@ class FastVideoArgs:
default=FastVideoArgs.taeh3_chunk_size,
help="TAEH3 latent frames per execution chunk.",
)
parser.add_argument(
"--h3-vae-nvfp4-decoder",
type=str,
default=FastVideoArgs.h3_vae_nvfp4_decoder,
help="Exported NVFP4 MiniMax-H3 decoder (decoder-nvfp4.safetensors) that replaces the VAE decoder at "
"load. Blackwell only. Overrides FASTVIDEO_H3_VAE_NVFP4_DECODER.",
)
parser.add_argument(
"--vae-parallel-decode",
action=StoreBoolean,
@@ -298,7 +298,6 @@ def test_registry_resolves_the_release_to_the_regenerate_pipeline(tmp_path):
def test_serve_config_forwards_the_nvfp4_decoder_option(monkeypatch):
"""`generator.pipeline.experimental.h3_vae_nvfp4_decoder` reaches FastVideoArgs through the serve path."""
from fastvideo import fastvideo_args as fva
from fastvideo.api import ComponentConfig, EngineConfig, GeneratorConfig, PipelineSelection
from fastvideo.api.compat import generator_config_to_fastvideo_args
@@ -327,11 +326,23 @@ def test_serve_config_forwards_the_nvfp4_decoder_option(monkeypatch):
assert captured["draft_size"] == "768p"
def test_cli_flag_sets_the_nvfp4_decoder_option():
from fastvideo.fastvideo_args import FastVideoArgs
def test_generate_dotted_override_sets_the_nvfp4_decoder_option(tmp_path):
from fastvideo.api.compat import generator_config_to_fastvideo_args
from fastvideo.entrypoints.cli.generate import GenerateSubcommand, build_generate_run_config
from fastvideo.utils import FlexibleArgumentParser
args = FastVideoArgs.add_cli_args(FlexibleArgumentParser()).parse_args(
["--h3-vae-nvfp4-decoder", "/tmp/decoder-nvfp4.safetensors"])
assert args.h3_vae_nvfp4_decoder == "/tmp/decoder-nvfp4.safetensors"
assert FastVideoArgs.add_cli_args(FlexibleArgumentParser()).parse_args([]).h3_vae_nvfp4_decoder is None
config_path = tmp_path / "run.yaml"
config_path.write_text("generator:\n model_path: Efficient-Large-Model/Open-H3-Regenerate-2K\n"
"request:\n prompt: hello\n", encoding="utf-8")
parser = FlexibleArgumentParser()
GenerateSubcommand().subparser_init(parser.add_subparsers(dest="subparser"))
args, unknown = parser.parse_known_args([
"generate", "--config", str(config_path), "--generator.pipeline.experimental.h3_vae_nvfp4_decoder",
"/tmp/decoder-nvfp4.safetensors"
])
config = build_generate_run_config(args, unknown)
assert config.generator.pipeline.experimental["h3_vae_nvfp4_decoder"] == "/tmp/decoder-nvfp4.safetensors"
assert generator_config_to_fastvideo_args(config.generator).h3_vae_nvfp4_decoder == "/tmp/decoder-nvfp4.safetensors"
@@ -502,7 +502,6 @@ def _load_h3_vae(vae_dir, cpu: bool = True, decoder: str | None = None, pipeline
def test_open_h3_regenerate_2k_vae_load_applies_the_exported_decoder(tmp_path):
"""Regenerate-2K loads its ``base_model/vae`` through the same swap, so the option applies there too."""
from fastvideo.configs.pipelines.open_h3_regenerate_2k import OpenH3Regenerate2KPipelineConfig
_write_vae_dir(tmp_path / "vae", decoder_layers=5)