#
# 根据 Apache 许可证 2.0 版本（“许可证”）授权
# 您只能在遵守许可证的情况下使用本文件。
# 您可以在以下位置获取许可证副本
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非适用法律要求或双方书面同意，软件
# 根据许可证分发，本软件按“原样”
# 不附带任何明示或暗示的保证或条件。
# 请参阅许可证中关于权限的具体语言
# 许可证下的限制。
-->

# Mochi 1 预览

  

> [!TIP]
> 目前仅提供模型权重的研究预览版本。

[Mochi 1](https://huggingface.co/genmo/mochi-1-preview) 是由 Genmo 推出的视频生成模型，在提示词遵循度和运动质量方面表现突出。该模型采用 10B 参数的 Asmmetric Diffusion Transformer (AsymmDiT) 架构，并使用非方形 QKV 和输出投影层以降低推理时的内存需求。提示词编码由单个 T5-XXL 模型完成。

*Mochi 1 preview 是一款开源的先进视频生成模型，在初步评估中展现出高保真度的运动表现和强大的提示词遵循能力。该模型大幅缩小了闭源与开源视频生成系统之间的差距。该模型以宽松的 Apache 2.0 许可证发布。*

> [!TIP]
> 请务必参阅 [调度器指南](../../using-diffusers/schedulers)，了解如何探索调度器速度与质量之间的权衡，并查看 [跨流水线复用组件](../../using-diffusers/loading#reusing-models-in-multiple-pipelines) 部分，了解如何高效地将相同组件加载到多个流水线中。

## 量化

量化通过以较低精度的数据类型存储模型权重，有助于降低超大模型的内存需求。不过，量化对视频质量的影响会因视频模型的不同而有所差异。

请参阅 [量化](../../quantization/overview) 概述，以了解支持的量化后端以及如何选择支持您使用场景的量化后端。下面的示例演示了如何使用 bitsandbytes 加载用于推理的量化 [MochiPipeline](/docs/diffusers/v0.43.0/zh/api/pipelines/mochi#diffusers.MochiPipeline)。

```py
import torch
from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig, MochiTransformer3DModel, MochiPipeline
from diffusers.utils import export_to_video
from transformers import BitsAndBytesConfig as BitsAndBytesConfig, T5EncoderModel

quant_config = BitsAndBytesConfig(load_in_8bit=True)
text_encoder_8bit = T5EncoderModel.from_pretrained(
    "genmo/mochi-1-preview",
    subfolder="text_encoder",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True)
transformer_8bit = MochiTransformer3DModel.from_pretrained(
    "genmo/mochi-1-preview",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)

pipeline = MochiPipeline.from_pretrained(
    "genmo/mochi-1-preview",
    text_encoder=text_encoder_8bit,
    transformer=transformer_8bit,
    dtype=torch.float16,
    device_map="balanced",
)

video = pipeline(
  "Close-up of a cats eye, with the galaxy reflected in the cats eye. Ultra high resolution 4k.",
  num_inference_steps=28,
  guidance_scale=3.5
).frames[0]
export_to_video(video, "cat.mp4")
```

## 使用 Mochi-1 Preview 生成视频

以下示例将下载全精度 `mochi-1-preview` 权重，并生成最高质量的结果，但运行至少需要 42GB 的 VRAM。

```python
import torch
from diffusers import MochiPipeline
from diffusers.utils import export_to_video

pipe = MochiPipeline.from_pretrained("genmo/mochi-1-preview")

# Enable memory savings
pipe.enable_model_cpu_offload()
pipe.vae.enable_tiling()

prompt = "Close-up of a chameleon's eye, with its scaly skin changing color. Ultra high resolution 4k."

with torch.autocast("cuda", torch.bfloat16, cache_enabled=False):
      frames = pipe(prompt, num_frames=85).frames[0]

export_to_video(frames, "mochi.mp4", fps=30)
```

## 使用较低精度的变体以节省内存

以下示例将使用模型的 `bfloat16` 变体，运行需要 22GB 显存。因此，生成视频的质量会略有下降。

```python
import torch
from diffusers import MochiPipeline
from diffusers.utils import export_to_video

pipe = MochiPipeline.from_pretrained("genmo/mochi-1-preview", variant="bf16", dtype=torch.bfloat16)

# Enable memory savings
pipe.enable_model_cpu_offload()
pipe.vae.enable_tiling()

prompt = "Close-up of a chameleon's eye, with its scaly skin changing color. Ultra high resolution 4k."
frames = pipe(prompt, num_frames=85).frames[0]

export_to_video(frames, "mochi.mp4", fps=30)
```

## 复现 Genmo Mochi 仓库中的结果

[Genmo Mochi 实现](https://github.com/genmoai/mochi/tree/main)在推理过程的各个阶段使用了不同的精度值。文本编码器和 VAE 使用 `torch.float32`，而 DiT 使用 `torch.bfloat16`，并将 [attention kernel](https://pytorch.org/docs/stable/generated/torch.nn.attention.sdpa_kernel.html#torch.nn.attention.sdpa_kernel) 设置为 `EFFICIENT_ATTENTION`。Diffusers 流水线目前不支持为流水线的不同阶段设置不同的 `dtypes`。为了以与原始实现相同的方式运行推理，请参阅以下示例。

> [!TIP]
> 原始的 Mochi 实现会将空提示词置零。但是，启用此选项并将整个流水线置于 autocast 之下，可能会导致 T5 文本编码器出现数值溢出。
>
> 启用 `force_zeros_for_empty_prompt` 时，建议在完整精度下于 autocast 上下文之外执行文本编码步骤。

> [!TIP]
> 以全精度解码潜在变量会消耗大量显存。要生成本示例中的 163 帧，至少需要 70GB 的 VRAM。为了降低显存占用，您可以减少帧数，或者在 `torch.bfloat16` 下执行解码步骤。

```python
import torch
from torch.nn.attention import SDPBackend, sdpa_kernel

from diffusers import MochiPipeline
from diffusers.utils import export_to_video
from diffusers.video_processor import VideoProcessor

pipe = MochiPipeline.from_pretrained("genmo/mochi-1-preview", force_zeros_for_empty_prompt=True)
pipe.vae.enable_tiling()
pipe.enable_model_cpu_offload()

prompt =  "An aerial shot of a parade of elephants walking across the African savannah. The camera showcases the herd and the surrounding landscape."

with torch.no_grad():
    prompt_embeds, prompt_attention_mask, negative_prompt_embeds, negative_prompt_attention_mask = (
        pipe.encode_prompt(prompt=prompt)
    )

with torch.autocast("cuda", torch.bfloat16):
    with sdpa_kernel(SDPBackend.EFFICIENT_ATTENTION):
        frames = pipe(
            prompt_embeds=prompt_embeds,
            prompt_attention_mask=prompt_attention_mask,
            negative_prompt_embeds=negative_prompt_embeds,
            negative_prompt_attention_mask=negative_prompt_attention_mask,
            guidance_scale=4.5,
            num_inference_steps=64,
            height=480,
            width=848,
            num_frames=163,
            generator=torch.Generator("cuda").manual_seed(0),
            output_type="latent",
            return_dict=False,
        )[0]

video_processor = VideoProcessor(vae_scale_factor=8)
has_latents_mean = hasattr(pipe.vae.config, "latents_mean") and pipe.vae.config.latents_mean is not None
has_latents_std = hasattr(pipe.vae.config, "latents_std") and pipe.vae.config.latents_std is not None
if has_latents_mean and has_latents_std:
    latents_mean = (
        torch.tensor(pipe.vae.config.latents_mean).view(1, 12, 1, 1, 1).to(frames.device, frames.dtype)
    )
    latents_std = (
        torch.tensor(pipe.vae.config.latents_std).view(1, 12, 1, 1, 1).to(frames.device, frames.dtype)
    )
    frames = frames * latents_std / pipe.vae.config.scaling_factor + latents_mean
else:
    frames = frames / pipe.vae.config.scaling_factor

with torch.no_grad():
    video = pipe.vae.decode(frames.to(pipe.vae.dtype), return_dict=False)[0]

video = video_processor.postprocess_video(video)[0]
export_to_video(video, "mochi.mp4", fps=30)
```

## 使用多个 GPU 运行推理

可以使用 `from_pretrained` 中的 `device_map` 和 `max_memory` 选项，将大型 Mochi transformer 拆分到多个 GPU 上。在下面的示例中，我们将模型拆分到两个 GPU 上，每个 GPU 拥有 24GB 的显存。

```python
import torch
from diffusers import MochiPipeline, MochiTransformer3DModel
from diffusers.utils import export_to_video

model_id = "genmo/mochi-1-preview"
transformer = MochiTransformer3DModel.from_pretrained(
    model_id,
    subfolder="transformer",
    device_map="auto",
    max_memory={0: "24GB", 1: "24GB"}
)

pipe = MochiPipeline.from_pretrained(model_id,  transformer=transformer)
pipe.enable_model_cpu_offload()
pipe.vae.enable_tiling()

with torch.autocast(device_type="cuda", dtype=torch.bfloat16, cache_enabled=False):
    frames = pipe(
        prompt="Close-up of a chameleon's eye, with its scaly skin changing color. Ultra high resolution 4k.",
        negative_prompt="",
        height=480,
        width=848,
        num_frames=85,
        num_inference_steps=50,
        guidance_scale=4.5,
        num_videos_per_prompt=1,
        generator=torch.Generator(device="cuda").manual_seed(0),  # or "mps", "xpu", "cpu"
        max_sequence_length=256,
        output_type="pil",
    ).frames[0]

export_to_video(frames, "output.mp4", fps=30)
```

## 使用单文件加载方式配合 Mochi Transformer

您可以使用 `from_single_file` 以原始格式加载 Mochi transformer。

> [!TIP]
> Diffusers 目前不支持使用 Mochi 单文件检查点的 FP8 缩放版本。

```python
import torch
from diffusers import MochiPipeline, MochiTransformer3DModel
from diffusers.utils import export_to_video

model_id = "genmo/mochi-1-preview"

ckpt_path = "https://huggingface.co/Comfy-Org/mochi_preview_repackaged/blob/main/split_files/diffusion_models/mochi_preview_bf16.safetensors"

transformer = MochiTransformer3DModel.from_pretrained(ckpt_path, dtype=torch.bfloat16)

pipe = MochiPipeline.from_pretrained(model_id,  transformer=transformer)
pipe.enable_model_cpu_offload()
pipe.vae.enable_tiling()

with torch.autocast(device_type="cuda", dtype=torch.bfloat16, cache_enabled=False):
    frames = pipe(
        prompt="Close-up of a chameleon's eye, with its scaly skin changing color. Ultra high resolution 4k.",
        negative_prompt="",
        height=480,
        width=848,
        num_frames=85,
        num_inference_steps=50,
        guidance_scale=4.5,
        num_videos_per_prompt=1,
        generator=torch.Generator(device="cuda").manual_seed(0),  # or "mps", "xpu", "cpu"
        max_sequence_length=256,
        output_type="pil",
    ).frames[0]

export_to_video(frames, "output.mp4", fps=30)
```

## MochiPipeline[[diffusers.MochiPipeline]]

#### diffusers.MochiPipeline[[diffusers.MochiPipeline]]

```python
diffusers.MochiPipeline(scheduler: FlowMatchEulerDiscreteScheduler, vae: AutoencoderKLMochi, text_encoder: T5EncoderModel, tokenizer: T5Tokenizer, transformer: MochiTransformer3DModel, force_zeros_for_empty_prompt: bool = False)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/mochi/pipeline_mochi.py#L138)

**参数：**

transformer ([MochiTransformer3DModel](/docs/diffusers/v0.43.0/zh/api/models/mochi_transformer3d#diffusers.MochiTransformer3DModel))：用于对编码后的视频潜变量进行去噪的条件 Transformer 架构。

scheduler ([FlowMatchEulerDiscreteScheduler](/docs/diffusers/v0.43.0/zh/api/schedulers/flow_match_euler_discrete#diffusers.FlowMatchEulerDiscreteScheduler))：用于与 `transformer` 配合，对编码后的图像潜变量进行去噪的调度器。

vae ([AutoencoderKLMochi](/docs/diffusers/v0.43.0/zh/api/models/autoencoderkl_mochi#diffusers.AutoencoderKLMochi))：变分自编码器（VAE）模型，用于将视频编码为潜在表示，以及从潜在表示解码为视频。

text_encoder (`T5EncoderModel`)：即 [T5](https://huggingface.co/docs/transformers/en/model_doc/t5#transformers.T5EncoderModel)，具体为 [google/t5-v1_1-xxl](https://huggingface.co/google/t5-v1_1-xxl) 变体。

tokenizer (`CLIPTokenizer`)：[CLIPTokenizer](https://huggingface.co/docs/transformers/en/model_doc/clip#transformers.CLIPTokenizer) 类的分词器。

tokenizer (`T5TokenizerFast`)：第二个 [T5TokenizerFast](https://huggingface.co/docs/transformers/en/model_doc/t5#transformers.T5TokenizerFast) 类的 Tokenizer。

用于文本到视频生成的 mochi 流水线。

参考：https://github.com/genmoai/models

#### __调用__[[diffusers.MochiPipeline.__call__]]

```python
__call__(prompt: str | list[str] = None, negative_prompt: str | list[str] | None = None, height: int | None = None, width: int | None = None, num_frames: int = 19, num_inference_steps: int = 64, timesteps: list[int] = None, guidance_scale: float = 4.5, num_videos_per_prompt: int | None = 1, generator: typing.Union[torch.Generator, list[torch.Generator], NoneType] = None, latents: typing.Optional[torch.Tensor] = None, prompt_embeds: typing.Optional[torch.Tensor] = None, prompt_attention_mask: typing.Optional[torch.Tensor] = None, negative_prompt_embeds: typing.Optional[torch.Tensor] = None, negative_prompt_attention_mask: typing.Optional[torch.Tensor] = None, output_type: str | None = 'pil', return_dict: bool = True, attention_kwargs: dict[str, typing.Any] | None = None, callback_on_step_end: typing.Optional[typing.Callable[[int, int], NoneType]] = None, callback_on_step_end_tensor_inputs: list[str] = ['latents'], max_sequence_length: int = 256)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/mochi/pipeline_mochi.py#L444)

**参数：**

prompt (`str` 或 `list[str]`，*可选*)：用于引导图像生成的提示词或提示词列表。如果未定义，则必须改为传入 `prompt_embeds`。

negative_prompt (`str` 或 `list[str]`，*可选*)：用于引导图像生成的负面提示词。如果未定义，则必须传入 `negative_prompt_embeds`。在未使用引导（`guidance_scale < 1`）时将被忽略。

height (`int`，*可选*，默认为 `self.default_height`)：生成图像的高度（以像素为单位）。默认设置为 480，以获得最佳效果。

width (`int`，*可选*，默认为 `self.default_width`)：生成图像的宽度（以像素为单位）。默认设置为 848，以获得最佳效果。

num_frames (`int`，默认为 `19`)：要生成的视频帧数

num_inference_steps (`int`, *可选*，默认为 50)：去噪步数。更多的去噪步数通常能带来更高质量的图像，但代价是推理速度变慢。

timesteps (`list[int]`，*可选*)：用于在支持 `set_timesteps` 方法中 `timesteps` 参数的调度器中，指定去噪过程所使用的自定义时间步。如果未定义，则使用传入 `num_inference_steps` 时的默认行为。必须按降序排列。

guidance_scale (`float`，默认值为 `4.5`) : 如 [Classifier-Free Diffusion Guidance](https://huggingface.co/papers/2207.12598) 中定义的引导尺度。`guidance_scale` 定义为 [Imagen Paper](https://huggingface.co/papers/2205.11487) 中公式 2 的 `w`。通过设置 `guidance_scale > 1` 来启用引导尺度。较高的引导尺度会促使生成与文本 `prompt` 紧密关联的图像，但通常以牺牲图像质量为代价。

num_videos_per_prompt (`int`，*可选*，默认为 1)：每个提示词生成的视频数量。

generator (`torch.Generator` 或 `list[torch.Generator]`，*可选*)：一个或一组 [torch 生成器](https://pytorch.org/docs/stable/generated/torch.Generator.html)，用于使生成过程具有确定性。

latents (`torch.Tensor`, *可选*) : 预先生成的噪声潜变量，从高斯分布中采样得到，用作图像生成的输入。可用于使用不同的提示词对同一生成过程进行微调。如果未提供，将通过使用提供的随机`generator`进行采样来生成潜变量张量。

prompt_embeds (`torch.Tensor`, *可选*) : 预生成的文本嵌入。可用于轻松调整文本输入，*例如* 提示词加权。如果未提供，文本嵌入将从 `prompt` 输入参数生成。

prompt_attention_mask (`torch.Tensor`, *可选*) : 为文本嵌入预生成的注意力掩码。

negative_prompt_embeds (`torch.FloatTensor`, *可选*) : 预生成的负向文本嵌入。对于 PixArt-Sigma，此负向提示应为 ""。如果未提供，negative_prompt_embeds 将根据 `negative_prompt` 输入参数生成。

negative_prompt_attention_mask (`torch.FloatTensor`, *可选*) : 为负文本嵌入预生成的注意力掩码。

output_type (`str`，*可选*，默认为 `"pil"`)：生成图像的输出格式。可选 [PIL](https://pillow.readthedocs.io/en/stable/)：`PIL.Image.Image` 或 `np.array`。

return_dict (`bool`，*可选*，默认为 `True`)：是否返回 `~pipelines.mochi.MochiPipelineOutput` 而不是普通元组。

attention_kwargs (`dict`, *可选*) : 一个 kwargs 字典，如果指定，将作为参数传递给 [diffusers.models.attention_processor](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py) 中 `self.processor` 下定义的 `AttentionProcessor`。

callback_on_step_end (`Callable`，*可选*)：一个在推理过程中每个去噪步骤结束时调用的函数。该函数以以下参数被调用：`callback_on_step_end(self: DiffusionPipeline, step: int, timestep: int, callback_kwargs: Dict)`。`callback_kwargs` 将包含由 `callback_on_step_end_tensor_inputs` 指定的所有张量列表。

callback_on_step_end_tensor_inputs (`list`，*可选*)：`callback_on_step_end` 函数的张量输入列表。列表中指定的张量将作为 `callback_kwargs` 参数传递。您只能包含流水线类的 `._callback_tensor_inputs` 属性中列出的变量。

max_sequence_length (`int` 默认为 `256`)：与 `prompt` 一起使用的最大序列长度。

**返回：** `~pipelines.mochi.MochiPipelineOutput` 或 `tuple`

如果 `return_dict` 为 `True`，则返回 `~pipelines.mochi.MochiPipelineOutput`，否则返回一个 `tuple`，其中第一个元素是包含生成图像的列表。

调用生成 pipeline 时调用的函数。

示例：
```py
>>> import torch
>>> from diffusers import MochiPipeline
>>> from diffusers.utils import export_to_video

>>> pipe = MochiPipeline.from_pretrained("genmo/mochi-1-preview", torch_dtype=torch.bfloat16)
>>> pipe.enable_model_cpu_offload()
>>> pipe.vae.enable_tiling()
>>> prompt = "Close-up of a chameleon's eye, with its scaly skin changing color. Ultra high resolution 4k."
>>> frames = pipe(prompt, num_inference_steps=28, guidance_scale=3.5).frames[0]
>>> export_to_video(frames, "mochi.mp4")
```

#### encode_prompt[[diffusers.MochiPipeline.encode_prompt]]

```python
encode_prompt(prompt: str | list[str], negative_prompt: str | list[str] | None = None, do_classifier_free_guidance: bool = True, num_videos_per_prompt: int = 1, prompt_embeds: typing.Optional[torch.Tensor] = None, negative_prompt_embeds: typing.Optional[torch.Tensor] = None, prompt_attention_mask: typing.Optional[torch.Tensor] = None, negative_prompt_attention_mask: typing.Optional[torch.Tensor] = None, max_sequence_length: int = 256, device: typing.Optional[torch.device] = None, dtype: typing.Optional[torch.dtype] = None)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/mochi/pipeline_mochi.py#L254)

**参数：**

prompt (`str` 或 `list[str]`，*可选*)：要编码的提示

negative_prompt (`str` 或 `list[str]`，*可选*)：用于引导图像生成的负面提示词。如果未定义，则必须传入 `negative_prompt_embeds`。当不使用引导时（即 `guidance_scale` 小于 `1` 时），此参数将被忽略。

do_classifier_free_guidance (`bool`，*可选*，默认为 `True`)：是否使用无分类器引导。

num_videos_per_prompt (`int`，*可选*，默认为 1)：每个提示词应生成的视频数量。用于放置结果嵌入的 torch 设备

prompt_embeds (`torch.Tensor`, *可选*) : 预生成的文本嵌入。可用于轻松调整文本输入，*例如* 提示词加权。如果未提供，文本嵌入将从 `prompt` 输入参数生成。

negative_prompt_embeds (`torch.Tensor`, *可选*) : 预生成的负向文本嵌入。可用于轻松调整文本输入，*例如* 提示词权重。如果未提供，negative_prompt_embeds 将从 `negative_prompt` 输入参数生成。

device : (`torch.device`, *可选*): torch 设备

dtype : (`torch.dtype`, *可选*): torch 数据类型

将提示词编码为文本编码器的隐藏状态。

## MochiPipelineOutput[[diffusers.pipelines.mochi.pipeline_output.MochiPipelineOutput]]

#### diffusers.pipelines.mochi.pipeline_output.MochiPipelineOutput[[diffusers.pipelines.mochi.pipeline_output.MochiPipelineOutput]]

```python
diffusers.pipelines.mochi.pipeline_output.MochiPipelineOutput(frames: Tensor)
```

[源代码](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/pipelines/mochi/pipeline_output.py#L9)

**参数：**

frames (`torch.Tensor`、`np.ndarray` 或 list[list[PIL.Image.Image]]) : 视频输出列表 - 它可以是一个长度为 `batch_size,` 的嵌套列表，其中每个子列表包含长度为 `num_frames.` 的去噪 PIL 图像序列。它也可以是一个形状为 `(batch_size, num_frames, channels, height, width)` 的 NumPy 数组或 Torch 张量。

Mochi 管道的输出类。

