---
title: reason1
---

<div class="python-reference">
<a id="fastvideo.models.encoders.reason1-classes"></a>
<a id="fastvideo.models.encoders.reason1-functions"></a>
<a id="fastvideo.models.encoders.reason1.Reason1TextEncoder-functions"></a>
<a id="fastvideo.models.encoders.reason1"></a>
<p>Reason1 (Qwen2.5-VL) text encoder.</p>
<h2 id="fastvideo.models.encoders.reason1.BaseEncoderOutput"><code>fastvideo.models.encoders.reason1.BaseEncoderOutput</code></h2>
<pre class="doc-signature"><code>BaseEncoderOutput(last_hidden_state: torch.FloatTensor | None = None, pooler_output: torch.FloatTensor | None = None, hidden_states: tuple&#91;torch.FloatTensor, ...&#93; | None = None, attentions: tuple&#91;torch.FloatTensor, ...&#93; | None = None, attention_mask: torch.Tensor | None = None)</code></pre>


<h2 id="fastvideo.models.encoders.reason1.Reason1Config"><code>fastvideo.models.encoders.reason1.Reason1Config</code></h2>
<pre class="doc-signature"><code>Reason1Config(arch_config: Reason1ArchConfig = Reason1ArchConfig(), prefix: str = &#x27;&#x27;, quant_config: QuantizationConfig | None = None, lora_config: Any | None = None, is_chat_model: bool = False, treat_empty_as_dot: bool = False, tokenizer_type: str = &#x27;Qwen/Qwen2.5-VL-7B-Instruct&#x27;, *, _resolved_attention_backend: AttentionBackendEnum | None = None, chat_template_enable_thinking: bool = False)</code></pre>
<p>Reason1 text encoder config.</p>

<h2 id="fastvideo.models.encoders.reason1.init_logger"><code>fastvideo.models.encoders.reason1.init_logger</code></h2>
<pre class="doc-signature"><code>init_logger(name: str) -&gt; _FastvideoLogger</code></pre>
<p>The main purpose of this function is to ensure that loggers are
retrieved in such a way that we can be sure the root fastvideo logger has
already been configured.</p>
<h2 id="fastvideo.models.encoders.reason1.TextEncoder"><code>fastvideo.models.encoders.reason1.TextEncoder</code></h2>
<pre class="doc-signature"><code>TextEncoder(config: TextEncoderConfig)</code></pre>
<p>Base for native encoders with a model-specific forward output contract.</p>

<h3 id="fastvideo.models.encoders.reason1.TextEncoder.forward"><code>fastvideo.models.encoders.reason1.TextEncoder.forward</code></h3>
<pre class="doc-signature"><code>forward(*args: Any, **kwargs: Any) -&gt; TextEncoderOutputT</code></pre>

<h2 id="fastvideo.models.encoders.reason1.default_weight_loader"><code>fastvideo.models.encoders.reason1.default_weight_loader</code></h2>
<pre class="doc-signature"><code>default_weight_loader(param: torch.Tensor, loaded_weight: torch.Tensor) -&gt; None</code></pre>
<p>Default weight loader.</p>
<h2 id="fastvideo.models.encoders.reason1.AttentionBackendEnum"><code>fastvideo.models.encoders.reason1.AttentionBackendEnum</code></h2>
<pre class="doc-signature"><code>AttentionBackendEnum()</code></pre>

<h2 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple</code></h2>
<pre class="doc-signature"><code>Qwen2_5_VLForConditionalGenerationSimple(config)</code></pre>


<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.init_weights"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.init_weights</code></h3>
<pre class="doc-signature"><code>init_weights(buffer_device: Optional&#91;torch.device&#93; = None)</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.can_generate"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.can_generate</code></h3>
<pre class="doc-signature"><code>can_generate()</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_input_embeddings"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_input_embeddings</code></h3>
<pre class="doc-signature"><code>get_input_embeddings()</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.set_input_embeddings"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.set_input_embeddings</code></h3>
<pre class="doc-signature"><code>set_input_embeddings(value)</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_output_embeddings"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_output_embeddings</code></h3>
<pre class="doc-signature"><code>get_output_embeddings()</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.set_output_embeddings"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.set_output_embeddings</code></h3>
<pre class="doc-signature"><code>set_output_embeddings(new_embeddings)</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.set_decoder"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.set_decoder</code></h3>
<pre class="doc-signature"><code>set_decoder(decoder)</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_decoder"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_decoder</code></h3>
<pre class="doc-signature"><code>get_decoder()</code></pre>

<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_rope_index"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.get_rope_index</code></h3>
<pre class="doc-signature"><code>get_rope_index(input_ids: Optional&#91;torch.LongTensor&#93; = None, image_grid_thw: Optional&#91;torch.LongTensor&#93; = None, video_grid_thw: Optional&#91;torch.LongTensor&#93; = None, second_per_grid_ts: Optional&#91;torch.Tensor&#93; = None, attention_mask: Optional&#91;torch.Tensor&#93; = None) -&gt; Tuple&#91;torch.Tensor, torch.Tensor&#93;</code></pre>
<p>Calculate the 3D rope index based on image and video's temporal, height and width in LLM.</p>
<h4>Explanation</h4>
<p>Each embedding sequence contains vision embedding and text embedding or just contains text embedding.</p>
<p>For pure text embedding sequence, the rotary position embedding has no difference with modern LLMs.
Examples:
    input_ids: [T T T T T], here T is for text.
    temporal position_ids: [0, 1, 2, 3, 4]
    height position_ids: [0, 1, 2, 3, 4]
    width position_ids: [0, 1, 2, 3, 4]</p>
<p>For vision and text embedding sequence, we calculate 3D rotary position embedding for vision part
and 1D rotary position embeddin for text part.
Examples:
    Temporal (Time): 3 patches, representing different segments of the video in time.
    Height: 2 patches, dividing each frame vertically.
    Width: 2 patches, dividing each frame horizontally.
    We also have some important parameters:
    fps (Frames Per Second): The video's frame rate, set to 1. This means one frame is processed each second.
    tokens_per_second: This is a crucial parameter. It dictates how many "time-steps" or "temporal tokens" are conceptually packed into a one-second interval of the video. In this case, we have 25 tokens per second. So each second of the video will be represented with 25 separate time points. It essentially defines the temporal granularity.
    temporal_patch_size: The number of frames that compose one temporal patch. Here, it's 2 frames.
    interval: The step size for the temporal position IDs, calculated as tokens_per_second * temporal_patch_size / fps. In this case, 25 * 2 / 1 = 50. This means that each temporal patch will be have a difference of 50 in the temporal position IDs.
    input_ids: [V V V V V V V V V V V V T T T T T], here V is for vision.
    vision temporal position_ids: [0, 0, 0, 0, 50, 50, 50, 50, 100, 100, 100, 100]
    vision height position_ids: [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1]
    vision width position_ids: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
    text temporal position_ids: [101, 102, 103, 104, 105]
    text height position_ids: [101, 102, 103, 104, 105]
    text width position_ids: [101, 102, 103, 104, 105]
    Here we calculate the text start position_ids as the max vision position_ids plus 1.</p>
<h4>Parameters</h4>
<dl>
<dt><code>input_ids: `torch.LongTensor` of shape `(batch_size, sequence_length)`</code></dt><dd><p>Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
it.</p></dd>
<dt><code>image_grid_thw: `torch.LongTensor` of shape `(num_images, 3)`, *optional*</code></dt><dd><p>The temporal, height and width of feature shape of each image in LLM.</p></dd>
<dt><code>video_grid_thw: `torch.LongTensor` of shape `(num_videos, 3)`, *optional*</code></dt><dd><p>The temporal, height and width of feature shape of each video in LLM.</p></dd>
<dt><code>second_per_grid_ts: `torch.Tensor` of shape `(num_videos)`, *optional*</code></dt><dd><p>The time interval (in seconds) for each grid along the temporal dimension in the 3D position IDs.</p></dd>
<dt><code>attention_mask: `torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*</code></dt><dd><p>Mask to avoid performing attention on padding token indices. Mask values selected in <code>[0, 1]</code>:</p>
<ul>
<li>1 for tokens that are <strong>not masked</strong>,</li>
<li>0 for tokens that are <strong>masked</strong>.</li>
</ul></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>position_ids (<code>torch.LongTensor</code> of shape <code>(3, batch_size, sequence_length)</code>)</p></dd>
<dt><code>torch.Tensor</code></dt><dd><p>mrope_position_deltas (<code>torch.Tensor</code> of shape <code>(batch_size)</code>)</p></dd>
</dl>
<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.forward"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.forward</code></h3>
<pre class="doc-signature"><code>forward(input_ids: torch.LongTensor = None, attention_mask: Optional&#91;torch.Tensor&#93; = None, position_ids: Optional&#91;torch.LongTensor&#93; = None, past_key_values: Optional&#91;List&#91;torch.FloatTensor&#93;&#93; = None, inputs_embeds: Optional&#91;torch.FloatTensor&#93; = None, labels: Optional&#91;torch.LongTensor&#93; = None, use_cache: Optional&#91;bool&#93; = None, output_attentions: Optional&#91;bool&#93; = None, output_hidden_states: Optional&#91;bool&#93; = None, return_dict: Optional&#91;bool&#93; = None, pixel_values: Optional&#91;torch.Tensor&#93; = None, pixel_values_videos: Optional&#91;torch.FloatTensor&#93; = None, image_grid_thw: Optional&#91;torch.LongTensor&#93; = None, video_grid_thw: Optional&#91;torch.LongTensor&#93; = None, rope_deltas: Optional&#91;torch.LongTensor&#93; = None, cache_position: Optional&#91;torch.LongTensor&#93; = None, second_per_grid_ts: Optional&#91;torch.Tensor&#93; = None) -&gt; Union&#91;Tuple, Qwen2_5_VLCausalLMOutputWithPast&#93;</code></pre>
<h4>Parameters</h4>
<dl>
<dt><code>labels: `torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*</code></dt><dd><p>Labels for computing the masked language modeling loss. Indices should either be in <code>[0, ...,
config.vocab_size]</code> or -100 (see <code>input_ids</code> docstring). Tokens with indices set to <code>-100</code> are ignored
(masked), the loss is only computed for the tokens with labels in <code>[0, ..., config.vocab_size]</code>.</p></dd>
</dl>
<p>Returns:</p>
<p>Example:</p>
<pre><code class="language-python">&gt;&gt;&gt; from PIL import Image
&gt;&gt;&gt; import requests
&gt;&gt;&gt; from transformers import AutoProcessor, Qwen2_5_VLForConditionalGeneration

&gt;&gt;&gt; model = Qwen2_5_VLForConditionalGeneration.from_pretrained(&quot;Qwen/Qwen2.5-VL-7B-Instruct&quot;)
&gt;&gt;&gt; processor = AutoProcessor.from_pretrained(&quot;Qwen/Qwen2.5-VL-7B-Instruct&quot;)

&gt;&gt;&gt; messages = [
    &#123;
        &quot;role&quot;: &quot;user&quot;,
        &quot;content&quot;: [
            &#123;&quot;type&quot;: &quot;image&quot;&#125;,
            &#123;&quot;type&quot;: &quot;text&quot;, &quot;text&quot;: &quot;What is shown in this image?&quot;&#125;,
        ],
    &#125;,
]
&gt;&gt;&gt; url = &quot;https://www.ilankelman.org/stopsigns/australia.jpg&quot;
&gt;&gt;&gt; image = Image.open(requests.get(url, stream=True).raw)

&gt;&gt;&gt; text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
&gt;&gt;&gt; inputs = processor(text=[text], images=[image], vision_infos=[vision_infos])

&gt;&gt;&gt; # Generate
&gt;&gt;&gt; generate_ids = model.generate(inputs.input_ids, max_length=30)
&gt;&gt;&gt; tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
&quot;The image shows a street scene with a red stop sign in the foreground. In the background, there is a large red gate with Chinese characters ...&quot;
</code></pre>
<h3 id="fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.prepare_inputs_for_generation"><code>fastvideo.models.encoders.reason1.Qwen2_5_VLForConditionalGenerationSimple.prepare_inputs_for_generation</code></h3>
<pre class="doc-signature"><code>prepare_inputs_for_generation(input_ids, past_key_values = None, attention_mask = None, inputs_embeds = None, cache_position = None, position_ids = None, use_cache = True, pixel_values = None, pixel_values_videos = None, image_grid_thw = None, video_grid_thw = None, second_per_grid_ts = None, **kwargs)</code></pre>

<h2 id="fastvideo.models.encoders.reason1.get_rope_index"><code>fastvideo.models.encoders.reason1.get_rope_index</code></h2>
<pre class="doc-signature"><code>get_rope_index(model_config, input_ids: Optional&#91;torch.LongTensor&#93; = None, image_grid_thw: Optional&#91;torch.LongTensor&#93; = None, video_grid_thw: Optional&#91;torch.LongTensor&#93; = None, second_per_grid_ts: Optional&#91;torch.Tensor&#93; = None, attention_mask: Optional&#91;torch.Tensor&#93; = None) -&gt; Tuple&#91;torch.Tensor, torch.Tensor&#93;</code></pre>
<p>Calculate the 3D rope index based on image and video's temporal, height and width in LLM.</p>
<h3>Explanation</h3>
<p>Each embedding sequence contains vision embedding and text embedding or just contains text embedding.</p>
<p>For pure text embedding sequence, the rotary position embedding has no difference with modern LLMs.
Examples:
    input_ids: [T T T T T], here T is for text.
    temporal position_ids: [0, 1, 2, 3, 4]
    height position_ids: [0, 1, 2, 3, 4]
    width position_ids: [0, 1, 2, 3, 4]</p>
<p>For vision and text embedding sequence, we calculate 3D rotary position embedding for vision part
and 1D rotary position embeddin for text part.
Examples:
    Temporal (Time): 3 patches, representing different segments of the video in time.
    Height: 2 patches, dividing each frame vertically.
    Width: 2 patches, dividing each frame horizontally.
    We also have some important parameters:
    fps (Frames Per Second): The video's frame rate, set to 1. This means one frame is processed each second.
    tokens_per_second: This is a crucial parameter. It dictates how many "time-steps" or "temporal tokens" are conceptually packed into a one-second interval of the video. In this case, we have 25 tokens per second. So each second of the video will be represented with 25 separate time points. It essentially defines the temporal granularity.
    temporal_patch_size: The number of frames that compose one temporal patch. Here, it's 2 frames.
    interval: The step size for the temporal position IDs, calculated as tokens_per_second * temporal_patch_size / fps. In this case, 25 * 2 / 1 = 50. This means that each temporal patch will be have a difference of 50 in the temporal position IDs.
    input_ids: [V V V V V V V V V V V V T T T T T], here V is for vision.
    vision temporal position_ids: [0, 0, 0, 0, 50, 50, 50, 50, 100, 100, 100, 100]
    vision height position_ids: [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1]
    vision width position_ids: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
    text temporal position_ids: [101, 102, 103, 104, 105]
    text height position_ids: [101, 102, 103, 104, 105]
    text width position_ids: [101, 102, 103, 104, 105]
    Here we calculate the text start position_ids as the max vision position_ids plus 1.</p>
<h3>Parameters</h3>
<dl>
<dt><code>input_ids: `torch.LongTensor` of shape `(batch_size, sequence_length)`</code></dt><dd><p>Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
it.</p></dd>
<dt><code>image_grid_thw: `torch.LongTensor` of shape `(num_images, 3)`, *optional*</code></dt><dd><p>The temporal, height and width of feature shape of each image in LLM.</p></dd>
<dt><code>video_grid_thw: `torch.LongTensor` of shape `(num_videos, 3)`, *optional*</code></dt><dd><p>The temporal, height and width of feature shape of each video in LLM.</p></dd>
<dt><code>second_per_grid_ts: `torch.Tensor` of shape `(num_videos)`, *optional*</code></dt><dd><p>The time interval (in seconds) for each grid along the temporal dimension in the 3D position IDs.</p></dd>
<dt><code>attention_mask: `torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*</code></dt><dd><p>Mask to avoid performing attention on padding token indices. Mask values selected in <code>[0, 1]</code>:</p>
<ul>
<li>1 for tokens that are <strong>not masked</strong>,</li>
<li>0 for tokens that are <strong>masked</strong>.</li>
</ul></dd>
</dl>
<h3>Returns</h3>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>position_ids (<code>torch.LongTensor</code> of shape <code>(3, batch_size, sequence_length)</code>)</p></dd>
<dt><code>torch.Tensor</code></dt><dd><p>mrope_position_deltas (<code>torch.Tensor</code> of shape <code>(batch_size)</code>)</p></dd>
</dl>
<h2 id="fastvideo.models.encoders.reason1.Reason1TextEncoder"><code>fastvideo.models.encoders.reason1.Reason1TextEncoder</code></h2>
<pre class="doc-signature"><code>Reason1TextEncoder(config: Reason1Config, prefix: str = &#x27;&#x27;, checkpoint_path: str | None = None)</code></pre>
<p>Reason1 (Qwen2.5-VL) text encoder.</p>

<details><summary>Source</summary><pre><code>class Reason1TextEncoder(TextEncoder):
    &quot;&quot;&quot;Reason1 (Qwen2.5-VL) text encoder.&quot;&quot;&quot;

    _supported_attention_backends: tuple&#91;AttentionBackendEnum, ...&#93; = (
        AttentionBackendEnum.FLASH_ATTN,
        AttentionBackendEnum.TORCH_SDPA,
    )

    def __init__(self, config: Reason1Config, prefix: str = &quot;&quot;, checkpoint_path: str | None = None):
        super().__init__(config)

        self.prefix = prefix
        self.quant_config = None  # For future quantization support

        self.embedding_concat_strategy = config.arch_config.embedding_concat_strategy
        self.n_layers_per_group = config.arch_config.n_layers_per_group
        self.num_embedding_padding_tokens = config.arch_config.num_embedding_padding_tokens

        config_path = checkpoint_path if checkpoint_path else config.tokenizer_type

        logger.info(&quot;Initializing Reason1TextEncoder (Qwen2.5-VL) from %s&quot;, config_path)
        try:
            from transformers import AutoConfig as HFAutoConfig
            hf_config = HFAutoConfig.from_pretrained(
                config_path,
                trust_remote_code=True,
            )
        except Exception as e:
            logger.warning(&quot;Failed to load HF config from %s (%s). Using default Qwen2.5-VL-7B config.&quot;, config_path, e)
            hf_config = Qwen2_5_VLConfig(
                hidden_size=3584,
                intermediate_size=18944,
                max_window_layers=28,
                num_attention_heads=28,
                num_hidden_layers=28,
                num_key_value_heads=4,
                tie_word_embeddings=False,
                vocab_size=152064,
            )

        hf_config.output_hidden_states = True

        if hasattr(config.arch_config, &#x27;_attn_implementation&#x27;) and config.arch_config._attn_implementation:
            hf_config._attn_implementation = config.arch_config._attn_implementation
        else:
            hf_config._attn_implementation = &quot;flash_attention_2&quot;
        logger.info(&quot;Reason1 attention implementation: %s&quot;, getattr(hf_config, &quot;_attn_implementation&quot;, None))

        with torch.device(&quot;meta&quot;):
            self.model = Qwen2_5_VLForConditionalGenerationSimple(hf_config)

        self.processor = AutoProcessor.from_pretrained(
            config_path,
            trust_remote_code=True,
        )

        weights_override = envs.FASTVIDEO_REASON1_WEIGHTS_PATH.get()
        if weights_override:
            self.secondary_weights = (_WeightsSource(
                model_or_path=weights_override,
                prefix=&quot;&quot;,
                fall_back_to_pt=True,
                allow_patterns_overrides=None,
            ), )
            logger.info(&quot;Reason1TextEncoder: overlaying weights from %s&quot;, weights_override)

        self._weights_loaded = False

    def forward(
        self,
        input_ids: torch.Tensor | None,
        position_ids: torch.Tensor | None = None,
        attention_mask: torch.Tensor | None = None,
        inputs_embeds: torch.Tensor | None = None,
        output_hidden_states: bool | None = None,
        **kwargs,
    ) -&gt; BaseEncoderOutput:
        # Cosmos2.5 alignment: keep attention_mask=None.
        outputs = self.model(
            input_ids=input_ids,
            attention_mask=None,
            position_ids=position_ids,
            inputs_embeds=inputs_embeds,
            output_hidden_states=True,
            return_dict=True,
            pixel_values=kwargs.get(&#x27;pixel_values&#x27;, None),
            pixel_values_videos=kwargs.get(&#x27;pixel_values_videos&#x27;, None),
            image_grid_thw=kwargs.get(&#x27;image_grid_thw&#x27;, None),
            video_grid_thw=kwargs.get(&#x27;video_grid_thw&#x27;, None),
        )

        hidden_states = outputs.hidden_states
        last_hidden_state = hidden_states&#91;-1&#93;

        return BaseEncoderOutput(
            last_hidden_state=last_hidden_state,
            hidden_states=hidden_states if output_hidden_states else None,
            attention_mask=None,
        )

    def load_weights(self, weights: Iterable&#91;tuple&#91;str, torch.Tensor&#93;&#93;) -&gt; set&#91;str&#93;:
        first_weight = None
        weights_list = &#91;&#93;
        for name, weight in weights:
            if first_weight is None:
                first_weight = weight
                self.model = self.model.to_empty(device=weight.device)
                self.model.init_weights(buffer_device=weight.device)
            weights_list.append((name, weight))

        params_dict = dict(self.model.named_parameters())
        loaded_params: set&#91;str&#93; = set()
        skipped_weights = &#123;&quot;lm_head&quot;: 0, &quot;visual&quot;: 0, &quot;decoder&quot;: 0&#125;

        for name, loaded_weight in weights_list:
            if &quot;lm_head&quot; in name:
                skipped_weights&#91;&quot;lm_head&quot;&#93; += 1
                continue
            if &quot;visual&quot; in name:
                skipped_weights&#91;&quot;visual&quot;&#93; += 1
                continue
            if &quot;decoder&quot; in name:
                skipped_weights&#91;&quot;decoder&quot;&#93; += 1
                continue

            # Handle stacked params mapping (for quantized models)
            for param_name, weight_name, shard_id in self.config.arch_config.stacked_params_mapping:
                if weight_name not in name:
                    continue
                name = name.replace(weight_name, param_name)
                if name.endswith(&quot;.bias&quot;) and name not in params_dict:
                    continue

                if name not in params_dict:
                    continue

                param = params_dict&#91;name&#93;
                weight_loader = param.weight_loader
                weight_loader(param, loaded_weight, shard_id)
                param_name_with_prefix = f&quot;model.&#123;name&#125;&quot; if self.prefix == &quot;&quot; else f&quot;&#123;self.prefix&#125;.&#123;name&#125;&quot;
                loaded_params.add(param_name_with_prefix)
                break
            else:
                if name.endswith(&quot;.bias&quot;) and name not in params_dict:
                    continue

                if name not in params_dict:
                    continue

                param = params_dict&#91;name&#93;
                weight_loader = getattr(param, &quot;weight_loader&quot;, default_weight_loader)
                weight_loader(param, loaded_weight)
                param_name_with_prefix = f&quot;model.&#123;name&#125;&quot; if self.prefix == &quot;&quot; else f&quot;&#123;self.prefix&#125;.&#123;name&#125;&quot;
                loaded_params.add(param_name_with_prefix)
        if first_weight is not None:
            self.model = self.model.to(first_weight.device)

        all_params = set(f&quot;model.&#123;name&#125;&quot; if self.prefix == &quot;&quot; else f&quot;&#123;self.prefix&#125;.&#123;name&#125;&quot;
                         for name in params_dict.keys())
        loaded_params.update(all_params)

        # Mark weights as loaded
        self._weights_loaded = True
        return loaded_params

    def compute_text_embeddings_online(
        self,
        data_batch: dict&#91;str, list&#91;str&#93;&#93;,
        input_caption_key: str,
    ) -&gt; torch.Tensor:
        prompts = data_batch&#91;input_caption_key&#93;
        return self.compute_text_embeddings(prompts)

    def compute_text_embeddings(
        self,
        prompts: list&#91;str&#93;,
        device: str | torch.device = &quot;cuda&quot;,
    ) -&gt; torch.Tensor:
        &quot;&quot;&quot;Compute embeddings for a list of prompts.&quot;&quot;&quot;
        input_ids_batch = &#91;&#93;

        tok = getattr(self.processor, &quot;tokenizer&quot;, None)
        if tok is None:
            raise RuntimeError(&quot;Reason1TextEncoder requires processor.tokenizer&quot;)
        pad_id = getattr(tok, &quot;pad_id&quot;, None)
        if pad_id is None:
            pad_id = getattr(tok, &quot;pad_token_id&quot;, None)
        if pad_id is None:
            pad_id = getattr(self.model.config, &quot;pad_token_id&quot;, None)
        if pad_id is None:
            pad_id = 0

        for prompt in prompts:
            conversations = &#91;
                &#123;
                    &quot;role&quot;:
                    &quot;system&quot;,
                    &quot;content&quot;: &#91;&#123;
                        &quot;type&quot;: &quot;text&quot;,
                        &quot;text&quot;: &quot;You are a helpful assistant who will provide prompts to an image generator.&quot;,
                    &#125;&#93;,
                &#125;,
                &#123;
                    &quot;role&quot;: &quot;user&quot;,
                    &quot;content&quot;: &#91;&#123;
                        &quot;type&quot;: &quot;text&quot;,
                        &quot;text&quot;: prompt,
                    &#125;&#93;,
                &#125;,
            &#93;

            try:
                tokenizer_output = tok.apply_chat_template(
                    conversations,
                    tokenize=True,
                    add_generation_prompt=False,
                    add_vision_id=False,
                )
            except TypeError:
                tokenizer_output = tok.apply_chat_template(
                    conversations,
                    tokenize=True,
                    add_generation_prompt=False,
                )

            input_ids = _normalize_chat_template_ids(tokenizer_output)

            if self.num_embedding_padding_tokens &gt; len(input_ids):
                pad_len = self.num_embedding_padding_tokens - len(input_ids)
                input_ids = input_ids + &#91;pad_id&#93; * pad_len
            else:
                input_ids = input_ids&#91;:self.num_embedding_padding_tokens&#93;

            input_ids = torch.LongTensor(input_ids).to(device=device)
            input_ids_batch.append(input_ids)

        input_ids_batch = torch.stack(input_ids_batch, dim=0)

        # Cosmos2.5 alignment: keep attention_mask=None.
        target_device = input_ids_batch.device
        try:
            embed_device = self.model.model.embed_tokens.weight.device  # type: ignore&#91;attr-defined&#93;
        except Exception:
            embed_device = None
        if embed_device is not None and embed_device != target_device:
            self.model = self.model.to(target_device)

        with torch.no_grad():
            position_ids, _ = get_rope_index(
                self.model.config,
                input_ids_batch,
                image_grid_thw=None,
                video_grid_thw=None,
                second_per_grid_ts=None,
                attention_mask=None,
            )
            position_ids = position_ids.to(target_device)

            outputs = self.model.model(
                input_ids=input_ids_batch,
                position_ids=position_ids,
                attention_mask=None,
                output_hidden_states=True,
                return_dict=True,
                use_cache=False,
            )
            hidden_states = outputs.hidden_states

        normalized_hidden_states = &#91;&#93;
        for layer_idx in range(1, len(hidden_states)):
            normalized_state = self._mean_normalize(hidden_states&#91;layer_idx&#93;)
            normalized_hidden_states.append(normalized_state)

        if self.embedding_concat_strategy == &quot;full_concat&quot;:
            text_embeddings = torch.cat(normalized_hidden_states, dim=-1)
        elif self.embedding_concat_strategy == &quot;mean_pooling&quot;:
            text_embeddings = torch.stack(normalized_hidden_states).mean(dim=0)
        elif self.embedding_concat_strategy == &quot;pool_every_n_layers_and_concat&quot;:
            pooled_embeddings = &#91;&#93;
            for i in range(0, len(normalized_hidden_states), self.n_layers_per_group):
                group = normalized_hidden_states&#91;i:i + self.n_layers_per_group&#93;
                pooled = torch.stack(group).mean(dim=0)
                pooled_embeddings.append(pooled)
            text_embeddings = torch.cat(pooled_embeddings, dim=-1)
        else:
            raise ValueError(f&quot;Unknown embedding_concat_strategy: &#123;self.embedding_concat_strategy&#125;&quot;)

        return text_embeddings

    @staticmethod
    def _mean_normalize(tensor: torch.Tensor) -&gt; torch.Tensor:
        return (tensor - tensor.mean(dim=-1, keepdim=True)) / (tensor.std(dim=-1, keepdim=True) + 1e-8)</code></pre></details>
<h3 id="fastvideo.models.encoders.reason1.Reason1TextEncoder.forward"><code>fastvideo.models.encoders.reason1.Reason1TextEncoder.forward</code></h3>
<pre class="doc-signature"><code>forward(input_ids: torch.Tensor | None, position_ids: torch.Tensor | None = None, attention_mask: torch.Tensor | None = None, inputs_embeds: torch.Tensor | None = None, output_hidden_states: bool | None = None, **kwargs) -&gt; BaseEncoderOutput</code></pre>

<details><summary>Source</summary><pre><code>def forward(
    self,
    input_ids: torch.Tensor | None,
    position_ids: torch.Tensor | None = None,
    attention_mask: torch.Tensor | None = None,
    inputs_embeds: torch.Tensor | None = None,
    output_hidden_states: bool | None = None,
    **kwargs,
) -&gt; BaseEncoderOutput:
    # Cosmos2.5 alignment: keep attention_mask=None.
    outputs = self.model(
        input_ids=input_ids,
        attention_mask=None,
        position_ids=position_ids,
        inputs_embeds=inputs_embeds,
        output_hidden_states=True,
        return_dict=True,
        pixel_values=kwargs.get(&#x27;pixel_values&#x27;, None),
        pixel_values_videos=kwargs.get(&#x27;pixel_values_videos&#x27;, None),
        image_grid_thw=kwargs.get(&#x27;image_grid_thw&#x27;, None),
        video_grid_thw=kwargs.get(&#x27;video_grid_thw&#x27;, None),
    )

    hidden_states = outputs.hidden_states
    last_hidden_state = hidden_states&#91;-1&#93;

    return BaseEncoderOutput(
        last_hidden_state=last_hidden_state,
        hidden_states=hidden_states if output_hidden_states else None,
        attention_mask=None,
    )</code></pre></details>
<h3 id="fastvideo.models.encoders.reason1.Reason1TextEncoder.load_weights"><code>fastvideo.models.encoders.reason1.Reason1TextEncoder.load_weights</code></h3>
<pre class="doc-signature"><code>load_weights(weights: Iterable&#91;tuple&#91;str, torch.Tensor&#93;&#93;) -&gt; set&#91;str&#93;</code></pre>

<details><summary>Source</summary><pre><code>def load_weights(self, weights: Iterable&#91;tuple&#91;str, torch.Tensor&#93;&#93;) -&gt; set&#91;str&#93;:
    first_weight = None
    weights_list = &#91;&#93;
    for name, weight in weights:
        if first_weight is None:
            first_weight = weight
            self.model = self.model.to_empty(device=weight.device)
            self.model.init_weights(buffer_device=weight.device)
        weights_list.append((name, weight))

    params_dict = dict(self.model.named_parameters())
    loaded_params: set&#91;str&#93; = set()
    skipped_weights = &#123;&quot;lm_head&quot;: 0, &quot;visual&quot;: 0, &quot;decoder&quot;: 0&#125;

    for name, loaded_weight in weights_list:
        if &quot;lm_head&quot; in name:
            skipped_weights&#91;&quot;lm_head&quot;&#93; += 1
            continue
        if &quot;visual&quot; in name:
            skipped_weights&#91;&quot;visual&quot;&#93; += 1
            continue
        if &quot;decoder&quot; in name:
            skipped_weights&#91;&quot;decoder&quot;&#93; += 1
            continue

        # Handle stacked params mapping (for quantized models)
        for param_name, weight_name, shard_id in self.config.arch_config.stacked_params_mapping:
            if weight_name not in name:
                continue
            name = name.replace(weight_name, param_name)
            if name.endswith(&quot;.bias&quot;) and name not in params_dict:
                continue

            if name not in params_dict:
                continue

            param = params_dict&#91;name&#93;
            weight_loader = param.weight_loader
            weight_loader(param, loaded_weight, shard_id)
            param_name_with_prefix = f&quot;model.&#123;name&#125;&quot; if self.prefix == &quot;&quot; else f&quot;&#123;self.prefix&#125;.&#123;name&#125;&quot;
            loaded_params.add(param_name_with_prefix)
            break
        else:
            if name.endswith(&quot;.bias&quot;) and name not in params_dict:
                continue

            if name not in params_dict:
                continue

            param = params_dict&#91;name&#93;
            weight_loader = getattr(param, &quot;weight_loader&quot;, default_weight_loader)
            weight_loader(param, loaded_weight)
            param_name_with_prefix = f&quot;model.&#123;name&#125;&quot; if self.prefix == &quot;&quot; else f&quot;&#123;self.prefix&#125;.&#123;name&#125;&quot;
            loaded_params.add(param_name_with_prefix)
    if first_weight is not None:
        self.model = self.model.to(first_weight.device)

    all_params = set(f&quot;model.&#123;name&#125;&quot; if self.prefix == &quot;&quot; else f&quot;&#123;self.prefix&#125;.&#123;name&#125;&quot;
                     for name in params_dict.keys())
    loaded_params.update(all_params)

    # Mark weights as loaded
    self._weights_loaded = True
    return loaded_params</code></pre></details>
<h3 id="fastvideo.models.encoders.reason1.Reason1TextEncoder.compute_text_embeddings_online"><code>fastvideo.models.encoders.reason1.Reason1TextEncoder.compute_text_embeddings_online</code></h3>
<pre class="doc-signature"><code>compute_text_embeddings_online(data_batch: dict&#91;str, list&#91;str&#93;&#93;, input_caption_key: str) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def compute_text_embeddings_online(
    self,
    data_batch: dict&#91;str, list&#91;str&#93;&#93;,
    input_caption_key: str,
) -&gt; torch.Tensor:
    prompts = data_batch&#91;input_caption_key&#93;
    return self.compute_text_embeddings(prompts)</code></pre></details>
<h3 id="fastvideo.models.encoders.reason1.Reason1TextEncoder.compute_text_embeddings"><code>fastvideo.models.encoders.reason1.Reason1TextEncoder.compute_text_embeddings</code></h3>
<pre class="doc-signature"><code>compute_text_embeddings(prompts: list&#91;str&#93;, device: str | torch.device = &#x27;cuda&#x27;) -&gt; torch.Tensor</code></pre>
<p>Compute embeddings for a list of prompts.</p>
<details><summary>Source</summary><pre><code>def compute_text_embeddings(
    self,
    prompts: list&#91;str&#93;,
    device: str | torch.device = &quot;cuda&quot;,
) -&gt; torch.Tensor:
    &quot;&quot;&quot;Compute embeddings for a list of prompts.&quot;&quot;&quot;
    input_ids_batch = &#91;&#93;

    tok = getattr(self.processor, &quot;tokenizer&quot;, None)
    if tok is None:
        raise RuntimeError(&quot;Reason1TextEncoder requires processor.tokenizer&quot;)
    pad_id = getattr(tok, &quot;pad_id&quot;, None)
    if pad_id is None:
        pad_id = getattr(tok, &quot;pad_token_id&quot;, None)
    if pad_id is None:
        pad_id = getattr(self.model.config, &quot;pad_token_id&quot;, None)
    if pad_id is None:
        pad_id = 0

    for prompt in prompts:
        conversations = &#91;
            &#123;
                &quot;role&quot;:
                &quot;system&quot;,
                &quot;content&quot;: &#91;&#123;
                    &quot;type&quot;: &quot;text&quot;,
                    &quot;text&quot;: &quot;You are a helpful assistant who will provide prompts to an image generator.&quot;,
                &#125;&#93;,
            &#125;,
            &#123;
                &quot;role&quot;: &quot;user&quot;,
                &quot;content&quot;: &#91;&#123;
                    &quot;type&quot;: &quot;text&quot;,
                    &quot;text&quot;: prompt,
                &#125;&#93;,
            &#125;,
        &#93;

        try:
            tokenizer_output = tok.apply_chat_template(
                conversations,
                tokenize=True,
                add_generation_prompt=False,
                add_vision_id=False,
            )
        except TypeError:
            tokenizer_output = tok.apply_chat_template(
                conversations,
                tokenize=True,
                add_generation_prompt=False,
            )

        input_ids = _normalize_chat_template_ids(tokenizer_output)

        if self.num_embedding_padding_tokens &gt; len(input_ids):
            pad_len = self.num_embedding_padding_tokens - len(input_ids)
            input_ids = input_ids + &#91;pad_id&#93; * pad_len
        else:
            input_ids = input_ids&#91;:self.num_embedding_padding_tokens&#93;

        input_ids = torch.LongTensor(input_ids).to(device=device)
        input_ids_batch.append(input_ids)

    input_ids_batch = torch.stack(input_ids_batch, dim=0)

    # Cosmos2.5 alignment: keep attention_mask=None.
    target_device = input_ids_batch.device
    try:
        embed_device = self.model.model.embed_tokens.weight.device  # type: ignore&#91;attr-defined&#93;
    except Exception:
        embed_device = None
    if embed_device is not None and embed_device != target_device:
        self.model = self.model.to(target_device)

    with torch.no_grad():
        position_ids, _ = get_rope_index(
            self.model.config,
            input_ids_batch,
            image_grid_thw=None,
            video_grid_thw=None,
            second_per_grid_ts=None,
            attention_mask=None,
        )
        position_ids = position_ids.to(target_device)

        outputs = self.model.model(
            input_ids=input_ids_batch,
            position_ids=position_ids,
            attention_mask=None,
            output_hidden_states=True,
            return_dict=True,
            use_cache=False,
        )
        hidden_states = outputs.hidden_states

    normalized_hidden_states = &#91;&#93;
    for layer_idx in range(1, len(hidden_states)):
        normalized_state = self._mean_normalize(hidden_states&#91;layer_idx&#93;)
        normalized_hidden_states.append(normalized_state)

    if self.embedding_concat_strategy == &quot;full_concat&quot;:
        text_embeddings = torch.cat(normalized_hidden_states, dim=-1)
    elif self.embedding_concat_strategy == &quot;mean_pooling&quot;:
        text_embeddings = torch.stack(normalized_hidden_states).mean(dim=0)
    elif self.embedding_concat_strategy == &quot;pool_every_n_layers_and_concat&quot;:
        pooled_embeddings = &#91;&#93;
        for i in range(0, len(normalized_hidden_states), self.n_layers_per_group):
            group = normalized_hidden_states&#91;i:i + self.n_layers_per_group&#93;
            pooled = torch.stack(group).mean(dim=0)
            pooled_embeddings.append(pooled)
        text_embeddings = torch.cat(pooled_embeddings, dim=-1)
    else:
        raise ValueError(f&quot;Unknown embedding_concat_strategy: &#123;self.embedding_concat_strategy&#125;&quot;)

    return text_embeddings</code></pre></details>
</div>
