{"id":7372,"date":"2026-09-29T23:20:01","date_gmt":"2026-09-29T14:20:01","guid":{"rendered":"https:\/\/localmodelwatch.tsuchitsuchi.com\/2026\/09\/29\/longlive-plug-wan21-ti2v-5b-cfg-lora\/"},"modified":"2026-10-02T13:33:48","modified_gmt":"2026-10-02T04:33:48","slug":"longlive-plug-wan21-ti2v-5b-cfg-lora","status":"publish","type":"post","link":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/29\/longlive-plug-wan21-ti2v-5b-cfg-lora\/","title":{"rendered":"LongLive-Plug-Wan2.2-TI2V-5B-cfg: Our Generated Video, File List"},"content":{"rendered":"<p><!-- lmw:facts --><\/p>\n<h2>At a Glance<\/h2>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>Item<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Repository<\/td>\n<td><a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg\">Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg<\/a><\/td>\n<\/tr>\n<tr>\n<td>Publisher guide<\/td>\n<td><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/publisher-efficient-large-model-en\/\">Efficient Large Model (NVIDIA and MIT): models and licenses<\/a><\/td>\n<\/tr>\n<tr>\n<td>Published<\/td>\n<td>2026-09-29<\/td>\n<\/tr>\n<tr>\n<td>License<\/td>\n<td>apache-2.0<\/td>\n<\/tr>\n<tr>\n<td>Formats<\/td>\n<td><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/format-safetensors-en\/\">safetensors<\/a><\/td>\n<\/tr>\n<tr>\n<td>Source type<\/td>\n<td>Primary source (the publisher itself)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>Values determined by this site&#8217;s code when the information was collected. Dates are JST.<\/em><\/p>\n<p><!-- \/lmw:facts --><\/p>\n<p><!-- lmw:lab-summary --><\/p>\n<p><strong>What we checked ourselves<\/strong><\/p>\n<ul>\n<li>We generated video on a rented cloud GPU from our own fixed prompts and show it unedited.<\/li>\n<\/ul>\n<p>Details and conditions are in \u201cOur Own Measurements\u201d below.<\/p>\n<p><!-- \/lmw:lab-summary --><\/p>\n<h2>Overview<\/h2>\n<p>LongLive-Plug-Wan2.2-TI2V-5B-cfg has been released as a LoRA adapter applying CFG (Classifier-Free Guidance) distillation for the text- and image-to-video generation model Wan2.2-TI2V-5B.<\/p>\n<p>This model is an adapter that distills the standard CFG=5 guided flow of the base model into a single conditional forward pass at CFG=1 on the student model side. It eliminates the need to calculate unconditional (negative) branches at each denoising step, reducing the DiT (Diffusion Transformer) forward processing to just once per step. Note that denoising schedule distillation is not performed, making this different from DMD (Distribution Matching Distillation) checkpoints that carry out few-step generation.<\/p>\n<h2>Specifications<\/h2>\n<p>The specifications and recommended settings listed in the model card are as follows:<\/p>\n<ul>\n<li>Parameter count: LoRA parameters are 161,218,560 (FP32 tensors: 600, base model is the 5-billion parameter scale Wan2.2-TI2V-5B)<\/li>\n<li>Architecture: PEFT LoRA (rank: 64, alpha: 64, dropout: 0.0) targeting 300 Linear layers spanning all 30 transformer blocks (self-attention q\/k\/v\/o, cross-attention q\/k\/v\/o, and FFN 0\/2 of each block)<\/li>\n<li>Output specifications: Resolution of 1280\u00d7704 (704\u00d71280 is also supported per base model specs), with the evaluation profile set to 121 frames at 24 FPS (5-second duration under original model specs)<\/li>\n<li>Recommended steps and sampler: 50 steps, FlowUniPC scheduler (timestep shift: 5.0)<\/li>\n<li>Recommended guidance and weight settings: guidance_scale is 1.0 (CFG=1), and LoRA weight scale is 1.0 (consistent scale during training)<\/li>\n<li>License terms: Distributed under the Apache-2.0 license, allowing use under the specified terms including commercial use<\/li>\n<\/ul>\n<h2>Performance and Quality<\/h2>\n<p>The release source provides the following configuration values regarding the distillation design and inference settings of this adapter:<\/p>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>Setting<\/th>\n<th style=\"text-align: right;\">Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Teacher CFG scale used for distillation<\/td>\n<td style=\"text-align: right;\"><strong>5.0<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Student CFG during training<\/td>\n<td style=\"text-align: right;\"><strong>1.0<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Recommended inference CFG<\/td>\n<td style=\"text-align: right;\"><strong>1.0<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Default LoRA weight scale<\/td>\n<td style=\"text-align: right;\"><strong>1.0<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Teacher \u2192 student denoising steps<\/td>\n<td style=\"text-align: right;\"><strong>50 \u2192 50<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Scheduler \/ timestep shift<\/td>\n<td style=\"text-align: right;\">FlowUniPC \/ <strong>5.0<\/strong><\/td>\n<\/tr>\n<tr>\n<td>LoRA rank \/ alpha<\/td>\n<td style=\"text-align: right;\"><strong>64 \/ 64<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Training checkpoint<\/td>\n<td style=\"text-align: right;\"><strong>step 250<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>In this method, training is performed to minimize the relative guidance-weighted MSE against a fixed teacher model trajectory state, maintaining the native 50 steps identical to the original model. The design does not perform rollout generation by the student model itself during training, and does not include a DMD critic. While it has the advantage of reducing computational load by skipping unconditional branch evaluation, the publisher states that this is a research checkpoint documenting artifact integrity and executed training specifications, and does not guarantee general-purpose quality across all prompts or downstream models.<\/p>\n<p>Regarding the performance of the base Wan2.2-TI2V-5B model itself, it employs the Wan2.2-VAE with a compression rate of 16\u00d716\u00d74 (4\u00d716\u00d716 across temporal, height, and width dimensions), achieving a total compression of 4\u00d732\u00d732 combined with patchify layers. According to the original model&#8217;s published information, it possesses the efficiency to generate 5 seconds of 720P video in under 9 minutes on a single consumer GPU even without optimizations.<\/p>\n<h2>Strengths and Use Cases<\/h2>\n<p>This adapter aims to improve computational efficiency during inference while maintaining the capabilities of the base model Wan2.2-TI2V-5B. Specifically, it streamlines the guidance process via CFG (Classifier-Free Guidance) for both text-to-video and image-to-video tasks.<\/p>\n<p>While conventional CFG-based inference required two forward passes per denoising step\u2014one &#8220;conditional&#8221; and one &#8220;unconditional (negative)&#8221;\u2014applying this LoRA and running with <code>guidance_scale: 1.0<\/code> enables operation with only a single conditional forward pass per step. This is expected to reduce the computational cost of inference while preserving general generation quality trends.<\/p>\n<p><!-- lmw:files --><\/p>\n<h2>Distributed Files<\/h2>\n<p><em>Weight files published in <a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg\/tree\/main\">Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg<\/a>, listed by this site from the Hugging Face API. Sizes are the actual file sizes.<\/em><\/p>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>File<\/th>\n<th>Size<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>adapter_model.safetensors<\/code><\/td>\n<td>645MB<\/td>\n<\/tr>\n<tr>\n<td><code>generator_lora.pt<\/code><\/td>\n<td>645MB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><!-- \/lmw:files --><\/p>\n<h2>How to Get It<\/h2>\n<p>This model is available from the Hugging Face repository. The following files are provided as distribution formats:<\/p>\n<ul>\n<li><code>adapter_model.safetensors<\/code>: Safe and portable format generator LoRA<\/li>\n<li><code>generator_lora.pt<\/code>: LongLive native payload<\/li>\n<li><code>adapter_config.json<\/code>: PEFT settings and target module information<\/li>\n<li><code>training_config.yaml<\/code>: Training configuration details<\/li>\n<li><code>inference_overrides.yaml<\/code>: Inference settings (50 steps, CFG=1)<\/li>\n<li><code>release_metadata.json<\/code>: Metadata<\/li>\n<li><code>provenance.json<\/code>: Provenance information and checksums<\/li>\n<li><code>SHA256SUMS<\/code>: Checksums for artifacts<\/li>\n<\/ul>\n<p>You can download <code>generator_lora.pt<\/code> using the Hugging Face <code>huggingface_hub<\/code> library with the following command:<\/p>\n<pre><code class=\"language-python\">from huggingface_hub import hf_hub_download\n\nlora_path = hf_hub_download(\n    repo_id=&quot;Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg&quot;,\n    filename=&quot;generator_lora.pt&quot;,\n)\nprint(lora_path)\n<\/code><\/pre>\n<p>When using it as an inference path for LongLive, it is recommended to use settings such as <code>sampling_steps: 50<\/code>, <code>guidance_scale: 1.0<\/code>, and <code>lora_weight_scale: 1.0<\/code>.<\/p>\n<p><!-- lmw:runnability --><\/p>\n<h2>Can You Run It Locally?<\/h2>\n<p>The publisher distributes this model as safetensors.<\/p>\n<p><strong>License \u2014 <code>apache-2.0<\/code> (Commercial use allowed):<\/strong> Permits commercial use, modification and redistribution. Redistribution requires including the license and stating changes; includes a patent grant.<\/p>\n<p><em>Compiled by this site&#8217;s code from the published formats and the license field. License summaries are not legal advice \u2014 check the publisher&#8217;s original terms before relying on them.<\/em><\/p>\n<p><!-- \/lmw:runnability --><\/p>\n<p><!-- lmw:lab --><\/p>\n<h2>Our Own Measurements<\/h2>\n<p>Generated by us \u2014 not samples copied from the model card. We cannot run video models on our own server (no GPU), so we generated on a rented cloud GPU (conditions below). How we measure, and the results for every model: <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/observations-en\/\">Our Measurements<\/a>.<\/p>\n<h3>Video We Generated (Cloud GPU)<\/h3>\n<p><a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg\">Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg<\/a> (apache-2.0 license) is a LoRA adapter and does not run on its own, so we merged it into the base model <a href=\"https:\/\/huggingface.co\/Wan-AI\/Wan2.2-TI2V-5B-Diffusers\">Wan-AI\/Wan2.2-TI2V-5B-Diffusers<\/a> (apache-2.0 license) in the combination the publisher recommends (LongLive-Plug-Wan2.2-TI2V-5B-few-step at weight 1.0, LongLive-Plug-Wan2.2-TI2V-5B-cfg at weight 0.5) and generated with 4 steps and guidance scale 1.0. We set the sampler to match the publisher&#8217;s inference code (<a href=\"https:\/\/github.com\/NVlabs\/LongLive\/blob\/fb16a879f46e604df4a0ca48ce2bf45adfa90352\/LongLive-Plug\/inference.py\">LongLive-Plug inference.py<\/a>): UniPC with shift 5.0 (diffusers&#8217; UniPCMultistepScheduler). The publisher says to use this adapter together with <a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step\">LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/a>, so we merged both, and the same videos also appear in that adapter&#8217;s article. We ran diffusers&#8217; <code>WanPipeline<\/code> (diffusers 0.40.0) and did not run any code from the publisher. The LoRA was merged by our own code: we map the original Wan layer names to diffusers&#8217; names and add weight \u00d7 (alpha \/ r) \u00d7 BA to each weight. This mapping is our interpretation, not something the publisher documents; we only confirmed that every layer name and shape matched.<\/p>\n<p>Conditions: NVIDIA L40S (VRAM 44GB) on Modal, weights in BF16 (VAE in FP32), 1280\u00d7704 pixels, 121 frames at 24 fps (about 5.04 s), seed 0, two fixed prompts without people, logos or text, generated 2026-10-02 (JST). Not selected \u2014 each clip is the first output. To fit our server&#8217;s upload limit we re-encoded each clip as H.264 (under 12.0 MB), so fine detail may be softer than the raw output.<\/p>\n<p><strong>Prompt: \u201ca small red paper boat drifting down a clear forest stream, sunlight flickering through the leaves, gentle ripples, realistic\u201d<\/strong><\/p>\n<p>Without the LoRA (base model, same 4 steps), 51 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291417_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-base-boat-1.mp4\"><\/video><\/p>\n<p>With the LoRA, 52 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291417_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-lora-boat-1.mp4\"><\/video><\/p>\n<p><strong>Prompt: \u201ctime-lapse of white clouds rolling over snowy mountain peaks at sunrise, golden light, wide shot\u201d<\/strong><\/p>\n<p>Without the LoRA (base model, same 4 steps), 52 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291417_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-base-clouds-1.mp4\"><\/video><\/p>\n<p>With the LoRA, 52 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291417_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-lora-clouds-1.mp4\"><\/video><\/p>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>Item<\/th>\n<th>Result<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>VRAM after loading the model (BF16, text encoder already released)<\/td>\n<td>12.0GB<\/td>\n<\/tr>\n<tr>\n<td>Peak VRAM while generating<\/td>\n<td>32.3GB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Generation times are for a rented cloud NVIDIA L40S and are not a guide to your own GPU; the text encoder runs first and is released before the video model loads, so the VRAM above does not include it. The \u201cwithout the LoRA\u201d clips use the same 4 steps for comparison only; the base model&#8217;s usual settings use many more steps with guidance, so they do not show what the base model can do.<\/p>\n<h4>Setup, Download and Run Steps (What We Actually Ran)<\/h4>\n<p>We split the work into two containers on Modal, both built from the Debian (slim) image with Python 3.12. The downloading container fetches only the listed files (configs, safetensors weights and the tokenizer) from Hugging Face at pinned revisions; the generating container has no network access. These are the packages we installed:<\/p>\n<pre><code class=\"language-bash\"># 1. Environment for downloading (no GPU)\npython -m pip install huggingface_hub\n\n# 2. Environment for generating (GPU, network blocked)\npython -m pip install torch diffusers transformers accelerate safetensors sentencepiece ftfy imageio-ffmpeg numpy\n<\/code><\/pre>\n<p>We then called <code>download(job)<\/code> in the first container and <code>run(job)<\/code> in the second one from the script below (<code>video_remote.py<\/code>, written by us; full text). Files go under <code>\/models\/&lt;dir&gt;<\/code>:<\/p>\n<pre><code class=\"language-python\">&quot;&quot;&quot;\nModal \u306e\u30b3\u30f3\u30c6\u30ca\u306e\u4e2d\u3067\u52d5\u304f\u3001\u52d5\u753b\u751f\u6210\u30e2\u30c7\u30eb\u306e\u751f\u6210(2026-10-01\u3001\u30e6\u30fc\u30b6\u30fc\u306e\u5224\u65ad)\u3002lmw\/lab\/gpu_modal.py \u306e\nvideo_download \/ video_run \u304b\u3089\u547c\u3070\u308c\u308b\u3002**\u6a19\u6e96\u30e9\u30a4\u30d6\u30e9\u30ea\u3060\u3051\u3092\u5148\u982d\u3067\u8aad\u307f**\u3001huggingface_hub\u30fbtorch\u30fbdiffusers \u306f\n\u5404\u95a2\u6570\u306e\u4e2d\u3067\u8aad\u3080(\u30b3\u30f3\u30c6\u30ca\u3054\u3068\u306b\u5165\u3063\u3066\u3044\u308b\u3082\u306e\u304c\u9055\u3046)\u3002\n\n\u3010\u914d\u5e03\u5143\u306e\u30b3\u30fc\u30c9\u306f\u52d5\u304b\u3055\u306a\u3044\u3011diffusers\u30fbtransformers \u306e\u516c\u958b\u30d1\u30c3\u30b1\u30fc\u30b8\u3060\u3051\u3067\u8aad\u307f\u8fbc\u3080\u3002\u91cd\u307f\u306f safetensors \u3060\u3051\u3067\u3001\nHugging Face \u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30b3\u30fc\u30c9\u3092\u8aad\u307f\u8fbc\u3080\u8a2d\u5b9a\u306f\u4f7f\u308f\u306a\u3044\u3002LoRA \u306f\u5f53\u30b5\u30a4\u30c8\u306e\u30b3\u30fc\u30c9(merge_lora)\u304c\u3001\u540d\u524d\u306e\u5bfe\u5fdc\u8868\u3068\n\u5f62\u3092\u7167\u5408\u3057\u306a\u304c\u3089\u5143\u306e\u91cd\u307f\u306b\u8db3\u3057\u8fbc\u3080(\u914d\u5e03\u5143\u306e\u8aad\u307f\u8fbc\u307f\u51e6\u7406\u306f\u4f7f\u308f\u306a\u3044)\u3002\n\n\u30102\u3064\u306e\u30b3\u30f3\u30c6\u30ca\u306b\u5206\u3051\u308b\u3011(lmw\/lab\/remote_code_remote.py \u3068\u540c\u3058)\n- download: GPU \u306e\u7121\u3044\u30b3\u30f3\u30c6\u30ca\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3042\u308a\u3002Hugging Face \u304b\u3089\u3001\u7248\u3092\u56fa\u5b9a\u3057\u3066\u6c7a\u307e\u3063\u305f\u30d5\u30a1\u30a4\u30eb\u3060\u3051\u3092\u843d\u3068\u3059\u3002\n- run: GPU \u306e\u30b3\u30f3\u30c6\u30ca\u30fb**\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u906e\u65ad**\u30fbModal \u306e\u6a5f\u80fd\u3082\u4f7f\u3048\u306a\u3044\u30fbVolume \u306f\u8aad\u307f\u53d6\u308a\u5c02\u7528\u3002\n\n\u3010VRAM \u3092\u7bc0\u7d04\u3059\u308b\u9806\u756a\u3011\u30c6\u30ad\u30b9\u30c8\u30a8\u30f3\u30b3\u30fc\u30c0(UMT5-XXL \u306f 11GB)\u3067\u30d7\u30ed\u30f3\u30d7\u30c8\u3092\u5148\u306b\u5168\u90e8\u57cb\u3081\u8fbc\u307f\u306b\u3057\u3066\u304b\u3089\u6368\u3066\u3001\n\u305d\u306e\u5f8c\u3067\u52d5\u753b\u306e\u672c\u4f53(transformer)\u3068 VAE \u3092\u8aad\u3080\u30022\u3064\u3092\u540c\u6642\u306b GPU \u306b\u8f09\u305b\u306a\u3044\u306e\u3067\u3001\u5b89\u3044 GPU \u306b\u53ce\u307e\u308b\u3002\n\n\u3010\u7d50\u679c\u306e\u8fd4\u3057\u65b9\u3011run \u306f\u751f\u6210\u5668\u3067\u3001\u52d5\u753b\u306e\u30d0\u30a4\u30c8\u5217\u3092 CHUNK_BYTES \u305a\u3064(kind: &quot;chunk&quot;)\u3001\u6700\u5f8c\u306b\u8a18\u9332(kind: &quot;record&quot;)\u3092\u8fd4\u3059\u3002\nModal \u306f 2MiB \u3092\u8d85\u3048\u308b\u623b\u308a\u5024\u3092\u81ea\u5206\u306e API \u3067\u9810\u3051\u308b\u304c\u3001\u751f\u6210\u306e\u30b3\u30f3\u30c6\u30ca\u306f Modal \u306e\u6a5f\u80fd\u3092\u906e\u65ad\u3057\u3066\u3044\u308b\n(restrict_modal_access)\u306e\u3067\u65ad\u3089\u308c\u308b(2026-10-02\u300114B \u306e4\u672c\u3092\u4f5c\u308a\u7d42\u3048\u305f\u5f8c\u306b 401 \u3067\u5168\u3066\u5931\u3063\u305f)\u30021\u56de\u306e\u623b\u308a\u5024\u3092\u5c0f\u3055\u304f\u4fdd\u3064\u3002\n\n\u3010\u8cbb\u7528\u3092\u6291\u3048\u308b\u3011\u540c\u3058\u8aad\u307f\u8fbc\u307f\u306e\u307e\u307e\u3001LoRA \u3092\u8db3\u3059\u524d(\u5143\u306e\u30e2\u30c7\u30eb)\u3068\u8db3\u3057\u305f\u5f8c\u3092\u7d9a\u3051\u3066\u751f\u6210\u3059\u308b(\u8aad\u307f\u8fbc\u307f\u306f1\u56de)\u3002\n\u52d5\u753b\u306f WordPress \u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306e\u4e0a\u9650\u306b\u53ce\u307e\u308b\u3088\u3046 H.264 \u3067\u5727\u7e2e\u3059\u308b(MAX_BYTES \u3092\u8d85\u3048\u305f\u3089\u753b\u8cea\u3092\u4e0b\u3052\u3066\u4f5c\u308a\u76f4\u3059)\u3002\n\n\u8a18\u4e8b\u57f7\u7b46\u7528\u306e LLM \u306f\u547c\u3070\u306a\u3044\u3002\n&quot;&quot;&quot;\nimport hashlib\nimport json\nimport os\nimport platform\nimport subprocess\nimport time\nfrom datetime import datetime, timezone\n\nMOUNT = &quot;\/models&quot;\nPYTHON_VERSION = &quot;3.12&quot;\nDOWNLOAD_PACKAGES = (&quot;huggingface_hub&quot;,)\n# diffusers \u306e Wan \u306e\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u304c\u4f7f\u3046\u3082\u306e(ftfy \u306f\u30d7\u30ed\u30f3\u30d7\u30c8\u306e\u6574\u5f62\u3001imageio-ffmpeg \u306f H.264 \u306e\u66f8\u304d\u51fa\u3057\u306b\u4f7f\u3046)\nRUN_PACKAGES = (&quot;torch&quot;, &quot;diffusers&quot;, &quot;transformers&quot;, &quot;accelerate&quot;, &quot;safetensors&quot;, &quot;sentencepiece&quot;, &quot;ftfy&quot;,\n                &quot;imageio-ffmpeg&quot;, &quot;numpy&quot;)\n# \u843d\u3068\u3057\u3066\u3088\u3044\u30d5\u30a1\u30a4\u30eb(pickle \u306e .bin \/ .pt \/ .ckpt \u306f\u843d\u3068\u3055\u306a\u3044)\nALLOWED_EXTS = (&quot;.json&quot;, &quot;.safetensors&quot;, &quot;.model&quot;, &quot;.txt&quot;)\n\n# \u5143\u306e Wan \u306e\u5c64\u306e\u540d\u524d(LoRA \u304c\u4f7f\u3046)\u2192 diffusers \u306e WanTransformer3DModel \u306e\u5c64\u306e\u540d\u524d\u3002\n# diffusers \u306e\u5909\u63db\u30b9\u30af\u30ea\u30d7\u30c8(scripts\/convert_wan_to_diffusers.py)\u3068\u540c\u3058\u5bfe\u5fdc\nWAN_LORA_MODULES = {\n    &quot;self_attn.q&quot;: &quot;attn1.to_q&quot;, &quot;self_attn.k&quot;: &quot;attn1.to_k&quot;, &quot;self_attn.v&quot;: &quot;attn1.to_v&quot;,\n    &quot;self_attn.o&quot;: &quot;attn1.to_out.0&quot;,\n    &quot;cross_attn.q&quot;: &quot;attn2.to_q&quot;, &quot;cross_attn.k&quot;: &quot;attn2.to_k&quot;, &quot;cross_attn.v&quot;: &quot;attn2.to_v&quot;,\n    &quot;cross_attn.o&quot;: &quot;attn2.to_out.0&quot;,\n    &quot;ffn.0&quot;: &quot;ffn.net.0.proj&quot;, &quot;ffn.2&quot;: &quot;ffn.net.2&quot;,\n}\n# 1\u56de\u306b\u8fd4\u3059\u30d0\u30a4\u30c8\u6570(Modal \u304c\u81ea\u5206\u306e API \u306b\u9810\u3051\u305a\u306b\u305d\u306e\u307e\u307e\u8fd4\u305b\u308b 2MiB \u3088\u308a\u5341\u5206\u5c0f\u3055\u304f)\nCHUNK_BYTES = 1024 * 1024\nLORA_PREFIXES = (&quot;base_model.model.&quot;, &quot;diffusion_model.&quot;, &quot;model.&quot;)\n# \u751f\u6210\u306b\u4f7f\u3046\u30c7\u30d0\u30a4\u30b9\u3002Modal \u3067\u306f\u5e38\u306b cuda(\u5f53\u30b5\u30a4\u30c8\u306e\u8a55\u4fa1\u3067\u3001\u5c0f\u3055\u306a\u30e2\u30c7\u30eb\u3092 CPU \u3067\u901a\u3059\u3068\u304d\u3060\u3051 cpu \u306b\u3059\u308b)\nDEVICE = &quot;cuda&quot;\n\ndef installed_packages() -&gt; list[str]:\n    from importlib import metadata\n    seen = {}\n    for dist in metadata.distributions():\n        name = dist.metadata[&quot;Name&quot;]\n        if name and name.lower() not in seen:\n            seen[name.lower()] = f&quot;{name}=={dist.version}&quot;\n    return sorted(seen.values(), key=str.lower)\n\ndef _log(t0: float, message: str) -&gt; None:\n    print(f&quot; {message}&quot;, flush=True)\n\ndef _sha256(path: str) -&gt; str:\n    h = hashlib.sha256()\n    with open(path, &quot;rb&quot;) as f:\n        for chunk in iter(lambda: f.read(1 &lt;&lt; 20), b&quot;&quot;):\n            h.update(chunk)\n    return h.hexdigest()\n\ndef download(job: dict) -&gt; dict:\n    &quot;&quot;&quot;\n    job: {&quot;dir&quot;, &quot;base&quot;: {&quot;repo&quot;, &quot;revision&quot;, &quot;files&quot;}, &quot;loras&quot;: [{&quot;repo&quot;, &quot;revision&quot;, &quot;file&quot;}]}\u3002\n    \u5143\u306e\u30e2\u30c7\u30eb\u306f &lt;dir&gt;\/base\u3001LoRA \u306f &lt;dir&gt;\/lora&lt;i&gt;\/ \u306b\u7f6e\u304f\u3002\u623b\u308a\u5024: {&quot;bytes&quot;, &quot;seconds&quot;, &quot;packages&quot;, &quot;lora_sha256&quot;}\u3002\n    &quot;&quot;&quot;\n    from huggingface_hub import hf_hub_download\n    t0 = time.time()\n    base_dir = os.path.join(MOUNT, job[&quot;dir&quot;])\n    total = 0\n    targets = [(job[&quot;base&quot;][&quot;repo&quot;], job[&quot;base&quot;][&quot;revision&quot;], name, os.path.join(base_dir, &quot;base&quot;))\n               for name in job[&quot;base&quot;][&quot;files&quot;]]\n    targets += [(lora[&quot;repo&quot;], lora[&quot;revision&quot;], lora[&quot;file&quot;], os.path.join(base_dir, f&quot;lora{i}&quot;))\n                for i, lora in enumerate(job.get(&quot;loras&quot;) or [])]\n    for repo, revision, name, dest in targets:\n        if not name.endswith(ALLOWED_EXTS) or &quot;..&quot; in name.split(&quot;\/&quot;):\n            raise ValueError(f&quot;\u843d\u3068\u3055\u306a\u3044\u7a2e\u985e\u306e\u30d5\u30a1\u30a4\u30eb\u3067\u3059: {name}&quot;)\n        path = hf_hub_download(repo, name, revision=revision, local_dir=dest)\n        total += os.path.getsize(path)\n    lora_sha = [_sha256(os.path.join(base_dir, f&quot;lora{i}&quot;, lora[&quot;file&quot;]))\n                for i, lora in enumerate(job.get(&quot;loras&quot;) or [])]\n    seconds = round(time.time() - t0)\n    _log(t0, f&quot;\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 {total \/ 1024 ** 3:.1f}GB\u30fb{seconds}\u79d2&quot;)\n    return {&quot;bytes&quot;: int(total), &quot;seconds&quot;: int(seconds), &quot;packages&quot;: installed_packages(), &quot;lora_sha256&quot;: lora_sha}\n\ndef _lora_pairs(state: dict) -&gt; dict:\n    &quot;&quot;&quot;{\u5143\u306e\u5c64\u306e\u540d\u524d: {&quot;A&quot;, &quot;B&quot;, &quot;alpha&quot;?}}\u3002\u540d\u524d\u306e\u982d(base_model.model. \u7b49)\u3092\u5916\u3057\u3001A \u3068 B \u306e\u63c3\u308f\u306a\u3044\u5c64\u306f\u65ad\u308b\u3002&quot;&quot;&quot;\n    pairs: dict = {}\n    for key, tensor in state.items():\n        name = key\n        for prefix in LORA_PREFIXES:\n            if name.startswith(prefix):\n                name = name[len(prefix):]\n                break\n        if name.endswith(&quot;.lora_A.weight&quot;):\n            pairs.setdefault(name[:-len(&quot;.lora_A.weight&quot;)], {})[&quot;A&quot;] = tensor\n        elif name.endswith(&quot;.lora_B.weight&quot;):\n            pairs.setdefault(name[:-len(&quot;.lora_B.weight&quot;)], {})[&quot;B&quot;] = tensor\n        elif name.endswith(&quot;.alpha&quot;):\n            pairs.setdefault(name[:-len(&quot;.alpha&quot;)], {})[&quot;alpha&quot;] = float(tensor.item())\n        else:\n            raise ValueError(f&quot;LoRA \u306e\u91cd\u307f\u3067\u306f\u306a\u3044\u540d\u524d\u3067\u3059: {key}&quot;)\n    broken = [n for n, p in pairs.items() if &quot;A&quot; not in p or &quot;B&quot; not in p]\n    if broken:\n        raise ValueError(f&quot;A \u3068 B \u304c\u63c3\u308f\u306a\u3044\u5c64\u304c\u3042\u308a\u307e\u3059: {broken[:5]}&quot;)\n    return pairs\n\ndef diffusers_module_name(name: str) -&gt; str:\n    &quot;&quot;&quot;blocks.12.self_attn.q \u2192 blocks.12.attn1.to_q\u3002\u5bfe\u5fdc\u8868\u306b\u7121\u3044\u5c64\u306f\u65ad\u308b(\u63a8\u6e2c\u3067\u5f53\u3066\u306a\u3044)\u3002&quot;&quot;&quot;\n    parts = name.split(&quot;.&quot;)\n    if len(parts) &lt; 4 or parts[0] != &quot;blocks&quot; or not parts[1].isdigit():\n        raise ValueError(f&quot;\u5bfe\u5fdc\u8868\u306b\u7121\u3044\u5c64\u3067\u3059: {name}&quot;)\n    tail = &quot;.&quot;.join(parts[2:])\n    if tail not in WAN_LORA_MODULES:\n        raise ValueError(f&quot;\u5bfe\u5fdc\u8868\u306b\u7121\u3044\u5c64\u3067\u3059: {name}&quot;)\n    return f&quot;blocks.{parts[1]}.{WAN_LORA_MODULES[tail]}&quot;\n\ndef merge_lora(transformer, path: str, weight: float, alpha: float | None, rank: int | None) -&gt; dict:\n    &quot;&quot;&quot;\n    LoRA \u3092\u5143\u306e\u91cd\u307f\u306b\u8db3\u3057\u8fbc\u3080: W \u2190 W + weight \u00d7 (alpha \/ r) \u00d7 (B @ A)\u3002alpha \u3068 r \u306f\u914d\u5e03\u5143\u306e adapter_config.json \u306e\u5024\u3092\n    \u30db\u30b9\u30c8\u5074\u304c\u6e21\u3059(\u91cd\u307f\u306e\u30d5\u30a1\u30a4\u30eb\u306b alpha \u304c\u3042\u308c\u3070\u305d\u3061\u3089\u3092\u4f7f\u3046)\u3002\u8db3\u3057\u8fbc\u307f\u306f float32 \u3067\u8a08\u7b97\u3057\u3066\u304b\u3089\u5143\u306e\u578b\u306b\u623b\u3059\u3002\n    \u5168\u3066\u306e\u5c64\u304c\u5bfe\u5fdc\u8868\u3067\u898b\u3064\u304b\u308a\u3001\u5f62\u304c\u4e00\u81f4\u3059\u308b\u3053\u3068\u3092\u78ba\u304b\u3081\u308b(1\u3064\u3067\u3082\u5916\u308c\u305f\u3089\u65ad\u308b)\u3002\n    &quot;&quot;&quot;\n    import torch\n    from safetensors.torch import load_file\n    pairs = _lora_pairs(load_file(path))\n    merged = 0\n    for name, p in sorted(pairs.items()):\n        module = transformer.get_submodule(diffusers_module_name(name))\n        a, b = p[&quot;A&quot;].float(), p[&quot;B&quot;].float()\n        r = a.shape[0]\n        if rank and r != rank:\n            raise ValueError(f&quot;{name}: \u30e9\u30f3\u30af {r} \u304c adapter_config.json \u306e {rank} \u3068\u9055\u3044\u307e\u3059&quot;)\n        scale = weight * ((p.get(&quot;alpha&quot;) or alpha or r) \/ r)\n        w = module.weight\n        delta = (b.to(w.device) @ a.to(w.device)) * scale\n        if tuple(delta.shape) != tuple(w.shape):\n            raise ValueError(f&quot;{name}: \u5f62 {tuple(delta.shape)} \u304c\u5143\u306e\u91cd\u307f {tuple(w.shape)} \u3068\u9055\u3044\u307e\u3059&quot;)\n        with torch.no_grad():\n            w.copy_((w.float() + delta).to(w.dtype))\n        merged += 1\n    return {&quot;modules&quot;: merged, &quot;weight&quot;: weight, &quot;scale&quot;: round(weight * ((alpha or rank or 1) \/ (rank or 1)), 6)}\n\ndef encode_mp4(frames, fps: int, path: str, max_bytes: int) -&gt; dict:\n    &quot;&quot;&quot;\n    0\u301c1 \u306e RGB \u306e\u30b3\u30de(F, H, W, 3)\u3092 H.264(yuv420p)\u306e mp4 \u306b\u3059\u308b\u3002max_bytes \u3092\u8d85\u3048\u305f\u3089\u3001\u30d3\u30c3\u30c8\u30ec\u30fc\u30c8\u306e\u4e0a\u9650\u3092\n    \u4e0b\u3052\u3066\u4f5c\u308a\u76f4\u3059(3\u56de\u307e\u3067)\u3002\u623b\u308a\u5024: \u5b9f\u969b\u306b\u4f7f\u3063\u305f ffmpeg \u306e\u5f15\u6570\u3068\u5927\u304d\u3055\u3002\n    &quot;&quot;&quot;\n    import imageio_ffmpeg\n    import numpy as np\n    pixels = (np.clip(frames, 0.0, 1.0) * 255).round().astype(np.uint8)\n    count, height, width = pixels.shape[0], pixels.shape[1], pixels.shape[2]\n    duration = count \/ fps\n    # \u4e0a\u9650\u306e\u5927\u304d\u3055\u306e 85% \u306b\u53ce\u307e\u308b\u30d3\u30c3\u30c8\u30ec\u30fc\u30c8(\u97f3\u58f0\u306a\u3057)\n    kbps = int(max_bytes * 8 * 0.85 \/ duration \/ 1000)\n    for attempt, crf in enumerate((18, 22, 26)):\n        rate = int(kbps * (0.8 ** attempt))\n        args = [&quot;-y&quot;, &quot;-f&quot;, &quot;rawvideo&quot;, &quot;-pix_fmt&quot;, &quot;rgb24&quot;, &quot;-s&quot;, f&quot;{width}x{height}&quot;, &quot;-r&quot;, str(fps), &quot;-i&quot;, &quot;-&quot;,\n                &quot;-an&quot;, &quot;-c:v&quot;, &quot;libx264&quot;, &quot;-preset&quot;, &quot;slow&quot;, &quot;-crf&quot;, str(crf), &quot;-maxrate&quot;, f&quot;{rate}k&quot;,\n                &quot;-bufsize&quot;, f&quot;{rate * 2}k&quot;, &quot;-pix_fmt&quot;, &quot;yuv420p&quot;, &quot;-movflags&quot;, &quot;+faststart&quot;, path]\n        proc = subprocess.run([imageio_ffmpeg.get_ffmpeg_exe(), *args], input=pixels.tobytes(),\n                              capture_output=True, timeout=600)\n        if proc.returncode != 0:\n            raise RuntimeError(f&quot;ffmpeg \u304c\u5931\u6557\u3057\u307e\u3057\u305f: {proc.stderr.decode(errors='replace')[-400:]}&quot;)\n        size = os.path.getsize(path)\n        if size &lt;= max_bytes:\n            return {&quot;ffmpeg_args&quot;: [&quot;ffmpeg&quot;, *args[:-1], os.path.basename(path)], &quot;bytes&quot;: size,\n                    &quot;frames&quot;: int(count), &quot;width&quot;: int(width), &quot;height&quot;: int(height), &quot;fps&quot;: int(fps),\n                    &quot;duration&quot;: round(duration, 2)}\n    raise ValueError(f&quot;\u52d5\u753b\u3092 {max_bytes} \u30d0\u30a4\u30c8\u4ee5\u4e0b\u306b\u5727\u7e2e\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f&quot;)\n\ndef run(job: dict):\n    &quot;&quot;&quot;\n    job: {&quot;dir&quot;, &quot;pipeline&quot;, &quot;settings&quot;: {height, width, num_frames, fps, steps, guidance, flow_shift?},\n          &quot;seed&quot;, &quot;prompts&quot;: [{&quot;id&quot;, &quot;en&quot;}], &quot;loras&quot;: [{&quot;file&quot;, &quot;weight&quot;, &quot;alpha&quot;, &quot;rank&quot;}], &quot;compare_base&quot;,\n          &quot;max_bytes&quot;}\u3002\n    \u751f\u6210\u5668: {&quot;kind&quot;: &quot;chunk&quot;, &quot;id&quot;, &quot;index&quot;, &quot;data&quot;: bytes} \u3092\u52d5\u753b\u3054\u3068\u306b\u9806\u306b\u8fd4\u3057\u3001\u6700\u5f8c\u306b\n    {&quot;kind&quot;: &quot;record&quot;, ...\u8a18\u9332\u306e\u4e00\u90e8(\u79d2\u6570\u30fbVRAM\u30fb\u7248\u3002\u52d5\u753b\u306e\u4e2d\u8eab\u306f\u542b\u307e\u306a\u3044)} \u3092\u8fd4\u3059\u3002\n    &quot;&quot;&quot;\n    import diffusers\n    import numpy as np\n    import torch\n    import transformers\n    os.environ[&quot;HF_HUB_OFFLINE&quot;] = &quot;1&quot;\n    os.environ[&quot;TRANSFORMERS_OFFLINE&quot;] = &quot;1&quot;\n    os.environ[&quot;HF_HUB_DISABLE_TELEMETRY&quot;] = &quot;1&quot;\n    t0 = time.time()\n    base_dir = os.path.join(MOUNT, job[&quot;dir&quot;])\n    model_dir = os.path.join(base_dir, &quot;base&quot;)\n    settings = job[&quot;settings&quot;]\n    guidance = float(settings[&quot;guidance&quot;])\n    cuda = DEVICE == &quot;cuda&quot;\n    gpu = torch.cuda.get_device_name(0) if cuda else &quot;cpu&quot;\n    _log(t0, f&quot;GPU: {gpu}\u30fbdiffusers {diffusers.__version__}\u30fbtorch {torch.__version__}&quot;)\n    record = {&quot;gpu&quot;: gpu, &quot;vram_total&quot;: int(torch.cuda.get_device_properties(0).total_memory) if cuda else 0,\n              &quot;diffusers&quot;: str(diffusers.__version__), &quot;transformers&quot;: str(transformers.__version__),\n              &quot;torch&quot;: str(torch.__version__), &quot;dtype&quot;: &quot;bfloat16&quot;, &quot;vae_dtype&quot;: &quot;float32&quot;,\n              &quot;packages&quot;: installed_packages(), &quot;python&quot;: platform.python_version(),\n              &quot;measured_at&quot;: datetime.now(timezone.utc).isoformat()}\n    pipeline_cls = getattr(diffusers, job[&quot;pipeline&quot;])\n\n    # 1. \u30d7\u30ed\u30f3\u30d7\u30c8\u3092\u57cb\u3081\u8fbc\u307f\u306b\u3059\u308b(\u30c6\u30ad\u30b9\u30c8\u30a8\u30f3\u30b3\u30fc\u30c0\u3060\u3051\u3092 GPU \u306b\u8f09\u305b\u3001\u7d42\u308f\u3063\u305f\u3089\u6368\u3066\u308b)\n    with open(os.path.join(model_dir, &quot;model_index.json&quot;), encoding=&quot;utf-8&quot;) as f:\n        index = json.load(f)\n    skip_models = {name: None for name, spec in index.items()\n                   if isinstance(spec, list) and name not in (&quot;text_encoder&quot;, &quot;tokenizer&quot;, &quot;scheduler&quot;)}\n    text_pipe = pipeline_cls.from_pretrained(model_dir, torch_dtype=torch.bfloat16, use_safetensors=True,\n                                             local_files_only=True, **skip_models)\n    text_pipe.text_encoder.to(DEVICE)\n    embeds = {}\n    with torch.no_grad():\n        for p in job[&quot;prompts&quot;]:\n            # max_sequence_length \u306f\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u306e __call__ \u306e\u65e2\u5b9a(512\u3002\u5143\u306e Wan \u3082 512)\u306b\u5408\u308f\u305b\u308b\u3002\n            # encode_prompt \u306e\u65e2\u5b9a\u306f 226 \u3067\u3001\u305d\u306e\u307e\u307e\u3060\u3068\u6a19\u6e96\u306e\u547c\u3073\u51fa\u3057\u3068\u9055\u3046\u57cb\u3081\u8fbc\u307f\u306b\u306a\u308b\n            pos, neg = text_pipe.encode_prompt(prompt=p[&quot;en&quot;], negative_prompt=&quot;&quot;, device=DEVICE,\n                                               do_classifier_free_guidance=guidance &gt; 1.0,\n                                               max_sequence_length=int(settings.get(&quot;max_sequence_length&quot;, 512)))\n            embeds[p[&quot;id&quot;]] = (pos.cpu(), None if neg is None else neg.cpu())\n    del text_pipe\n    if cuda:\n        torch.cuda.empty_cache()\n    record[&quot;encode_sec&quot;] = round(time.time() - t0)\n\n    # 2. \u672c\u4f53\u3068 VAE \u3092\u8aad\u3080(VAE \u306f float32\u3002diffusers \u306e Wan \u306e\u4f8b\u3068\u540c\u3058)\n    vae_cls = getattr(diffusers, index[&quot;vae&quot;][1])\n    vae = vae_cls.from_pretrained(model_dir, subfolder=&quot;vae&quot;, torch_dtype=torch.float32, use_safetensors=True,\n                                  local_files_only=True)\n    pipe = pipeline_cls.from_pretrained(model_dir, vae=vae, text_encoder=None, tokenizer=None,\n                                        torch_dtype=torch.bfloat16, use_safetensors=True, local_files_only=True)\n    if settings.get(&quot;flow_shift&quot;) is not None:\n        pipe.scheduler = type(pipe.scheduler).from_config(pipe.scheduler.config, flow_shift=float(settings[&quot;flow_shift&quot;]))\n    record[&quot;scheduler&quot;] = {&quot;class&quot;: type(pipe.scheduler).__name__,\n                           **{k: v for k, v in dict(pipe.scheduler.config).items()\n                              if k in (&quot;flow_shift&quot;, &quot;use_flow_sigmas&quot;, &quot;prediction_type&quot;, &quot;solver_order&quot;)}}\n    pipe.to(DEVICE)\n    if cuda:\n        torch.cuda.synchronize()\n    record[&quot;vram_loaded&quot;] = int(torch.cuda.memory_allocated()) if cuda else 0\n    record[&quot;load_sec&quot;] = round(time.time() - t0)\n    _log(t0, f&quot;\u8aad\u307f\u8fbc\u307f: VRAM {record['vram_loaded'] \/ 1024 ** 3:.1f}GB\u30fb{record['load_sec']}\u79d2&quot;)\n    if cuda:\n        torch.cuda.reset_peak_memory_stats()\n\n    def generate(group: str) -&gt; list[dict]:\n        out = []\n        for p in job[&quot;prompts&quot;]:\n            pos, neg = embeds[p[&quot;id&quot;]]\n            started = time.time()\n            generator = torch.Generator(&quot;cpu&quot;).manual_seed(int(job[&quot;seed&quot;]))\n            frames = pipe(prompt_embeds=pos.to(DEVICE),\n                          negative_prompt_embeds=None if neg is None else neg.to(DEVICE),\n                          height=int(settings[&quot;height&quot;]), width=int(settings[&quot;width&quot;]),\n                          num_frames=int(settings[&quot;num_frames&quot;]), num_inference_steps=int(settings[&quot;steps&quot;]),\n                          guidance_scale=guidance, generator=generator, output_type=&quot;np&quot;).frames[0]\n            if cuda:\n                torch.cuda.synchronize()\n            seconds = time.time() - started\n            frames = np.asarray(frames, dtype=np.float32)\n            if not np.isfinite(frames).all():\n                raise FloatingPointError(&quot;\u751f\u6210\u3057\u305f\u30b3\u30de\u306b\u6570\u3067\u306a\u3044\u5024\u304c\u3042\u308a\u307e\u3059&quot;)\n            # \u51e6\u7406\u306e\u8aa4\u308a(\u771f\u3063\u9ed2\u30fb\u4e00\u8272\u306e\u52d5\u753b)\u3092\u53d6\u308a\u8fbc\u307f\u5f79\u306e\u6a5f\u68b0\u306e\u691c\u67fb(lmw\/lab\/sanity.py)\u304c\u898b\u3064\u3051\u308b\u305f\u3081\u306e\u5024\n            stats = {&quot;pixel_mean&quot;: round(float(frames.mean()) * 255, 2), &quot;pixel_std&quot;: round(float(frames.std()) * 255, 2)}\n            path = os.path.join(&quot;\/tmp&quot;, f&quot;{group}-{p['id']}.mp4&quot;)\n            encoded = encode_mp4(frames, int(settings[&quot;fps&quot;]), path, int(job[&quot;max_bytes&quot;]))\n            with open(path, &quot;rb&quot;) as f:\n                raw = f.read()\n            blobs[f&quot;{group}-{p['id']}&quot;] = raw\n            out.append({&quot;id&quot;: f&quot;{group}-{p['id']}&quot;, &quot;prompt_id&quot;: p[&quot;id&quot;], &quot;group&quot;: group,\n                        &quot;seconds&quot;: round(seconds, 1), **encoded, **stats,\n                        &quot;sha256&quot;: hashlib.sha256(raw).hexdigest()})\n            _log(t0, f&quot;{group}\/{p['id']}: {encoded['frames']}\u30b3\u30de\u30fb\u751f\u6210 {seconds:.0f}\u79d2\u30fb{encoded['bytes'] \/ 1e6:.2f}MB&quot;)\n        return out\n\n    videos = []\n    blobs: dict[str, bytes] = {}\n    loras = job.get(&quot;loras&quot;) or []\n    # 3. LoRA \u3092\u8db3\u3059\u524d\u306e\u5143\u306e\u30e2\u30c7\u30eb(\u6bd4\u3079\u308b\u305f\u3081\u3002\u540c\u3058\u30d7\u30ed\u30f3\u30d7\u30c8\u30fb\u30b7\u30fc\u30c9\u30fb\u30b9\u30c6\u30c3\u30d7\u6570)\n    if loras and job.get(&quot;compare_base&quot;):\n        videos += generate(&quot;base&quot;)\n    # 4. LoRA \u3092\u8db3\u3057\u8fbc\u3093\u3067\u304b\u3089\u751f\u6210\u3059\u308b\n    merges = []\n    for i, lora in enumerate(loras):\n        path = os.path.join(base_dir, f&quot;lora{i}&quot;, lora[&quot;file&quot;])\n        merges.append(merge_lora(pipe.transformer, path, float(lora[&quot;weight&quot;]), lora.get(&quot;alpha&quot;), lora.get(&quot;rank&quot;)))\n        _log(t0, f&quot;LoRA {i}: {merges[-1]['modules']}\u5c64\u3092\u8db3\u3057\u8fbc\u307f\u307e\u3057\u305f(\u91cd\u307f {lora['weight']})&quot;)\n    if merges:\n        record[&quot;merges&quot;] = merges\n    videos += generate(&quot;lora&quot; if loras else &quot;model&quot;)\n    record[&quot;vram_peak&quot;] = int(torch.cuda.max_memory_allocated()) if cuda else 0\n    record[&quot;videos&quot;] = videos\n    for vid, raw in blobs.items():\n        for index in range(0, len(raw), CHUNK_BYTES):\n            yield {&quot;kind&quot;: &quot;chunk&quot;, &quot;id&quot;: vid, &quot;index&quot;: index \/\/ CHUNK_BYTES, &quot;data&quot;: raw[index:index + CHUNK_BYTES]}\n    yield {&quot;kind&quot;: &quot;record&quot;, **plain(record)}\n\ndef plain(value):\n    &quot;&quot;&quot;JSON \u306b\u901a\u3057\u3066\u3001\u6a19\u6e96\u306e\u578b\u3060\u3051\u306b\u3059\u308b(\u30db\u30b9\u30c8\u306b\u306f torch \u3082 diffusers \u3082\u7121\u3044)\u3002&quot;&quot;&quot;\n    return json.loads(json.dumps(value, default=str))\n<\/code><\/pre>\n<p>The <code>job<\/code> passed to <code>download<\/code> (as used):<\/p>\n<pre><code class=\"language-json\">{\n  &quot;dir&quot;: &quot;video-1790915190&quot;,\n  &quot;base&quot;: {\n    &quot;repo&quot;: &quot;Wan-AI\/Wan2.2-TI2V-5B-Diffusers&quot;,\n    &quot;revision&quot;: &quot;b8fff7315c768468a5333511427288870b2e9635&quot;,\n    &quot;files&quot;: [\n      &quot;model_index.json&quot;,\n      &quot;scheduler\/scheduler_config.json&quot;,\n      &quot;text_encoder\/config.json&quot;,\n      &quot;text_encoder\/model-00001-of-00003.safetensors&quot;,\n      &quot;text_encoder\/model-00002-of-00003.safetensors&quot;,\n      &quot;text_encoder\/model-00003-of-00003.safetensors&quot;,\n      &quot;text_encoder\/model.safetensors.index.json&quot;,\n      &quot;tokenizer\/special_tokens_map.json&quot;,\n      &quot;tokenizer\/spiece.model&quot;,\n      &quot;tokenizer\/tokenizer.json&quot;,\n      &quot;tokenizer\/tokenizer_config.json&quot;,\n      &quot;transformer\/config.json&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00001-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00002-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00003-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00004-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00005-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model.safetensors.index.json&quot;,\n      &quot;vae\/config.json&quot;,\n      &quot;vae\/diffusion_pytorch_model.safetensors&quot;\n    ]\n  },\n  &quot;loras&quot;: [\n    {\n      &quot;repo&quot;: &quot;Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step&quot;,\n      &quot;revision&quot;: &quot;38a6ec4e8f5b644749d3072bfe1ac383d00951c0&quot;,\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;\n    },\n    {\n      &quot;repo&quot;: &quot;Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg&quot;,\n      &quot;revision&quot;: &quot;fa1f9280778aa27c8038fe06e29fb5f2ed6be451&quot;,\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;\n    }\n  ]\n}\n<\/code><\/pre>\n<p>The <code>job<\/code> passed to <code>run<\/code> (as used):<\/p>\n<pre><code class=\"language-json\">{\n  &quot;dir&quot;: &quot;video-1790915190&quot;,\n  &quot;pipeline&quot;: &quot;WanPipeline&quot;,\n  &quot;settings&quot;: {\n    &quot;height&quot;: 704,\n    &quot;width&quot;: 1280,\n    &quot;num_frames&quot;: 121,\n    &quot;fps&quot;: 24,\n    &quot;steps&quot;: 4,\n    &quot;guidance&quot;: 1.0,\n    &quot;flow_shift&quot;: 5.0\n  },\n  &quot;seed&quot;: 0,\n  &quot;prompts&quot;: [\n    {\n      &quot;id&quot;: &quot;boat&quot;,\n      &quot;en&quot;: &quot;a small red paper boat drifting down a clear forest stream, sunlight flickering through the leaves, gentle ripples, realistic&quot;\n    },\n    {\n      &quot;id&quot;: &quot;clouds&quot;,\n      &quot;en&quot;: &quot;time-lapse of white clouds rolling over snowy mountain peaks at sunrise, golden light, wide shot&quot;\n    }\n  ],\n  &quot;loras&quot;: [\n    {\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;,\n      &quot;weight&quot;: 1.0,\n      &quot;alpha&quot;: 128,\n      &quot;rank&quot;: 128\n    },\n    {\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;,\n      &quot;weight&quot;: 0.5,\n      &quot;alpha&quot;: 64,\n      &quot;rank&quot;: 64\n    }\n  ],\n  &quot;compare_base&quot;: true,\n  &quot;max_bytes&quot;: 12000000\n}\n<\/code><\/pre>\n<details>\n<summary>Package versions in the generating container (full list)<\/summary>\n<pre><code>accelerate==1.15.0 aiohappyeyeballs==2.6.1 aiohttp==3.12.7 aiosignal==1.3.2 annotated-doc==0.0.5 anyio==4.15.1 attrs==25.3.0 cbor2==5.7.0 certifi==2026.7.22 charset-normalizer==3.5.2 click==8.5.0 cuda-bindings==13.4.3 cuda-pathfinder==1.8.2 cuda-toolkit==13.0.3.0 diffusers==0.40.0 filelock==4.0.9 frozenlist==1.6.0 fsspec==2026.9.0 ftfy==6.3.1 grpclib==0.4.8 h11==0.16.0 h2==4.2.0 hf-xet==1.6.0 hpack==4.1.0 httpcore==1.0.9 httpx==0.28.1 huggingface_hub==1.33.0 hyperframe==6.1.0 idna==3.20 imageio-ffmpeg==0.6.0 importlib_metadata==9.0.1 Jinja2==3.1.6 markdown-it-py==4.2.0 MarkupSafe==3.0.3 mdurl==0.1.2 mpmath==1.3.0 multidict==6.4.4 networkx==3.7 numpy==2.5.3 nvidia-cublas==13.1.1.3 nvidia-cuda-cupti==13.0.85 nvidia-cuda-nvrtc==13.0.88 nvidia-cuda-runtime==13.0.96 nvidia-cudnn-cu13==9.24.0.43 nvidia-cufft==12.0.0.61 nvidia-cufile==1.15.1.6 nvidia-curand==10.4.0.35 nvidia-cusolver==12.0.4.66 nvidia-cusparse==12.6.3.3 nvidia-cusparselt-cu13==0.8.1 nvidia-nccl-cu13==2.30.7 nvidia-nvjitlink==13.4.92 nvidia-nvshmem-cu13==3.4.5 nvidia-nvtx==13.0.85 packaging==26.3 pillow==12.3.0 pip==25.1.1 propcache==0.3.1 protobuf==6.31.1 psutil==7.2.2 Pygments==2.21.0 PyYAML==6.0.3 regex==2026.9.29 requests==2.34.2 rich==15.0.0 safetensors==0.8.0 sentencepiece==0.2.2 setuptools==84.0.0 shellingham==1.5.4 sympy==1.14.0 tokenizers==0.23.2 torch==2.14.1 tqdm==4.70.1 transformers==5.18.0 triton==3.8.0 typer==0.27.2 typing_extensions==4.16.0 urllib3==2.8.0 uv==0.7.19 wcwidth==0.9.1 wheel==0.45.1 yarl==1.20.0 zipp==4.1.0<\/code><\/pre>\n<\/details>\n<details>\n<summary>Package versions in the downloading container (full list)<\/summary>\n<pre><code>aiohappyeyeballs==2.6.1 aiohttp==3.12.7 aiosignal==1.3.2 anyio==4.15.1 attrs==25.3.0 cbor2==5.7.0 certifi==2025.4.26 click==8.5.0 filelock==4.0.7 frozenlist==1.6.0 fsspec==2026.9.0 grpclib==0.4.8 h11==0.16.0 h2==4.2.0 hf-xet==1.6.0 hpack==4.1.0 httpcore2==2.13.1 httpx2==2.13.1 huggingface_hub==2.0.0 hyperframe==6.1.0 idna==3.20 multidict==6.4.4 packaging==26.3 pip==25.1.1 propcache==0.3.1 protobuf==6.31.1 PyYAML==6.0.3 tqdm==4.70.1 truststore==0.10.4 typing_extensions==4.16.0 uv==0.7.19 wheel==0.45.1 yarl==1.20.0<\/code><\/pre>\n<\/details>\n<p><!-- \/lmw:lab --><\/p>\n<p><!-- lmw:related --><\/p>\n<h2>Related Articles<\/h2>\n<ul>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/29\/longlive-plug-wan2-2-ti2v-5b-few-step-2\/\">LongLive-Plug-Wan2.2-TI2V-5B-few-step: Our Generated Video, File List<\/a><\/li>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/30\/longlive-plug-wan21-t2v-14b-few-step-2\/\">LongLive-Plug-Wan2.1-T2V-14B-few-step: Our Generated Video, File List<\/a><\/li>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/30\/longlive-plug-wan2-1-t2v-14b-cfg\/\">LongLive-Plug-Wan2.1-T2V-14B-cfg: Our Generated Video, File List<\/a><\/li>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/10\/h3-to-ltx-latent-adapter-released\/\">H3-to-LTX-Latent-Adapter: 4GB+ VRAM, File List<\/a><\/li>\n<\/ul>\n<p><!-- \/lmw:related --><\/p>\n<p><!-- lmw:next-steps --><\/p>\n<h2>What to Read Next<\/h2>\n<ul>\n<li><strong>Formats this model is available in<\/strong> \u2192 <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/format-safetensors-en\/\">Safetensors format guide and models<\/a><\/li>\n<li><strong>Learn about the publisher<\/strong> \u2192 <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/publisher-efficient-large-model-en\/\">Efficient Large Model (NVIDIA and MIT): models, licenses and articles<\/a><\/li>\n<li><strong>Other models for the same task<\/strong> \u2192 <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/models-by-task-en\/#task-video\">Other video generation models<\/a><\/li>\n<\/ul>\n<p><!-- \/lmw:next-steps --><\/p>\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg\">https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg<\/a><\/li>\n<\/ul>\n<p><!-- lmw:updates --><\/p>\n<h2>Update History<\/h2>\n<ul>\n<li>2026-09-30: Changed the title to show what the article covers (VRAM requirements, file list, etc.).<\/li>\n<li>2026-10-02: Added our own measurements: video we generated.<\/li>\n<li>2026-10-02: Changed the title to show what the article covers (VRAM requirements, file list, etc.).<\/li>\n<\/ul>\n<p><!-- \/lmw:updates --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A CFG-distilled LoRA adapter for Wan2.2-TI2V-5B that reduces DiT forward passes to one per step, improving inference efficiency.<\/p>\n","protected":false},"author":1,"featured_media":9118,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[203],"tags":[2659,724,2661,111,1547,2643,2645,959,2663],"class_list":["post-7372","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-image-video-and-audio","tag-cfg-en","tag-efficient-large-model-en","tag-longlive-en","tag-lora-en","tag-verified","tag-wan2-2-ti2v-en","tag-wan2-2-ti2v-5b-en","tag--en"],"lang":"en","translations":{"en":7372,"ja":7370},"_links":{"self":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts\/7372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/comments?post=7372"}],"version-history":[{"count":12,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts\/7372\/revisions"}],"predecessor-version":[{"id":9171,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts\/7372\/revisions\/9171"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/media\/9118"}],"wp:attachment":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/media?parent=7372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/categories?post=7372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/tags?post=7372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}