Diffusers documentation

SANA-WM

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.42.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

SANA-WM

SANA-WM là mô hình thế giới từ ảnh sang video có điều khiển bởi camera, được xây dựng dựa trên SANA. Với một hình ảnh khung đầu tiên, một prompt văn bản và một quỹ đạo camera (dạng các tư thế c2w tường minh hoặc chuỗi hành động WASD/IJKL), nó tạo ra một video có chuyển động tuân theo đường đi camera được yêu cầu.

Việc suy luận được thực hiện qua hai giai đoạn:

  1. Giai đoạn 1 — SANA-WM DiT. Một DiT hai chiều có 1,6 tỷ tham số, sử dụng chú ý tuyến tính GDN-Triton và một nhánh điều khiển camera UCPE. Quá trình lấy mẫu sử dụng trình lập lịch Euler flow-matching kiểu LTX với các bước thời gian cho từng token; khung tiềm ẩn đầu tiên đóng vai trò là neo điều kiện.
  2. Giai đoạn 2 — bộ tinh chỉnh LTX-2 (tuỳ chọn). Một pipeline Euler hai chiều kiểu sink riêng biệt (SanaWMLTX2Refiner) bao bọc SanaWMLTX2RefinerTransformer3DModel + LTX2TextConnectors và một bộ mã hoá văn bản Gemma-3, chạy trong 3 bước sigma đã chưng cất.

Cả hai giai đoạn đều giải mã thông qua VAE AutoencoderKLLTX2Video.

Các model có sẵn:

Mô hìnhdtype được khuyến nghị
Efficient-Large-Model/SANA-WM_bidirectional-diffuserstorch.bfloat16
Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refinertorch.bfloat16

SANA-WM được huấn luyện ở độ phân giải cố định 704×1280. dtype được khuyến nghị cho trọng số của transformer — giữ text encoder ở torch.bfloat16 và VAE ở torch.float32 để có số học tốt nhất. Pipeline kỳ vọng các tham số nội tại của camera [fx, fy, cx, cy] trong tọa độ pixel của ảnh gốc; phép biến đổi resize-and-center-crop được áp dụng bên trong.

Suy luận

import torch
from PIL import Image

from diffusers import SanaWMPipeline
from diffusers.utils import export_to_video

pipe = SanaWMPipeline.from_pretrained(
    "Efficient-Large-Model/SANA-WM_bidirectional-diffusers",
    torch_dtype=torch.bfloat16,
)
pipe.enable_model_cpu_offload()  # ~45 GB of weights — offload between stages

# SANA-WM was trained on the LTX-2 VAE in framewise mode with tiling enabled. Without these
# settings the VAE encodes the whole (B, C, T, H, W) clip in one shot, which gives subtly
# different numerics from the released checkpoint.
pipe.vae.enable_tiling()
pipe.vae.use_framewise_encoding = True
pipe.vae.use_framewise_decoding = True
pipe.vae.tile_sample_stride_num_frames = 64
pipe.vae.tile_sample_min_num_frames = 96

prompt = "A car driving across a vast desert plain at golden hour."
output = pipe(
    image=Image.open("input.png").convert("RGB"),
    prompt=prompt,
    action="w-80,jw-40,w-40",        # WASD-style action DSL: forward 80f, jump+forward 40f, forward 40f
    intrinsics=[800.0, 800.0, 845.0, 464.0],  # fx, fy, cx, cy in original-image pixels
    num_frames=161,
    num_inference_steps=60,
    guidance_scale=5.0,
    generator=torch.Generator(device="cuda").manual_seed(42),
    output_type="latent",            # hand the latents to the refiner below
)

Truyền action=None và cung cấp các tư thế c2w của riêng bạn ((F, 4, 4) mảng numpy) để điều khiển quỹ đạo camera một cách tường minh. Bỏ output_type="latent" để nhận video trực tiếp từ giai đoạn 1 và bỏ qua bộ tinh chỉnh.

Giai đoạn 2 — bộ tinh chỉnh LTX-2

SanaWMLTX2Refiner được phát hành dưới dạng một kho lưu trữ riêng, tương tự cách SDXL tách riêng base và refiner. Hãy truyền VAE của pipeline base để các trọng số được chia sẻ thay vì được nạp hai lần:

from diffusers import SanaWMLTX2Refiner

refiner = SanaWMLTX2Refiner.from_pretrained(
    "Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refiner",
    vae=pipe.vae,
    torch_dtype=torch.bfloat16,
)
refiner.enable_model_cpu_offload()

frames = refiner(output.latent, prompt, fps=16)
export_to_video(list(frames), "sana_wm.mp4", fps=16)

Nếu không có vae, refiner sẽ trả về các latents đã tinh chỉnh thay vì video, điều này hữu ích nếu bạn muốn tự giải mã.

Bật offloading cho cả hai pipeline, hoặc giải phóng stage 1 trước khi chạy stage 2 (pipe.transformer.to("cpu")). Tổng dung lượng của hai stage này vào khoảng 45 GB ở torch.bfloat16, và việc giữ cả hai trên một card 80 GB sẽ không còn đủ chỗ cho activations. Lưu ý rằng stage 2 tuân theo torch_dtype: nạp refiner ở torch.float32 sẽ làm tăng bộ nhớ lên gấp đôi và thay đổi đầu ra một chút.

Nếu bạn không có thông số nội tại của camera, một khối module được lưu trữ sẵn có thể ước lượng chúng từ một khung hình duy nhất. Khối này nằm bên ngoài diffusers vì nó kéo theo Pi3X — một phụ thuộc bổ sung và một checkpoint thứ hai — nên không có gì được tải xuống cho đến khi bạn yêu cầu:

from diffusers import ModularPipeline

# One-time per image. Requires `pip install pi3-vision`.
estimator = ModularPipeline.from_pretrained(
    "Efficient-Large-Model/pi3x-intrinsics-estimator", trust_remote_code=True
)
estimator.load_components(dtype=torch.bfloat16)
intrinsics = estimator(image=Image.open("input.png").convert("RGB"), output="intrinsics")

Chuyển đổi checkpoint đã phát hành

Nếu bạn có bản phát hành SANA-WM nguồn (không phải bản snapshot diffusers đã chuyển đổi sẵn), hãy chạy script chuyển đổi một lần:

python scripts/convert_sana_wm_to_diffusers.py \
    --src Efficient-Large-Model/SANA-WM_bidirectional \
    --dst ./SANA-WM_bidirectional-diffusers

Việc này sẽ ghi hai thư mục: pipeline cơ bản tại --dst, và refiner giai đoạn 2 nằm cạnh nó tại ./SANA-WM_bidirectional-diffusers-refiner (có thể ghi đè bằng --dst-refiner). Sau đó, hãy nạp từng thư mục từ đường dẫn cục bộ của chúng như bình thường.

Các thành phần

Refiner giai đoạn 2 là một kho lưu trữ riêng với transformer (SanaWMLTX2RefinerTransformer3DModel), connectors (LTX2TextConnectors), tokenizer, text_encoder Gemma-3 và scheduler riêng. Nó không có vae riêng — hãy truyền vae của pipeline cơ sở.

SanaWMPipeline

lớp diffusers.SanaWMPipeline

< >

( tokenizer: GemmaTokenizer | GemmaTokenizerFasttext_encoder: Gemma2PreTrainedModelvae: AutoencoderKLLTX2Videotransformer: SanaWMTransformer3DModelscheduler: FlowMatchEulerDiscreteScheduler )

Tham số

  • tokenizer ([GemmaTokenizer] hoặc [GemmaTokenizerFast]) — Tokenizer của Gemma-2.
  • text_encoder ([Gemma2PreTrainedModel]) — Bộ mã hóa văn bản Gemma-2.
  • vae ([AutoencoderKLLTX2Video]) — VAE của LTX-2.
  • transformer ([SanaWMTransformer3DModel]) — DiT hai chiều 1600M của SANA-WM.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — Trình lập lịch Euler cho flow-matching (các bước thời gian theo token kiểu LTX). latents trực tiếp.

Pipeline tạo video từ hình ảnh có điều khiển bằng camera của SANA-WM.

Tạo video từ hình ảnh khung đầu tiên, một prompt văn bản và quỹ đạo camera (các tư thế c2w tường minh hoặc chuỗi hành động WASD/IJKL). Sử dụng SANA DiT hai chiều 1600M cho lấy mẫu giai đoạn 1 và bộ hoàn thiện Euler sink-hai chiều LTX-2 cho tinh chỉnh giai đoạn 2; cả hai đều được giải mã thông qua VAE của LTX-2.

__call__

< >

( image: PIL.Image.Image | str | Pathprompt: strc2w: np.ndarray | None = Noneaction: str | None = Noneintrinsics: np.ndarray | list[float] | None = Noneheight: int = 704width: int = 1280num_frames: int = 161fps: int = 16num_inference_steps: int = 60guidance_scale: float = 5.0negative_prompt: str = ''generator: torch.Generator | list[torch.Generator] | None = Noneprompt_embeds: torch.Tensor | None = Noneprompt_attention_mask: torch.Tensor | None = Nonenegative_prompt_embeds: torch.Tensor | None = Nonenegative_prompt_attention_mask: torch.Tensor | None = Nonemax_sequence_length: int = 300chi_prompt: list[str] | None = Noneoutput_type: Literal['np', 'pil', 'pt', 'latent'] = 'np'callback_on_step_end: Callable[[DiffusionPipeline, int, int, dict], dict] | None = Nonecallback_on_step_end_tensor_inputs: list[str] = ['latents']return_dict: bool = True )

Tham số

  • image (PIL.Image.Image hoặc str) — Hình ảnh của khung đầu tiên (PIL hoặc đường dẫn).
  • prompt (str) — Prompt văn bản.
  • c2w (np.ndarray, optional) — (F, 4, 4) tư thế camera-to-world. Loại trừ lẫn nhau với action.
  • action (str, optional) — Chuỗi Action-DSL, ví dụ "w-80,jw-40,w-40". Loại trừ lẫn nhau với c2w.
  • intrinsics (np.ndarray hoặc list[float]) — [fx, fy, cx, cy] trong tọa độ pixel của ảnh gốc. Pipeline sẽ tự động áp dụng phép biến đổi resize+crop bên trong.
  • height (int, mặc định là 704) — Chiều cao khung hình đầu ra (cố định cho mô hình công khai).
  • width (int, mặc định là 1280) — Chiều rộng khung hình đầu ra (cố định cho mô hình công khai).
  • num_frames (int, mặc định là 161) — Số khung hình mục tiêu; được làm tròn đến 8k+1 (ràng buộc của VAE LTX-2).
  • fps (int, mặc định là 16) — Tốc độ khung hình đầu ra (cũng được truyền vào refiner).
  • num_inference_steps (int, mặc định là 60) — Số bước lấy mẫu DiT của giai đoạn 1.
  • guidance_scale (float, mặc định là 5.0) — Thang độ hướng dẫn không có bộ phân loại.
  • negative_prompt (str, mặc định là "") — Prompt tiêu cực tùy chọn.
  • generator (torch.Generator hoặc list[torch.Generator], tuỳ chọn) — Một hoặc nhiều bộ sinh torch để làm cho việc lấy mẫu nhiễu trở nên tất định. Nếu là None, việc lấy mẫu sẽ không tất định.
  • prompt_embeds (torch.Tensor, optional) — Các embedding văn bản đã được tính trước, dùng để bỏ qua text encoder. Phải được truyền cùng với prompt_attention_mask.
  • prompt_attention_mask (torch.Tensor, optional) — Mặt nạ chú ý cho prompt_embeds.
  • negative_prompt_embeds (torch.Tensor, optional) — Các embedding văn bản âm đã được tính trước. Phải được truyền cùng với negative_prompt_attention_mask.
  • negative_prompt_attention_mask (torch.Tensor, optional) — Mặt nạ chú ý cho negative_prompt_embeds.
  • max_sequence_length (int, mặc định là 300) — Số token tối đa của prompt.
  • chi_prompt (list[str], optional) — Ghi đè tiền tố chi-prompt (mặc định giống bản phát hành công khai).
  • output_type (“np”, “pil”, “pt”, hoặc “latent”, mặc định là “np”) — Định dạng đầu ra.
  • callback_on_step_end (Callable, optional) — Được gọi vào cuối mỗi bước khử nhiễu dưới dạng callback_on_step_end(self, step, timestep, callback_kwargs), trong đó callback_kwargs chứa các tensor được đặt tên trong callback_on_step_end_tensor_inputs. Các tensor trong dict trả về sẽ thay thế các tensor của pipeline.
  • callback_on_step_end_tensor_inputs (list[str], mặc định là [“latents”]) — Các tensor cần truyền cho callback_on_step_end; phải là một tập con của ._callback_tensor_inputs.
  • return_dict (bool, mặc định là True) — Trả về [SanaWMPipelineOutput] thay vì tuple.

Tạo video điều khiển bằng camera SANA-WM.

Ví dụ:

>>> import torch
>>> from PIL import Image
>>> from diffusers import SanaWMPipeline

>>> pipe = SanaWMPipeline.from_pretrained(
...     "Efficient-Large-Model/SANA-WM_bidirectional-diffusers", torch_dtype=torch.bfloat16
... ).to("cuda")

>>> output = pipe(
...     image=Image.open("input.png").convert("RGB"),
...     prompt="A car driving across a vast desert plain at golden hour.",
...     action="w-80,jw-40,w-40",
...     intrinsics=[800.0, 800.0, 845.0, 464.0],  # fx, fy, cx, cy in original-image pixels
...     num_inference_steps=60,
... )
>>> # output.frames is (T, H, W, 3) float np.ndarray in [0, 1] (diffusers convention).

check_inputs

< >

( c2w: np.ndarray | Noneaction: str | Noneintrinsics: np.ndarray | list[float] | Nonecallback_on_step_end_tensor_inputs: list[str] | None = None )

Kiểm tra đầu vào của __call__. Ném ngoại lệ nếu đầu vào không hợp lệ và không trả về gì.

encode_prompt

< >

( prompt: strnegative_prompt: str = ''device: torch.device | None = Nonemax_sequence_length: int = 300chi_prompt: list[str] | None = Noneprompt_embeds: torch.Tensor | None = Noneprompt_attention_mask: torch.Tensor | None = Nonenegative_prompt_embeds: torch.Tensor | None = Nonenegative_prompt_attention_mask: torch.Tensor | None = None )

Mã hóa prompt + negative prompt thông qua Gemma-2.

Giống với kỹ thuật chi-prompt-prefix của SANA: chi prompt được thêm vào trước user prompt, sau đó một lát cắt select_index = [0, -L+1, ..., -1] lấy token BOS cùng max_sequence_length - 1 token cuối.

prepare_camera_trajectory

< >

( c2w: np.ndarray | Noneaction: str | Noneintrinsics: np.ndarray | list[float]num_frames: int )

Chuẩn hóa các đầu vào camera thành (c2w_(F, 4, 4), intrinsics_(F, 4)).

Ngoài ra, num_frames cũng được làm tròn về dạng 8k+1 thân thiện với VAE và cả hai mảng đều được cắt cho khớp. Ảnh đã cắt và các thông số nội tại đã được điều chỉnh tỷ lệ sẽ được xử lý sau, khi độ phân giải đích đã được xác định.

prepare_latents

< >

( first_latent: torch.Tensornum_frames: intheight: intwidth: intdtype: torch.dtypedevice: torch.devicegenerator: torch.Generator )

Mẫu các latent ban đầu và cố định khung đầu tiên làm neo điều kiện.

Trả về (latents, condition_mask) trong đó condition_mask có giá trị 1 ở các token của khung hình đầu tiên (chúng được giữ sạch trong suốt quá trình lấy mẫu) và 0 ở các vị trí còn lại.

SanaWMLTX2Refiner

Refiner giai đoạn 2 của LTX-2 là một DiffusionPipeline độc lập, nhận latents từ giai đoạn 1. Hãy cung cấp cho nó một vae (của pipeline cơ sở, để các trọng số được chia sẻ) nhằm giải mã thành video; nếu không có, nó sẽ trả về các latents đã tinh chỉnh.

lớp diffusers.SanaWMLTX2Refiner

< >

( transformer: SanaWMLTX2RefinerTransformer3DModelconnectors: LTX2TextConnectorstokenizer: GemmaTokenizer | GemmaTokenizerFasttext_encoder: Gemma3ForConditionalGenerationscheduler: FlowMatchEulerDiscreteSchedulervae: AutoencoderKLLTX2Video | None = Nonetext_max_sequence_length: int = 1024 )

Tham số

  • transformer ([SanaWMLTX2RefinerTransformer3DModel]) — DiT video LTX-2 với bộ nhớ đệm KV trượt cửa sổ theo chunk-causal.
  • connectors ([LTX2TextConnectors]) — Bộ kết nối văn bản của LTX-2.
  • tokenizer — tokenizer của Gemma-3.
  • text_encoder — Bộ mã hóa văn bản của Gemma-3.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — Trình lập lịch Euler cho flow-matching. Được khởi tạo với shift=1.0 để các sigma đã chưng cất đi qua mà không bị thay đổi.
  • vae ([AutoencoderKLLTX2Video], optional) — Cùng một VAE được sử dụng bởi [SanaWMPipeline]; truyền vae=pipe.vae để chia sẻ trọng số. Khi được cung cấp, refiner sẽ giải mã thành video, ngược lại nó sẽ trả về các latents đã tinh chỉnh.
  • text_max_sequence_length (int, mặc định là 1024) — Số token tối đa được truyền cho bộ phân từ Gemma-3.

LTX-2 sink-bidirectional Euler refiner — SANA-WM giai đoạn 2, dưới dạng pipeline độc lập.

Bọc các thành phần của LTX-2 (refiner transformer + text connectors + text encoder Gemma-3 + tokenizer) cùng với [FlowMatchEulerDiscreteScheduler] mang theo lịch trình sigma đã chưng cất và thực hiện các bước Euler. Nó được đăng ký như một thành phần tùy chọn của [SanaWMPipeline] và cũng có thể được sử dụng độc lập để tinh chỉnh các latents của giai đoạn 1.

__call__

< >

( sana_latent: torch.Tensorprompt: strfps: floatsink_size: int = 1generator: torch.Generator | None = Noneblock_size: int = 3kv_max_frames: int = 11sigmas: tuple[float, ...] = (0.909375, 0.725, 0.421875, 0.0)output_type: str = 'np' ) → torch.Tensor

Tham số

  • sana_latent — latent giai đoạn 1, (B, C, F, H, W).
  • prompt — prompt văn bản.
  • fps — tốc độ khung hình của video (quyết định việc mở rộng theo thời gian của LTX-2 RoPE).
  • sink_size — số lượng khung z_sana thô đầu tiên được neo làm attention sink (chuẩn: 1).
  • generator — torch.Generator cho nhiễu tại điểm cuối của FM. Mặc định là một generator được khởi tạo với hạt 42 để kết quả có thể tái lập ngay từ đầu.
  • block_size — số khung latent trên mỗi khối AR (chuẩn: 3).
  • kv_max_frames — số khung context+active tối đa được giữ lại trong cửa sổ trượt (chuẩn: 11 = 1 sink + 10 gần nhất).
  • sigmas — lịch trình Euler giảm dần kết thúc tại 0.0 (3 bước chưng cất chuẩn: (0.909375, 0.725, 0.421875, 0.0)). Được truyền vào self.scheduler (không gồm 0.0 ở cuối, vì trình lập lịch sẽ tự thêm).
  • output_type — “latent” trả về các latent đã tinh chỉnh. Mọi giá trị khác sẽ được giải mã thông qua self.vae và tiền xử lý thành kiểu đó (“np”, “pt”, “pil”); nếu không có vae, các latent sẽ được trả về bất kể.

Trả về

torch.Tensor

Latent VAE đã tinh chỉnh có hình dạng (B, C, F, H, W) — sink_size khung đầu tiên giữ nguyên latent sink thô của giai đoạn 1, phần còn lại chứa đầu ra đã tinh chỉnh.

Chạy bộ tinh chỉnh LTX-2 và trả về các latents VAE đã được tinh chỉnh.

Sử dụng công thức AR chunk-causal mà mô hình được huấn luyện (block_size=3, kv_max_frames=11): một cửa sổ trượt của [source_sink + recent_history + active_block] K/V được đưa vào transformer từng khối một, nhờ đó chi phí tính toán cho mỗi khối bị giới hạn và tổng chi phí tinh chỉnh tăng tuyến tính theo độ dài video.

SanaWMPipelineOutput

lớp diffusers.SanaWMPipelineOutput

< >

( frames: typing.Union[torch.Tensor, numpy.ndarray, list[list[PIL.Image.Image]]]c2w: numpy.ndarray | None = Nonelatent: typing.Optional[torch.Tensor] = None )

Tham số

  • frames (torch.Tensor, np.ndarray, hoặc list[PIL.Image.Image]) — Video đã tạo: một np.ndarray float có hình dạng (T, H, W, 3) trong khoảng [0, 1] cho output_type="np", một tensor (T, 3, H, W) cho "pt", một danh sách gồm T `PIL.Image cho "pil", hoặc tensor latent (B, C, T_lat, H_lat, W_lat) cho "latent".
  • c2w (np.ndarray) — Các tư thế camera-to-world (T, 4, 4) được căn chỉnh với frames (refiner sẽ loại bỏ khung neo sink; mảng này được căn chỉnh lại tương ứng khi refiner đã chạy).
  • latent (torch.Tensor, optional) — Tensor ẩn trong không gian VAE của LTX-2, shape (B, C, T_lat, H_lat, W_lat). Được trả về khi `output_type=“latent”“.

Lớp đầu ra cho pipeline image-to-video của SANA-WM.

Update on GitHub