Files
hao-ai-lab-FastVideo/tests/local_tests/flux/test_flux_dev_component_loaders.py
T
Davids048andClaude Opus 5.5 4117696a4f [refactor]: describe and use the resolved config in docs, examples, and local tests
- Docs, AGENTS.md files, and skills describe ResolvedGeneratorConfig,
  resolve_inference_config, typed YAML, and --config plus dotted
  overrides for training and preprocessing instead of FastVideoArgs and
  flat flags.
- The local tests build resolved configs (or small fakes that expose typed
  paths) instead of FastVideoArgs; the LoRA extraction scripts build
  pipelines with from_pretrained(model_path, resolved_config=...).
- The mixkit README's NVFP4 snippet uses from_config with
  engine.quantization.transformer_quant (the from_pretrained keyword it
  used is rejected).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012M91wnVFmPEvJ9h39r5BH7
2026-10-03 06:16:10 +00:00

123 lines
4.6 KiB
Python

# SPDX-License-Identifier: Apache-2.0
"""Loader smoke tests for FLUX.1-dev component loading from a local checkpoint.
Verifies that tokenizers, CLIP/T5 text encoders, VAE, and FlowMatch scheduler
all load correctly from a Diffusers-layout ``FLUX.1-dev`` directory.
Requires ``official_weights/FLUX.1-dev`` (or set ``FLUX_DEV_ROOT``) and CUDA.
Run from repo root::
pytest tests/local_tests/flux/test_flux_dev_component_loaders.py -vs
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
from pathlib import Path
import pytest
import torch
from fastvideo.configs.models.encoders import (
BaseEncoderOutput,
CLIPTextConfig,
T5LargeConfig,
)
from fastvideo.configs.models.vaes.autoencoder_kl import AutoencoderKLVAEConfig
from fastvideo.configs.pipelines.base import PipelineConfig, preprocess_text
os.environ.setdefault("MASTER_ADDR", "localhost")
os.environ.setdefault("MASTER_PORT", "29517")
_REPO_ROOT = Path(__file__).resolve().parents[3]
_FLUX_DEV_ROOT = os.environ.get(
"FLUX_DEV_ROOT",
str(_REPO_ROOT / "official_weights" / "FLUX.1-dev"),
)
def _flux_clip_post(outputs: BaseEncoderOutput) -> torch.Tensor:
if outputs.pooler_output is None:
raise RuntimeError("CLIP pooled output required")
return outputs.pooler_output
def _flux_t5_post(outputs: BaseEncoderOutput) -> torch.Tensor:
if outputs.last_hidden_state is None:
raise RuntimeError("T5 last_hidden_state required")
return outputs.last_hidden_state
@dataclass
class _FluxDevLoaderPipelineConfig(PipelineConfig):
"""Two text encoders (CLIP + T5) matching FLUX.1-dev model_index.json."""
vae_config: AutoencoderKLVAEConfig = field(default_factory=AutoencoderKLVAEConfig)
text_encoder_configs: tuple[CLIPTextConfig,
T5LargeConfig] = field(default_factory=lambda: (CLIPTextConfig(), T5LargeConfig()))
text_encoder_precisions: tuple[str, ...] = ("fp32", "bf16")
preprocess_text_funcs: tuple = field(default_factory=lambda: (preprocess_text, preprocess_text))
postprocess_text_funcs: tuple = field(default_factory=lambda: (_flux_clip_post, _flux_t5_post))
def test_flux_dev_model_index_components_load() -> None:
"""CLIP/T5 encoders, tokenizers, VAE, and FlowMatch scheduler load."""
if not torch.cuda.is_available():
pytest.skip("FLUX component loader test requires CUDA")
if not Path(_FLUX_DEV_ROOT, "model_index.json").is_file():
pytest.skip("official_weights/FLUX.1-dev missing "
"(set FLUX_DEV_ROOT or download black-forest-labs/FLUX.1-dev)")
from fastvideo.api.inference_resolution import resolve_inference_config
from fastvideo.distributed import (
cleanup_dist_env_and_memory,
maybe_init_distributed_environment_and_model_parallel,
)
from fastvideo.models.loader.component_loader import (
SchedulerLoader,
TextEncoderLoader,
TokenizerLoader,
VAELoader,
)
maybe_init_distributed_environment_and_model_parallel(1, 1)
try:
args = resolve_inference_config({
"model_path": _FLUX_DEV_ROOT,
"engine": {
"parallelism": {
"hsdp_shard_dim": 1
},
"offload": {
"pin_cpu_memory": False
},
},
"pipeline": {
"experimental": {
"pipeline_config": _FluxDevLoaderPipelineConfig()
}
},
})
tok_clip = TokenizerLoader().load(os.path.join(_FLUX_DEV_ROOT, "tokenizer"), args)
tok_t5 = TokenizerLoader().load(os.path.join(_FLUX_DEV_ROOT, "tokenizer_2"), args)
assert "CLIP" in tok_clip.__class__.__name__
assert "T5" in tok_t5.__class__.__name__
te_clip = TextEncoderLoader().load(os.path.join(_FLUX_DEV_ROOT, "text_encoder"), args)
te_t5 = TextEncoderLoader().load(os.path.join(_FLUX_DEV_ROOT, "text_encoder_2"), args)
# Distributed init may wrap encoders in an FSDP shell.
assert te_clip.__class__.__name__.endswith("CLIPTextModel")
assert te_t5.__class__.__name__.endswith("T5EncoderModel")
vae = VAELoader().load(os.path.join(_FLUX_DEV_ROOT, "vae"), args)
assert vae.__class__.__name__ == "AutoencoderKL"
scheduler = SchedulerLoader().load(os.path.join(_FLUX_DEV_ROOT, "scheduler"), args)
assert scheduler.__class__.__name__ == "FlowMatchEulerDiscreteScheduler"
scheduler.set_timesteps(4, mu=0.7)
assert len(scheduler.timesteps) == 4
finally:
cleanup_dist_env_and_memory()