Support multiple prompts - #468
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for loading generation prompts from a file (prompt_file) across multiple video generation scripts (generate_ltx2.py, generate_ltx_video.py, and generate_wan.py), alongside updating configuration files and improving GCS upload paths. It also fixes latent decoding in wan_pipeline.py by concatenating addressable shards. The review feedback highlights a critical performance bottleneck and a NameError in generate_ltx_video.py caused by initializing the pipeline inside the prompt loop. Additionally, the reviewer recommends raising a ValueError in max_utils.py to prevent downstream IndexError crashes when no prompts are found, and suggests removing an unused last_out variable in generate_ltx2.py.
177d687 to
09435d4
Compare
mbohlool
left a comment
There was a problem hiding this comment.
Summary & Thanks
Thanks for putting this together! Adding prompt-file support across Wan and LTX will be very valuable for automated evaluation workflows like VBench.
The recent update guarding the shard concatenation in WanPipeline._decode_latents_to_video (video.addressable_shards[0].data.shape[0] < video.shape[0]) nicely resolves the replicated tensor duplication issue that caused the WanKvCacheTest failure.
There are still two blocking issues (one runtime IAM permission issue with GCS and one pipeline API signature inconsistency) along with a few important improvements before this can be merged.
🔴 Required Changes (Blockers)
1. GCS IAM Permission failure: storage_client.get_bucket
Location: src/maxdiffusion/max_utils.py (around line 383)
bucket_name, prefix_name = parse_gcs_bucket_and_prefix(prompt_file_path)
storage_client = storage.Client()
bucket = storage_client.get_bucket(bucket_name)
blob = bucket.blob(prefix_name)Issue:
storage_client.get_bucket(bucket_name) performs an HTTP GET request to retrieve bucket metadata, which requires storage.buckets.get permission. Service accounts and TPU VM workloads are typically granted object-level reader access (storage.objects.get / Storage Object Viewer) but lack bucket metadata permissions. This will trigger a 403 Forbidden error when attempting to download prompts from gs://....
Fix:
Use client-side bucket instantiation storage_client.bucket(bucket_name) instead (matching how upload_file_to_gcs works):
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(prefix_name)
content = blob.download_as_text()2. Pipeline API signature inconsistency in LTXVideoPipeline
Location: src/maxdiffusion/pipelines/ltx_video/ltx_video_pipeline.py (around line 630 & line 1157)
Issue:
In LTXMultiScalePipeline.__call__, prompt was explicitly added as a typed parameter:
def __call__(
self,
...,
prompt: Optional[Union[str, List[str]]] = None,
) -> Any:However, in LTXVideoPipeline.__call__, prompt was not added to the method signature and is extracted via kwargs.get("prompt", self.config.prompt). This creates an inconsistent public interface between the base and multi-scale pipelines and prevents type checkers/IDEs from discovering the parameter.
Fix:
Explicitly add prompt: Optional[Union[str, List[str]]] = None to the parameter list of LTXVideoPipeline.__call__.
🟡 Important Improvements
-
Add explicit timeout to
requests.get(src/maxdiffusion/max_utils.py:393):response = requests.get(prompt_file_path, timeout=30)
Without a timeout, dropped packets or unresponsive HTTP servers can cause TPU worker threads to hang indefinitely.
-
Defensive handling against
Noneconfig values inget_gcs_output_path(src/maxdiffusion/max_utils.py:347):
Ifoutput_dirorbase_output_directoryisNonein the config,getattr(config, "output_dir", "")returnsNone, leading toAttributeError: 'NoneType' object has no attribute 'startswith'.output_dir = getattr(config, "output_dir", "") or "" base_output_dir = getattr(config, "base_output_directory", "") or ""
-
Deduplicate batch chunking and padding:
The exact same prompt slicing and tail-batch replication logic is duplicated acrossgenerate_wan.py(inference_generate_videoandrun) andgenerate_ltx2.py. Consider extracting a reusable generator inmax_utils.py, e.g.:def chunk_and_pad(items: list, batch_size: int): for i in range(0, len(items), batch_size): chunk = items[i : i + batch_size] actual_len = len(chunk) padded_chunk = chunk + [chunk[-1]] * (batch_size - actual_len) if actual_len < batch_size else chunk yield i, padded_chunk, actual_len
-
Expand unit test coverage in
tests/maxdiffusion_utils_test.py:
Currently only the empty stringValueErroris tested. Please consider adding unit tests for:- Reading valid multi-line prompt files (handling newlines, empty lines, and trimming whitespace).
- Fallback to
default_promptwhen prompt file contains only whitespace. get_gcs_output_pathpath resolution.
🟢 Nits & Suggestions
- 💡 Support
#comments in prompt files: Inload_prompts, consider ignoring comment lines:if line.strip() and not line.strip().startswith('#'). This makes prompt files much friendlier for benchmark suites. - 🟢 Dead config in
base_wan_animate.yml:prompt_file: ""was added tobase_wan_animate.yml, butgenerate_wan_animate.pydoes not load or useprompt_file. Either implement prompt file support ingenerate_wan_animate.pyor remove it from the YAML.
09435d4 to
f3716ce
Compare
|
Thanks for the extensive review @mbohlool. I've addressed all your comments. For wan_animate, earlier |
f3716ce to
3f861b2
Compare
61def9c to
3f861b2
Compare
This PR adds supports for enabling inference scripts to provide multiple prompt-inputs to generate videos via txt files or GCS locations.
It will be useful for integrating VBench evals into this repo.