gheinrich commited on
Commit
300c478
·
0 Parent(s):

Release NLD-Uni

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
.gitattributes ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
2
+ *.pt filter=lfs diff=lfs merge=lfs -text
3
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ validation-output/
LICENSE ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ NVIDIA License
2
+
3
+ 1. Definitions
4
+
5
+ “Licensor” means any person or entity that distributes its Work.
6
+
7
+ “Work” means (a) the original work of authorship made available under this license,
8
+ which may include software, documentation, or other files, and (b) any additions to or
9
+ derivative works thereof that are made available under this license.
10
+
11
+ The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the
12
+ meaning as provided under U.S. copyright law; provided, however, that for the purposes
13
+ of this license, derivative works shall not include works that remain separable from, or
14
+ merely link (or bind by name) to the interfaces of, the Work.
15
+
16
+ Works are “made available” under this license by including in or with the Work either
17
+ (a) a copyright notice referencing the applicability of this license to the Work, or
18
+ (b) a copy of this license.
19
+
20
+ 2. License Grant
21
+
22
+ 2.1 Copyright Grant. Subject to the terms and conditions of this license, each Licensor
23
+ grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to
24
+ use, reproduce, prepare derivative works of, publicly display, publicly perform,
25
+ sublicense and distribute its Work and any resulting derivative works in any form.
26
+
27
+ 3. Limitations
28
+
29
+ 3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under
30
+ this license, (b) you include a complete copy of this license with your distribution,
31
+ and (c) you retain without modification any copyright, patent, trademark, or attribution
32
+ notices that are present in the Work.
33
+
34
+ 3.2 Derivative Works. You may specify that additional or different terms apply to the
35
+ use, reproduction, and distribution of your derivative works of the Work (“Your Terms”)
36
+ only if (a) Your Terms provide that the use limitation in Section 3.3 applies to your
37
+ derivative works, and (b) you identify the specific derivative works that are subject
38
+ to Your Terms. Notwithstanding Your Terms, this license (including the redistribution
39
+ requirements in Section 3.1) will continue to apply to the Work itself.
40
+
41
+ 3.3 Use Limitation. The Work and any derivative works thereof only may be used or
42
+ intended for use non-commercially. Notwithstanding the foregoing, NVIDIA Corporation
43
+ and its affiliates may use the Work and any derivative works commercially. As used
44
+ herein, “non-commercially” means for research or evaluation purposes only.
45
+
46
+ 3.4 Patent Claims. If you bring or threaten to bring a patent claim against any
47
+ Licensor (including any claim, cross-claim or counterclaim in a lawsuit) to enforce any
48
+ patents that you allege are infringed by any Work, then your rights under this license
49
+ from such Licensor (including the grant in Section 2.1) will terminate immediately.
50
+
51
+ 3.5 Trademarks. This license does not grant any rights to use any Licensor’s or its
52
+ affiliates’ names, logos, or trademarks, except as necessary to reproduce the notices
53
+ described in this license.
54
+
55
+ 3.6 Termination. If you violate any term of this license, then your rights under this
56
+ license (including the grant in Section 2.1) will terminate immediately.
57
+
58
+ 4. Disclaimer of Warranty.
59
+
60
+ THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
61
+ EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR
62
+ A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY
63
+ ACTIVITIES UNDER THIS LICENSE.
64
+
65
+ 5. Limitation of Liability.
66
+
67
+ EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL THEORY, WHETHER
68
+ IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE SHALL ANY LICENSOR BE LIABLE TO
69
+ YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
70
+ DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK
71
+ (INCLUDING BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR
72
+ DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER DAMAGES OR LOSSES), EVEN IF THE
73
+ LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
README.md ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ pipeline_tag: any-to-any
4
+ tags:
5
+ - custom_code
6
+ - image-text-to-text
7
+ - text-to-image
8
+ - image-to-image
9
+ ---
10
+
11
+ # Nemotron-Labs-Diffusion-Uni-8B
12
+
13
+ ## Description
14
+
15
+ NLD-Uni is a unified multimodal model for image understanding and image generation. It combines a diffusion language model with specialized visual components and a mixture-of-transformers design. Understanding and generation use distinct transformer parameter paths within a common multimodal framework.
16
+
17
+ For image understanding, NLD-Uni encodes images into continuous visual features and generates text responses. For image generation, it models discrete visual tokens through iterative diffusion and decodes those tokens into RGB images. The architecture supports autoregressive and blockwise diffusion decoding for text, as well as image-conditioned generation and editing when enabled by the checkpoint and inference implementation.
18
+
19
+ This card describes the NLD-Uni architecture generally.
20
+
21
+ ### License/Terms of Use
22
+
23
+ GOVERNING TERMS: Use of this model is governed by the [NVIDIA Open Source License Agreement](https://huggingface.co/nvidia/NL-Diffusion-Image/raw/main/LICENSE).
24
+
25
+ ## Deployment Geography
26
+
27
+ Global, subject to the governing release terms.
28
+
29
+ ## Use Case
30
+
31
+ NLD-Uni is intended for research and evaluation of unified multimodal systems, including:
32
+
33
+ - Visual question answering and image-grounded reasoning.
34
+ - Document, chart, and scene-text understanding.
35
+ - Visual grounding and interface localization using task-specific prompts and output formats.
36
+ - Text-to-image generation.
37
+ - Image-conditioned generation and editing for checkpoints trained for these tasks.
38
+
39
+ ## Release Date
40
+
41
+ GitLab 10/17/2026 via [NLD-Uni](https://gitlab-master.nvidia.com/shufanl/nld-uni).
42
+
43
+ ## Model Architecture
44
+
45
+ **Architecture Type:** Transformer
46
+
47
+ **Network Architecture:** Diffusion language model with understanding and generation transformer paths, a continuous visual encoder for understanding, and a discrete image tokenizer for generation.
48
+
49
+ **Language-model foundation:** Nemotron diffusion language model.
50
+
51
+ ## Input
52
+
53
+ **Input Type(s):** Text and images.
54
+
55
+ **Input Format(s):** Text strings and image objects or tensors accepted by the supplied processor.
56
+
57
+ **Input Parameters:** One-dimensional text-token sequences and two-dimensional image content, represented internally as visual features or discrete image tokens according to the task.
58
+
59
+ **Other Properties Related to Input:** Context length, image resolution, visual-token budget, and preprocessing are checkpoint- and task-dependent. The released inference configuration defines the supported limits; a universal 900-token prompt limit is not specified for the architecture.
60
+
61
+ ## Output
62
+
63
+ **Output Type(s):**
64
+
65
+ - Text
66
+ - Image
67
+
68
+ **Output Format(s):**
69
+
70
+ - **Text:** `.json` (UTF-8 JSON records containing generated text).
71
+ - **Image:** `.png` (RGB images).
72
+
73
+ These serialized formats are implemented by `validate.py`. The inference API returns text strings or token IDs for understanding and decoded image objects or tensors for generation. Grounding outputs follow the requested coordinate or location-token format.
74
+
75
+ **Output Parameters:** One-dimensional token sequences or images with height, width, and three color channels. Tensor layout and pixel range are defined by the inference API.
76
+
77
+ **Other Properties Related to Output:** Text output length and generated image resolution depend on the checkpoint and inference settings. Configurations for 1,024 × 1,024 image generation are implemented; the release should list its validated resolutions.
78
+
79
+ ## Software Integration
80
+
81
+ NLD-Uni’s native implementation uses PyTorch with CUDA-accelerated execution. The codebase also includes a dedicated SGLang integration for the image-understanding and text-generation path. This does not establish SGLang support for the image-generation path.
82
+
83
+ **Runtime Engine(s):**
84
+
85
+ - PyTorch for native multimodal inference.
86
+ - SGLang with the NLD-Uni/LaVida RADIO-H adapter for supported understanding configurations.
87
+
88
+ **Reference Platform:** Linux with NVIDIA CUDA GPUs.
89
+
90
+ **Reference Evaluation Hardware:** NVIDIA H100 (Hopper).
91
+
92
+ ## Model Version(s)
93
+
94
+ - **NLD-Uni:** Unified image-understanding and image-generation architecture based on LaVida-O.
95
+
96
+ Training stage, checkpoint revision, tokenizer revision, and inference configuration are part of the identity of an evaluated model. Results from earlier LaVida-O or image-only diffusion models should retain their original model names.
97
+
98
+ # Training and Evaluation Datasets
99
+
100
+ ## Training Dataset
101
+
102
+ More than 100M image-text pairs.
103
+
104
+ **Data Collection Method by dataset**
105
+
106
+ - Hybrid: Automated, Manually-Collected, Synthetic
107
+
108
+ **Labeling Method by dataset**
109
+
110
+ - Hybrid: Automated, Manually-Labeled, Synthetic
111
+
112
+ ## Evaluation Datasets
113
+
114
+ ### Documented Functional Validation Dataset
115
+
116
+ - **Modalities:** Text and RGB images.
117
+ - **Nature of content:** Synthetic everyday-object, animal, and landscape scenes; text-to-image prompts, edit instructions, and image-understanding questions. The generated images are used as inputs to subsequent editing and understanding tasks.
118
+ - **Linguistic characteristics:** English prompts, edit instructions, questions, and recorded answers.
119
+ - **Collection and labeling:** Three scripted scene cases in `validate.py`; model-generated images and answers were manually inspected for prompt alignment and editing fidelity.
120
+
121
+ Counts and results are recorded in [VALIDATION.md](VALIDATION.md), [validation.json](validation.json), and [examples/results.json](examples/results.json). These are functional smoke tests, not measurements of benchmark accuracy.
122
+
123
+ ### Benchmark Evaluation Properties
124
+
125
+ The benchmark suite below covers image and text inputs, including mathematical and scientific questions, documents, charts, scene text, interfaces, referring expressions, and image-generation prompts. OCRBenchV2-EN identifies an English subset; the exact language coverage of the other evaluated splits must be documented from the evaluation records.
126
+
127
+ ### Image Understanding
128
+
129
+ The evaluation suite should identify the following benchmarks and splits explicitly:
130
+
131
+ | Benchmark | Evaluation target | Primary reporting requirement |
132
+ |---|---|---|
133
+ | MathVista_MINI | Visual mathematical reasoning | Full 1,000-example accuracy; identify answer-extraction judge |
134
+ | MMMU_DEV_VAL | Multidisciplinary visual reasoning | Report development and validation splits separately |
135
+ | AI2D_TEST | Diagram understanding | Accuracy and image/prompt protocol |
136
+ | ChartQA_TEST | Chart question answering | Relaxed accuracy and subset aggregation |
137
+ | DocVQA_VAL | Document question answering | ANLS |
138
+ | TextVQA_VAL | Scene-text question answering | VQA accuracy with specified normalization |
139
+ | RealWorldQA | Real-world visual understanding | Accuracy |
140
+ | InfoVQA_VAL | Infographic question answering | ANLS |
141
+ | ScienceQA_TEST | Science question answering | Identify the image-containing subset when used |
142
+ | ScreenSpot-Pro | Interface grounding | Point-localization accuracy; separate first-pass and crop-refined results |
143
+ | RefCOCO | Referring-expression grounding | IoU ≥ 0.5 accuracy for val, testA, and testB; disclose the native LOC protocol |
144
+ | OCRBenchV2-EN | OCR and document understanding | Official English category aggregation |
145
+
146
+ ### Image Generation
147
+
148
+ | Benchmark | Evaluation target | Primary metric |
149
+ |---|---|---|
150
+ | GenEval | Object presence, counts, colors, positions, and attribute binding | Overall and category scores |
151
+ | DPG-Bench | Alignment with detailed compositional prompts | Overall and category scores |
152
+ | MJHQ-30K | Generated-image distribution and quality | FID; any additional preference metric must identify its model and version |
153
+
154
+ Evaluation should identify the exact checkpoint, prompt processing, image preprocessing, decoding parameters, seed policy, sample count, and evaluator version. Report reasoning and non-reasoning results separately. Tokenizer reconstruction evaluation, if performed, should be identified separately from end-to-end image-generation quality.
155
+
156
+ ## Key Considerations
157
+
158
+ NLD-Uni can produce incorrect text, inaccurate grounding coordinates, and synthetic images that do not fully follow the prompt. Generated content may reflect biases in training data or contain inappropriate material. Image-conditioned outputs may change details that users intended to preserve.
159
+
160
+ Applications should be evaluated on their intended tasks and data, with appropriate input and output controls. Model outputs should not be treated as verified factual evidence solely because they are fluent or visually plausible.
161
+
162
+ ## Inference
163
+
164
+ **Native Engine:** PyTorch.
165
+
166
+ **Understanding Serving Integration:** SGLang with the model-specific adapter, for validated configurations.
167
+
168
+ **Reference Precision:** BF16 where supported by the selected implementation.
169
+
170
+ **Reference Hardware:** NVIDIA H100.
171
+
172
+ Use the model-specific tokenizer, processor, chat template, and task interface. Image understanding uses the continuous visual encoder; image generation uses the discrete image-token pipeline. Runtime optimizations, including CUDA graphs, should be evaluated with the exact checkpoint and decode configuration before publishing accuracy or speed claims.
173
+
174
+ ## Ethical Considerations
175
+
176
+ NVIDIA believes trustworthy AI is a shared responsibility. Developers should evaluate NLD-Uni for the intended application, including potential errors, bias, privacy concerns, and misuse of generated content.
177
+
178
+ Users should have appropriate rights and permissions for input images and other supplied content. Generated or edited images may alter identities, text, object proportions, or scene details. Applications should communicate the synthetic nature of generated content where appropriate.
179
+
180
+ Users are responsible for model inputs and outputs and for implementing appropriate safeguards before deployment.
181
+
182
+ Report model quality concerns, security vulnerabilities, or NVIDIA AI concerns through [NVIDIA’s reporting channel](https://www.nvidia.com/en-us/support/submit-security-vulnerability/).
183
+
184
+ ## Environment
185
+
186
+ Install the dependencies in `requirements.txt` with Python 3.13 and CUDA 12.6. Install PyTorch before building FlashAttention:
187
+
188
+ ```bash
189
+ pip install -r requirements.txt
190
+ pip install --no-build-isolation flash-attn==2.8.0.post2
191
+ ```
192
+
193
+ Validated on an NVIDIA H100 80 GB. The eight BF16 weight shards contain all 1,557 active model tensors. `weights_manifest.json` records their hashes.
194
+
195
+ ## Python inference
196
+
197
+ ```python
198
+ import torch
199
+ from transformers import AutoModelForCausalLM
200
+
201
+ model = AutoModelForCausalLM.from_pretrained(
202
+ '/path/to/hf_checkpoint', # or 'organization/model-name'
203
+ trust_remote_code=True,
204
+ torch_dtype=torch.bfloat16,
205
+ ).to('cuda').eval()
206
+
207
+ image = model.text_to_image('A red ceramic mug on a wooden table.', seed=42)
208
+ image.save('mug.png')
209
+
210
+ edited = model.image_edit(image, 'Change the mug to blue.', seed=42)
211
+ edited.save('blue_mug.png')
212
+
213
+ answer = model.generate('What color is the mug?', image=edited)
214
+ print(answer)
215
+ ```
216
+
217
+ Image inputs accept Pillow images or local file paths. Image methods return Pillow images; `generate` returns text by default. Token IDs can be supplied through `input_ids` for text prompts, and `return_token_ids=True` returns the generated token tensor. The `inference.py` command exposes each task.
218
+
219
+ ## Minimal command-line inference
220
+
221
+ ```bash
222
+ python inference.py /path/to/hf_checkpoint --task t2i --prompt 'A red mug.' --output mug.png
223
+ python inference.py /path/to/hf_checkpoint --task edit --image mug.png --prompt 'Make the mug blue.' --output blue.png
224
+ python inference.py /path/to/hf_checkpoint --task understand --image blue.png --prompt 'What color is the mug?'
225
+ ```
226
+
227
+ Replace the model argument with the published Hugging Face model ID for remote loading. The standalone script only uses Transformers and this repository's model code.
attention.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ from typing import Optional, Tuple
4
+ import torch
5
+ import torch.nn.functional as F
6
+ from torch.nn.attention.flex_attention import BlockMask, flex_attention, create_block_mask
7
+ from transformers.modeling_flash_attention_utils import FlashAttentionKwargs
8
+ from transformers.processing_utils import Unpack
9
+ from transformers.cache_utils import Cache
10
+ from flash_attn import flash_attn_func, flash_attn_varlen_func
11
+ from .core import Ministral3Attention, _MixedTokenRoutingPlan, _create_split_tower_block_mask, _get_llama_4_attn_scale, _routing_mask, apply_rotary_pos_emb, repeat_kv
12
+ try:
13
+ from flash_attn import flash_attn_func
14
+ except:
15
+ pass
16
+ try:
17
+ from flash_attn import flash_attn_varlen_func
18
+ except:
19
+ flash_attn_varlen_func = None
20
+
21
+ @torch.compile(fullgraph=True, dynamic=False)
22
+ def fused_flex_attention(q, k, v, block_mask=None):
23
+ return flex_attention(q, k, v, block_mask=block_mask)
24
+ _flex_attn_debug_printed = False
25
+
26
+ def _routed_flash_attention(query_states, key_states, value_states, *, query_selection, key_value_selection, causal):
27
+ if flash_attn_varlen_func is None:
28
+ raise RuntimeError('partial dual-tower FlashAttention requires flash_attn_varlen_func')
29
+ query_tokens = query_states.transpose(1, 2)
30
+ key_tokens = key_states.transpose(1, 2)
31
+ value_tokens = value_states.transpose(1, 2)
32
+ query_unpadded = query_tokens[query_selection]
33
+ key_unpadded = key_tokens[key_value_selection]
34
+ value_unpadded = value_tokens[key_value_selection]
35
+ query_lengths = query_selection.sum(dim=1, dtype=torch.int32)
36
+ key_value_lengths = key_value_selection.sum(dim=1, dtype=torch.int32)
37
+ zero = torch.zeros(1, dtype=torch.int32, device=query_states.device)
38
+ cumulative_query_lengths = torch.cat((zero, query_lengths.cumsum(dim=0, dtype=torch.int32)))
39
+ cumulative_key_value_lengths = torch.cat((zero, key_value_lengths.cumsum(dim=0, dtype=torch.int32)))
40
+ output_unpadded = flash_attn_varlen_func(query_unpadded, key_unpadded, value_unpadded, cumulative_query_lengths, cumulative_key_value_lengths, query_selection.shape[1], key_value_selection.shape[1], dropout_p=0.0, softmax_scale=None, causal=causal)
41
+ output = torch.zeros_like(query_tokens)
42
+ output[query_selection] = output_unpadded
43
+ return output.transpose(1, 2)
44
+
45
+ class MinistralFlexAttention(Ministral3Attention):
46
+
47
+ def __init__(self, *args, **kwargs):
48
+ super().__init__(*args, **kwargs)
49
+ self.max_seq_length = getattr(self.config, 'max_seq_length', 4096)
50
+ self.block_size_orig = self.config.block_size
51
+ self.bidirectional_mask = None
52
+ self.sbd_block_diff_mask = None
53
+ self.block_size = self.block_size_orig
54
+ self.mode = 'sbd_block_diff'
55
+ self._quadratic_block_mask = {}
56
+ import torch._dynamo.config as dcfg
57
+ dcfg.cache_size_limit = 512
58
+
59
+ def set_attention_mode(self, mode, block_size=None):
60
+ self.mode = mode
61
+ self.block_size = block_size
62
+
63
+ def forward(self, hidden_states: torch.Tensor, position_embeddings: Tuple[torch.Tensor, torch.Tensor], attention_mask: Optional[torch.Tensor], past_key_values: Optional[Cache]=None, cache_position: Optional[torch.LongTensor]=None, overwrite_block_mask=None, overwrite_attn_impl=None, use_cache: Optional[bool]=False, routing=None, single_stream_image_diffusion: bool=False, **kwargs: Unpack[FlashAttentionKwargs]) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
64
+ if overwrite_attn_impl == 'base':
65
+ return super().forward(hidden_states=hidden_states, position_embeddings=position_embeddings, attention_mask=attention_mask, past_key_values=past_key_values, cache_position=cache_position, use_cache=use_cache, routing=routing, **kwargs)
66
+ (bsz, q_len, _) = hidden_states.size()
67
+ input_shape = hidden_states.shape[:-1]
68
+ hidden_shape = (*input_shape, -1, self.head_dim)
69
+ (query_states, key_states, value_states) = self._project_qkv(hidden_states, routing)
70
+ query_states = query_states.view(hidden_shape).transpose(1, 2)
71
+ key_states = key_states.view(hidden_shape).transpose(1, 2)
72
+ value_states = value_states.view(hidden_shape).transpose(1, 2)
73
+ (cos, sin) = position_embeddings
74
+ (query_states, key_states) = apply_rotary_pos_emb(query_states, key_states, cos, sin)
75
+ query_states = query_states * _get_llama_4_attn_scale(cache_position, self.config.rope_parameters.get('llama_4_scaling_beta'), self.config.rope_parameters.get('original_max_position_embeddings')).to(query_states.dtype)
76
+ current_key_states = key_states
77
+ current_value_states = value_states
78
+ cached_routing_metadata = getattr(past_key_values, '_nlduni_dual_tower_routing', None)
79
+ isolate_generation_flash = overwrite_attn_impl == 'flash_attn' and self.split_tower and (routing is not None or cached_routing_metadata is not None)
80
+ cached_has_generation = bool(getattr(past_key_values, '_nlduni_dual_tower_has_generation', False))
81
+ drop_cached_understanding = isolate_generation_flash and routing is True and (not cached_has_generation)
82
+ if past_key_values is not None:
83
+ if use_cache:
84
+ cache_kwargs = {'sin': sin, 'cos': cos, 'cache_position': cache_position}
85
+ (key_states, value_states) = past_key_values.update(key_states, value_states, self.layer_idx, cache_kwargs)
86
+ elif not drop_cached_understanding:
87
+ (old_k, old_v) = (past_key_values.layers[self.layer_idx].keys, past_key_values.layers[self.layer_idx].values)
88
+ key_states = torch.cat([old_k, key_states], dim=-2)
89
+ value_states = torch.cat([old_v, value_states], dim=-2)
90
+ self_spec_inference_mode = None
91
+ if overwrite_attn_impl == 'flash_attn':
92
+ block_mask = None
93
+ elif overwrite_block_mask is not None:
94
+ block_mask = overwrite_block_mask
95
+ if block_mask == 'full':
96
+ block_mask = None
97
+ elif self.mode == 'bidirectional':
98
+ block_mask = None
99
+ overwrite_attn_impl = 'flash_attn'
100
+ elif True:
101
+ raise ValueError('Supply an explicit block mask or use FlashAttention')
102
+ if overwrite_block_mask is None and overwrite_attn_impl != 'flash_attn' and self.split_tower and (routing is not None or cached_routing_metadata is not None):
103
+ current_routing = _routing_mask(routing, hidden_states)
104
+ cached_routing = cached_routing_metadata
105
+ if cached_routing is None:
106
+ cached_routing = torch.zeros(bsz, key_states.shape[-2] - q_len, dtype=torch.bool, device=hidden_states.device)
107
+ block_mask = _create_split_tower_block_mask(block_mask, current_routing=current_routing, cached_routing=cached_routing)
108
+ if isinstance(block_mask, BlockMask) and overwrite_attn_impl != 'flash_attn':
109
+ (mask_query_length, mask_key_value_length) = block_mask.seq_lengths
110
+ query_length = query_states.shape[-2]
111
+ key_value_length = key_states.shape[-2]
112
+ if mask_query_length < query_length:
113
+ raise ValueError(f'FlexAttention block-mask query length is shorter than the projected queries: {mask_query_length} < {query_length}')
114
+ if mask_key_value_length < key_value_length:
115
+ raise ValueError(f'FlexAttention block-mask key/value length is shorter than the projected keys: {mask_key_value_length} < {key_value_length}')
116
+ query_padding = mask_query_length - query_length
117
+ key_value_padding = mask_key_value_length - key_value_length
118
+ if query_padding:
119
+ query_states = F.pad(query_states, (0, 0, 0, query_padding))
120
+ if key_value_padding:
121
+ key_states = F.pad(key_states, (0, 0, 0, key_value_padding))
122
+ value_states = F.pad(value_states, (0, 0, 0, key_value_padding))
123
+ if overwrite_attn_impl == 'flash_attn':
124
+ if self.diffusion_lm:
125
+ causal = False
126
+ else:
127
+ causal = True
128
+ isolate_generation_flash = self.split_tower and (routing is not None or cached_routing_metadata is not None)
129
+ if isolate_generation_flash and routing is True and (not cached_has_generation):
130
+ attn_output = flash_attn_func(query_states.transpose(1, 2), current_key_states.transpose(1, 2), current_value_states.transpose(1, 2), dropout_p=0.0, softmax_scale=None, causal=causal).transpose(1, 2)
131
+ elif isolate_generation_flash:
132
+ if routing is True:
133
+ query_routing = torch.ones(bsz, q_len, dtype=torch.bool, device=hidden_states.device)
134
+ elif routing is None:
135
+ query_routing = torch.zeros(bsz, q_len, dtype=torch.bool, device=hidden_states.device)
136
+ elif isinstance(routing, _MixedTokenRoutingPlan):
137
+ query_routing = routing.mask
138
+ else:
139
+ raise TypeError('split-tower FlashAttention requires canonical routing')
140
+ cached_routing = cached_routing_metadata
141
+ cached_length = key_states.shape[-2] - q_len
142
+ if cached_routing is None:
143
+ cached_routing = torch.zeros(bsz, cached_length, dtype=torch.bool, device=hidden_states.device)
144
+ elif tuple(cached_routing.shape) != (bsz, cached_length):
145
+ raise ValueError('cached dual-tower routing does not align with FlashAttention keys')
146
+ key_value_routing = torch.cat((cached_routing, query_routing), dim=1)
147
+ if routing is None:
148
+ attn_output = _routed_flash_attention(query_states, key_states, value_states, query_selection=~query_routing, key_value_selection=~key_value_routing, causal=causal)
149
+ elif routing is True:
150
+ attn_output = _routed_flash_attention(query_states, key_states, value_states, query_selection=query_routing, key_value_selection=key_value_routing, causal=causal)
151
+ else:
152
+ attn_output = _routed_flash_attention(query_states, key_states, value_states, query_selection=~query_routing, key_value_selection=~key_value_routing, causal=causal)
153
+ attn_output = attn_output + _routed_flash_attention(query_states, key_states, value_states, query_selection=query_routing, key_value_selection=key_value_routing, causal=causal)
154
+ else:
155
+ key_states = repeat_kv(key_states, self.num_key_value_groups)
156
+ value_states = repeat_kv(value_states, self.num_key_value_groups)
157
+ attn_output = flash_attn_func(query_states.transpose(1, 2), key_states.transpose(1, 2), value_states.transpose(1, 2), dropout_p=0.0, softmax_scale=None, causal=causal).transpose(1, 2)
158
+ else:
159
+ key_states = repeat_kv(key_states, self.num_key_value_groups)
160
+ value_states = repeat_kv(value_states, self.num_key_value_groups)
161
+ global _flex_attn_debug_printed
162
+ if not _flex_attn_debug_printed:
163
+ _flex_attn_debug_printed = True
164
+ attn_output = fused_flex_attention(query_states, key_states, value_states, block_mask=block_mask)
165
+ if attn_output.shape[-2] != q_len:
166
+ attn_output = attn_output[..., :q_len, :]
167
+ attn_output = attn_output.transpose(1, 2).reshape(*input_shape, -1).contiguous()
168
+ attn_output = self._project_output(attn_output, routing)
169
+ return (attn_output, None)
bridge.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import torch
4
+ from torch import nn
5
+ IMAGE_LOCAL_AR_CHILD_COUNT = 4
6
+
7
+ class PackedLinearImageCodec(nn.Module):
8
+
9
+ def __init__(self, channels: int, *, norm_eps: float=1e-06, device: torch.device | str | None=None, dtype: torch.dtype | None=None) -> None:
10
+ super().__init__()
11
+ if isinstance(channels, bool) or not isinstance(channels, int) or channels < 1:
12
+ raise ValueError('channels must be a positive integer')
13
+ factory_kwargs = {'device': device, 'dtype': dtype}
14
+ self.channels = channels
15
+ self.down_norm = nn.RMSNorm(channels, eps=norm_eps, elementwise_affine=True, **factory_kwargs)
16
+ self.down_projection = nn.Linear(4 * channels, channels, bias=False, **factory_kwargs)
17
+ self.up_norm = nn.RMSNorm(channels, eps=norm_eps, elementwise_affine=True, **factory_kwargs)
18
+ self.up_projection = nn.Linear(channels, 4 * channels, bias=False, **factory_kwargs)
19
+
20
+ @staticmethod
21
+ def _shape(shape: tuple[int, int] | list[int]) -> tuple[int, int]:
22
+ if not isinstance(shape, (tuple, list)) or len(shape) != 2:
23
+ raise ValueError('image token shape must contain height and width')
24
+ (height, width) = shape
25
+ if any((isinstance(value, bool) or not isinstance(value, int) for value in shape)):
26
+ raise TypeError('image token height and width must be integers')
27
+ if height < 1 or width < 1 or height % 2 or width % 2:
28
+ raise ValueError('packed-linear image grids must have positive even dimensions')
29
+ return (height, width)
30
+
31
+ @staticmethod
32
+ def _patches(grid: torch.Tensor) -> torch.Tensor:
33
+ return torch.stack((grid[..., 0::2, 0::2, :], grid[..., 0::2, 1::2, :], grid[..., 1::2, 0::2, :], grid[..., 1::2, 1::2, :]), dim=-2)
34
+
35
+ @classmethod
36
+ def pack_raster_values(cls, child_values: torch.Tensor, shape: tuple[int, int] | list[int]) -> torch.Tensor:
37
+ (height, width) = cls._shape(shape)
38
+ if not isinstance(child_values, torch.Tensor):
39
+ raise TypeError('child_values must be a tensor')
40
+ if child_values.ndim < 2 or child_values.shape[1] != height * width:
41
+ raise ValueError(f'child_values must have shape [B, {height * width}, ...]')
42
+ grid = child_values.reshape(child_values.shape[0], height, width, *child_values.shape[2:])
43
+ patches = torch.stack((grid[:, 0::2, 0::2, ...], grid[:, 0::2, 1::2, ...], grid[:, 1::2, 0::2, ...], grid[:, 1::2, 1::2, ...]), dim=3)
44
+ return patches.flatten(1, 2)
45
+
46
+ @classmethod
47
+ def unpack_patch_values(cls, patch_values: torch.Tensor, shape: tuple[int, int] | list[int]) -> torch.Tensor:
48
+ (height, width) = cls._shape(shape)
49
+ (parent_height, parent_width) = (height // 2, width // 2)
50
+ parent_count = parent_height * parent_width
51
+ if not isinstance(patch_values, torch.Tensor):
52
+ raise TypeError('patch_values must be a tensor')
53
+ if patch_values.ndim < 3 or patch_values.shape[1] != parent_count or patch_values.shape[2] != IMAGE_LOCAL_AR_CHILD_COUNT:
54
+ raise ValueError(f'patch_values must have shape [B, {parent_count}, {IMAGE_LOCAL_AR_CHILD_COUNT}, ...]')
55
+ patches = patch_values.reshape(patch_values.shape[0], parent_height, parent_width, IMAGE_LOCAL_AR_CHILD_COUNT, *patch_values.shape[3:])
56
+ grid = patch_values.new_empty(patch_values.shape[0], height, width, *patch_values.shape[3:])
57
+ grid[:, 0::2, 0::2, ...] = patches[:, :, :, 0, ...]
58
+ grid[:, 0::2, 1::2, ...] = patches[:, :, :, 1, ...]
59
+ grid[:, 1::2, 0::2, ...] = patches[:, :, :, 2, ...]
60
+ grid[:, 1::2, 1::2, ...] = patches[:, :, :, 3, ...]
61
+ return grid.flatten(1, 2)
62
+
63
+ def compress_fixed_grid(self, child_states: torch.Tensor, shape: tuple[int, int] | list[int]) -> torch.Tensor:
64
+ (height, width) = self._shape(shape)
65
+ if child_states.ndim != 3 or child_states.shape[1:] != (height * width, self.channels):
66
+ raise ValueError(f'child_states must have shape [B, {height * width}, {self.channels}]')
67
+ grid = child_states.reshape(child_states.shape[0], height, width, self.channels)
68
+ patches = self._patches(grid)
69
+ normalized = self.down_norm(patches)
70
+ parents = self.down_projection(normalized.reshape(child_states.shape[0], height // 2, width // 2, 4 * self.channels))
71
+ return parents.flatten(1, 2)
72
+
73
+ def expand_fixed_grid(self, parent_states: torch.Tensor, shape: tuple[int, int] | list[int]) -> torch.Tensor:
74
+ children = self.expand_fixed_grid_patches(parent_states, shape)
75
+ return self.unpack_patch_values(children, shape)
76
+
77
+ def expand_fixed_grid_patches(self, parent_states: torch.Tensor, shape: tuple[int, int] | list[int]) -> torch.Tensor:
78
+ (height, width) = self._shape(shape)
79
+ parent_count = height // 2 * (width // 2)
80
+ if parent_states.ndim != 3 or parent_states.shape[1:] != (parent_count, self.channels):
81
+ raise ValueError(f'parent_states must have shape [B, {parent_count}, {self.channels}]')
82
+ return self.up_projection(self.up_norm(parent_states)).reshape(parent_states.shape[0], parent_count, 4, self.channels)
chat_template.jinja ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro render_extra_keys(json_dict, handled_keys) %}
2
+ {%- if json_dict is mapping %}
3
+ {%- for json_key in json_dict if json_key not in handled_keys %}
4
+ {%- if json_dict[json_key] is mapping or (json_dict[json_key] is sequence and json_dict[json_key] is not string) %}
5
+ {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | tojson | safe) ~ '</' ~ json_key ~ '>' }}
6
+ {%- else %}
7
+ {{-'\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | string) ~ '</' ~ json_key ~ '>' }}
8
+ {%- endif %}
9
+ {%- endfor %}
10
+ {%- endif %}
11
+ {% endmacro %}
12
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else True %}
13
+ {%- set reasoning_budget = reasoning_budget if reasoning_budget is defined else None %}
14
+ {%- set truncate_history_thinking = truncate_history_thinking if truncate_history_thinking is defined else True %}
15
+
16
+ {%- set ns = namespace(last_user_idx = -1) %}
17
+ {%- set loop_messages = messages %}
18
+ {%- for m in loop_messages %}
19
+ {%- if m["role"] == "user" %}
20
+ {%- set ns.last_user_idx = loop.index0 %}
21
+ {%- endif %}
22
+ {%- endfor %}
23
+
24
+ {%- if messages[0]["role"] == "system" %}
25
+ {%- set system_message = messages[0]["content"] %}
26
+ {%- set loop_messages = messages[1:] %}
27
+ {%- else %}
28
+ {%- set system_message = "" %}
29
+ {%- set loop_messages = messages %}
30
+ {%- endif %}
31
+ {%- if not tools is defined %}
32
+ {%- set tools = [] %}
33
+ {%- endif %}
34
+ {# Recompute last_user_idx relative to loop_messages after handling system #}
35
+ {%- set ns = namespace(last_user_idx = -1) %}
36
+ {%- for m in loop_messages %}
37
+ {%- if m["role"] == "user" %}
38
+ {%- set ns.last_user_idx = loop.index0 %}
39
+ {%- endif %}
40
+ {%- endfor %}
41
+ {%- if system_message is defined %}
42
+ {{- "<|im_start|>system\n" + system_message }}
43
+ {%- else %}
44
+ {%- if tools is iterable and tools | length > 0 %}
45
+ {{- "<|im_start|>system\n" }}
46
+ {%- endif %}
47
+ {%- endif %}
48
+ {%- if tools is iterable and tools | length > 0 %}
49
+ {%- if system_message is defined and system_message | length > 0 %}
50
+ {{- "\n\n" }}
51
+ {%- endif %}
52
+ {{- "# Tools\n\nYou have access to the following functions:\n\n" }}
53
+ {{- "<tools>" }}
54
+ {%- for tool in tools %}
55
+ {%- if tool.function is defined %}
56
+ {%- set tool = tool.function %}
57
+ {%- endif %}
58
+ {{- "\n<function>\n<name>" ~ tool.name ~ "</name>" }}
59
+ {%- if tool.description is defined %}
60
+ {{- '\n<description>' ~ (tool.description | trim) ~ '</description>' }}
61
+ {%- endif %}
62
+ {{- '\n<parameters>' }}
63
+ {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping %}
64
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
65
+ {{- '\n<parameter>' }}
66
+ {{- '\n<name>' ~ param_name ~ '</name>' }}
67
+ {%- if param_fields.type is defined %}
68
+ {{- '\n<type>' ~ (param_fields.type | string) ~ '</type>' }}
69
+ {%- endif %}
70
+ {%- if param_fields.description is defined %}
71
+ {{- '\n<description>' ~ (param_fields.description | trim) ~ '</description>' }}
72
+ {%- endif %}
73
+ {%- if param_fields.enum is defined %}
74
+ {{- '\n<enum>' ~ (param_fields.enum | tojson | safe) ~ '</enum>' }}
75
+ {%- endif %}
76
+ {%- set handled_keys = ['name', 'type', 'description', 'enum'] %}
77
+ {{- render_extra_keys(param_fields, handled_keys) }}
78
+ {{- '\n</parameter>' }}
79
+ {%- endfor %}
80
+ {%- endif %}
81
+ {% set handled_keys = ['type', 'properties', 'required'] %}
82
+ {{- render_extra_keys(tool.parameters, handled_keys) }}
83
+ {%- if tool.parameters is defined and tool.parameters.required is defined %}
84
+ {{- '\n<required>' ~ (tool.parameters.required | tojson | safe) ~ '</required>' }}
85
+ {%- endif %}
86
+ {{- '\n</parameters>' }}
87
+ {%- set handled_keys = ['type', 'name', 'description', 'parameters'] %}
88
+ {{- render_extra_keys(tool, handled_keys) }}
89
+ {{- '\n</function>' }}
90
+ {%- endfor %}
91
+ {{- "\n</tools>" }}
92
+
93
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
94
+ {%- endif %}
95
+
96
+
97
+ {%- if system_message is defined %}
98
+ {{- '<|im_end|>\n' }}
99
+ {%- else %}
100
+ {%- if tools is iterable and tools | length > 0 %}
101
+ {{- '<|im_end|>\n' }}
102
+ {%- endif %}
103
+ {%- endif %}
104
+
105
+ {%- for message in loop_messages %}
106
+ {%- if message.role == "assistant" %}
107
+ {# Add reasoning content in to content field for unified processing below. #}
108
+ {%- if message.reasoning_content is defined and message.reasoning_content is string and message.reasoning_content | trim | length > 0 %}
109
+ {%- set content = "<think>\n" ~ message.reasoning_content ~ "\n</think>\n" ~ (message.content | default('', true)) %}
110
+ {%- else %}
111
+ {%- set content = message.content | default('', true) %}
112
+ {%- if content is string -%}
113
+ {# Allow downstream logic to to take care of broken thought, only handle coherent reasoning here. #}
114
+ {%- if '<think>' not in content and '</think>' not in content -%}
115
+ {%- set content = "<think></think>" ~ content -%}
116
+ {%- endif -%}
117
+ {%- else -%}
118
+ {%- set content = content -%}
119
+ {%- endif -%}
120
+ {%- endif %}
121
+ {%- if message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}
122
+ {# Assistant message has tool calls. #}
123
+ {{- '<|im_start|>assistant\n' }}
124
+ {%- set include_content = not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
125
+ {%- if content is string and content | trim | length > 0 %}
126
+ {%- if include_content %}
127
+ {{- (content | trim) ~ '\n' -}}
128
+ {%- else %}
129
+ {%- set c = (content | string) %}
130
+ {%- if '</think>' in c %}
131
+ {# Keep only content after the last closing think. Also generation prompt causes this. #}
132
+ {%- set c = c.split('</think>')[-1] %}
133
+ {%- elif '<think>' in c %}
134
+ {# If <think> was opened but never closed, drop the trailing think segment #}
135
+ {%- set c = c.split('<think>')[0] %}
136
+ {%- endif %}
137
+ {%- set c = "<think></think>" ~ c | trim %}
138
+ {%- if c | length > 0 %}
139
+ {{- c ~ '\n' -}}
140
+ {%- endif %}
141
+ {%- endif %}
142
+ {%- else %}
143
+ {{- "<think></think>" -}}
144
+ {%- endif %}
145
+ {%- for tool_call in message.tool_calls %}
146
+ {%- if tool_call.function is defined %}
147
+ {%- set tool_call = tool_call.function %}
148
+ {%- endif %}
149
+ {{- '<tool_call>\n<function=' ~ tool_call.name ~ '>\n' -}}
150
+ {%- if tool_call.arguments is defined %}
151
+ {%- for args_name, args_value in tool_call.arguments|items %}
152
+ {{- '<parameter=' ~ args_name ~ '>\n' -}}
153
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
154
+ {{- args_value ~ '\n</parameter>\n' -}}
155
+ {%- endfor %}
156
+ {%- endif %}
157
+ {{- '</function>\n</tool_call>\n' -}}
158
+ {%- endfor %}
159
+ {{- '<|im_end|>\n' }}
160
+ {%- else %}
161
+ {# Assistant message doesn't have tool calls. #}
162
+ {%- if not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
163
+ {{- '<|im_start|>assistant\n' ~ (content | default('', true) | string | trim) ~ '<|im_end|>\n' }}
164
+ {%- else %}
165
+ {%- set c = (content | default('', true) | string) %}
166
+ {%- if '<think>' in c and '</think>' in c %}
167
+ {%- set c = "<think></think>" ~ c.split('</think>')[-1] %}
168
+ {%- endif %}
169
+ {%- set c = c | trim %}
170
+ {%- if c | length > 0 %}
171
+ {{- '<|im_start|>assistant\n' ~ c ~ '<|im_end|>\n' }}
172
+ {%- else %}
173
+ {{- '<|im_start|>assistant\n<|im_end|>\n' }}
174
+ {%- endif %}
175
+ {%- endif %}
176
+ {%- endif %}
177
+ {%- elif message.role == "user" or message.role == "system" %}
178
+ {{- '<|im_start|>' + message.role + '\n' }}
179
+ {%- set content = message.content | string %}
180
+ {%- if message.role == "user" and loop.index0 == ns.last_user_idx and reasoning_budget is not none %}
181
+ {{- content + '\n\n{thinking token budget: ' + (reasoning_budget | string) + '}' }}
182
+ {%- else %}
183
+ {{- content }}
184
+ {%- endif %}
185
+ {{- '<|im_end|>\n' }}
186
+ {%- elif message.role == "tool" %}
187
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
188
+ {{- '<|im_start|>user\n' }}
189
+ {%- endif %}
190
+ {{- '<tool_response>\n' }}
191
+ {{- message.content }}
192
+ {{- '\n</tool_response>\n' }}
193
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
194
+ {{- '<|im_end|>\n' }}
195
+ {%- elif loop.last %}
196
+ {{- '<|im_end|>\n' }}
197
+ {%- endif %}
198
+ {%- else %}
199
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }}
200
+ {%- endif %}
201
+ {%- endfor %}
202
+
203
+ {%- if add_generation_prompt %}
204
+ {%- if enable_thinking %}
205
+ {{- '<|im_start|>assistant\n<think>\n' }}
206
+ {%- else %}
207
+ {{- '<|im_start|>assistant\n<think></think>' }}
208
+ {%- endif %}
209
+ {%- endif %}
chat_utils.py ADDED
@@ -0,0 +1,342 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import numpy as np
4
+ import torch
5
+ import torch.nn.functional as F
6
+ from torch.nn.attention.flex_attention import create_block_mask
7
+ from transformers.utils import ModelOutput
8
+ from dataclasses import dataclass
9
+ from transformers.cache_utils import Cache
10
+
11
+ @dataclass
12
+ class SimpleOutputWithPast(ModelOutput):
13
+ loss: torch.FloatTensor | None = None
14
+ logits: torch.FloatTensor | None = None
15
+ causal_logits: torch.FloatTensor | None = None
16
+ past_key_values: Cache | None = None
17
+ hidden_states: tuple[torch.FloatTensor, ...] | None = None
18
+ attentions: tuple[torch.FloatTensor, ...] | None = None
19
+ from .utils import maybe_truncate_last_dim, pad_along_last_dim
20
+ from .configuration_nlduni import get_ministral_shift_sbd_logits
21
+ from .sbd_attention import build_image_attention_doc_ids
22
+
23
+ def _resolve_shift_sbd_logits(model, shift_logits):
24
+ model_module = model.module if hasattr(model, 'module') else model
25
+ config = getattr(model_module, 'config', None)
26
+ configured = get_ministral_shift_sbd_logits(config) if config is not None else None
27
+ has_alignment_contract = config is not None
28
+ if shift_logits is None:
29
+ return bool(configured) if configured is not None else False
30
+ requested = bool(shift_logits)
31
+ if has_alignment_contract and requested != configured:
32
+ raise ValueError('Inference shift_logits must match config.shift_sbd_logits to avoid a one-token alignment error. Update the model config explicitly if this override is intentional.')
33
+ return requested
34
+
35
+ def wte(model, x, t2i_inference=False, gen_shape=None, x_gen=None, inputs_embeds_curr=None, new_token_mask=None, x_gen_child_embeddings=None, gen_parent_mask=None, gen_source_null_mask=None, gen_role=None):
36
+ if t2i_inference:
37
+ if (x_gen is None) == (x_gen_child_embeddings is None):
38
+ raise ValueError('provide exactly one of x_gen or x_gen_child_embeddings')
39
+ if new_token_mask is None:
40
+ new_token_mask = x >= INT_MAX
41
+ if gen_parent_mask is not None or gen_source_null_mask is not None or gen_role is not None:
42
+ raise ValueError('structured generation masks and roles require Infinity BSQ')
43
+ gen_latents_comp_embeds = model.call_gen_embedding(x_gen, gen_shape, child_embeddings=x_gen_child_embeddings)
44
+ if inputs_embeds_curr is None:
45
+ x_txt_only = x.clone()
46
+ x_txt_only[new_token_mask] = 0
47
+ inputs_embeds_curr = model.embed_tokens(x_txt_only)
48
+ inputs_embeds_curr[new_token_mask] = pad_along_last_dim(gen_latents_comp_embeds, inputs_embeds_curr.shape[-1]).view(-1, inputs_embeds_curr.shape[-1])
49
+ else:
50
+ inputs_embeds_curr = model.embed_tokens(x)
51
+ new_token_mask = None
52
+ return (inputs_embeds_curr, new_token_mask)
53
+ INT_MAX = 1000000
54
+ SBD_FLEX_ATTENTION_PAD_MULTIPLE = 512
55
+
56
+ def _round_up_to_multiple(length, multiple):
57
+ if isinstance(multiple, bool) or not isinstance(multiple, int) or multiple < 1:
58
+ raise ValueError('padding multiple must be a positive integer')
59
+ return (length + multiple - 1) // multiple * multiple
60
+
61
+ def single_stream_sbd_sampling_mask(block_size, past_length, b, h, q_idx, kv_idx, query_image_doc_id, key_value_image_doc_id):
62
+ del block_size, h
63
+ absolute_q = q_idx + past_length
64
+ token_causal = absolute_q >= kv_idx
65
+ image_query = query_image_doc_id[b, q_idx] > 0
66
+ same_image_doc = image_query & (query_image_doc_id[b, q_idx] == key_value_image_doc_id[b, kv_idx])
67
+ return token_causal | same_image_doc
68
+
69
+ def _create_single_stream_sbd_sampling_block_mask(input_embeddings, *, past_key_values, block_size, input_modality_indices, generation_token_mask=None, pad_to_multiple=None):
70
+ if isinstance(block_size, bool) or not isinstance(block_size, int) or block_size < 1:
71
+ raise ValueError('SBD diffusion sampling requires a positive integer block_size')
72
+ query_length = input_embeddings.shape[1]
73
+ past_length = past_key_values.get_seq_length() if past_key_values is not None else 0
74
+ key_value_length = past_length + query_length
75
+ padded_query_length = _round_up_to_multiple(query_length, pad_to_multiple) if pad_to_multiple is not None else query_length
76
+ padded_key_value_length = _round_up_to_multiple(key_value_length, pad_to_multiple) if pad_to_multiple is not None else key_value_length
77
+ if input_modality_indices is None:
78
+ raise ValueError('SBD diffusion sampling requires input_modality_indices to route same-block generation attention')
79
+ if tuple(input_modality_indices.shape) != tuple(input_embeddings.shape[:2]):
80
+ raise ValueError('SBD diffusion sampling requires input_modality_indices to align with the current input embeddings')
81
+ query_transformer_routing = input_modality_indices.to(dtype=torch.bool)
82
+ if generation_token_mask is None:
83
+ generation_token_mask = query_transformer_routing
84
+ elif tuple(generation_token_mask.shape) != tuple(input_embeddings.shape[:2]):
85
+ raise ValueError('SBD diffusion sampling requires generation_token_mask to align with the current input embeddings')
86
+ query_target_generation_routing = generation_token_mask.to(dtype=torch.bool)
87
+ cached_generation_routing = torch.zeros(query_transformer_routing.shape[0], past_length, dtype=torch.bool, device=query_transformer_routing.device)
88
+ padded_generation_routing = torch.zeros(query_transformer_routing.shape[0], padded_key_value_length - key_value_length, dtype=torch.bool, device=query_transformer_routing.device)
89
+ key_value_target_generation_routing = torch.cat((cached_generation_routing, query_target_generation_routing, padded_generation_routing), dim=1)
90
+ key_value_valid = (torch.arange(padded_key_value_length, device=query_transformer_routing.device).unsqueeze(0) < key_value_length).expand(query_transformer_routing.shape[0], -1).contiguous()
91
+ key_value_image_doc_id = build_image_attention_doc_ids(key_value_target_generation_routing, valid_tokens=key_value_valid)
92
+ query_image_doc_id = torch.cat((key_value_image_doc_id[:, past_length:past_length + query_length], torch.zeros(query_transformer_routing.shape[0], padded_query_length - query_length, dtype=key_value_image_doc_id.dtype, device=query_transformer_routing.device)), dim=1)
93
+ past_length_tensor = torch.tensor(past_length, dtype=torch.long, device=query_transformer_routing.device)
94
+ query_valid = (torch.arange(padded_query_length, device=query_transformer_routing.device).unsqueeze(0) < query_length).expand(query_transformer_routing.shape[0], -1).contiguous()
95
+
96
+ def mask_mod(b, h, q_idx, kv_idx):
97
+ logical_attention = single_stream_sbd_sampling_mask(block_size, past_length_tensor, b, h, q_idx, kv_idx, query_image_doc_id, key_value_image_doc_id) & query_valid[b, q_idx] & key_value_valid[b, kv_idx]
98
+ padded_query_attention = ~query_valid[b, q_idx] & (kv_idx == 0)
99
+ return logical_attention | padded_query_attention
100
+ return create_block_mask(mask_mod, B=input_embeddings.shape[0], H=None, Q_LEN=padded_query_length, KV_LEN=padded_key_value_length, device=input_embeddings.device)
101
+
102
+ def get_logits(model, input_emnbeddings, modality_indices=None, t2i_inference=False, past_key_values=None, gen_shape=None, timesteps=None, input_modality_indices=None, generation_attention_mask=None, sbd_diffusion_sampling=False, full_attention_approx=False, loop_k=None):
103
+ if t2i_inference:
104
+ resolved_loop_k = None
105
+ if input_modality_indices is None:
106
+ input_modality_indices = modality_indices
107
+ attention_kwargs = {}
108
+ if full_attention_approx:
109
+ attention_kwargs['overwrite_block_mask'] = 'full'
110
+ attention_kwargs['overwrite_attn_impl'] = 'flash_attn'
111
+ elif sbd_diffusion_sampling:
112
+ if generation_attention_mask is None:
113
+ generation_attention_mask = modality_indices
114
+ attention_kwargs['overwrite_block_mask'] = _create_single_stream_sbd_sampling_block_mask(input_emnbeddings, past_key_values=past_key_values, block_size=getattr(model.config, 'block_size', None), input_modality_indices=input_modality_indices, generation_token_mask=generation_attention_mask, pad_to_multiple=SBD_FLEX_ATTENTION_PAD_MULTIPLE)
115
+ else:
116
+ attention_kwargs['overwrite_attn_impl'] = 'flash_attn'
117
+ output = model(None, input_embeddings=input_emnbeddings, modality_indices=input_modality_indices, output_hidden_states=True, past_key_values=past_key_values, use_cache=None, single_stream_image_diffusion=True, loop_k=None, **attention_kwargs)
118
+ hidden_states = getattr(output, 'last_hidden_state', None)
119
+ if hidden_states is None:
120
+ hidden_states = output.hidden_states[-1]
121
+ gen_hidden_states = hidden_states[modality_indices]
122
+ gen_hidden_states = maybe_truncate_last_dim(gen_hidden_states, model.config.d_model_gen)
123
+ gen_logits = model.call_gen_predictor(gen_hidden_states, gen_shape, timesteps=timesteps)
124
+ seq_len_per_img = np.prod(gen_shape)
125
+ if len(gen_logits.shape) == 2:
126
+ gen_logits = gen_logits.view(-1, seq_len_per_img, gen_logits.shape[-1])
127
+ else:
128
+ gen_logits = gen_logits.view(-1, seq_len_per_img, *gen_logits.shape[-2:])
129
+ return gen_logits
130
+ else:
131
+ raise ValueError('get_logits is the image sampler helper')
132
+
133
+ def add_gumbel_noise(logits, temperature):
134
+ if temperature == 0:
135
+ return logits
136
+ logits = logits.to(torch.float64)
137
+ noise = torch.rand_like(logits, dtype=torch.float64)
138
+ gumbel_noise = (-torch.log(noise)) ** temperature
139
+ return logits.exp() / gumbel_noise
140
+
141
+ def get_transfer_index(logits, temperature, remasking, mask_index, x, num_transfer_tokens, threshold=None, neg_entropy=False):
142
+ logits_with_noise = add_gumbel_noise(logits, temperature=temperature)
143
+ x0 = torch.argmax(logits_with_noise, dim=-1)
144
+ if remasking == 'low_confidence':
145
+ p = F.softmax(logits, dim=-1)
146
+ x0_p = torch.squeeze(torch.gather(p, dim=-1, index=torch.unsqueeze(x0, -1)), -1)
147
+ elif remasking == 'top_p_margin':
148
+ p = F.softmax(logits, dim=-1)
149
+ top2 = torch.topk(p, k=2, dim=-1).values
150
+ margin = top2[..., 0] - top2[..., 1]
151
+ plus_inf = torch.full_like(margin, 1e309)
152
+ minus_inf = torch.full_like(margin, -1e309)
153
+ masked_for_min = torch.where(mask_index, margin, plus_inf)
154
+ masked_for_max = torch.where(mask_index, margin, minus_inf)
155
+ row_min = masked_for_min.amin(dim=1, keepdim=True)
156
+ row_max = masked_for_max.amax(dim=1, keepdim=True)
157
+ denom = row_max - row_min
158
+ normalized = torch.zeros_like(margin)
159
+ nonzero = denom > 0
160
+ normalized = torch.where(mask_index & nonzero, (margin - row_min) / (denom + 1e-12), normalized)
161
+ normalized = torch.where(mask_index & ~nonzero, torch.ones_like(normalized), normalized)
162
+ x0_p = normalized
163
+ elif remasking == 'random':
164
+ x0_p = torch.rand((x0.shape[0], x0.shape[1]), device=x0.device)
165
+ else:
166
+ raise NotImplementedError(remasking)
167
+ if neg_entropy:
168
+ p = F.softmax(logits, dim=-1)
169
+ epsilon = 1e-10
170
+ log_probs = torch.log(p + epsilon)
171
+ confidence_scores = torch.sum(p * log_probs, dim=-1)
172
+ else:
173
+ confidence_scores = x0_p
174
+ x0 = torch.where(mask_index, x0, x)
175
+ confidence = torch.where(mask_index, confidence_scores, -np.inf)
176
+ transfer_index = torch.zeros_like(x0, dtype=torch.bool, device=x0.device)
177
+ if threshold is not None:
178
+ num_transfer_tokens = mask_index.sum(dim=1, keepdim=True)
179
+ for j in range(confidence.shape[0]):
180
+ (_, select_index) = torch.topk(confidence[j], k=num_transfer_tokens[j])
181
+ transfer_index[j, select_index] = True
182
+ if threshold is not None:
183
+ for k in range(1, num_transfer_tokens[j]):
184
+ if confidence[j, select_index[k]] < threshold:
185
+ transfer_index[j, select_index[k]] = False
186
+ return (x0, transfer_index)
187
+
188
+ def get_num_transfer_tokens(mask_index, steps: int):
189
+ mask_num = mask_index.sum(dim=1, keepdim=True)
190
+ base = mask_num // steps
191
+ remainder = mask_num % steps
192
+ num_transfer_tokens = torch.zeros(mask_num.size(0), steps, device=mask_index.device, dtype=torch.int64) + base
193
+ for i in range(mask_num.size(0)):
194
+ num_transfer_tokens[i, :int(remainder[i])] += 1
195
+ return num_transfer_tokens
196
+
197
+ def simple_fwd(model, input_ids=None, inputs_embeds=None, attention_mask=None, position_ids=None, past_key_values=None, **kwargs):
198
+ enc_out = model.encoder(past_key_values=past_key_values, input_ids=input_ids, inputs_embeds=inputs_embeds, attention_mask=attention_mask, position_ids=position_ids, overwrite_attn_impl='flash_attn', **kwargs)
199
+ logits = model.diffusion_head(enc_out.last_hidden_state)
200
+ return SimpleOutputWithPast(loss=logits, logits=logits, causal_logits=None, past_key_values=enc_out.past_key_values, hidden_states=None, attentions=None)
201
+
202
+ @torch.no_grad()
203
+ def generate_with_prefix_cache_block_diff(model, prompt=None, prompt_embeds=None, steps=128, gen_length=128, block_length=128, temperature=0.0, remasking='low_confidence', mask_id=126336, threshold=None, factor=None, shift_logits=None, neg_entropy=False, causal_context=False, eos_token_id=None, max_thinking_tokens=None, end_think_token_id=None):
204
+ shift_logits = _resolve_shift_sbd_logits(model, shift_logits)
205
+ dream_style = shift_logits
206
+ if (prompt is None) == (prompt_embeds is None):
207
+ raise ValueError('Exactly one of `prompt` or `prompt_embeds` must be provided.')
208
+ if prompt is not None:
209
+ prompt_ids = prompt
210
+ prompt_len = prompt_ids.shape[1]
211
+ x_accum = prompt_ids.clone()
212
+ B = prompt_ids.shape[0]
213
+ token_device = prompt_ids.device
214
+ token_dtype = prompt_ids.dtype
215
+ else:
216
+ prompt_ids = None
217
+ prompt_len = prompt_embeds.shape[1]
218
+ B = prompt_embeds.shape[0]
219
+ token_device = prompt_embeds.device
220
+ token_dtype = torch.long
221
+ x_accum = torch.full((B, prompt_len), mask_id, dtype=token_dtype, device=token_device)
222
+ if gen_length % block_length != 0:
223
+ gen_length = (gen_length // block_length + 1) * block_length
224
+ num_blocks = gen_length // block_length
225
+ assert steps % num_blocks == 0
226
+ steps_per_block = steps // num_blocks
227
+ nfe = 0
228
+ model_module = model.module if hasattr(model, 'module') else model
229
+ for layer in model_module.encoder.layers:
230
+ layer.self_attn.mode = 'bidirectional'
231
+ if causal_context:
232
+ for layer in model_module.encoder.layers:
233
+ if hasattr(layer.self_attn, 'diffusion_lm'):
234
+ layer.self_attn.diffusion_lm = False
235
+ output = simple_fwd(model, input_ids=prompt_ids, inputs_embeds=prompt_embeds, use_cache=True, use_causal_mask=causal_context)
236
+ past_key_values = output.past_key_values
237
+ if causal_context:
238
+ for layer in model_module.encoder.layers:
239
+ if hasattr(layer.self_attn, 'diffusion_lm'):
240
+ layer.self_attn.diffusion_lm = True
241
+ next_token = None
242
+ if causal_context:
243
+ last_logit = output.logits[:, -1, :]
244
+ if temperature > 0:
245
+ probs = torch.softmax(last_logit / temperature, dim=-1)
246
+ next_token = torch.multinomial(probs, num_samples=1)
247
+ else:
248
+ next_token = torch.argmax(last_logit, dim=-1, keepdim=True)
249
+ next_logits_context = None
250
+ if dream_style:
251
+ next_logits_context = output.logits[:, -1:, :]
252
+ for num_block in range(num_blocks):
253
+ mask_block = torch.ones((B, block_length), dtype=token_dtype, device=token_device) * mask_id
254
+ if causal_context:
255
+ mask_block[:, 0] = next_token[:, 0]
256
+ x_accum = torch.cat([x_accum, mask_block], dim=1)
257
+ current_block_start = prompt_len + num_block * block_length
258
+ block_slice = slice(current_block_start, current_block_start + block_length)
259
+ if end_think_token_id is not None and max_thinking_tokens is not None:
260
+ tokens_before_block = num_block * block_length
261
+ tokens_after_block = tokens_before_block + block_length
262
+ if tokens_after_block > max_thinking_tokens:
263
+ gen_so_far = x_accum[:, prompt_len:current_block_start]
264
+ has_end_think = (gen_so_far == end_think_token_id).any(dim=1) if gen_so_far.size(1) > 0 else torch.zeros(B, dtype=torch.bool, device=token_device)
265
+ if not has_end_think.all():
266
+ if tokens_before_block < max_thinking_tokens:
267
+ offset = max_thinking_tokens - tokens_before_block
268
+ else:
269
+ offset = 0
270
+ inject_pos = current_block_start + offset
271
+ for b in range(B):
272
+ if not has_end_think[b]:
273
+ x_accum[b, inject_pos] = end_think_token_id
274
+ mask_block_idx0 = x_accum[:, block_slice] == mask_id
275
+ if dream_style:
276
+ schedule_mask = mask_block_idx0
277
+ else:
278
+ schedule_mask = mask_block_idx0
279
+ num_transfer_tokens = get_num_transfer_tokens(schedule_mask, steps_per_block)
280
+ for i in range(steps_per_block):
281
+ mask_block_idx = x_accum[:, block_slice] == mask_id
282
+ if mask_block_idx.sum() == 0:
283
+ break
284
+ nfe += 1
285
+ logits_block = simple_fwd(model, x_accum[:, block_slice], past_key_values=past_key_values, use_cache=False).logits
286
+ if dream_style:
287
+ if block_length == 1:
288
+ logits_use = next_logits_context
289
+ else:
290
+ logits_use = torch.cat([next_logits_context, logits_block[:, :-1, :]], dim=1)
291
+ mask_use = mask_block_idx
292
+ x_use = x_accum[:, block_slice]
293
+ (x0, transfer_idx) = get_transfer_index(logits_use, temperature, remasking, mask_use, x_use, num_transfer_tokens=num_transfer_tokens[:, i], threshold=threshold, neg_entropy=neg_entropy)
294
+ cur = x_accum[:, block_slice].clone()
295
+ cur[transfer_idx] = x0[transfer_idx]
296
+ x_accum[:, block_slice] = cur
297
+ else:
298
+ (x0, transfer_idx) = get_transfer_index(logits_block, temperature, remasking, mask_block_idx, x_accum[:, block_slice], num_transfer_tokens=num_transfer_tokens[:, i], threshold=threshold, neg_entropy=neg_entropy)
299
+ cur = x_accum[:, block_slice].clone()
300
+ cur[transfer_idx] = x0[transfer_idx]
301
+ x_accum[:, block_slice] = cur
302
+ if eos_token_id is not None:
303
+ block_tokens = x_accum[:, block_slice]
304
+ eos_mask = block_tokens == eos_token_id
305
+ any_eos = eos_mask.any(dim=1)
306
+ if any_eos.any():
307
+ after_eos = eos_mask.cumsum(dim=1).bool()
308
+ mask_before = (block_tokens == mask_id) & ~after_eos
309
+ if (any_eos & ~mask_before.any(dim=1)).any():
310
+ break
311
+ if causal_context:
312
+ for layer in model_module.encoder.layers:
313
+ if hasattr(layer.self_attn, 'diffusion_lm'):
314
+ layer.self_attn.diffusion_lm = False
315
+ output = simple_fwd(model, x_accum[:, block_slice], past_key_values=past_key_values, use_cache=True, use_causal_mask=causal_context)
316
+ past_key_values = output.past_key_values
317
+ nfe += 1
318
+ if causal_context:
319
+ for layer in model_module.encoder.layers:
320
+ if hasattr(layer.self_attn, 'diffusion_lm'):
321
+ layer.self_attn.diffusion_lm = True
322
+ last_logit = output.logits[:, -1, :]
323
+ if temperature > 0:
324
+ probs = torch.softmax(last_logit / temperature, dim=-1)
325
+ next_token = torch.multinomial(probs, num_samples=1)
326
+ else:
327
+ next_token = torch.argmax(last_logit, dim=-1, keepdim=True)
328
+ if dream_style and num_block < num_blocks - 1:
329
+ next_logits_context = output.logits[:, -1:, :]
330
+ if eos_token_id is not None:
331
+ gen_so_far = x_accum[:, prompt_len:]
332
+ is_eos = gen_so_far == eos_token_id
333
+ has_eos = is_eos.any(dim=1)
334
+ if has_eos.all():
335
+ first_eos_pos = is_eos.to(torch.int64).argmax(dim=1)
336
+ max_eos = first_eos_pos.max().item()
337
+ if prompt_ids is None:
338
+ return (x_accum[:, prompt_len:prompt_len + max_eos + 1], nfe)
339
+ return (x_accum[:, :prompt_len + max_eos + 1], nfe)
340
+ if prompt_ids is None:
341
+ return (x_accum[:, prompt_len:], nfe)
342
+ return (x_accum, nfe)
config.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "hidden_size": 4096,
3
+ "intermediate_size": 14336,
4
+ "num_hidden_layers": 34,
5
+ "num_attention_heads": 32,
6
+ "num_key_value_heads": 8,
7
+ "head_dim": 128,
8
+ "vocab_size": 132101,
9
+ "max_position_embeddings": 131072,
10
+ "rms_norm_eps": 1e-05,
11
+ "rope_parameters": {
12
+ "beta_fast": 32.0,
13
+ "beta_slow": 1.0,
14
+ "factor": 8.0,
15
+ "llama_4_scaling_beta": 0.1,
16
+ "mscale": 1.0,
17
+ "mscale_all_dim": 1.0,
18
+ "original_max_position_embeddings": 16384,
19
+ "rope_theta": 1000000.0,
20
+ "rope_type": "yarn"
21
+ },
22
+ "bos_token_id": 1,
23
+ "eos_token_id": 11,
24
+ "pad_token_id": 11,
25
+ "tie_word_embeddings": false,
26
+ "model_type": "nlduni",
27
+ "architectures": [
28
+ "NLDUniForCausalLM"
29
+ ],
30
+ "torch_dtype": "bfloat16",
31
+ "auto_map": {
32
+ "AutoConfig": "configuration_nlduni.NLDUniConfig",
33
+ "AutoModel": "modeling_nlduni.NLDUniForCausalLM",
34
+ "AutoModelForCausalLM": "modeling_nlduni.NLDUniForCausalLM"
35
+ }
36
+ }
configuration_nlduni.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+ class NLDUniConfig(PretrainedConfig):
4
+ model_type = 'nlduni'
5
+ # Architecture invariants; deliberately absent from serialized configuration.
6
+ d_model_gen = 4096
7
+ d_model = 4096
8
+ diffusion_lm = True
9
+ block_size = 32
10
+ mm_native_newline_token = '\n'
11
+ mm_hidden_size = 1280
12
+ projector_hidden_size = 4096
13
+ gen_image_fixed_prefix_tokens = 128
14
+ gen_image_row_markers = True
15
+ generation_skip_down_sample = False
16
+ image_aspect_ratio = 'radio_h_native'
17
+ semantic_tree_token_diffusion = True
18
+ single_stream_image_diffusion = True
19
+ shift_sbd_logits = True
20
+ downsample = True
21
+ mm_vqvae = 'emu3'
22
+ image_embedding_refinement_steps = 4
23
+ lock_source_padding_vq = True
24
+ generation_embedding_scale = 0.005357294692673304
25
+ generation_downsample_scale = 0.4498539166224965
26
+ def __init__(self, hidden_size=4096, intermediate_size=14336, num_hidden_layers=34,
27
+ num_attention_heads=32, num_key_value_heads=8, head_dim=128,
28
+ vocab_size=132101, max_position_embeddings=131072,
29
+ rms_norm_eps=1e-5, rope_parameters=None, **kwargs):
30
+ super().__init__(**kwargs)
31
+ self.hidden_size=hidden_size
32
+ self.intermediate_size=intermediate_size
33
+ self.num_hidden_layers=num_hidden_layers
34
+ self.num_attention_heads=num_attention_heads
35
+ self.num_key_value_heads=num_key_value_heads
36
+ self.head_dim=head_dim
37
+ self.vocab_size=vocab_size
38
+ self.max_position_embeddings=max_position_embeddings
39
+ self.rms_norm_eps=rms_norm_eps
40
+ self.hidden_act='silu'
41
+ self.attention_bias=False
42
+ self.attention_dropout=0.0
43
+ self.mlp_bias=False
44
+ self.sliding_window=None
45
+ self.initializer_range=0.02
46
+ self.rope_parameters=rope_parameters or dict(rope_type='yarn',rope_theta=1000000.,factor=8.,original_max_position_embeddings=16384,beta_fast=32.,beta_slow=1.,mscale=1.,mscale_all_dim=1.,llama_4_scaling_beta=.1)
47
+ self.rope_scaling=self.rope_parameters
48
+ self.rope_theta=self.rope_parameters['rope_theta']
49
+
50
+ def to_dict(self):
51
+ values = super().to_dict()
52
+ values.pop('image_token_tree_path', None)
53
+ values.pop('_name_or_path', None)
54
+ return values
55
+
56
+ MinistralDLMConfig = NLDUniConfig
57
+
58
+ def get_ministral_shift_sbd_logits(config):
59
+ return True
constants.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ class NemotronMinistralDLMConstant:
4
+ reserve_id = 18
5
+ reserve_id_token = '<SPECIAL_18>'
6
+ reserve_id_enc = 19
7
+ reserve_id_token_enc = '<SPECIAL_19>'
8
+ mask_id = 100
9
+ mask_id_token = '<SPECIAL_100>'
10
+ fim_id = 20
11
+ fim_id_token = '<SPECIAL_20>'
12
+ eos_id = 11
13
+ eos_id_token = '<|im_end|>'
14
+ gen_im_start_token = '<SPECIAL_21>'
15
+ gen_im_end_token = '<SPECIAL_22>'
16
+ und_im_pad_token = '<SPECIAL_23>'
17
+ und_im_pad_token_id = 23
conversation.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+
3
+ class Conversation:
4
+ roles = ('<|im_start|>user', '<|im_start|>assistant')
5
+ system = '<|im_start|>system\nYou are a helpful language and vision assistant. You are able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language.'
6
+ def __init__(self):
7
+ self.messages = []
8
+ def copy(self):
9
+ return copy.deepcopy(self)
10
+ def append_message(self, role, message):
11
+ self.messages.append((role, message))
12
+ def get_prompt(self):
13
+ text = self.system + '<|im_end|>\n' if self.system else ''
14
+ for role, message in self.messages:
15
+ text += role + '\n'
16
+ if message:
17
+ text += message + '<|im_end|>\n'
18
+ return text
19
+
20
+ conv_templates = {'ministral': Conversation()}
core.py ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ from collections.abc import Callable
4
+ from dataclasses import dataclass
5
+ from typing import Optional, Union
6
+ import torch
7
+ from torch import nn
8
+ from transformers.utils.generic import check_model_inputs
9
+ from transformers.activations import ACT2FN
10
+ from transformers.cache_utils import Cache, DynamicCache
11
+ from transformers.integrations import use_kernel_forward_from_hub
12
+ from transformers.masking_utils import create_causal_mask, create_sliding_window_causal_mask
13
+ from transformers.modeling_flash_attention_utils import FlashAttentionKwargs
14
+ from transformers.modeling_layers import GradientCheckpointingLayer
15
+ from transformers.modeling_outputs import BaseModelOutputWithPast
16
+ from transformers.modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
17
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
18
+ from transformers.processing_utils import Unpack
19
+ from transformers.utils import TransformersKwargs, auto_docstring
20
+ from .configuration_nlduni import MinistralDLMConfig
21
+
22
+ def rotate_half(x):
23
+ x1 = x[..., :x.shape[-1] // 2]
24
+ x2 = x[..., x.shape[-1] // 2:]
25
+ return torch.cat((-x2, x1), dim=-1)
26
+
27
+ def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
28
+ cos = cos.unsqueeze(unsqueeze_dim)
29
+ sin = sin.unsqueeze(unsqueeze_dim)
30
+ q_embed = q * cos + rotate_half(q) * sin
31
+ k_embed = k * cos + rotate_half(k) * sin
32
+ return (q_embed, k_embed)
33
+
34
+ def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
35
+ (batch, num_key_value_heads, slen, head_dim) = hidden_states.shape
36
+ if n_rep == 1:
37
+ return hidden_states
38
+ hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
39
+ return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
40
+
41
+ def eager_attention_forward(module: nn.Module, query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, attention_mask: Optional[torch.Tensor], scaling: float, dropout: float=0.0, **kwargs: Unpack[TransformersKwargs]):
42
+ key_states = repeat_kv(key, module.num_key_value_groups)
43
+ value_states = repeat_kv(value, module.num_key_value_groups)
44
+ attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
45
+ if attention_mask is not None:
46
+ causal_mask = attention_mask[:, :, :, :key_states.shape[-2]]
47
+ attn_weights = attn_weights + causal_mask
48
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
49
+ attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=False)
50
+ attn_output = torch.matmul(attn_weights, value_states)
51
+ attn_output = attn_output.transpose(1, 2).contiguous()
52
+ return (attn_output, attn_weights)
53
+
54
+ def _get_llama_4_attn_scale(positions_ids: torch.Tensor, beta: float, max_position_embeddings: int) -> torch.Tensor:
55
+ scaling = 1 + beta * torch.log(1 + torch.floor(positions_ids / max_position_embeddings))
56
+ return scaling.unsqueeze(-1)
57
+
58
+ @dataclass(frozen=True, slots=True)
59
+ class _MixedTokenRoutingPlan:
60
+ mask: torch.Tensor
61
+ understanding_indices: torch.Tensor
62
+ generation_indices: torch.Tensor
63
+
64
+ @classmethod
65
+ def from_mask(cls, mask: torch.Tensor) -> '_MixedTokenRoutingPlan':
66
+ flat_mask = mask.reshape(-1)
67
+ return cls(mask=mask, understanding_indices=(~flat_mask).nonzero(as_tuple=False).flatten(), generation_indices=flat_mask.nonzero(as_tuple=False).flatten())
68
+ TokenRouting = Optional[Union[bool, _MixedTokenRoutingPlan]]
69
+
70
+ def _resolve_dual_tower_layers(config: MinistralDLMConfig) -> int:
71
+ num_hidden_layers = config.num_hidden_layers
72
+ configured = 18
73
+ if configured is None:
74
+ return num_hidden_layers
75
+ if isinstance(configured, bool) or not isinstance(configured, int):
76
+ raise TypeError('dual_tower_layers must be an integer')
77
+ if not 0 <= configured <= num_hidden_layers:
78
+ raise ValueError(f'dual_tower_layers must be between 0 and num_hidden_layers ({num_hidden_layers}), got {configured}')
79
+ return configured
80
+
81
+ def _routing_mask(routing: TokenRouting, hidden_states: torch.Tensor) -> torch.Tensor:
82
+ if routing is None:
83
+ return torch.zeros(hidden_states.shape[:2], dtype=torch.bool, device=hidden_states.device)
84
+ if routing is True:
85
+ return torch.ones(hidden_states.shape[:2], dtype=torch.bool, device=hidden_states.device)
86
+ return routing.mask
87
+
88
+ def _create_split_tower_block_mask(block_mask, *, current_routing: torch.Tensor, cached_routing: torch.Tensor):
89
+ from torch.nn.attention.flex_attention import BlockMask, create_block_mask
90
+ if isinstance(block_mask, str):
91
+ if block_mask != 'full':
92
+ raise ValueError(f'Unsupported attention block-mask sentinel: {block_mask}')
93
+ base_mask_mod = None
94
+ query_length = current_routing.shape[1]
95
+ key_value_length = cached_routing.shape[1] + query_length
96
+ block_size = 128
97
+ elif isinstance(block_mask, BlockMask):
98
+ base_mask_mod = block_mask.mask_mod
99
+ (query_length, key_value_length) = block_mask.seq_lengths
100
+ block_size = block_mask.BLOCK_SIZE
101
+ else:
102
+ raise TypeError("partial dual-tower FlexAttention requires an explicit BlockMask or the 'full' sentinel")
103
+ current_length = current_routing.shape[1]
104
+ cached_length = cached_routing.shape[1]
105
+ if query_length < current_length:
106
+ raise ValueError(f'FlexAttention block-mask query length is shorter than routing: {query_length} < {current_length}')
107
+ if key_value_length < cached_length + current_length:
108
+ raise ValueError(f'FlexAttention block-mask key/value length is shorter than cached and current routing: {key_value_length} < {cached_length + current_length}')
109
+ query_routing = torch.nn.functional.pad(current_routing, (0, query_length - current_length), value=False)
110
+ key_value_routing = torch.cat((cached_routing, current_routing), dim=1)
111
+ key_value_routing = torch.nn.functional.pad(key_value_routing, (0, key_value_length - key_value_routing.shape[1]), value=False)
112
+
113
+ def split_tower_mask(b, h, q_idx, kv_idx):
114
+ same_tower = query_routing[b, q_idx] == key_value_routing[b, kv_idx]
115
+ same_tower = same_tower | (q_idx >= current_length)
116
+ if base_mask_mod is None:
117
+ return same_tower
118
+ return base_mask_mod(b, h, q_idx, kv_idx) & same_tower
119
+ return create_block_mask(split_tower_mask, B=current_routing.shape[0], H=None, Q_LEN=query_length, KV_LEN=key_value_length, device=current_routing.device, BLOCK_SIZE=block_size)
120
+
121
+ def _canonicalize_token_routing(routing: Optional[torch.Tensor], hidden_states: torch.Tensor, *, dual_tower: bool) -> TokenRouting:
122
+ if routing is None:
123
+ return None
124
+ if not torch.is_tensor(routing) or routing.ndim != 2:
125
+ raise TypeError('routing must be a rank-2 tensor with shape [batch, sequence]')
126
+ if tuple(routing.shape) != tuple(hidden_states.shape[:2]):
127
+ raise ValueError(f'routing must match the transformer token shape: expected {tuple(hidden_states.shape[:2])}, got {tuple(routing.shape)}')
128
+ if routing.device != hidden_states.device:
129
+ raise ValueError('routing and transformer hidden states must share a device')
130
+ if routing.dtype == torch.bool:
131
+ normalized = routing
132
+ elif routing.dtype in {torch.uint8, torch.int8, torch.int16, torch.int32, torch.int64}:
133
+ if bool(((routing != 0) & (routing != 1)).any()):
134
+ raise ValueError('routing values must be binary (0 for U, 1 for G)')
135
+ normalized = routing.to(dtype=torch.bool)
136
+ else:
137
+ raise TypeError('routing must have boolean or integer dtype')
138
+ has_generation_route = bool(normalized.any())
139
+ if has_generation_route and (not dual_tower):
140
+ raise ValueError('routing selects G but config.dual_tower is false')
141
+ if not has_generation_route:
142
+ return None
143
+ if bool(normalized.all()):
144
+ return True
145
+ return _MixedTokenRoutingPlan.from_mask(normalized)
146
+
147
+ def _routed_module(hidden_states: torch.Tensor, routing: TokenRouting, understanding_module: Callable[[torch.Tensor], torch.Tensor], generation_module: Optional[Callable[[torch.Tensor], torch.Tensor]]) -> torch.Tensor:
148
+ if routing is None:
149
+ return understanding_module(hidden_states)
150
+ if routing is True:
151
+ if generation_module is None:
152
+ raise RuntimeError('G routing requires generation-tower parameters')
153
+ return generation_module(hidden_states)
154
+ if generation_module is None:
155
+ raise RuntimeError('mixed routing requires generation-tower parameters')
156
+ if not isinstance(routing, _MixedTokenRoutingPlan):
157
+ raise TypeError('mixed routing must use a canonical dispatch plan')
158
+ flat_hidden = hidden_states.reshape(-1, hidden_states.shape[-1])
159
+ understanding_output = understanding_module(flat_hidden.index_select(0, routing.understanding_indices))
160
+ generation_output = generation_module(flat_hidden.index_select(0, routing.generation_indices))
161
+ flat_output = understanding_output.new_empty((flat_hidden.shape[0], *understanding_output.shape[1:]))
162
+ flat_output = flat_output.index_copy(0, routing.understanding_indices, understanding_output)
163
+ flat_output = flat_output.index_copy(0, routing.generation_indices, generation_output)
164
+ return flat_output.reshape(*hidden_states.shape[:-1], *flat_output.shape[1:])
165
+
166
+ class Ministral3Attention(nn.Module):
167
+
168
+ def __init__(self, config: MinistralDLMConfig, layer_idx: int):
169
+ super().__init__()
170
+ self.config = config
171
+ self.layer_idx = layer_idx
172
+ self.split_tower = layer_idx >= _resolve_dual_tower_layers(config)
173
+ self.head_dim = getattr(config, 'head_dim', None) or config.hidden_size // config.num_attention_heads
174
+ self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
175
+ self.scaling = self.head_dim ** -0.5
176
+ self.attention_dropout = config.attention_dropout
177
+ self.is_causal = True
178
+ self.q_proj = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=False)
179
+ self.k_proj = nn.Linear(config.hidden_size, config.num_key_value_heads * self.head_dim, bias=False)
180
+ self.v_proj = nn.Linear(config.hidden_size, config.num_key_value_heads * self.head_dim, bias=False)
181
+ self.o_proj = nn.Linear(config.num_attention_heads * self.head_dim, config.hidden_size, bias=False)
182
+ self.q_proj_gen = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=False)
183
+ self.k_proj_gen = nn.Linear(config.hidden_size, config.num_key_value_heads * self.head_dim, bias=False)
184
+ self.v_proj_gen = nn.Linear(config.hidden_size, config.num_key_value_heads * self.head_dim, bias=False)
185
+ self.o_proj_gen = nn.Linear(config.num_attention_heads * self.head_dim, config.hidden_size, bias=False)
186
+ self.diffusion_lm = config.diffusion_lm
187
+
188
+ def _project_qkv(self, hidden_states: torch.Tensor, routing: TokenRouting) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
189
+ return (_routed_module(hidden_states, routing, self.q_proj, getattr(self, 'q_proj_gen', None)), _routed_module(hidden_states, routing, self.k_proj, getattr(self, 'k_proj_gen', None)), _routed_module(hidden_states, routing, self.v_proj, getattr(self, 'v_proj_gen', None)))
190
+
191
+ def _project_output(self, hidden_states: torch.Tensor, routing: TokenRouting) -> torch.Tensor:
192
+ return _routed_module(hidden_states, routing, self.o_proj, getattr(self, 'o_proj_gen', None))
193
+
194
+ def forward(self, hidden_states: torch.Tensor, position_embeddings: tuple[torch.Tensor, torch.Tensor], attention_mask: Optional[torch.Tensor], past_key_values: Optional[Cache]=None, cache_position: Optional[torch.LongTensor]=None, use_cache: Optional[bool]=False, routing: TokenRouting=None, **kwargs: Unpack[FlashAttentionKwargs]) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
195
+ input_shape = hidden_states.shape[:-1]
196
+ hidden_shape = (*input_shape, -1, self.head_dim)
197
+ (query_states, key_states, value_states) = self._project_qkv(hidden_states, routing)
198
+ query_states = query_states.view(hidden_shape).transpose(1, 2)
199
+ key_states = key_states.view(hidden_shape).transpose(1, 2)
200
+ value_states = value_states.view(hidden_shape).transpose(1, 2)
201
+ (cos, sin) = position_embeddings
202
+ (query_states, key_states) = apply_rotary_pos_emb(query_states, key_states, cos, sin)
203
+ query_states = query_states * _get_llama_4_attn_scale(cache_position, self.config.rope_parameters.get('llama_4_scaling_beta'), self.config.rope_parameters.get('original_max_position_embeddings')).to(query_states.dtype)
204
+ if past_key_values is not None:
205
+ if use_cache:
206
+ cache_kwargs = {'sin': sin, 'cos': cos, 'cache_position': cache_position}
207
+ (key_states, value_states) = past_key_values.update(key_states, value_states, self.layer_idx, cache_kwargs)
208
+ else:
209
+ (old_k, old_v) = (past_key_values.layers[self.layer_idx].keys, past_key_values.layers[self.layer_idx].values)
210
+ key_states = torch.cat([old_k, key_states], dim=-2)
211
+ value_states = torch.cat([old_v, value_states], dim=-2)
212
+ attention_interface: Callable = eager_attention_forward
213
+ if self.config._attn_implementation != 'eager':
214
+ attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
215
+ if self.diffusion_lm:
216
+ (attn_output, attn_weights) = attention_interface(self, query_states, key_states, value_states, None, dropout=0.0, scaling=self.scaling, is_causal=False, **kwargs)
217
+ else:
218
+ (attn_output, attn_weights) = attention_interface(self, query_states, key_states, value_states, attention_mask, dropout=0.0, scaling=self.scaling, sliding_window=getattr(self.config, 'sliding_window', None), **kwargs)
219
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
220
+ attn_output = self._project_output(attn_output, routing)
221
+ return (attn_output, attn_weights)
222
+
223
+ class Ministral3MLP(nn.Module):
224
+
225
+ def __init__(self, config):
226
+ super().__init__()
227
+ self.config = config
228
+ self.hidden_size = config.hidden_size
229
+ self.intermediate_size = config.intermediate_size
230
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
231
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
232
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
233
+ self.gate_proj_gen = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
234
+ self.up_proj_gen = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
235
+ self.down_proj_gen = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
236
+ self.act_fn = ACT2FN[config.hidden_act]
237
+
238
+ def _understanding_forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
239
+ return self.down_proj(self.act_fn(self.gate_proj(hidden_states)) * self.up_proj(hidden_states))
240
+
241
+ def _generation_forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
242
+ return self.down_proj_gen(self.act_fn(self.gate_proj_gen(hidden_states)) * self.up_proj_gen(hidden_states))
243
+
244
+ def forward(self, hidden_states: torch.Tensor, routing: TokenRouting=None) -> torch.Tensor:
245
+ generation_module = self._generation_forward if hasattr(self, 'gate_proj_gen') else None
246
+ return _routed_module(hidden_states, routing, self._understanding_forward, generation_module)
247
+
248
+ @use_kernel_forward_from_hub('RMSNorm')
249
+ class Ministral3RMSNorm(nn.Module):
250
+
251
+ def __init__(self, hidden_size, eps=1e-06):
252
+ super().__init__()
253
+ self.weight = nn.Parameter(torch.ones(hidden_size))
254
+ self.variance_epsilon = eps
255
+
256
+ def forward(self, hidden_states):
257
+ input_dtype = hidden_states.dtype
258
+ hidden_states = hidden_states.to(torch.float32)
259
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
260
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
261
+ return self.weight * hidden_states.to(input_dtype)
262
+
263
+ def extra_repr(self):
264
+ return f'{tuple(self.weight.shape)}, eps={self.variance_epsilon}'
265
+
266
+ class Ministral3DecoderLayer(GradientCheckpointingLayer):
267
+
268
+ def __init__(self, config: MinistralDLMConfig, layer_idx: int):
269
+ super().__init__()
270
+ self.hidden_size = config.hidden_size
271
+ from .attention import MinistralFlexAttention
272
+ attn_class = MinistralFlexAttention
273
+ self.self_attn = attn_class(config=config, layer_idx=layer_idx)
274
+ self.mlp = Ministral3MLP(config)
275
+ self.input_layernorm = Ministral3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
276
+ self.post_attention_layernorm = Ministral3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
277
+ self.input_layernorm_gen = Ministral3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
278
+ self.post_attention_layernorm_gen = Ministral3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
279
+
280
+ def forward(self, hidden_states: torch.Tensor, attention_mask: Optional[torch.Tensor]=None, position_ids: Optional[torch.LongTensor]=None, past_key_values: Optional[Cache]=None, use_cache: Optional[bool]=False, cache_position: Optional[torch.LongTensor]=None, position_embeddings: Optional[tuple[torch.Tensor, torch.Tensor]]=None, routing: TokenRouting=None, **kwargs: Unpack[TransformersKwargs]) -> torch.Tensor:
281
+ residual = hidden_states
282
+ hidden_states = _routed_module(hidden_states, routing, self.input_layernorm, getattr(self, 'input_layernorm_gen', None))
283
+ (hidden_states, _) = self.self_attn(hidden_states=hidden_states, attention_mask=attention_mask, position_ids=position_ids, past_key_values=past_key_values, use_cache=use_cache, cache_position=cache_position, position_embeddings=position_embeddings, routing=routing, **kwargs)
284
+ hidden_states = residual + hidden_states
285
+ residual = hidden_states
286
+ hidden_states = _routed_module(hidden_states, routing, self.post_attention_layernorm, getattr(self, 'post_attention_layernorm_gen', None))
287
+ hidden_states = self.mlp(hidden_states, routing=routing)
288
+ hidden_states = residual + hidden_states
289
+ return hidden_states
290
+
291
+ class Ministral3PreTrainedModel(PreTrainedModel):
292
+ config: MinistralDLMConfig
293
+ base_model_prefix = 'model'
294
+ supports_gradient_checkpointing = True
295
+ _no_split_modules = ['Ministral3DecoderLayer']
296
+ _skip_keys_device_placement = ['past_key_values']
297
+ _supports_flash_attn = True
298
+ _supports_sdpa = True
299
+ _supports_flex_attn = True
300
+ _can_compile_fullgraph = True
301
+ _supports_attention_backend = True
302
+ _can_record_outputs = {'hidden_states': Ministral3DecoderLayer, 'attentions': Ministral3Attention}
303
+
304
+ class Ministral3RotaryEmbedding(nn.Module):
305
+ inv_freq: torch.Tensor
306
+
307
+ def __init__(self, config: MinistralDLMConfig, device=None):
308
+ super().__init__()
309
+ self.max_seq_len_cached = config.max_position_embeddings
310
+ self.original_max_seq_len = config.max_position_embeddings
311
+ self.config = config
312
+ self.rope_type = self.config.rope_parameters['rope_type']
313
+ rope_init_fn: Callable = self.compute_default_rope_parameters
314
+ if self.rope_type != 'default':
315
+ rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
316
+ (inv_freq, self.attention_scaling) = rope_init_fn(self.config, device)
317
+ self.register_buffer('inv_freq', inv_freq, persistent=False)
318
+ self.original_inv_freq = inv_freq
319
+
320
+ @staticmethod
321
+ def compute_default_rope_parameters(config: Optional[MinistralDLMConfig]=None, device: Optional['torch.device']=None, seq_len: Optional[int]=None) -> tuple['torch.Tensor', float]:
322
+ base = config.rope_parameters['rope_theta']
323
+ dim = getattr(config, 'head_dim', None) or config.hidden_size // config.num_attention_heads
324
+ attention_factor = 1.0
325
+ inv_freq = 1.0 / base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
326
+ return (inv_freq, attention_factor)
327
+
328
+ @torch.no_grad()
329
+ @dynamic_rope_update
330
+ def forward(self, x, position_ids):
331
+ with torch.autocast(device_type=x.device.type, enabled=False):
332
+ inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
333
+ position_ids_expanded = position_ids[:, None, :].float()
334
+ freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
335
+ emb = torch.cat((freqs, freqs), dim=-1)
336
+ cos = emb.cos() * self.attention_scaling
337
+ sin = emb.sin() * self.attention_scaling
338
+ return (cos.to(dtype=x.dtype), sin.to(dtype=x.dtype))
339
+
340
+ class Ministral3Model(Ministral3PreTrainedModel):
341
+
342
+ def __init__(self, config: MinistralDLMConfig):
343
+ super().__init__(config)
344
+ self.padding_idx = config.pad_token_id
345
+ self.vocab_size = config.vocab_size
346
+ self.dual_tower_layers = _resolve_dual_tower_layers(config)
347
+ self._layer_loop_config = None
348
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
349
+ self.layers = nn.ModuleList([Ministral3DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)])
350
+ self.norm = Ministral3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
351
+ self.norm_gen = Ministral3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
352
+ self.rotary_emb = Ministral3RotaryEmbedding(config=config)
353
+ self.gradient_checkpointing = False
354
+ self.post_init()
355
+
356
+ @check_model_inputs
357
+ def forward(self, input_ids: Optional[torch.LongTensor]=None, attention_mask: Optional[torch.Tensor]=None, position_ids: Optional[torch.LongTensor]=None, past_key_values: Optional[Cache]=None, inputs_embeds: Optional[torch.FloatTensor]=None, use_cache: Optional[bool]=None, cache_position: Optional[torch.LongTensor]=None, input_embeddings: Optional[torch.FloatTensor]=None, routing: Optional[torch.Tensor]=None, modality_indices: Optional[torch.Tensor]=None, loop_k: Optional[int]=None, loop_depths: Optional[torch.LongTensor]=None, **kwargs: Unpack[TransformersKwargs]) -> BaseModelOutputWithPast:
358
+ if input_embeddings is not None:
359
+ inputs_embeds = input_embeddings
360
+ input_embeddings = None
361
+ if (input_ids is None) ^ (inputs_embeds is not None):
362
+ raise ValueError('You must specify exactly one of input_ids or inputs_embeds')
363
+ if inputs_embeds is None:
364
+ inputs_embeds = self.embed_tokens(input_ids)
365
+ single_stream_call = kwargs.get('single_stream_image_diffusion', False)
366
+ if single_stream_call is None:
367
+ single_stream_call = False
368
+ if not isinstance(single_stream_call, bool):
369
+ raise TypeError('single_stream_image_diffusion must be boolean')
370
+ use_layer_loop = self._layer_loop_config is not None and single_stream_call
371
+ if loop_k is not None or loop_depths is not None:
372
+ raise ValueError('loop_k and loop_depths require an active single-stream looped_layer_execution call')
373
+ resolved_loop_depths = None
374
+ loop_visits = 1
375
+ dual_tower = True
376
+ partial_dual_tower = dual_tower and self.dual_tower_layers < self.config.num_hidden_layers
377
+ if dual_tower and modality_indices is not None:
378
+ modality_routing = _canonicalize_token_routing(modality_indices, inputs_embeds, dual_tower=dual_tower)
379
+ if routing is None:
380
+ canonical_routing = modality_routing
381
+ else:
382
+ canonical_routing = _canonicalize_token_routing(routing, inputs_embeds, dual_tower=dual_tower)
383
+ if not torch.equal(routing.to(dtype=torch.bool), modality_indices.to(dtype=torch.bool)):
384
+ raise ValueError('routing and deprecated modality_indices alias must select identical U/G tokens when both are provided')
385
+ else:
386
+ canonical_routing = _canonicalize_token_routing(routing, inputs_embeds, dual_tower=dual_tower)
387
+ if use_cache and past_key_values is None:
388
+ past_key_values = DynamicCache()
389
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None and (partial_dual_tower or cache_position is None) else 0
390
+ stored_cached_routing = getattr(past_key_values, '_nlduni_dual_tower_routing', None)
391
+ track_dual_tower_routing = partial_dual_tower and (canonical_routing is not None or stored_cached_routing is not None)
392
+ current_routing = _routing_mask(canonical_routing, inputs_embeds) if track_dual_tower_routing else None
393
+ cached_routing = stored_cached_routing
394
+ if track_dual_tower_routing and cached_routing is None:
395
+ cached_routing = torch.zeros(current_routing.shape[0], past_seen_tokens, dtype=torch.bool, device=current_routing.device)
396
+ elif track_dual_tower_routing and tuple(cached_routing.shape) != (current_routing.shape[0], past_seen_tokens):
397
+ raise ValueError(f'cached dual-tower routing must match the KV cache shape: expected {(current_routing.shape[0], past_seen_tokens)}, got {tuple(cached_routing.shape)}')
398
+ elif track_dual_tower_routing and cached_routing.device != current_routing.device:
399
+ raise ValueError('cached dual-tower routing and inputs must share a device')
400
+ if track_dual_tower_routing and past_key_values is not None:
401
+ past_key_values._nlduni_dual_tower_routing = cached_routing
402
+ past_key_values._nlduni_dual_tower_has_generation = bool(getattr(past_key_values, '_nlduni_dual_tower_has_generation', False))
403
+ if cache_position is None:
404
+ cache_position = torch.arange(past_seen_tokens, past_seen_tokens + inputs_embeds.shape[1], device=inputs_embeds.device)
405
+ if position_ids is None:
406
+ position_ids = cache_position.unsqueeze(0)
407
+ if kwargs.get('use_causal_mask', False):
408
+ mask_function = create_causal_mask if self.config.sliding_window is None else create_sliding_window_causal_mask
409
+ causal_mask = mask_function(config=self.config, input_embeds=inputs_embeds, attention_mask=attention_mask, cache_position=cache_position, past_key_values=past_key_values, position_ids=position_ids)
410
+ else:
411
+ causal_mask = None
412
+ hidden_states = inputs_embeds
413
+ position_embeddings = self.rotary_emb(hidden_states, position_ids=position_ids)
414
+ split_layer_kwargs = None
415
+ has_split_layers = track_dual_tower_routing
416
+ if has_split_layers and kwargs.get('overwrite_attn_impl') != 'flash_attn' and (kwargs.get('overwrite_block_mask') is not None):
417
+ split_layer_kwargs = dict(kwargs)
418
+ split_layer_kwargs['overwrite_block_mask'] = _create_split_tower_block_mask(kwargs['overwrite_block_mask'], current_routing=current_routing, cached_routing=cached_routing)
419
+ for (layer_idx, decoder_layer) in enumerate(self.layers[:self.config.num_hidden_layers]):
420
+ layer_kwargs = split_layer_kwargs if split_layer_kwargs is not None and layer_idx >= self.dual_tower_layers else kwargs
421
+ hidden_states = decoder_layer(hidden_states, attention_mask=causal_mask, position_ids=position_ids, past_key_values=past_key_values, use_cache=use_cache, cache_position=cache_position, position_embeddings=position_embeddings, routing=canonical_routing, **layer_kwargs)
422
+ if track_dual_tower_routing and use_cache and (past_key_values is not None):
423
+ past_key_values._nlduni_dual_tower_routing = torch.cat((cached_routing, current_routing), dim=1)
424
+ past_key_values._nlduni_dual_tower_has_generation = past_key_values._nlduni_dual_tower_has_generation or canonical_routing is not None
425
+ hidden_states = _routed_module(hidden_states, canonical_routing, self.norm, getattr(self, 'norm_gen', None))
426
+ return BaseModelOutputWithPast(last_hidden_state=hidden_states, past_key_values=past_key_values if use_cache else None)
generation_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 1,
3
+ "eos_token_id": 11,
4
+ "pad_token_id": 11,
5
+ "max_new_tokens": 16000,
6
+ "do_sample": false
7
+ }
image_utils.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADOBE CONFIDENTIAL
2
+ # Copyright 2025 Adobe
3
+ # All Rights Reserved.
4
+ # NOTICE: All information contained herein is, and remains
5
+ # the property of Adobe and its suppliers, if any. The intellectual
6
+ # and technical concepts contained herein are proprietary to Adobe
7
+ # and its suppliers and are protected by all applicable intellectual
8
+ # property laws, including trade secret and copyright laws.
9
+ # Dissemination of this information or reproduction of this material
10
+ # is strictly forbidden unless prior written permission is obtained
11
+ # from Adobe.
12
+
13
+ from __future__ import annotations
14
+ import torch
15
+ from .token_constants import DEFAULT_IMAGE_PAD_TOKEN, DEFAULT_IMAGE_TOKEN
16
+ import numpy as np
17
+ from PIL import ImageOps
18
+
19
+ def pad_to_square_and_resize(img, size=1024):
20
+ padded_img = ImageOps.pad(img, (max(img.size), max(img.size)), color=(0, 0, 0))
21
+ resized_img = padded_img.resize((size, size))
22
+ return resized_img
23
+
24
+ def process_images(images, image_processor, model_cfg):
25
+ result = []
26
+ for image in images:
27
+ pixels = image_processor(images=[image], return_tensors='pt').pixel_values
28
+ (h, w) = pixels.shape[-2:]
29
+ result.append((pixels, torch.tensor([[1, h // 16, w // 16]], dtype=torch.long)))
30
+ return result
31
+
32
+ def tokenizer_image_token(prompt, tokenizer, image_token_index=-200, return_tensors=None, constant_version=None):
33
+ prompt = prompt.replace('<image_padding>', '<SPECIAL_23>')
34
+ ids = torch.tensor(tokenizer(prompt).input_ids, dtype=torch.long)
35
+ ids[ids == 23] = -500
36
+ return ids if return_tensors == 'pt' else ids.tolist()
37
+
38
+ def compute_num_image_tokens(x, image_aspect_ratio, image_processor):
39
+ grid = x[0][1]
40
+ return (int(grid[0, 1]) // 2, int(grid[0, 2]) // 2)
41
+
42
+ def fix_one_prompt(prompt, config, n_image_tokens):
43
+ image_idx = 0
44
+ while DEFAULT_IMAGE_TOKEN in prompt:
45
+ newline_token = config.mm_native_newline_token
46
+ if newline_token:
47
+ if len(n_image_tokens[image_idx]) == 2:
48
+ (hh, ww) = n_image_tokens[image_idx]
49
+ row = DEFAULT_IMAGE_PAD_TOKEN * ww + newline_token
50
+ rows = row * hh
51
+ rows = rows.rstrip(newline_token)
52
+ prompt = prompt.replace('<image>', rows, 1)
53
+ elif len(n_image_tokens[image_idx]) == 3:
54
+ (tt, hh, ww) = (int(value) for value in n_image_tokens[image_idx])
55
+ row = DEFAULT_IMAGE_PAD_TOKEN * ww + newline_token
56
+ per_image = row * hh + newline_token + newline_token
57
+ images = (per_image * tt).rstrip(newline_token + newline_token)
58
+ prompt = prompt.replace('<image>', images, 1)
59
+ else:
60
+ raise NotImplementedError()
61
+ else:
62
+ image_tokens = DEFAULT_IMAGE_PAD_TOKEN * np.prod(n_image_tokens[image_idx])
63
+ prompt = prompt.replace('<image>', image_tokens, 1)
64
+ image_idx += 1
65
+ return prompt
inference.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Examples: python inference.py /path/to/model --task t2i --prompt 'A red mug'."""
2
+ import argparse
3
+ from pathlib import Path
4
+ import torch
5
+ from transformers import AutoModelForCausalLM
6
+
7
+ parser=argparse.ArgumentParser()
8
+ parser.add_argument('model')
9
+ parser.add_argument('--task',choices=['t2i','edit','understand'],default='t2i')
10
+ parser.add_argument('--prompt',required=True)
11
+ parser.add_argument('--image')
12
+ parser.add_argument('--output',default='output.png')
13
+ parser.add_argument('--seed',type=int,default=42)
14
+ args=parser.parse_args()
15
+ model=AutoModelForCausalLM.from_pretrained(args.model,trust_remote_code=True,torch_dtype=torch.bfloat16).to('cuda').eval()
16
+ if args.task=='t2i':
17
+ model.text_to_image(args.prompt,seed=args.seed).save(args.output)
18
+ elif args.task=='edit':
19
+ if not args.image:parser.error('--image is required for editing')
20
+ model.image_edit(args.image,args.prompt,seed=args.seed).save(args.output)
21
+ else:
22
+ print(model.generate(args.prompt,image=args.image))
markers.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import math
4
+ from numbers import Integral
5
+ import torch
6
+ from torch import nn
7
+ GEN_IMAGE_ROW_MARKERS = 'gen_image_row_markers'
8
+ GEN_IMAGE_FIXED_PREFIX_TOKENS = 'gen_image_fixed_prefix_tokens'
9
+ GENERATION_SKIP_DOWNSAMPLE = 'generation_skip_down_sample'
10
+ ROW_MARKER_OFFSET = 0
11
+ IMAGE_MASK_OFFSET = 1
12
+ IMAGE_END_OFFSET = 2
13
+ FIXED_PREFIX_OFFSET = 3
14
+ RESERVED_GENERATION_ROWS = 256
15
+ MARKERS_PER_RAW_ROW = 2
16
+ UNCOMPRESSED_MARKERS_PER_RAW_ROW = 1
17
+ _SUPPORTED_MARKERS_PER_ROW = (UNCOMPRESSED_MARKERS_PER_RAW_ROW, MARKERS_PER_RAW_ROW)
18
+
19
+ def _validate_markers_per_row(value) -> int:
20
+ if isinstance(value, bool) or not isinstance(value, Integral):
21
+ raise TypeError('markers_per_row must be an integer')
22
+ value = int(value)
23
+ if value not in _SUPPORTED_MARKERS_PER_ROW:
24
+ raise ValueError('markers_per_row must be 1 for an uncompressed image grid or 2 for a grid that will undergo 2x spatial compression')
25
+ return value
26
+
27
+ def _validate_fixed_prefix_count(value) -> int:
28
+ if value is None:
29
+ return 0
30
+ if isinstance(value, bool) or not isinstance(value, Integral):
31
+ raise TypeError(f'config.{GEN_IMAGE_FIXED_PREFIX_TOKENS} must be an integer')
32
+ value = int(value)
33
+ max_tokens = RESERVED_GENERATION_ROWS - FIXED_PREFIX_OFFSET
34
+ if not 0 <= value <= max_tokens:
35
+ raise ValueError(f'config.{GEN_IMAGE_FIXED_PREFIX_TOKENS} must be between 0 and {max_tokens}')
36
+ return value
37
+
38
+ def image_row_markers_enabled(config) -> bool:
39
+ value = getattr(config, GEN_IMAGE_ROW_MARKERS, False)
40
+ if value is None:
41
+ return False
42
+ if not isinstance(value, bool):
43
+ raise TypeError(f'config.{GEN_IMAGE_ROW_MARKERS} must be boolean')
44
+ return value
45
+
46
+ def resolve_generation_skip_down_sample(config, *, runtime_value=None) -> bool:
47
+ configured = getattr(config, GENERATION_SKIP_DOWNSAMPLE, None)
48
+ if configured is not None and (not isinstance(configured, bool)):
49
+ raise TypeError(f'config.{GENERATION_SKIP_DOWNSAMPLE} must be boolean or null')
50
+ runtime_configured = runtime_value is not None
51
+ runtime_enabled = bool(runtime_value)
52
+ if configured is None:
53
+ return runtime_enabled
54
+ if runtime_configured and runtime_enabled != configured:
55
+ raise ValueError(f'SKIP_DOWN_SAMPLE conflicts with checkpoint-backed config.{GENERATION_SKIP_DOWNSAMPLE}: runtime={runtime_enabled}, checkpoint={configured}')
56
+ return configured
57
+
58
+ def image_generation_special_ids(codebook_size: int) -> tuple[int, int, int]:
59
+ if isinstance(codebook_size, bool) or not isinstance(codebook_size, Integral):
60
+ raise TypeError('codebook_size must be a positive integer')
61
+ codebook_size = int(codebook_size)
62
+ if codebook_size < 1:
63
+ raise ValueError('codebook_size must be a positive integer')
64
+ return (codebook_size + ROW_MARKER_OFFSET, codebook_size + IMAGE_MASK_OFFSET, codebook_size + IMAGE_END_OFFSET)
65
+
66
+ def image_fixed_prefix_token_count(config) -> int:
67
+ return _validate_fixed_prefix_count(getattr(config, GEN_IMAGE_FIXED_PREFIX_TOKENS, 0))
68
+
69
+ def image_generation_fixed_prefix_ids(codebook_size: int, count: int) -> tuple[int, ...]:
70
+ image_generation_special_ids(codebook_size)
71
+ count = _validate_fixed_prefix_count(count)
72
+ start = int(codebook_size) + FIXED_PREFIX_OFFSET
73
+ return tuple(range(start, start + count))
74
+
75
+ def split_generation_fixed_prefix(generation_placeholder_mask: torch.Tensor, *, codebook_size: int, count: int) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
76
+ if not torch.is_tensor(generation_placeholder_mask):
77
+ raise TypeError('generation_placeholder_mask must be a tensor')
78
+ if generation_placeholder_mask.ndim != 2:
79
+ raise ValueError('generation_placeholder_mask must have shape [batch, sequence]')
80
+ placeholder_mask = generation_placeholder_mask.to(dtype=torch.bool)
81
+ fixed_ids = image_generation_fixed_prefix_ids(codebook_size, count)
82
+ if not fixed_ids:
83
+ return (torch.zeros_like(placeholder_mask), placeholder_mask, torch.empty(0, dtype=torch.long, device=placeholder_mask.device))
84
+ previous_placeholder = torch.cat((torch.zeros_like(placeholder_mask[:, :1]), placeholder_mask[:, :-1]), dim=1)
85
+ run_starts = placeholder_mask & ~previous_placeholder
86
+ positions = torch.arange(placeholder_mask.shape[1], device=placeholder_mask.device, dtype=torch.long).unsqueeze(0).expand_as(placeholder_mask)
87
+ most_recent_start = torch.where(run_starts, positions, positions.new_full((), -1)).cummax(dim=1).values
88
+ run_offsets = positions - most_recent_start
89
+ fixed_mask = placeholder_mask & run_offsets.lt(len(fixed_ids))
90
+ image_mask = placeholder_mask & ~fixed_mask
91
+ next_placeholder = torch.cat((placeholder_mask[:, 1:], torch.zeros_like(placeholder_mask[:, :1])), dim=1)
92
+ run_ends = placeholder_mask & ~next_placeholder
93
+ run_lengths = run_offsets[run_ends] + 1
94
+ if bool(run_lengths.le(len(fixed_ids)).any()):
95
+ shortest = int(run_lengths.min().item())
96
+ raise ValueError(f'each generated-image placeholder run must contain the fixed prefix plus at least one image slot; shortest run={shortest}, fixed prefix={len(fixed_ids)}')
97
+ dense_ids = int(codebook_size) + FIXED_PREFIX_OFFSET + run_offsets
98
+ return (fixed_mask, image_mask, dense_ids[fixed_mask])
99
+
100
+ def generation_embedding_capacity(generation_model) -> int:
101
+ embedding = getattr(generation_model, 'gen_embedding', None)
102
+ if isinstance(embedding, nn.Embedding):
103
+ return int(embedding.num_embeddings)
104
+ if isinstance(embedding, nn.Module):
105
+ for module in embedding.modules():
106
+ if isinstance(module, nn.Embedding):
107
+ return int(module.num_embeddings)
108
+ raise TypeError('generation model does not expose an nn.Embedding lookup')
109
+
110
+ def image_row_marker_count(generation_model, *, skip_down_sample=False) -> int:
111
+ compression_available = getattr(generation_model, 'packed_image_codec', None) is not None or getattr(generation_model, 'downsample_gen', None) is not None
112
+ if compression_available and (not skip_down_sample):
113
+ return MARKERS_PER_RAW_ROW
114
+ return UNCOMPRESSED_MARKERS_PER_RAW_ROW
115
+
116
+ def validate_image_row_marker_support(generation_model, *, skip_down_sample=False):
117
+ config = generation_model.config
118
+ if 'emu3' not in 'emu3'.lower():
119
+ raise NotImplementedError("generation image row markers currently require Emu3's single-codebook tokenizer")
120
+ image_row_marker_count(generation_model, skip_down_sample=skip_down_sample)
121
+ codebook_size = int(generation_model.vqvae.config.num_vq_embeddings)
122
+ (row_id, mask_id, end_id) = image_generation_special_ids(codebook_size)
123
+ capacity = generation_embedding_capacity(generation_model)
124
+ if end_id >= capacity:
125
+ raise ValueError(f'generation embedding has no spare rows for row/end markers: required ID {end_id}, capacity {capacity}')
126
+ return (row_id, mask_id, end_id)
127
+
128
+ def validate_image_fixed_prefix_support(generation_model) -> tuple[int, ...]:
129
+ config = generation_model.config
130
+ count = image_fixed_prefix_token_count(config)
131
+ if count == 0:
132
+ return ()
133
+ if getattr(config, 'generation_embedding_scale', None) is None:
134
+ raise ValueError('generation fixed-prefix tokens require factorized generation scaling so uncompressed tokens receive the common input scale')
135
+ if 'emu3' not in 'emu3'.lower():
136
+ raise NotImplementedError("generation fixed-prefix tokens currently require Emu3's single-codebook tokenizer")
137
+ codebook_size = int(generation_model.vqvae.config.num_vq_embeddings)
138
+ fixed_ids = image_generation_fixed_prefix_ids(codebook_size, count)
139
+ capacity = generation_embedding_capacity(generation_model)
140
+ if fixed_ids[-1] >= capacity:
141
+ raise ValueError(f'generation embedding has no spare rows for the requested fixed prefix: required ID {fixed_ids[-1]}, capacity {capacity}')
142
+ special_ids = set(image_generation_special_ids(codebook_size))
143
+ if special_ids.intersection(fixed_ids):
144
+ raise RuntimeError('generation fixed-prefix IDs overlap image mask/row/end markers')
145
+ return fixed_ids
146
+
147
+ def augmented_image_shape(gen_shape, *, markers_per_row: int=MARKERS_PER_RAW_ROW) -> tuple[int, int]:
148
+ if gen_shape is None or len(gen_shape) != 2:
149
+ raise ValueError('gen_shape must contain image height and width')
150
+ markers_per_row = _validate_markers_per_row(markers_per_row)
151
+ (height, width) = (int(value) for value in gen_shape)
152
+ if height < 1 or width < 1:
153
+ raise ValueError('image row markers require a positive image grid')
154
+ if markers_per_row == MARKERS_PER_RAW_ROW and (height % 2 or width % 2):
155
+ raise ValueError('two-column image row markers require an even-height, even-width grid for 2x spatial compression')
156
+ return (height, width + markers_per_row)
157
+
158
+ def append_image_row_markers(token_ids: torch.Tensor, gen_shape, *, row_marker_id: int, image_end_id: int, markers_per_row: int=MARKERS_PER_RAW_ROW) -> tuple[torch.Tensor, tuple[int, int], torch.Tensor]:
159
+ if not torch.is_tensor(token_ids) or token_ids.ndim != 2:
160
+ raise ValueError('token_ids must have shape [batch, raw_image_tokens]')
161
+ markers_per_row = _validate_markers_per_row(markers_per_row)
162
+ (height, width) = (int(value) for value in gen_shape)
163
+ augmented_shape = augmented_image_shape((height, width), markers_per_row=markers_per_row)
164
+ if token_ids.shape[-1] != height * width:
165
+ raise ValueError(f'raw image token count does not match gen_shape: {token_ids.shape[-1]} != {height * width}')
166
+ grid = token_ids.reshape(token_ids.shape[0], height, width)
167
+ markers = torch.full((token_ids.shape[0], height, markers_per_row), int(row_marker_id), dtype=token_ids.dtype, device=token_ids.device)
168
+ markers[:, -1, :] = int(image_end_id)
169
+ augmented = torch.cat((grid, markers), dim=-1).flatten(1)
170
+ structural_mask = torch.zeros_like(augmented, dtype=torch.bool)
171
+ structural_mask.reshape(token_ids.shape[0], *augmented_shape)[:, :, -markers_per_row:] = True
172
+ return (augmented, augmented_shape, structural_mask)
173
+
174
+ def strip_image_row_markers(token_ids: torch.Tensor, original_gen_shape, *, markers_per_row: int=MARKERS_PER_RAW_ROW) -> torch.Tensor:
175
+ if not torch.is_tensor(token_ids) or token_ids.ndim != 2:
176
+ raise ValueError('token_ids must have shape [batch, augmented_tokens]')
177
+ markers_per_row = _validate_markers_per_row(markers_per_row)
178
+ (height, width) = (int(value) for value in original_gen_shape)
179
+ augmented_shape = augmented_image_shape((height, width), markers_per_row=markers_per_row)
180
+ if token_ids.shape[-1] != math.prod(augmented_shape):
181
+ raise ValueError(f'augmented image token count does not match marker grid: {token_ids.shape[-1]} != {math.prod(augmented_shape)}')
182
+ return token_ids.reshape(token_ids.shape[0], *augmented_shape)[:, :, :width].flatten(1)
model-00001-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c4d490e010475dde3e2b57de64261a56d6bf8e9ca7d077754913fd628f7de5f6
3
+ size 4974634832
model-00002-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:933c4b2f44f9cd7be30ac7a40efbb3c58485aa9fbd6396245d8e2337faf5c5b3
3
+ size 4999819672
model-00003-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6893a316ec6655eb3f518be0f3ae3dfc80621922741df7d14f12b3d9fd123bf6
3
+ size 4949454016
model-00004-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:858fab295f100b897634b72824d01e01f368dc1d500de03916854d7b2769986c
3
+ size 4999819744
model-00005-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0d31608093622df48c2284fa310170f9a1bfd127d7108bdacbc8106fcf296691
3
+ size 4999819776
model-00006-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4356b837d798b2d3250cd067c15b7f5d56fd19a8b8605bb107fb9d727c1726d0
3
+ size 4999819272
model-00007-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:003f5a6c4c727e5f560e16ad91ee2264ed138c7190108dfc9b68d1b8c8445545
3
+ size 4456023446
model-00008-of-00008.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:299783fae2f540dfd723abbb09f8661b57122210d44b23a4c65f24b254542550
3
+ size 2155913464
model.safetensors.index.json ADDED
The diff for this file is too large to render. See raw diff
 
modeling_nlduni.py ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import math
3
+ import torch
4
+ from torch import nn
5
+ from PIL import Image
6
+ from transformers import AutoTokenizer
7
+ from transformers.generation import GenerationMixin
8
+ from transformers.modeling_outputs import CausalLMOutputWithPast
9
+ from transformers.utils.hub import cached_file
10
+ from .configuration_nlduni import NLDUniConfig
11
+ from .core import Ministral3Model, Ministral3PreTrainedModel
12
+ from .attention import MinistralFlexAttention
13
+ from .bridge import PackedLinearImageCodec
14
+ from .vq import Emu3VQ, Emu3ImageProcessor
15
+ from .vision import RadioVisionTower
16
+ from .projector import RadioHProjector
17
+ from .positions import _build_2d_sincos_position_embedding, GENERATION_2D_SINCOS_SCALE
18
+ from .markers import strip_image_row_markers
19
+ from .chat_utils import generate_with_prefix_cache_block_diff
20
+ from .sampling import text_to_image as sample_image
21
+ from .image_utils import process_images, fix_one_prompt, tokenizer_image_token
22
+ from .conversation import Conversation
23
+ from .tree import BalancedSemanticTree, production_semantic_tree_contract
24
+
25
+ class NLDUniBackbone(Ministral3Model):
26
+ def __init__(self, config):
27
+ super().__init__(config)
28
+ self.vision_tower=RadioVisionTower()
29
+ self.mm_projector=RadioHProjector(config)
30
+ self.image_newline=nn.Parameter(torch.empty(config.hidden_size))
31
+ self.vqvae=Emu3VQ()
32
+ self.image_processor_gen=Emu3ImageProcessor()
33
+ self.gen_embedding=nn.Embedding(131072+256,4096)
34
+ self.gen_predictor=nn.Linear(4096,131072,bias=False)
35
+ self.packed_image_codec=PackedLinearImageCodec(4096,norm_eps=1e-6)
36
+ self.downsample_gen=None
37
+ self.upsample_gen=None
38
+ self.downsample_gen_enc=None
39
+ self.gen_embedding_2=None
40
+ self.gen_predictor_2=None
41
+ self.extra_gen_dit=None
42
+ def get_vision_tower(self):
43
+ return self.vision_tower
44
+ def get_gen_tokenizer(self):
45
+ return self.vqvae
46
+ def call_gen_token_embedding(self, token_ids):
47
+ return self.gen_embedding(token_ids)
48
+ def call_gen_fixed_token_embedding(self, token_ids):
49
+ return self.gen_embedding(token_ids)*self.config.generation_embedding_scale
50
+ def call_gen_embedding(self, token_ids=None, gen_shape=None, enc=False, child_embeddings=None,
51
+ spatial_compression=True, add_spatial_position=True):
52
+ values=self.gen_embedding(token_ids) if child_embeddings is None else child_embeddings
53
+ if spatial_compression:
54
+ values=self.packed_image_codec.compress_fixed_grid(values,gen_shape)
55
+ scale=self.config.generation_embedding_scale
56
+ if spatial_compression:scale*=self.config.generation_downsample_scale
57
+ values=values*scale
58
+ if add_spatial_position:
59
+ h,w=gen_shape
60
+ if spatial_compression:h,w=h//2,w//2
61
+ pos=_build_2d_sincos_position_embedding(h,w,values.shape[-1],marker_column=not enc,device=values.device,dtype=values.dtype)
62
+ values=values+pos.unsqueeze(0)*GENERATION_2D_SINCOS_SCALE
63
+ return values
64
+ def call_gen_predictor(self, hidden_states, gen_shape=None, timesteps=None):
65
+ h,w=gen_shape
66
+ states=self.packed_image_codec.expand_fixed_grid(hidden_states.reshape(-1,(h//2)*(w//2),4096),gen_shape)
67
+ return self.gen_predictor(states.flatten(0,1))
68
+
69
+ class NLDUniForCausalLM(Ministral3PreTrainedModel, GenerationMixin):
70
+ config_class=NLDUniConfig
71
+ base_model_prefix=''
72
+ def __init__(self, config):
73
+ super().__init__(config)
74
+ self.encoder=NLDUniBackbone(config)
75
+ self.diffusion_head=nn.Linear(config.hidden_size,config.vocab_size,bias=False)
76
+ self.mask_token_id=100
77
+ self.vocab_size=config.vocab_size
78
+ self._tokenizer=None
79
+ self._asset_root=None
80
+ self.post_init()
81
+ @classmethod
82
+ def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
83
+ model=super().from_pretrained(pretrained_model_name_or_path,*args,**kwargs)
84
+ target=model[0] if isinstance(model,tuple) else model
85
+ options={k:kwargs[k] for k in ('revision','cache_dir','local_files_only','token','subfolder') if k in kwargs}
86
+ target._tokenizer=AutoTokenizer.from_pretrained(pretrained_model_name_or_path,**options)
87
+ tree=cached_file(pretrained_model_name_or_path,'pca_tree.pt',**options)
88
+ BalancedSemanticTree.from_artifact(production_semantic_tree_contract(tree))
89
+ target.config.image_token_tree_path=tree
90
+ target.eval()
91
+ return model
92
+ def save_pretrained(self, save_directory, **kwargs):
93
+ import shutil
94
+ destination = Path(save_directory)
95
+ destination.mkdir(parents=True, exist_ok=True)
96
+ super().save_pretrained(destination, **kwargs)
97
+ self.tokenizer.save_pretrained(destination)
98
+ asset = Path(self.config.image_token_tree_path)
99
+ if asset.resolve() != (destination / 'pca_tree.pt').resolve():
100
+ shutil.copyfile(asset, destination / 'pca_tree.pt')
101
+ @property
102
+ def model(self):return self.encoder
103
+ def get_model(self):return self.encoder
104
+ def get_vision_tower(self):return self.encoder.vision_tower
105
+ def get_input_embeddings(self):return self.encoder.embed_tokens
106
+ def set_input_embeddings(self, value):self.encoder.embed_tokens=value
107
+ def get_output_embeddings(self):return self.diffusion_head
108
+ def set_output_embeddings(self,value):self.diffusion_head=value
109
+ @property
110
+ def tokenizer(self):
111
+ if self._tokenizer is None:raise RuntimeError('Load with from_pretrained before inference')
112
+ return self._tokenizer
113
+ def forward(self,input_ids=None,inputs_embeds=None,attention_mask=None,position_ids=None,past_key_values=None,use_cache=False,**kwargs):
114
+ result=self.encoder(input_ids=input_ids,inputs_embeds=inputs_embeds,attention_mask=attention_mask,position_ids=position_ids,past_key_values=past_key_values,use_cache=use_cache,**kwargs)
115
+ return CausalLMOutputWithPast(logits=self.diffusion_head(result.last_hidden_state),past_key_values=result.past_key_values)
116
+ def prepare_inputs_labels_for_multimodal(self, input_ids, position_ids, attention_mask,
117
+ past_key_values, labels, images, modalities=None, image_sizes=None, return_inputs=False, **kwargs):
118
+ embeds=self.encoder.embed_tokens(input_ids.clamp_min(0))
119
+ if images:
120
+ features=[]
121
+ for pixels,grid in images:
122
+ visual=self.encoder.vision_tower(pixels).squeeze(0)
123
+ features.append(self.encoder.mm_projector(visual,grid.to(visual.device)))
124
+ visual=torch.cat(features)
125
+ mask=input_ids.eq(-500)
126
+ if int(mask.sum())!=len(visual):raise ValueError('Image placeholder count does not match vision features')
127
+ embeds[mask]=visual.to(embeds)
128
+ result=(None,position_ids,attention_mask,past_key_values,embeds,labels)
129
+ return result+(input_ids,) if return_inputs else result
130
+ def encode_image_gen(self, images, enc=False):
131
+ ref=next(self.encoder.vqvae.parameters())
132
+ quant,_,(_,_,ids)=self.encoder.vqvae.encode(images.to(ref))
133
+ return ids.reshape(len(images),-1),tuple(quant.shape[-2:])
134
+ def decode_image_gen(self, codes, height, width):
135
+ shape=(height//16,width//16)
136
+ if codes.shape[-1] != math.prod(shape):
137
+ codes=strip_image_row_markers(codes,shape,markers_per_row=2)
138
+ if (codes>=131072).any():raise ValueError('Unresolved image tokens at decoding')
139
+ quant=self.encoder.vqvae.quantize.get_codebook_entry(codes)
140
+ quant=quant.reshape(len(codes),*shape,256).permute(0,3,1,2).contiguous()
141
+ pixels=self.encoder.vqvae.decode(quant).float().clamp(-1,1)
142
+ return ((pixels+1)/2*255).permute(0,2,3,1).cpu().numpy().astype('uint8')
143
+ def _sample(self,prompt,*,image=None,resolution=1024,steps=64,refinement_steps=4,guidance_scale=3.,image_guidance_scale=2.,temperature=.8,seed=None,top_k=0,top_p=1.,shift=5.,show_progress=False):
144
+ if resolution not in (256,512,1024):raise ValueError('resolution must be 256, 512, or 1024')
145
+ if steps<1 or not math.isfinite(temperature) or temperature<=0:raise ValueError('steps and temperature must be positive')
146
+ # A supplied seed is local to this call and does not disturb caller RNG state.
147
+ devices=[self.device.index if self.device.index is not None else torch.cuda.current_device()] if self.device.type=='cuda' else []
148
+ with torch.random.fork_rng(devices=devices,enabled=seed is not None):
149
+ if seed is not None:torch.manual_seed(seed)
150
+ return sample_image(self,prompt,tokenizer=self.tokenizer,edit_image=image,image_processor=self.encoder.vision_tower.image_processor,
151
+ image_resolution=resolution,n_tokens=(resolution//16)**2,n_steps=steps,image_embedding_refinement_steps=refinement_steps,
152
+ guidance_scale=guidance_scale,guidance_scale_image=image_guidance_scale,temperature=temperature,
153
+ confidence_policy='stratified',shift=shift,schedule='shift',alg_temp=5.,dynamic_temperature=True,
154
+ min_temperature=.5,schedule_temp='cosine2',top_k=top_k,top_p=top_p,disable_tqdm=not show_progress,
155
+ micro_cond=f'ORIGINAL WIDTH : {resolution}; ORIGINAL HEIGHT : {resolution}; TOP : 0; LEFT : 0; SCORE : 7.110;',
156
+ template='Generate an image with the caption:\n <prompt>',edit_mode=1 if image is not None else 0)
157
+ @torch.inference_mode()
158
+ def text_to_image(self,prompt,*,resolution=1024,steps=64,refinement_steps=4,guidance_scale=3.,temperature=.8,seed=None,top_k=0,top_p=1.,shift=5.,show_progress=False):
159
+ """Generate one PIL image using the checkpoint's semantic-tree sampler."""
160
+ return self._sample(prompt,resolution=resolution,steps=steps,refinement_steps=refinement_steps,guidance_scale=guidance_scale,temperature=temperature,seed=seed,top_k=top_k,top_p=top_p,shift=shift,show_progress=show_progress)
161
+ @torch.inference_mode()
162
+ def image_edit(self,image,prompt,*,resolution=1024,steps=64,refinement_steps=4,guidance_scale=1.6,image_guidance_scale=2.,temperature=.8,seed=None,top_k=0,top_p=1.,shift=5.,crop_to_source=True,show_progress=False):
163
+ """Edit a PIL image or local image path; return a PIL image."""
164
+ if isinstance(image,(str,Path)):image=Image.open(image)
165
+ image=image.convert('RGB')
166
+ result=self._sample(prompt,image=image,resolution=resolution,steps=steps,refinement_steps=refinement_steps,guidance_scale=guidance_scale,image_guidance_scale=image_guidance_scale,temperature=temperature,seed=seed,top_k=top_k,top_p=top_p,shift=shift,show_progress=show_progress)
167
+ if crop_to_source:
168
+ w,h=image.size; scale=resolution/max(w,h)
169
+ cw,ch=round(w*scale),round(h*scale)
170
+ left,top=(resolution-cw)//2,(resolution-ch)//2
171
+ result=result.crop((left,top,left+cw,top+ch)).resize((w,h),Image.Resampling.LANCZOS)
172
+ return result
173
+ @torch.inference_mode()
174
+ def generate(self,prompt=None,*,image=None,inputs=None,input_ids=None,max_new_tokens=16000,block_length=32,steps_per_block=32,threshold=.9,temperature=0.,return_token_ids=False,**kwargs):
175
+ """Visual/text understanding, using greedy block diffusion without thinking."""
176
+ if kwargs:raise TypeError(f'Unknown inference options: {sorted(kwargs)}')
177
+ if max_new_tokens<1 or block_length<1 or steps_per_block<1:raise ValueError('Token and step counts must be positive')
178
+ if not 0<=threshold<=1:raise ValueError('threshold must be between 0 and 1')
179
+ if isinstance(prompt,torch.Tensor):input_ids,prompt=prompt,None
180
+ if inputs is not None:input_ids=inputs
181
+ if input_ids is None:
182
+ if not isinstance(prompt,str):raise TypeError('prompt must be a string, or provide input_ids')
183
+ conv=Conversation(); images=[]
184
+ if image is not None:
185
+ if isinstance(image,(str,Path)):image=Image.open(image)
186
+ images=process_images([image.convert('RGB')],self.encoder.vision_tower.image_processor,self.config)
187
+ prompt='<image>\n'+prompt
188
+ conv.append_message(conv.roles[0],prompt)
189
+ conv.append_message(conv.roles[1],None)
190
+ rendered=conv.get_prompt()
191
+ if images:
192
+ grid=images[0][1]
193
+ rendered=fix_one_prompt(rendered,self.config,[(int(grid[0,1])//2,int(grid[0,2])//2)])
194
+ input_ids=tokenizer_image_token(rendered,self.tokenizer,return_tensors='pt',constant_version='ministral').unsqueeze(0).to(self.device)
195
+ embeds=self.prepare_inputs_labels_for_multimodal(input_ids,None,None,None,None,images)[4]
196
+ else:
197
+ if image is not None:raise ValueError('Use a string prompt when providing image')
198
+ input_ids=input_ids.to(self.device)
199
+ embeds=self.encoder.embed_tokens(input_ids)
200
+ length=math.ceil(max_new_tokens/block_length)*block_length
201
+ ids,_=generate_with_prefix_cache_block_diff(self,prompt_embeds=embeds,gen_length=length,steps=steps_per_block*(length//block_length),block_length=block_length,temperature=temperature,mask_id=100,threshold=threshold,shift_logits=True,causal_context=True,eos_token_id=11)
202
+ ids=ids[:, :max_new_tokens]
203
+ if return_token_ids:return ids
204
+ return self.tokenizer.decode(ids[0],skip_special_tokens=True).strip()
205
+
206
+ from .positions import _generation_grid_shape as _bundle_positions
207
+
208
+ from .core import rotate_half as _bundle_core
209
+
210
+ from .refinement import _validate_refinement_steps as _bundle_refinement
211
+
212
+ from .conversation import Conversation
213
+ from .tree import BalancedSemanticTree, production_semantic_tree_contract as _bundle_conversation
214
+
215
+ from .constants import NemotronMinistralDLMConstant as _bundle_constants
216
+
217
+ from .chat_utils import SimpleOutputWithPast as _bundle_chat_utils
218
+
219
+ from .tree import _plain_positive_int as _bundle_tree
220
+
221
+ from .schedules import cosine_schedule_2 as _bundle_schedules
222
+
223
+ from .radio_cls import ClsToken as _bundle_radio_cls
224
+
225
+ from .padding import resolve_source_padding_vq_lock as _bundle_padding
226
+
227
+ from .pmj import stratified_random as _bundle_pmj
228
+
229
+ from .image_utils import pad_to_square_and_resize as _bundle_image_utils
230
+
231
+ from .sampling import _load_prediction_image as _bundle_sampling
232
+
233
+ from .markers import _validate_markers_per_row as _bundle_markers
234
+
235
+ from .radio_patch import ViTPatchGenerator as _bundle_radio_patch
236
+
237
+ from .vision import RadioBackbone as _bundle_vision
238
+
239
+ from .sbd_attention import build_image_attention_doc_ids as _bundle_sbd_attention
240
+
241
+ from .attention import fused_flex_attention as _bundle_attention
242
+
243
+ from .vq import Codebook as _bundle_vq
244
+
245
+ from .utils import pad_along_last_dim as _bundle_utils
246
+
247
+ from .vq_model import nonlinearity as _bundle_vq_model
248
+
249
+ from .projector import SquaredReLU as _bundle_projector
250
+
251
+ from .bridge import PackedLinearImageCodec as _bundle_bridge
252
+ from .token_constants import IMAGE_PAD_TOKEN_INDEX as _bundle_token_constants
padding.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import numpy as np
4
+ import torch
5
+
6
+ def resolve_source_padding_vq_lock(model_config, override=None, *, has_edit_image):
7
+ if not isinstance(has_edit_image, bool):
8
+ raise TypeError('has_edit_image must be boolean')
9
+ if override is None:
10
+ resolved = getattr(model_config, 'lock_source_padding_vq', False)
11
+ if resolved is None:
12
+ resolved = False
13
+ if not isinstance(resolved, bool):
14
+ raise TypeError('config.lock_source_padding_vq must be boolean or null')
15
+ if resolved and (not has_edit_image):
16
+ return False
17
+ return resolved
18
+ if not isinstance(override, bool):
19
+ raise TypeError('lock_source_padding_vq override must be boolean or null')
20
+ if override and (not has_edit_image):
21
+ raise ValueError('lock_source_padding_vq requires an edit_image')
22
+ return override
23
+
24
+ def _resolve_source_native_size(value, *, fallback):
25
+ resolved = fallback if value is None else value
26
+ if not isinstance(resolved, (tuple, list)) or len(resolved) != 2 or any((isinstance(item, bool) or not isinstance(item, (int, np.integer)) or int(item) < 1 for item in resolved)):
27
+ raise ValueError('edit_source_native_size must contain positive integer width and height')
28
+ return (int(resolved[0]), int(resolved[1]))
29
+
30
+ def _source_padding_vq_mask(source_native_size, raw_grid_shape, *, device):
31
+ (width, height) = _resolve_source_native_size(source_native_size, fallback=source_native_size)
32
+ if not isinstance(raw_grid_shape, (tuple, list)) or len(raw_grid_shape) != 2 or any((isinstance(item, bool) or not isinstance(item, (int, np.integer)) or int(item) < 1 for item in raw_grid_shape)):
33
+ raise ValueError('raw_grid_shape must contain positive integer height and width')
34
+ (grid_height, grid_width) = (int(value) for value in raw_grid_shape)
35
+ if grid_height != grid_width:
36
+ raise ValueError('source-padding VQ locking requires a square raw VQ grid')
37
+ side = max(width, height)
38
+ left = round((side - width) * 0.5)
39
+ top = round((side - height) * 0.5)
40
+ right = left + width
41
+ bottom = top + height
42
+ columns = torch.arange(grid_width, dtype=torch.long, device=device)
43
+ rows = torch.arange(grid_height, dtype=torch.long, device=device)
44
+ horizontally_outside = ((columns + 1) * side <= left * grid_width) | (columns * side >= right * grid_width)
45
+ vertically_outside = ((rows + 1) * side <= top * grid_height) | (rows * side >= bottom * grid_height)
46
+ return (vertically_outside[:, None] | horizontally_outside[None, :]).reshape(1, -1)
47
+
48
+ def _augment_source_padding_vq_mask(state, raw_padding_mask, content_positions):
49
+ if not torch.is_tensor(state) or state.ndim != 2:
50
+ raise ValueError('generation state must have shape [batch, tokens]')
51
+ if not torch.is_tensor(raw_padding_mask) or raw_padding_mask.dtype is not torch.bool or raw_padding_mask.ndim != 2 or (raw_padding_mask.shape[0] != state.shape[0]) or (raw_padding_mask.device != state.device):
52
+ raise TypeError('raw_padding_mask must be device-local bool with the state batch size')
53
+ if not torch.is_tensor(content_positions) or content_positions.ndim != 1 or content_positions.dtype is not torch.long or (content_positions.device != state.device) or (content_positions.numel() != raw_padding_mask.shape[1]):
54
+ raise TypeError('content_positions must be a device-local long vector covering raw cells')
55
+ if bool((content_positions < 0).any()) or bool((content_positions >= state.shape[1]).any()):
56
+ raise ValueError('content_positions contains an out-of-range state index')
57
+ locked_mask = torch.zeros_like(state, dtype=torch.bool)
58
+ locked_mask[:, content_positions] = raw_padding_mask
59
+ return locked_mask
60
+
61
+ def _prefill_source_padding_vq(state, source_codes, raw_padding_mask, content_positions):
62
+ if not torch.is_tensor(state) or state.ndim != 2:
63
+ raise ValueError('generation state must have shape [batch, tokens]')
64
+ if not torch.is_tensor(source_codes) or source_codes.ndim != 2 or source_codes.dtype != state.dtype or (source_codes.device != state.device):
65
+ raise TypeError('source_codes must match the state integer dtype and device')
66
+ if source_codes.shape != raw_padding_mask.shape:
67
+ raise TypeError('raw_padding_mask must be bool and match source_codes')
68
+ locked_mask = _augment_source_padding_vq_mask(state, raw_padding_mask, content_positions)
69
+ locked_codes = torch.zeros_like(state)
70
+ locked_codes[:, content_positions] = source_codes
71
+ prefilled = state.clone()
72
+ prefilled[locked_mask] = locked_codes[locked_mask]
73
+ return (prefilled, locked_mask, locked_codes)
74
+
75
+ def _restore_source_padding_vq(state, locked_mask, locked_codes):
76
+ if locked_mask is None:
77
+ return state
78
+ if not torch.is_tensor(state) or state.ndim != 2 or (not torch.is_tensor(locked_mask)) or (locked_mask.dtype is not torch.bool) or (locked_mask.shape != state.shape) or (locked_mask.device != state.device) or (not torch.is_tensor(locked_codes)) or (locked_codes.shape != state.shape) or (locked_codes.dtype != state.dtype) or (locked_codes.device != state.device):
79
+ raise TypeError('locked source-padding tensors must align with sampler state')
80
+ restored = state.clone()
81
+ restored[locked_mask] = locked_codes[locked_mask]
82
+ return restored
83
+
84
+ def _assert_source_padding_vq_locked(state, locked_mask, locked_codes):
85
+ if locked_mask is None:
86
+ return
87
+ if not torch.is_tensor(locked_mask) or locked_mask.dtype is not torch.bool or locked_mask.shape != state.shape or (not torch.is_tensor(locked_codes)) or (locked_codes.shape != state.shape):
88
+ raise TypeError('locked source-padding tensors must align with sampler state')
89
+ if not torch.equal(state[locked_mask], locked_codes[locked_mask]):
90
+ raise RuntimeError('a locked source-padding VQ code changed during sampling')
pca_tree.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4b7ee94fbb10fd4146a4ad167b595b037e3f591eaa12ecf3f0b411c82384a714
3
+ size 1052237
pmj.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADOBE CONFIDENTIAL
2
+ # Copyright 2025 Adobe
3
+ # All Rights Reserved.
4
+ # NOTICE: All information contained herein is, and remains
5
+ # the property of Adobe and its suppliers, if any. The intellectual
6
+ # and technical concepts contained herein are proprietary to Adobe
7
+ # and its suppliers and are protected by all applicable intellectual
8
+ # property laws, including trade secret and copyright laws.
9
+ # Dissemination of this information or reproduction of this material
10
+ # is strictly forbidden unless prior written permission is obtained
11
+ # from Adobe.
12
+
13
+ from __future__ import annotations
14
+ from typing import List, Tuple, Optional
15
+ import random
16
+
17
+ def stratified_random(n: int=64, seed: Optional[int]=None, shuffle_blocks: bool=True) -> List[int]:
18
+ if n <= 0 or n & n - 1 != 0:
19
+ raise ValueError('n must be a positive power of two (e.g., 64)')
20
+ rng = random.Random(seed)
21
+ occupied = [[False] * n for _ in range(n)]
22
+ seq: List[int] = []
23
+ blocks: List[Tuple[int, int, int]] = [(0, 0, n)]
24
+
25
+ def block_has_sample(x0: int, y0: int, size: int) -> bool:
26
+ for yy in range(y0, y0 + size):
27
+ row = occupied[yy]
28
+ for xx in range(x0, x0 + size):
29
+ if row[xx]:
30
+ return True
31
+ return False
32
+
33
+ def place_random_in_block(x0: int, y0: int, size: int):
34
+ x = rng.randrange(x0, x0 + size)
35
+ y = rng.randrange(y0, y0 + size)
36
+ attempts = 0
37
+ while occupied[y][x]:
38
+ x = rng.randrange(x0, x0 + size)
39
+ y = rng.randrange(y0, y0 + size)
40
+ attempts += 1
41
+ if attempts > 10000:
42
+ raise RuntimeError('Too many attempts to place a sample; logic error?')
43
+ occupied[y][x] = True
44
+ seq.append(y * n + x)
45
+ size = n
46
+ while size > 1:
47
+ half = size // 2
48
+ children: List[Tuple[int, int, int]] = []
49
+ for (x0, y0, s) in blocks:
50
+ assert s == size
51
+ children.extend([(x0, y0, half), (x0 + half, y0, half), (x0, y0 + half, half), (x0 + half, y0 + half, half)])
52
+ if shuffle_blocks:
53
+ rng.shuffle(children)
54
+ for (x0, y0, s) in children:
55
+ if not block_has_sample(x0, y0, s):
56
+ place_random_in_block(x0, y0, s)
57
+ blocks = children
58
+ size = half
59
+ remaining: List[int] = []
60
+ for y in range(n):
61
+ for x in range(n):
62
+ if not occupied[y][x]:
63
+ remaining.append(y * n + x)
64
+ rng.shuffle(remaining)
65
+ seq.extend(remaining)
66
+ assert len(seq) == n * n, (len(seq), n * n)
67
+ return seq
positions.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADOBE CONFIDENTIAL
2
+ # Copyright 2025 Adobe
3
+ # All Rights Reserved.
4
+ # NOTICE: All information contained herein is, and remains
5
+ # the property of Adobe and its suppliers, if any. The intellectual
6
+ # and technical concepts contained herein are proprietary to Adobe
7
+ # and its suppliers and are protected by all applicable intellectual
8
+ # property laws, including trade secret and copyright laws.
9
+ # Dissemination of this information or reproduction of this material
10
+ # is strictly forbidden unless prior written permission is obtained
11
+ # from Adobe.
12
+
13
+ # Copyright 2023 Haotian Liu
14
+ #
15
+ # Licensed under the Apache License, Version 2.0 (the "License");
16
+ # you may not use this file except in compliance with the License.
17
+ # You may obtain a copy of the License at
18
+ #
19
+ # http://www.apache.org/licenses/LICENSE-2.0
20
+ #
21
+ # Unless required by applicable law or agreed to in writing, software
22
+ # distributed under the License is distributed on an "AS IS" BASIS,
23
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ # See the License for the specific language governing permissions and
25
+ # limitations under the License.
26
+
27
+
28
+ from __future__ import annotations
29
+ from numbers import Integral
30
+ import torch
31
+ GENERATION_2D_SINCOS_SCALE = 0.0018
32
+ GENERATION_2D_SINCOS_CANONICAL_CONTENT_SIZE = 32
33
+
34
+ def _generation_grid_shape(gen_shape, *, compressed: bool, encoder_compressed: bool, token_count: int) -> tuple[int, int]:
35
+ if not isinstance(gen_shape, (tuple, list)) or len(gen_shape) != 2:
36
+ raise ValueError('gen_enc_add_pos_emb requires gen_shape=(height, width)')
37
+ if any((isinstance(value, bool) or not isinstance(value, Integral) for value in gen_shape)):
38
+ raise TypeError('generation image height and width must be integers')
39
+ (height, width) = (int(value) for value in gen_shape)
40
+ if height < 1 or width < 1:
41
+ raise ValueError('generation image height and width must be positive')
42
+ for (stage_name, stage_enabled) in (('generation', compressed), ('generation-encoder', encoder_compressed)):
43
+ if not stage_enabled:
44
+ continue
45
+ if height % 2 or width % 2:
46
+ raise ValueError(f'{stage_name} compression requires an even image-token grid')
47
+ height //= 2
48
+ width //= 2
49
+ if height * width != token_count:
50
+ raise ValueError(f'generation positional grid does not match the transformer image tokens: {height}x{width} != {token_count}')
51
+ return (height, width)
52
+
53
+ def _build_2d_sincos_position_embedding(height: int, width: int, embedding_dim: int, *, marker_column: bool=False, device: torch.device, dtype: torch.dtype) -> torch.Tensor:
54
+ if embedding_dim % 4:
55
+ raise ValueError('gen_enc_add_pos_emb requires d_model_gen divisible by 4')
56
+ if not isinstance(marker_column, bool):
57
+ raise TypeError('marker_column must be boolean')
58
+ content_width = width - int(marker_column)
59
+ if height < 1 or content_width < 1:
60
+ raise ValueError('generation positional grid must contain positive content height and width')
61
+ axis_frequency_count = embedding_dim // 4
62
+ frequencies = torch.arange(axis_frequency_count, device=device, dtype=torch.float32)
63
+ frequencies = 10000.0 ** (-frequencies / axis_frequency_count)
64
+ canonical_size = float(GENERATION_2D_SINCOS_CANONICAL_CONTENT_SIZE)
65
+ column_stride = canonical_size / float(content_width)
66
+ row_stride = canonical_size / float(height)
67
+ columns = torch.arange(width, device=device, dtype=torch.float32) * column_stride
68
+ rows = torch.arange(height, device=device, dtype=torch.float32) * row_stride
69
+ column_angles = torch.outer(columns, frequencies)
70
+ row_angles = torch.outer(rows, frequencies)
71
+ column_embedding = torch.cat((column_angles.sin(), column_angles.cos()), dim=-1)
72
+ row_embedding = torch.cat((row_angles.sin(), row_angles.cos()), dim=-1)
73
+ position_embedding = torch.cat((column_embedding.unsqueeze(0).expand(height, -1, -1), row_embedding.unsqueeze(1).expand(-1, width, -1)), dim=-1)
74
+ return position_embedding.reshape(height * width, embedding_dim).to(dtype=dtype)
projector.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import torch
4
+ import torch.nn as nn
5
+
6
+ class SquaredReLU(nn.Module):
7
+
8
+ def forward(self, x):
9
+ return torch.pow(torch.nn.functional.relu(x), 2)
10
+
11
+ class RMSNorm(nn.Module):
12
+
13
+ def __init__(self, hidden_size, eps=1e-05):
14
+ super().__init__()
15
+ self.weight = nn.Parameter(torch.ones(hidden_size))
16
+ self.eps = eps
17
+
18
+ def forward(self, hidden_states):
19
+ input_dtype = hidden_states.dtype
20
+ hidden_states = hidden_states.to(torch.float32)
21
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
22
+ hidden_states = hidden_states * torch.rsqrt(variance + self.eps)
23
+ return (self.weight.to(torch.float32) * hidden_states).to(input_dtype)
24
+
25
+ class RadioHProjector(nn.Module):
26
+
27
+ def __init__(self, config):
28
+ super().__init__()
29
+ self.downsample_ratio = 0.5
30
+ self.ps_version = 'v2'
31
+ vit_hidden_size = 1280
32
+ vision_projection_hidden_size = getattr(config, 'projector_hidden_size', config.hidden_size)
33
+ llm_hidden_size = config.hidden_size
34
+ in_dim = int(vit_hidden_size * (1 / self.downsample_ratio) ** 2)
35
+ self.mlp = nn.Sequential(RMSNorm(in_dim, eps=1e-05), nn.Linear(in_dim, vision_projection_hidden_size, bias=False), SquaredReLU(), nn.Linear(vision_projection_hidden_size, llm_hidden_size, bias=False))
36
+ self.radio_multiply = True
37
+
38
+ def pixel_shuffle(self, x, scale_factor=0.5):
39
+ (n, w, h, c) = x.size()
40
+ x = x.view(n, w, int(h * scale_factor), int(c / scale_factor))
41
+ x = x.permute(0, 2, 1, 3).contiguous()
42
+ x = x.view(n, int(h * scale_factor), int(w * scale_factor), int(c / (scale_factor * scale_factor)))
43
+ if self.ps_version != 'v1':
44
+ x = x.permute(0, 2, 1, 3).contiguous()
45
+ return x
46
+
47
+ def forward(self, image_features: torch.Tensor, image_grid_thw: torch.Tensor):
48
+ device = image_features.device
49
+ indices = []
50
+ offset = 0
51
+ for (_, H, W) in image_grid_thw.tolist():
52
+ (H, W) = (int(H), int(W))
53
+ (H2, W2) = (H // 2, W // 2)
54
+ k = torch.arange(H2 * W2, device=device)
55
+ if self.ps_version == 'v1':
56
+ (out_r, out_c) = (k % H2, k // H2)
57
+ else:
58
+ (out_r, out_c) = (k // W2, k % W2)
59
+ tl = offset + 2 * out_r * W + 2 * out_c
60
+ indices.append(torch.stack([tl, tl + 1, tl + W, tl + W + 1], dim=1).reshape(-1))
61
+ offset += H * W
62
+ gather_idx = torch.cat(indices)
63
+ merged = image_features[gather_idx].view(-1, 4 * image_features.shape[-1])
64
+ if self.radio_multiply:
65
+ return 0.01 * self.mlp(merged)
66
+ return self.mlp(merged)
radio_cls.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved.
2
+ #
3
+ # NVIDIA CORPORATION and its licensors retain all intellectual property
4
+ # and proprietary rights in and to this software, related documentation
5
+ # and any modifications thereto. Any use, reproduction, disclosure or
6
+ # distribution of this software and related documentation without an express
7
+ # license agreement from NVIDIA CORPORATION is strictly prohibited.
8
+ from __future__ import annotations
9
+ from typing import Optional
10
+ import torch
11
+ from torch import nn
12
+
13
+ class ClsToken(nn.Module):
14
+
15
+ def __init__(self, ndim: int, num_tokens: int=1, enabled: bool=True, register_multiple: Optional[int]=None, num_registers: Optional[int]=None):
16
+ super().__init__()
17
+ self.ndim = ndim
18
+ self.enabled = enabled
19
+ self.num_registers = 0
20
+ self.num_tokens = num_tokens
21
+ if enabled:
22
+ if num_registers:
23
+ self.num_registers = num_registers
24
+ elif register_multiple:
25
+ self.num_registers = register_multiple - num_tokens % register_multiple
26
+ scale = ndim ** -0.5
27
+ self.token = nn.Parameter(torch.randn(num_tokens + self.num_registers, ndim) * scale)
28
+ else:
29
+ self.token = None
30
+ self.num_patches = self.num_tokens + self.num_registers
31
+
32
+ def disable(self):
33
+ self.token = None
34
+ self.enabled = False
35
+
36
+ def forward(self, x: torch.Tensor):
37
+ if self.token is None:
38
+ return x
39
+ token = self.token.unsqueeze(0).expand(x.shape[0], -1, -1)
40
+ x = torch.cat([token, x], dim=1)
41
+ return x
42
+
43
+ def no_weight_decay(self):
44
+ return ['token']
radio_patch.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved.
2
+ #
3
+ # NVIDIA CORPORATION and its licensors retain all intellectual property
4
+ # and proprietary rights in and to this software, related documentation
5
+ # and any modifications thereto. Any use, reproduction, disclosure or
6
+ # distribution of this software and related documentation without an express
7
+ # license agreement from NVIDIA CORPORATION is strictly prohibited.
8
+
9
+ from __future__ import annotations
10
+ import math
11
+ from typing import Union, Tuple, Optional
12
+ import torch
13
+ import torch.nn.functional as F
14
+ from torch import nn
15
+ from einops import rearrange
16
+ from .radio_cls import ClsToken
17
+ input_dim_t = Union[int, Tuple[int, int]]
18
+
19
+ class ViTPatchGenerator(nn.Module):
20
+
21
+ def __init__(self, patch_size: int, embed_dim: int, input_dims: input_dim_t, abs_pos: bool=True, normalize_patches: bool=False, cls_token: bool=False, max_input_dims: Optional[input_dim_t]=None, pos_dropout: float=0.0, return_pos_enc: bool=False, num_cls_tokens: int=1, register_multiple: Optional[int]=None, num_registers: Optional[int]=None, patch_bias: bool=False, device=None, dtype=None):
22
+ super().__init__()
23
+ if isinstance(input_dims, int):
24
+ input_dims = (input_dims, input_dims)
25
+ if max_input_dims is None:
26
+ max_input_dims = input_dims
27
+ if isinstance(max_input_dims, int):
28
+ max_input_dims = (max_input_dims, max_input_dims)
29
+ max_input_dims = tuple((int(math.ceil(d / patch_size) * patch_size) for d in max_input_dims))
30
+ self.cpe_mode = max_input_dims != input_dims
31
+ self.pos_dropout = pos_dropout
32
+ self.return_pos_enc = return_pos_enc
33
+ factory = dict(device=device, dtype=dtype)
34
+ self.patch_size = patch_size
35
+ self.abs_pos = abs_pos
36
+ self.embed_dim = embed_dim
37
+ self.num_rows = max_input_dims[0] // patch_size
38
+ self.num_cols = max_input_dims[1] // patch_size
39
+ self.input_dims = tuple((d // patch_size for d in input_dims))
40
+ self.num_patches = self.num_rows * self.num_cols
41
+ self.max_input_dims = max_input_dims
42
+ self.im_to_patches = Im2Patches(patch_size)
43
+ self.embedder = ViTPatchLinear(patch_size, embed_dim, bias=patch_bias, **factory)
44
+ if abs_pos:
45
+ scale = embed_dim ** -0.5
46
+ self.pos_embed = nn.Parameter(torch.randn(1, self.num_patches, embed_dim, **factory) * scale)
47
+ self.cls_token = ClsToken(embed_dim, num_tokens=num_cls_tokens, enabled=cls_token, register_multiple=register_multiple, num_registers=num_registers)
48
+ self.patch_normalizer = nn.LayerNorm(embed_dim) if normalize_patches else nn.Identity()
49
+ self.num_video_frames = None
50
+
51
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
52
+ patches = self.embed_patches(x)
53
+ (patches, pos_enc) = self.apply_pos_enc(patches, input_size=x.shape[2:])
54
+ patches = self.cls_token(patches)
55
+ patches = self.patch_normalizer(patches)
56
+ if self.return_pos_enc:
57
+ return (patches, pos_enc)
58
+ return patches
59
+
60
+ @property
61
+ def apply_cls_token(self):
62
+ return self.cls_token.enabled
63
+
64
+ @property
65
+ def num_cls_tokens(self):
66
+ return self.cls_token.num_tokens
67
+
68
+ @property
69
+ def num_cls_patches(self):
70
+ return self.cls_token.num_patches
71
+
72
+ @property
73
+ def num_registers(self):
74
+ return self.cls_token.num_registers
75
+
76
+ @property
77
+ def num_skip(self):
78
+ return self.num_cls_tokens + self.num_registers
79
+
80
+ def no_weight_decay(self):
81
+ return ['pos_embed']
82
+
83
+ def _load_embed(self, src_embed: torch.Tensor, targ_embed: nn.Parameter):
84
+ if src_embed.shape != targ_embed.shape:
85
+ src_size = int(math.sqrt(src_embed.shape[1]))
86
+ assert src_size ** 2 == src_embed.shape[1], 'Unable to interpolate non-square embedding'
87
+ src_embed = rearrange(src_embed, 'b (h w) c -> b c h w', h=src_size, w=src_size)
88
+ src_embed = F.interpolate(src_embed, size=(self.num_rows, self.num_cols), mode='bicubic', align_corners=True, antialias=False)
89
+ src_embed = rearrange(src_embed, 'b c h w -> b (h w) c')
90
+ targ_embed.data.copy_(src_embed)
91
+
92
+ def _load_projection(self, src_proj_weight: torch.Tensor, targ_proj_weight: torch.Tensor):
93
+ if src_proj_weight.shape != targ_proj_weight.shape:
94
+ src_patch_size = int(math.sqrt(src_proj_weight.shape[1] // 3))
95
+ assert src_patch_size ** 2 * 3 == src_proj_weight.shape[1], 'Unable to interpolate non-square patch size'
96
+ src_proj_weight = rearrange(src_proj_weight, 'b (c h w) -> b c h w', c=3, h=src_patch_size, w=src_patch_size)
97
+ src_proj_weight = F.interpolate(src_proj_weight, size=(self.patch_size, self.patch_size), mode='bicubic', align_corners=True, antialias=False)
98
+ src_proj_weight = rearrange(src_proj_weight, 'b c h w -> b (c h w)')
99
+ targ_proj_weight.data.copy_(src_proj_weight)
100
+
101
+ def embed_patches(self, x: torch.Tensor) -> torch.Tensor:
102
+ patches = self.im_to_patches(x)
103
+ patches = self.embedder(patches)
104
+ return patches
105
+
106
+ def apply_pos_enc(self, patches: torch.Tensor, patch_idxs: Optional[torch.Tensor]=None, input_size: Optional[Tuple[int, int]]=None) -> torch.Tensor:
107
+ if not self.abs_pos:
108
+ return patches
109
+ pos_enc = self.get_pos_enc(patches.shape[0], patch_idxs, input_size)
110
+ pos_enc_drop = pos_enc
111
+ return (patches + pos_enc_drop, pos_enc)
112
+
113
+ def get_pos_enc(self, batch_size: int, patch_idxs: Optional[torch.Tensor]=None, input_size: Optional[Tuple[int, int]]=None) -> torch.Tensor:
114
+ if input_size is None:
115
+ input_dims = self.input_dims
116
+ else:
117
+ input_dims = tuple((d // self.patch_size for d in input_size))
118
+ pos_embed = self._get_pos_embeddings(batch_size, input_dims)
119
+ if patch_idxs is None:
120
+ return pos_embed
121
+ exp_patch_idxs = patch_idxs.unsqueeze(-1).expand(-1, -1, pos_embed.shape[-1])
122
+ pos_embed = torch.gather(pos_embed.expand(patch_idxs.shape[0], -1, -1), dim=1, index=exp_patch_idxs)
123
+ return pos_embed
124
+
125
+ def _get_pos_embeddings(self, batch_size: int, input_dims: Tuple[int, int]):
126
+ if (self.num_rows, self.num_cols) == input_dims:
127
+ return self.pos_embed
128
+ pos_embed = self.pos_embed.reshape(1, self.num_rows, self.num_cols, -1).permute(0, 3, 1, 2)
129
+
130
+ def window_select(pos_embed):
131
+ if input_dims[0] < pos_embed.shape[-2]:
132
+ pos_embed = pos_embed[..., :input_dims[0], :]
133
+ if input_dims[1] < pos_embed.shape[-1]:
134
+ pos_embed = pos_embed[..., :, :input_dims[1]]
135
+ return pos_embed
136
+ if self.cpe_mode:
137
+ max_dim = max(input_dims)
138
+ pos_embed = F.interpolate(pos_embed.float(), size=(max_dim, max_dim), align_corners=False, mode='bilinear').to(pos_embed.dtype)
139
+ pos_embed = window_select(pos_embed)
140
+ else:
141
+ pos_embed = window_select(pos_embed)
142
+ if pos_embed.shape[-2:] != input_dims:
143
+ pos_embed = F.interpolate(pos_embed.float(), size=input_dims, align_corners=False, mode='bilinear').to(pos_embed.dtype)
144
+ pos_embed = pos_embed.flatten(2).permute(0, 2, 1)
145
+ return pos_embed
146
+
147
+ class Im2Patches(nn.Module):
148
+
149
+ def __init__(self, patch_size: int):
150
+ super().__init__()
151
+ self.patch_size = patch_size
152
+
153
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
154
+ if self.patch_size == 1:
155
+ patches = x.flatten(2)
156
+ patches = patches.permute(0, 2, 1)
157
+ return patches
158
+ py = x.shape[-2] // self.patch_size
159
+ px = x.shape[-1] // self.patch_size
160
+ patches = rearrange(x, 'b c (py yy) (px xx) -> b (py px) (c yy xx)', py=py, yy=self.patch_size, px=px, xx=self.patch_size)
161
+ return patches
162
+
163
+ class ViTPatchLinear(nn.Linear):
164
+
165
+ def __init__(self, patch_size: int, embed_dim: int, bias: bool=False, **factory):
166
+ super().__init__(3 * patch_size ** 2, embed_dim, bias=bias, **factory)
167
+ self.patch_size = patch_size
refinement.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ from numbers import Integral
4
+ import torch
5
+
6
+ def _validate_refinement_steps(value: object, *, source: str) -> int:
7
+ if isinstance(value, bool) or not isinstance(value, Integral):
8
+ raise TypeError(f'{source} must be a positive integer')
9
+ value = int(value)
10
+ if value < 1:
11
+ raise ValueError(f'{source} must be a positive integer')
12
+ return value
13
+
14
+ def refinement_mask_fraction(ages: torch.Tensor, *, steps: int) -> torch.Tensor:
15
+ steps = _validate_refinement_steps(steps, source='steps')
16
+ if ages.dtype == torch.bool or ages.is_floating_point():
17
+ raise TypeError('ages must use an integer dtype')
18
+ effective_age = ages.clamp(min=0, max=steps).to(dtype=torch.float32)
19
+ return (1.0 - effective_age / steps).mean(dim=-1)
release_manifest.json ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "revision": "generation-only-step-10000",
3
+ "sha256": {
4
+ ".gitattributes": "50360a3ded843d95a2667395b3131f6d499b905d941331a4e84e7f0351769023",
5
+ ".gitignore": "e1900f365321556fa39bfe45527be4e15a1de7fe96b71ca8d294b690a1026a8d",
6
+ "README.md": "50038fb0e318e290c123382d4f6284ce80699bd60d7fabf0ee6db27419e12b07",
7
+ "attention.py": "5617bdd53aaa0d6f0e79745c5e811f36335a0c1f458218ab1fc02c4606d79f37",
8
+ "bridge.py": "0e20f9ad1c81912489dd7c5063507b7fb72ead7d1895467442277e06ee3bc846",
9
+ "chat_template.jinja": "b80135b85225bef1a5129eb2068d0d5df4975edf4ffb102a50de1fb069c9e78a",
10
+ "chat_utils.py": "0683087dbadea1ce510d77816eed8ccfba998aa6c64833fd93c4e46c6edbc734",
11
+ "config.json": "9dd7b2514b477712b9e023dec3f0d3749e8ccd9e27869cb4bf70fe9a8097fff0",
12
+ "configuration_nlduni.py": "fa6d15657c9fadeb1f2bc142ea33b73c225374d5646565a077b43d6fd3e25f38",
13
+ "constants.py": "1149095b05a6da911aae371d4899edcaba154352dc30efd2d5b72bb8767f785f",
14
+ "conversation.py": "5e11082e6f5201978a0eb99523120d1272a6e0b311bfa75b273fa02d927d1002",
15
+ "core.py": "4dad9ea004daa31236fb1eb628d2ad1b46d310914114bd93c401fd41161d5c66",
16
+ "generation_config.json": "35e13707e4e588edaa4d7c12dff1d9ccd49efe0e07c99e3392c42b88f9398faa",
17
+ "image_utils.py": "62755735051898eb909937712e0badcf6614d30405ea51d7d33522f484a319d1",
18
+ "inference.py": "37e0b19b3d003621a620b226d6a9d39725e9450a7a6431d992ceea49cb2b92b2",
19
+ "markers.py": "17f69056ff9db548dc223971021a91444ecaef3257df5b5f30fd2e5230bbadc7",
20
+ "model-00001-of-00008.safetensors": "c4d490e010475dde3e2b57de64261a56d6bf8e9ca7d077754913fd628f7de5f6",
21
+ "model-00002-of-00008.safetensors": "933c4b2f44f9cd7be30ac7a40efbb3c58485aa9fbd6396245d8e2337faf5c5b3",
22
+ "model-00003-of-00008.safetensors": "6893a316ec6655eb3f518be0f3ae3dfc80621922741df7d14f12b3d9fd123bf6",
23
+ "model-00004-of-00008.safetensors": "858fab295f100b897634b72824d01e01f368dc1d500de03916854d7b2769986c",
24
+ "model-00005-of-00008.safetensors": "0d31608093622df48c2284fa310170f9a1bfd127d7108bdacbc8106fcf296691",
25
+ "model-00006-of-00008.safetensors": "4356b837d798b2d3250cd067c15b7f5d56fd19a8b8605bb107fb9d727c1726d0",
26
+ "model-00007-of-00008.safetensors": "003f5a6c4c727e5f560e16ad91ee2264ed138c7190108dfc9b68d1b8c8445545",
27
+ "model-00008-of-00008.safetensors": "299783fae2f540dfd723abbb09f8661b57122210d44b23a4c65f24b254542550",
28
+ "model.safetensors.index.json": "f2c7c2353c2a2eb70e7f80889c4fca85caceba217f1ccd9aa6647a7c644f6e30",
29
+ "modeling_nlduni.py": "d7a04c330d1cd14fc638297a61a674cfdc666d8eb5ee24c41625ff1875040021",
30
+ "padding.py": "53ba2cc8b37eec837b4fd0a3932a5f2d55051bbe5796c848921ce95171336dce",
31
+ "pca_tree.pt": "4b7ee94fbb10fd4146a4ad167b595b037e3f591eaa12ecf3f0b411c82384a714",
32
+ "pmj.py": "33920c0bb48ab99bafb3dde99f0e44eff7e6004596777d2e09ec4d07e039bfa3",
33
+ "positions.py": "3e0ee23d4bd59059690bc9962fa0948c18f52af13c1295d5322309ba6472f0c4",
34
+ "projector.py": "b402ae3a9ca1d7867c139e3180f905411d4932901cd7ce19910865db8709691f",
35
+ "radio_cls.py": "6c04ff0ac364676b7ca2610d8103c53f3b7a26d5d4b6cfd593415556e721c710",
36
+ "radio_patch.py": "41d63126936a4691d28979f9bb7a7b35c2daa9f10c8e98ef909656930ec861c2",
37
+ "refinement.py": "b69a5bcfec2ecdbc97d5b5796dbcd6dfa83d29fe8b835017a18b2e96596891ca",
38
+ "requirements.txt": "a3725eb78eb9ed882a46b2b0370f4b93eafc93e59d6e8db38698963016b9405d",
39
+ "sampling.py": "6111a83d7d737eab9c702af281f209316e7458a785d0102c4f2bf3fd4e315491",
40
+ "sbd_attention.py": "828f02ae59d430485507b00c76d0b85158dfa10dfea7888519ec80522798a134",
41
+ "schedules.py": "243d3fa6924f11397df422c9e50dc37bd4e85d882c518c3a4a75545a3b1a367e",
42
+ "special_tokens_map.json": "57cc1f9b3ea2a038d1107bdf4f4b3c45b5ed9ce175e7410d70070e07a3f35a76",
43
+ "token_constants.py": "6515bb3f128730edcd02907cf49334ac9cae2ed373611b0a260b3bdf4ff678f1",
44
+ "tokenizer.json": "f9ad3482369ba91711ff939f9eeb761d618b3157fcbfc0715f18e34b918eca97",
45
+ "tokenizer_config.json": "5eb18e9f9e0653added53a9200a8d38fdbc1d0cdb4602f8e354f30391f8cb1f3",
46
+ "tree.py": "b22d647f4d6def2a8df6f1b336db0b03a9cf0131dccf124f949cfa704e227c81",
47
+ "tree_metadata.json": "16ccc59386d2d73094ba9b2562feff45b7a171f4f37053f9b5ed756d5c44e3d5",
48
+ "utils.py": "6a0036a6451918de85fcc9cc3a82f5c195227bda5df58103156dd9941f6da0bc",
49
+ "vision.py": "375c9cd952135701b71b35581a72c46cc58bb9701392343f9817f9cf1e68bb72",
50
+ "vq.py": "3029623e15687b8fe95594b25410cfa2c0a82eebaa821b6ab380d1dcc394e537",
51
+ "vq_model.py": "0f28d77789671b9c05402de7dca7bfccaa57264336ba778a76f3b59966baced7",
52
+ "weights_manifest.json": "fe3af69d1ff222d3de89efd6305fcb3d396204b3c208491866d4da1137bea6f9"
53
+ }
54
+ }
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python 3.13, CUDA 12.6; install torch before building flash-attn.
2
+ torch==2.7.0
3
+ torchvision==0.22.0
4
+ transformers==4.57.6
5
+ huggingface-hub==0.36.2
6
+ tokenizers==0.22.2
7
+ accelerate==1.6.0
8
+ safetensors==0.7.0
9
+ timm==1.0.26
10
+ einops==0.6.1
11
+ numpy==2.4.3
12
+ pillow==12.1.1
13
+ tqdm>=4.66,<5
sampling.py ADDED
@@ -0,0 +1,831 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADOBE CONFIDENTIAL
2
+ # Copyright 2025 Adobe
3
+ # All Rights Reserved.
4
+ # NOTICE: All information contained herein is, and remains
5
+ # the property of Adobe and its suppliers, if any. The intellectual
6
+ # and technical concepts contained herein are proprietary to Adobe
7
+ # and its suppliers and are protected by all applicable intellectual
8
+ # property laws, including trade secret and copyright laws.
9
+ # Dissemination of this information or reproduction of this material
10
+ # is strictly forbidden unless prior written permission is obtained
11
+ # from Adobe.
12
+
13
+
14
+ from __future__ import annotations
15
+ import os
16
+ from .image_utils import compute_num_image_tokens, fix_one_prompt, process_images, tokenizer_image_token
17
+ from .token_constants import IMAGE_TOKEN_INDEX, IMAGE_PAD_TOKEN_INDEX
18
+ from .conversation import conv_templates
19
+ from PIL import Image
20
+ import copy
21
+ import functools
22
+ import math
23
+ import torch
24
+ from .schedules import cosine_schedule_2, logit_normal_schedule
25
+ import time
26
+ from .chat_utils import wte as wte_ministral
27
+ from .chat_utils import get_logits as get_logits_ministral
28
+ from .chat_utils import _resolve_shift_sbd_logits as resolve_ministral_shift_sbd_logits
29
+ from .sbd_attention import generated_image_attention_window
30
+ from tqdm.auto import tqdm
31
+ import numpy as np
32
+ import torch.distributions as dists
33
+ import torch.nn.functional as F
34
+ from .image_utils import pad_to_square_and_resize
35
+ from .utils import pad_along_last_dim
36
+ from .padding import _assert_source_padding_vq_locked, _prefill_source_padding_vq, _restore_source_padding_vq, _resolve_source_native_size, _source_padding_vq_mask, resolve_source_padding_vq_lock
37
+ from .refinement import refinement_mask_fraction
38
+ from .markers import append_image_row_markers, augmented_image_shape, image_fixed_prefix_token_count, image_generation_special_ids, image_row_marker_count, image_row_markers_enabled, resolve_generation_skip_down_sample, split_generation_fixed_prefix, strip_image_row_markers, validate_image_fixed_prefix_support, validate_image_row_marker_support
39
+ from .tree import BalancedSemanticTree, advance_revisable_semantic_tree, build_semantic_tree_embeddings, production_semantic_tree_contract, resolve_semantic_tree_atomic_block_size, resolve_semantic_tree_refinement_gap, resolve_semantic_tree_steps, semantic_tree_activation_counts, semantic_tree_decode_schedule, semantic_tree_noise_for_ages, semantic_tree_refinement_due
40
+ from .pmj import stratified_random
41
+
42
+ def _load_prediction_image(image):
43
+ if isinstance(image, (str, os.PathLike)):
44
+ image = Image.open(image)
45
+ return image.convert('RGB')
46
+
47
+ def _validate_text_to_image_batch_size(batch_size):
48
+ if batch_size != 1:
49
+ raise ValueError(f'text_to_image currently supports batch_size=1 only; got {batch_size}')
50
+
51
+ def _prediction_constant_version(model_config):
52
+ model_type = str(getattr(model_config, 'model_type', ''))
53
+ return 'ministral'
54
+ return None
55
+
56
+ def _move_image_to_device(value, *, device, dtype):
57
+ if torch.is_tensor(value):
58
+ return value.to(device=device, dtype=dtype)
59
+ if isinstance(value, tuple):
60
+ if not value:
61
+ return value
62
+ return (_move_image_to_device(value[0], device=device, dtype=dtype), *value[1:])
63
+ if isinstance(value, list):
64
+ return [_move_image_to_device(item, device=device, dtype=dtype) for item in value]
65
+ raise TypeError(f'Unsupported processed image type: {type(value).__name__}')
66
+
67
+ def _tokenize_prediction_prompt_with_images(prompt, tokenizer, model, image_processor, image_tensor):
68
+ image_aspect_ratio = 'radio_h_native'
69
+ native_image_token_shapes = None
70
+ if 'native' in image_aspect_ratio:
71
+ native_images = image_tensor if isinstance(image_tensor, list) else [image_tensor]
72
+ native_image_token_shapes = [compute_num_image_tokens([item], image_aspect_ratio, image_processor) for item in native_images]
73
+ prompt = fix_one_prompt(prompt, model.config, native_image_token_shapes)
74
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt', constant_version=_prediction_constant_version(model.config))
75
+ if native_image_token_shapes is not None:
76
+ expected_slots = sum((math.prod(shape) for shape in native_image_token_shapes))
77
+ actual_slots = int(input_ids.eq(IMAGE_PAD_TOKEN_INDEX).sum().item())
78
+ if actual_slots != expected_slots:
79
+ raise RuntimeError(f'Native-image T2I prompt/token mismatch: expected {expected_slots} image slots but tokenization produced {actual_slots}.')
80
+ return (prompt, input_ids)
81
+
82
+ def _transformer_image_token_count(model, raw_token_count, gen_shape):
83
+ raw_token_count = int(raw_token_count)
84
+ raw_grid_tokens = math.prod(gen_shape)
85
+ if raw_token_count != raw_grid_tokens:
86
+ raise ValueError(f'Raw generation token count must match gen_shape: {raw_token_count} != {raw_grid_tokens}')
87
+ generation_model = model.get_model()
88
+ skip_down_sample = resolve_generation_skip_down_sample(generation_model.config, runtime_value=False)
89
+ compression_active = (getattr(generation_model, 'packed_image_codec', None) is not None or getattr(generation_model, 'downsample_gen', None) is not None) and (not skip_down_sample)
90
+ if not compression_active:
91
+ return raw_token_count
92
+ (height, width) = (int(value) for value in gen_shape)
93
+ return height // 2 * (width // 2)
94
+
95
+ def gumbel_noise(t, generator=None):
96
+ noise = torch.zeros_like(t).uniform_(0, 1, generator=generator)
97
+ return -torch.log(-torch.log(noise))
98
+
99
+ def top_k_top_p_filtering(logits: torch.Tensor, top_k: int=0, top_p: float=1.0, filter_value: float=-1e309, min_tokens_to_keep: int=1) -> torch.Tensor:
100
+ if top_k > 0:
101
+ top_k = min(max(top_k, min_tokens_to_keep), logits.size(-1))
102
+ indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None]
103
+ logits[indices_to_remove] = filter_value
104
+ if top_p < 1.0:
105
+ (sorted_logits, sorted_indices) = torch.sort(logits, descending=True)
106
+ cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
107
+ sorted_indices_to_remove = cumulative_probs > top_p
108
+ if min_tokens_to_keep > 1:
109
+ sorted_indices_to_remove[..., :min_tokens_to_keep] = 0
110
+ sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
111
+ sorted_indices_to_remove[..., 0] = 0
112
+ indices_to_remove = sorted_indices_to_remove.scatter(1, sorted_indices, sorted_indices_to_remove)
113
+ logits[indices_to_remove] = filter_value
114
+ return logits
115
+ from .constants import NemotronMinistralDLMConstant
116
+ NC = NemotronMinistralDLMConstant
117
+
118
+ def _resolve_ministral_sbd_diffusion_sampling(model, requested):
119
+ model_module = model.module if hasattr(model, 'module') else model
120
+ config = model_module.config
121
+ if requested is None:
122
+ requested = True
123
+ enabled = bool(requested)
124
+ return enabled
125
+
126
+ def _configure_ministral_t2i_attention(model_module, *, sbd_diffusion_sampling):
127
+ config = model_module.config
128
+ for layer in model_module.encoder.layers:
129
+ attention = layer.self_attn
130
+ if sbd_diffusion_sampling:
131
+ attention.set_attention_mode('sbd_block_diff', block_size=config.block_size)
132
+ else:
133
+ attention.mode = 'bidirectional'
134
+ if hasattr(attention, 'diffusion_lm'):
135
+ attention.diffusion_lm = True
136
+
137
+ def _restore_attention_state_after_prediction(function):
138
+
139
+ @functools.wraps(function)
140
+ def wrapped(model, *args, **kwargs):
141
+ model_module = model.module if hasattr(model, 'module') else model
142
+ encoder = getattr(model_module, 'encoder', None)
143
+ layers = getattr(encoder, 'layers', ())
144
+ saved_states = []
145
+ for layer in layers:
146
+ attention = layer.self_attn
147
+ saved_states.append((attention, getattr(attention, 'mode', None), getattr(attention, 'block_size', None), getattr(attention, 'diffusion_lm', None)))
148
+ try:
149
+ return function(model, *args, **kwargs)
150
+ finally:
151
+ for (attention, mode, block_size, diffusion_lm) in saved_states:
152
+ if hasattr(attention, 'mode'):
153
+ attention.mode = mode
154
+ if hasattr(attention, 'block_size'):
155
+ attention.block_size = block_size
156
+ if hasattr(attention, 'diffusion_lm'):
157
+ attention.diffusion_lm = diffusion_lm
158
+ return wrapped
159
+
160
+ def _load_semantic_tree_path(model_config, *, cache_owner, device, vocab_size):
161
+ artifact_path = getattr(model_config, 'image_token_tree_path', None)
162
+ if not isinstance(artifact_path, str) or not artifact_path.strip():
163
+ raise ValueError('semantic-tree token sampling requires config.image_token_tree_path')
164
+ artifact_path = os.path.abspath(os.path.expanduser(artifact_path.strip()))
165
+ cache_key = (artifact_path, str(torch.device(device)), int(vocab_size))
166
+ cache_entry = cache_owner.__dict__.get('_semantic_tree_token_path_cache')
167
+ if isinstance(cache_entry, tuple) and len(cache_entry) == 2 and (cache_entry[0] == cache_key):
168
+ return cache_entry[1]
169
+ tree = BalancedSemanticTree.from_artifact(production_semantic_tree_contract(artifact_path), expected_vocab_size=int(vocab_size)).to(device)
170
+ cache_owner.__dict__['_semantic_tree_token_path_cache'] = (cache_key, tree)
171
+ return tree
172
+
173
+ def _select_within_unstarted(scores, unstarted, count, *, multinomial=False):
174
+ if scores.ndim != 2 or unstarted.shape != scores.shape:
175
+ raise ValueError('scores and unstarted must have matching [batch, token] shapes')
176
+ if unstarted.dtype != torch.bool:
177
+ raise TypeError('unstarted must use torch.bool')
178
+ if scores.shape[0] != 1:
179
+ raise ValueError('delayed refinement selection currently requires batch size 1')
180
+ count = int(count.item()) if torch.is_tensor(count) else int(count)
181
+ eligible = unstarted[0].nonzero(as_tuple=False).flatten()
182
+ if count < 0 or count > eligible.numel():
183
+ raise ValueError('selection count exceeds the unstarted-token set')
184
+ if count == 0:
185
+ return eligible[:0]
186
+ if count == eligible.numel():
187
+ return eligible
188
+ eligible_scores = scores[0, eligible]
189
+ if multinomial:
190
+ local_indices = torch.multinomial(eligible_scores, num_samples=count)
191
+ else:
192
+ local_indices = torch.topk(eligible_scores, k=count).indices
193
+ return eligible[local_indices]
194
+
195
+ def _combine_edit_guidance_logits(logits_full, logits_unconditional, logits_vq_dropped, *, guidance_scale, guidance_scale_image, edit_mode, guidance_mode='legacy', logits_image_only=None):
196
+ if guidance_mode == 'legacy':
197
+ if edit_mode in [0, 3]:
198
+ logits_cond = (1 + guidance_scale_image) * logits_full - guidance_scale_image * logits_vq_dropped
199
+ elif edit_mode in [1, 2]:
200
+ if guidance_scale_image <= -1:
201
+ raise ValueError('legacy edit modes 1/2 require guidance_scale_image > -1')
202
+ logits_cond = (logits_full + guidance_scale_image * logits_vq_dropped) / (1 + guidance_scale_image)
203
+ else:
204
+ raise ValueError(f'Unsupported edit_mode: {edit_mode}')
205
+ return (1 + guidance_scale) * logits_cond - guidance_scale * logits_unconditional
206
+ if guidance_mode == 'independent':
207
+ return logits_full + guidance_scale * (logits_full - logits_unconditional) + guidance_scale_image * (logits_full - logits_vq_dropped)
208
+ if guidance_mode == 'ip2p':
209
+ if logits_image_only is None:
210
+ raise ValueError('ip2p guidance requires image-only logits')
211
+ return logits_unconditional + (1 + guidance_scale_image) * (logits_image_only - logits_unconditional) + (1 + guidance_scale) * (logits_full - logits_image_only)
212
+ raise ValueError("edit_guidance_mode must be 'legacy', 'independent', or 'ip2p'")
213
+
214
+ def _resolve_guidance_scale_schedule(guidance_scale_schedule, n_steps):
215
+ if guidance_scale_schedule is None:
216
+ return None
217
+ if not isinstance(guidance_scale_schedule, list):
218
+ raise TypeError('guidance_scale_schedule must be a list')
219
+ if isinstance(n_steps, bool) or not isinstance(n_steps, int) or n_steps < 1:
220
+ raise ValueError('guidance_scale_schedule requires a positive integer n_steps')
221
+ if len(guidance_scale_schedule) != n_steps:
222
+ raise ValueError(f'guidance_scale_schedule must contain exactly n_steps values: {len(guidance_scale_schedule)} != {n_steps}')
223
+ resolved = []
224
+ for value in guidance_scale_schedule:
225
+ if isinstance(value, bool) or not isinstance(value, (int, float, np.integer, np.floating)):
226
+ raise TypeError('guidance_scale_schedule values must be real numbers')
227
+ value = float(value)
228
+ if not math.isfinite(value):
229
+ raise ValueError('guidance_scale_schedule values must be finite')
230
+ resolved.append(value)
231
+ return tuple(resolved)
232
+
233
+ def _resolve_semantic_tree_guidance_scale_range(guidance_scale_range):
234
+ if guidance_scale_range is None:
235
+ return None
236
+ if not isinstance(guidance_scale_range, (list, tuple)):
237
+ raise TypeError('semantic_tree_guidance_scale_range must be a two-value sequence')
238
+ if len(guidance_scale_range) != 2:
239
+ raise ValueError('semantic_tree_guidance_scale_range must contain exactly two values')
240
+ resolved = []
241
+ for value in guidance_scale_range:
242
+ if isinstance(value, bool) or not isinstance(value, (int, float, np.integer, np.floating)):
243
+ raise TypeError('semantic_tree_guidance_scale_range values must be real numbers')
244
+ value = float(value)
245
+ if not math.isfinite(value):
246
+ raise ValueError('semantic_tree_guidance_scale_range values must be finite')
247
+ resolved.append(value)
248
+ return tuple(resolved)
249
+
250
+ def _resolve_semantic_tree_global_guidance_scale_range(guidance_scale_range):
251
+ if guidance_scale_range is None:
252
+ return None
253
+ if not isinstance(guidance_scale_range, (list, tuple)):
254
+ raise TypeError('semantic_tree_global_guidance_scale_range must be a two-value sequence')
255
+ if len(guidance_scale_range) != 2:
256
+ raise ValueError('semantic_tree_global_guidance_scale_range must contain exactly two values')
257
+ resolved = []
258
+ for value in guidance_scale_range:
259
+ if isinstance(value, bool) or not isinstance(value, (int, float, np.integer, np.floating)):
260
+ raise TypeError('semantic_tree_global_guidance_scale_range values must be real numbers')
261
+ value = float(value)
262
+ if not math.isfinite(value):
263
+ raise ValueError('semantic_tree_global_guidance_scale_range values must be finite')
264
+ resolved.append(value)
265
+ return tuple(resolved)
266
+
267
+ def _resolve_semantic_tree_cfg_noise_interval(noise_interval):
268
+ if noise_interval is None:
269
+ return None
270
+ if not isinstance(noise_interval, (list, tuple)):
271
+ raise TypeError('semantic_tree_cfg_noise_interval must be a two-value sequence')
272
+ if len(noise_interval) != 2:
273
+ raise ValueError('semantic_tree_cfg_noise_interval must contain exactly two values')
274
+ resolved = []
275
+ for value in noise_interval:
276
+ if isinstance(value, bool) or not isinstance(value, (int, float, np.integer, np.floating)):
277
+ raise TypeError('semantic_tree_cfg_noise_interval values must be real numbers')
278
+ value = float(value)
279
+ if not math.isfinite(value):
280
+ raise ValueError('semantic_tree_cfg_noise_interval values must be finite')
281
+ resolved.append(value)
282
+ (minimum, maximum) = resolved
283
+ if not 0.0 <= minimum <= maximum <= 1.0:
284
+ raise ValueError('semantic_tree_cfg_noise_interval must satisfy 0 <= min_q <= max_q <= 1')
285
+ return (minimum, maximum)
286
+
287
+ @torch.no_grad()
288
+ @_restore_attention_state_after_prediction
289
+ def text_to_image(model, prompt, confidence_policy='mmada', guidance_scale=5, n_steps=20, tokenizer=None, image_resolution=512, n_tokens=1024, shift=3, alg_temp=1, schedule='shift', min_temperature=0.01, dynamic_temperature=False, micro_cond='ORIGINAL WIDTH : 1024; ORIGINAL HEIGHT : 1024; TOP : 0; LEFT : 0; SCORE : 6.5', temperature=1, schedule_temp='linear', shift_alg=None, top_p=None, top_k=None, unmask_order=None, cfg_interval=[0, 1], edit_image=None, image_processor=None, lock_source_padding_vq=None, edit_source_native_size=None, guidance_scale_image=5, edit_guidance_mode='legacy', edit_mode=0, template='Generate an image with the caption:\n <prompt>', plan=None, conv_template='llada', use_cache=None, cache_prompt=None, causal_context=True, edit_threshold=-1, disable_tqdm=False, ministral_sbd_sampling=None, ministral_full_attention_approx=True, ministral_shift_sbd_logits=None, image_embedding_refinement_steps=None, loop_k=None):
290
+ _validate_text_to_image_batch_size(1)
291
+ lock_source_padding_vq = resolve_source_padding_vq_lock(model.get_model().config, lock_source_padding_vq, has_edit_image=edit_image is not None)
292
+ if edit_source_native_size is not None and (not lock_source_padding_vq):
293
+ raise ValueError('edit_source_native_size is valid only with lock_source_padding_vq=true')
294
+ semantic_tree_refinement_gap = resolve_semantic_tree_refinement_gap(0)
295
+ semantic_tree_atomic_block_size = resolve_semantic_tree_atomic_block_size(1)
296
+ if shift_alg is None:
297
+ shift_alg = shift
298
+ resolved_loop_k = None
299
+ guidance_scale_schedule = _resolve_guidance_scale_schedule(None, n_steps)
300
+ semantic_tree_guidance_scale_range = _resolve_semantic_tree_guidance_scale_range(None)
301
+ semantic_tree_global_guidance_scale_range = _resolve_semantic_tree_global_guidance_scale_range(None)
302
+ semantic_tree_cfg_noise_interval = _resolve_semantic_tree_cfg_noise_interval(None)
303
+ guidance_scale_modes = sum((value is not None for value in (None, None, None)))
304
+ if guidance_scale_modes > 1:
305
+ raise ValueError('guidance_scale_schedule, semantic_tree_guidance_scale_range, and semantic_tree_global_guidance_scale_range are mutually exclusive')
306
+ device = model.get_model().device
307
+ use_image_local_ar_diffusion = False
308
+ if isinstance(edit_image, (str, os.PathLike)):
309
+ edit_image = _load_prediction_image(edit_image)
310
+ source_native_size = None
311
+ if lock_source_padding_vq:
312
+ source_native_size = _resolve_source_native_size(edit_source_native_size, fallback=edit_image.size)
313
+ conv_template = conv_template
314
+ use_mdm_prime = False
315
+ use_semantic_tree_tokens = True
316
+ semantic_tree_noise_cfg_requested = any((value is not None for value in (None, None, None)))
317
+ if semantic_tree_noise_cfg_requested:
318
+ if edit_image is not None:
319
+ raise NotImplementedError('semantic-tree noise-dependent CFG currently supports T2I only')
320
+ image_embedding_refinement_steps = resolve_semantic_tree_steps(model.get_model().config, image_embedding_refinement_steps)
321
+ use_refinement_state = True
322
+ reserve_token = '<|reserved_token_5|>'
323
+ reserve_token_2 = '<|reserved_token_6|>'
324
+ reserve_id = 126089
325
+ reserve_id2 = 126090
326
+ INT_MAX = 1000000
327
+ is_emu3 = 'emu3' in 'emu3'.lower()
328
+ use_image_row_markers = image_row_markers_enabled(model.get_model().config)
329
+ fixed_prefix_count = image_fixed_prefix_token_count(model.get_model().config)
330
+ if fixed_prefix_count:
331
+ validate_image_fixed_prefix_support(model.get_model())
332
+ row_marker_id = None
333
+ image_end_id = None
334
+ markers_per_row = None
335
+ skip_down_sample = resolve_generation_skip_down_sample(model.get_model().config, runtime_value=False)
336
+ (row_marker_id, _, image_end_id) = validate_image_row_marker_support(model.get_model(), skip_down_sample=skip_down_sample)
337
+ markers_per_row = image_row_marker_count(model.get_model(), skip_down_sample=skip_down_sample)
338
+ image_discrete_path = 'tree_metric'
339
+ use_tree_metric_path = False
340
+ use_affine_mixture_path = False
341
+ use_endpoint_probability_path = False
342
+ config = model.get_model().config
343
+ semantic_block_size = getattr(config, 'block_size', None)
344
+ if isinstance(semantic_block_size, bool) or not isinstance(semantic_block_size, int) or semantic_block_size < 1:
345
+ raise NotImplementedError('semantic_tree_token_diffusion requires a positive integer block_size')
346
+ if ministral_sbd_sampling is False:
347
+ raise NotImplementedError('semantic_tree_token_diffusion cannot disable checkpoint-native Ministral SBD sampling')
348
+ semantic_edit_controls_requested = edit_threshold > 0
349
+ if semantic_edit_controls_requested:
350
+ raise NotImplementedError('semantic_tree_token_diffusion does not support post-commit edit/refinement controls')
351
+ codebook_size = int(model.get_model().vqvae.config.num_vq_embeddings)
352
+ (_, img_mask_id, _) = image_generation_special_ids(codebook_size)
353
+ txt_mask_id = 126336
354
+ eot_id = 126384
355
+ model_type = 'llada'
356
+ model_type = 'ministral'
357
+ is_ministral = True
358
+ use_ministral_sbd_sampling = False
359
+ _wte = wte_ministral
360
+ img_begin = NC.gen_im_start_token
361
+ img_end = NC.gen_im_end_token
362
+ if use_cache is None:
363
+ use_cache = True
364
+ if cache_prompt is None:
365
+ cache_prompt = True
366
+ conv_template = 'ministral'
367
+ reserve_id = NC.reserve_id
368
+ reserve_id2 = NC.reserve_id_enc
369
+ reserve_token = NC.reserve_id_token
370
+ reserve_token_2 = NC.reserve_id_token_enc
371
+ img_begin = NC.gen_im_start_token
372
+ img_end = NC.gen_im_end_token
373
+ txt_mask_id = NC.mask_id
374
+ eot_id = NC.eos_id
375
+ _wte = wte_ministral
376
+ model_module = model.module if hasattr(model, 'module') else model
377
+ use_ministral_sbd_sampling = _resolve_ministral_sbd_diffusion_sampling(model_module, ministral_sbd_sampling)
378
+ resolve_ministral_shift_sbd_logits(model_module, ministral_shift_sbd_logits)
379
+ _configure_ministral_t2i_attention(model_module, sbd_diffusion_sampling=use_ministral_sbd_sampling)
380
+ gen_shape_map = {1024: (64, 64), 512: (32, 32), 256: (16, 16)}
381
+ content_gen_shape = gen_shape_map[image_resolution]
382
+ if int(n_tokens) != math.prod(content_gen_shape):
383
+ raise ValueError(f'Raw generation token count must match the content image grid: {n_tokens} != {math.prod(content_gen_shape)}')
384
+ gen_shape = augmented_image_shape(content_gen_shape, markers_per_row=markers_per_row)
385
+ micro_cond = micro_cond
386
+ if edit_image is not None:
387
+ micro_cond = ''
388
+ prompt = f'{prompt} {micro_cond}'
389
+ question = template.replace('<prompt>', prompt)
390
+ image_tokens_txt = _transformer_image_token_count(model, math.prod(gen_shape), gen_shape)
391
+ n_tokens_txt = image_tokens_txt + fixed_prefix_count
392
+ if plan is None:
393
+ plan = ''
394
+ edit_source_vq_codes = None
395
+ if edit_image is not None:
396
+ image = edit_image
397
+ image_tensor = process_images([image], image_processor, model.config)
398
+ image_tensor = _move_image_to_device(image_tensor, device=model.device, dtype=torch.bfloat16)
399
+ modalities = ['image']
400
+ image_sizes = [image.size]
401
+ conv = copy.deepcopy(conv_templates[conv_template])
402
+ image = image.convert('RGB')
403
+ image_1024 = pad_to_square_and_resize(image, image_resolution)
404
+ (enc_latents, _gen_shape) = model.encode_image_gen(model.model.image_processor_gen.preprocess(image_1024).to(model.device, model.dtype), enc=True)
405
+ if lock_source_padding_vq:
406
+ if tuple((int(value) for value in _gen_shape)) != tuple(content_gen_shape):
407
+ raise RuntimeError(f'edit source VQ grid does not match generation grid: {tuple(_gen_shape)} != {tuple(content_gen_shape)}')
408
+ if enc_latents.ndim != 2 or tuple(enc_latents.shape) != (1, n_tokens):
409
+ raise RuntimeError(f'edit source VQ codes must have shape [1, {n_tokens}], got {tuple(enc_latents.shape)}')
410
+ edit_source_vq_codes = enc_latents.detach().clone()
411
+ enc_embeddings = model.model.call_gen_embedding(enc_latents, _gen_shape, enc=True)
412
+ conv.append_message(conv.roles[0], f'<image> {reserve_token_2 * enc_embeddings.shape[1]}\n {prompt} ')
413
+ conv.append_message(conv.roles[1], f'Sure {plan}{img_begin}{reserve_token * n_tokens_txt}{img_end}')
414
+ prompt_question = conv.get_prompt()
415
+ prompt_question.removesuffix('<|start_header_id|>assistant<|end_header_id|>\n\n')
416
+ (prompt_question, input_ids) = _tokenize_prediction_prompt_with_images(prompt_question, tokenizer, model, image_processor, image_tensor)
417
+ input_ids = input_ids.unsqueeze(0).to(model.device)
418
+ attention_mask = None
419
+ position_ids = None
420
+ image_sizes = [image.size]
421
+ modalities = ['image']
422
+ (inputs, position_ids, attention_mask, _, inputs_embeds, _, raw_input_ids) = model.prepare_inputs_labels_for_multimodal(input_ids, position_ids, attention_mask, None, None, image_tensor, modalities, image_sizes=image_sizes, return_inputs=True)
423
+ expected_encoder_slots = int(enc_embeddings.shape[0] * enc_embeddings.shape[1])
424
+ actual_encoder_slots = int(raw_input_ids.eq(reserve_id2).sum().item())
425
+ if actual_encoder_slots != expected_encoder_slots:
426
+ raise RuntimeError(f'T2I edit encoder prompt/token mismatch: expected {expected_encoder_slots} slots but tokenization produced {actual_encoder_slots}.')
427
+ inputs_embeds[raw_input_ids == reserve_id2] = 0
428
+ _enc = pad_along_last_dim(enc_embeddings, inputs_embeds.shape[-1])
429
+ inputs_embeds[raw_input_ids == reserve_id2] = _enc.flatten(0, 1)
430
+ is_eot = torch.where(raw_input_ids == eot_id)[1]
431
+ assert len(is_eot) == 3
432
+ prompt_cutoff = is_eot[1]
433
+ is_prompt = torch.zeros_like(raw_input_ids, dtype=torch.bool)
434
+ is_prompt[:, :prompt_cutoff + 1] = True
435
+ is_gen = raw_input_ids == reserve_id
436
+ is_gen_enc = raw_input_ids == reserve_id2
437
+ else:
438
+ conv = copy.deepcopy(conv_templates[conv_template])
439
+ conv.append_message(conv.roles[0], question)
440
+ conv.append_message(conv.roles[1], f'Sure {plan}{img_begin}{reserve_token * n_tokens_txt}{img_end}')
441
+ prompt_question = conv.get_prompt()
442
+ prompt_question.removesuffix('<|start_header_id|>assistant<|end_header_id|>\n\n')
443
+ input_ids = tokenizer_image_token(prompt_question, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).to(device)
444
+ is_gen = input_ids == reserve_id
445
+ is_gen_enc = input_ids == reserve_id2
446
+ is_eot = torch.where(input_ids == eot_id)[1]
447
+ assert len(is_eot) == 3
448
+ prompt_cutoff = is_eot[1]
449
+ is_prompt = torch.zeros_like(input_ids, dtype=torch.bool)
450
+ is_prompt[:, :prompt_cutoff + 1] = True
451
+ raw_input_ids = input_ids
452
+ (inputs_embeds, _) = _wte(model.model, raw_input_ids)
453
+ generation_placeholder_mask = is_gen
454
+ generated_prompt_slots = int(generation_placeholder_mask.sum().item())
455
+ if generated_prompt_slots != n_tokens_txt:
456
+ raise RuntimeError(f'T2I prompt/token mismatch: expected {n_tokens_txt} generated-image slots but tokenization produced {generated_prompt_slots}.')
457
+ (fixed_prefix_mask, is_gen, fixed_prefix_ids) = split_generation_fixed_prefix(generation_placeholder_mask, codebook_size=int(model.get_model().vqvae.config.num_vq_embeddings), count=fixed_prefix_count)
458
+ if int(is_gen.sum().item()) != image_tokens_txt:
459
+ raise RuntimeError(f'T2I image-token mismatch after removing the fixed prefix: expected {image_tokens_txt}, found {int(is_gen.sum().item())}.')
460
+ generation_attention_mask = fixed_prefix_mask | is_gen
461
+ if fixed_prefix_ids.numel():
462
+ fixed_prefix_embeddings = model.get_model().call_gen_fixed_token_embedding(fixed_prefix_ids)
463
+ inputs_embeds[fixed_prefix_mask] = pad_along_last_dim(fixed_prefix_embeddings, inputs_embeds.shape[-1]).reshape(-1, inputs_embeds.shape[-1])
464
+ if plan:
465
+ is_gen_min = torch.where(raw_input_ids == reserve_id)[1][0]
466
+ is_prompt[:, :is_gen_min] = True
467
+ ministral_sbd_attention_window = None
468
+ use_exact_ministral_flash = bool(ministral_full_attention_approx)
469
+ use_ministral_prefix_cache = bool(use_cache and cache_prompt)
470
+ if use_ministral_sbd_sampling:
471
+ ministral_sbd_attention_window = generated_image_attention_window(generation_attention_mask)
472
+ use_ministral_prefix_cache = bool(use_cache and cache_prompt and causal_context)
473
+ if use_exact_ministral_flash and (not use_ministral_prefix_cache):
474
+ use_exact_ministral_flash = False
475
+ inputs_embeds_uncond = inputs_embeds.clone()
476
+ noise_embed = model.model.embed_tokens(torch.tensor([txt_mask_id]).to(model.device))
477
+ inputs_embeds_uncond[is_prompt] = noise_embed
478
+ if edit_image is not None:
479
+ inputs_embeds_image_only = inputs_embeds_uncond.clone()
480
+ inputs_embeds_image_only[is_gen_enc] = inputs_embeds[is_gen_enc]
481
+ inputs_embeds_uncond_enc = inputs_embeds.clone()
482
+ if edit_mode == 0:
483
+ inputs_embeds_uncond_enc[~is_gen_enc] = noise_embed
484
+ is_gen_enc_ccc = is_gen_enc
485
+ elif edit_mode == 1:
486
+ inputs_embeds_uncond_enc[is_gen_enc] = noise_embed
487
+ is_gen_enc_ccc = torch.zeros_like(is_gen_enc, dtype=torch.bool)
488
+ elif edit_mode == 2:
489
+ inputs_embeds_uncond_enc[is_gen_enc | (raw_input_ids < 0)] = noise_embed
490
+ is_gen_enc_ccc = torch.zeros_like(is_gen_enc, dtype=torch.bool)
491
+ elif edit_mode == 3:
492
+ inputs_embeds_uncond_enc[~is_gen_enc & (raw_input_ids > 0)] = noise_embed
493
+ is_gen_enc_ccc = is_gen_enc
494
+ else:
495
+ raise ValueError('Not Supported edit_mode')
496
+ inputs_embeds_uncond_enc[fixed_prefix_mask] = inputs_embeds[fixed_prefix_mask]
497
+ image_gen_latents_offset = torch.zeros(1, n_tokens, dtype=torch.long, device=input_ids.device)
498
+ is_unitok = False
499
+ structural_mask = None
500
+ endpoint_probability_path = None
501
+ semantic_tree = None
502
+ semantic_representatives = None
503
+ image_vocab_size = int(model.get_model().vqvae.config.num_vq_embeddings)
504
+ semantic_tree = _load_semantic_tree_path(model.get_model().config, cache_owner=model.get_model(), device=input_ids.device, vocab_size=image_vocab_size)
505
+ if image_embedding_refinement_steps > semantic_tree.depth:
506
+ raise ValueError(f'semantic-tree delayed commit steps cannot exceed tree depth: {image_embedding_refinement_steps} > {semantic_tree.depth}')
507
+ semantic_representatives = semantic_tree.sample_representatives(torch.zeros_like(image_gen_latents_offset), levels=0)
508
+ image_gen_latents_offset[:] = img_mask_id
509
+ xt = image_gen_latents_offset.clone()
510
+ (xt, marker_gen_shape, structural_mask) = append_image_row_markers(xt, content_gen_shape, row_marker_id=row_marker_id, image_end_id=image_end_id, markers_per_row=markers_per_row)
511
+ if marker_gen_shape != gen_shape:
512
+ raise RuntimeError('inference marker grid does not match the prompt grid')
513
+ (semantic_representatives, semantic_marker_shape, semantic_structural_mask) = append_image_row_markers(semantic_representatives, content_gen_shape, row_marker_id=row_marker_id, image_end_id=image_end_id, markers_per_row=markers_per_row)
514
+ if semantic_marker_shape != gen_shape or not torch.equal(semantic_structural_mask, structural_mask):
515
+ raise RuntimeError('semantic-tree marker layout does not match generation')
516
+ if structural_mask is None:
517
+ content_positions = torch.arange(xt.shape[-1], device=xt.device, dtype=torch.long)
518
+ else:
519
+ content_positions = (~structural_mask[0]).nonzero(as_tuple=False).flatten()
520
+ source_padding_raw_mask = None
521
+ source_padding_lock_mask = None
522
+ source_padding_locked_codes = None
523
+ source_padding_locked_embeddings = None
524
+ if lock_source_padding_vq:
525
+ if edit_source_vq_codes is None or source_native_size is None:
526
+ raise RuntimeError('source-padding VQ locking lost its source codes or geometry')
527
+ source_padding_raw_mask = _source_padding_vq_mask(source_native_size, content_gen_shape, device=xt.device).expand(edit_source_vq_codes.shape[0], -1)
528
+ (_, source_padding_lock_mask, source_padding_locked_codes) = _prefill_source_padding_vq(xt, edit_source_vq_codes.to(device=xt.device, dtype=xt.dtype), source_padding_raw_mask, content_positions)
529
+ source_padding_locked_embeddings = model.get_model().call_gen_token_embedding(source_padding_locked_codes)
530
+ sampling_protected_mask = structural_mask
531
+ refinement_child_embeddings = None
532
+ refinement_stage = None
533
+ semantic_next_refinement_round = None
534
+ refinement_stage = torch.full_like(xt, -1)
535
+ semantic_next_refinement_round = torch.zeros_like(refinement_stage)
536
+ if structural_mask is not None:
537
+ refinement_stage[structural_mask] = image_embedding_refinement_steps
538
+ semantic_noise_levels = semantic_tree_noise_for_ages(refinement_stage.clamp_min(0), steps=image_embedding_refinement_steps)
539
+ refinement_child_embeddings = build_semantic_tree_embeddings(semantic_representatives, semantic_noise_levels, model.get_model().call_gen_token_embedding, img_mask_id)
540
+ prime_digits = None
541
+ endpoint_sampling_times = None
542
+ mask_idx = xt == img_mask_id
543
+ n_mask = mask_idx.sum()
544
+ mask_idx_sch = mask_idx
545
+ semantic_counts = [semantic_tree_activation_counts(int(row_mask.sum().item()), activation_steps=n_steps, schedule=schedule, shift=shift, device=mask_idx_sch.device) for row_mask in mask_idx_sch]
546
+ if any((row_counts.shape != semantic_counts[0].shape for row_counts in semantic_counts[1:])):
547
+ raise ValueError('semantic-tree inference requires equal activation-step counts across batch rows')
548
+ num_transfer_tokens = torch.stack(semantic_counts)
549
+ activation_steps = num_transfer_tokens.shape[1]
550
+ decode_num_transfer_tokens = semantic_tree_decode_schedule(num_transfer_tokens, refinement_steps=image_embedding_refinement_steps, refinement_gap=0)
551
+ sch_temperatures = torch.linspace(0, 1, n_steps, device='cpu').numpy()
552
+ if schedule_temp == 'linear':
553
+ sch_temperatures = (1 - sch_temperatures) * (1 - min_temperature) + min_temperature
554
+ elif schedule_temp == 'cosine2':
555
+ sch_temperatures = cosine_schedule_2(1 - sch_temperatures) * (1 - min_temperature) + min_temperature
556
+ elif schedule_temp == 'shift':
557
+ sch_temperatures = logit_normal_schedule(shift_alg, 1 - sch_temperatures) * (1 - min_temperature) + min_temperature
558
+ else:
559
+ raise NotImplementedError(f'Unknown schedule_temp: {schedule_temp}')
560
+ sch_temperatures_samp = torch.linspace(0, 1, n_steps, device='cpu').numpy()
561
+ sch_temperatures_samp = (1 - sch_temperatures_samp) * (1 - 1) + 1
562
+ sch_temperatures = torch.tensor(sch_temperatures, device=device, dtype=torch.float32)
563
+ sch_temperatures_samp = torch.tensor(sch_temperatures_samp, device=device, dtype=torch.float32)
564
+ temp_idx = 0
565
+ cfg_start = int(cfg_interval[0] * n_steps)
566
+ cfg_end = int(cfg_interval[1] * n_steps)
567
+ use_optional_guidance_scale = any((value is not None for value in (None, None, None, None)))
568
+ scheduled_run_cfg_branches = None
569
+ if isinstance(unmask_order, str):
570
+ unmask_order = torch.load(unmask_order).tolist()
571
+ eligible_parent_positions = None
572
+ if confidence_policy == 'stratified' and unmask_order is None:
573
+ stratified_tokens = n_tokens
574
+ _dim = int(np.sqrt(stratified_tokens))
575
+ if _dim * _dim != stratified_tokens:
576
+ raise ValueError('stratified local AR sampling requires a square parent grid')
577
+ seq = stratified_random(n=_dim, seed=42, shuffle_blocks=True)
578
+ unmask_order = seq
579
+ stratified_token_count = n_tokens
580
+ if confidence_policy == 'stratified':
581
+ assert unmask_order is not None
582
+ n_c = 0
583
+ cat_cfg_time = 0
584
+ post_cfg_time = 0
585
+ wte_time = 0
586
+ fwd_time = 0
587
+ sample_time = 0
588
+ all_time = 0
589
+ total_edited = 0
590
+ edit_transitions = []
591
+ last_edit_step = torch.full_like(xt, -10000)
592
+ distribution_trace = {'initial_commits': [], 'edit_proposals': [], 'edits': []}
593
+ initial_trace_top_ids = None
594
+ initial_trace_top_logits = None
595
+ initial_trace_top_probs = None
596
+ initial_trace_top_sampling_probs = None
597
+ previous_trace_top_ids = None
598
+ previous_trace_top_logits = None
599
+ previous_trace_top_probs = None
600
+ intermediate_x0s = []
601
+ for (decode_step_idx, num_transfer) in tqdm(enumerate(decode_num_transfer_tokens[0]), total=decode_num_transfer_tokens.shape[1], disable=disable_tqdm):
602
+ t0 = time.time()
603
+ schedule_temp_idx = temp_idx
604
+ schedule_temp_idx = min(schedule_temp_idx, min(activation_steps, n_steps) - 1)
605
+ local_temp = sch_temperatures[schedule_temp_idx]
606
+ local_temp_samp = sch_temperatures_samp[schedule_temp_idx]
607
+ temp_idx += 1
608
+ schedule_progress_idx = temp_idx
609
+ schedule_progress_idx = min(schedule_progress_idx, activation_steps)
610
+ if schedule_progress_idx / n_steps > 100:
611
+ confidence_policy = 'mmada'
612
+ hard_mask_idx = refinement_stage < image_embedding_refinement_steps
613
+ mask_idx = refinement_stage < 0
614
+ n_mask = mask_idx.sum()
615
+ timestep_refinement_stage = refinement_stage[:, content_positions]
616
+ timesteps = refinement_mask_fraction(timestep_refinement_stage, steps=image_embedding_refinement_steps)
617
+ semantic_tree_cfg_q = None
618
+ cfg_step_idx = temp_idx
619
+ cfg_step_idx = min(cfg_step_idx, activation_steps)
620
+ guidance_scale_for_step = guidance_scale
621
+ if scheduled_run_cfg_branches is None:
622
+ run_cfg_branches = guidance_scale != 0 or guidance_scale_image != 0
623
+ else:
624
+ run_cfg_branches = scheduled_run_cfg_branches
625
+ do_cfg = run_cfg_branches and cfg_start <= cfg_step_idx and (cfg_end >= cfg_step_idx)
626
+ model_xt = _restore_source_padding_vq(xt, source_padding_lock_mask, source_padding_locked_codes)
627
+ if run_cfg_branches:
628
+ if edit_image is not None:
629
+ if edit_guidance_mode == 'ip2p':
630
+ input_embeddings_input = torch.cat([inputs_embeds_uncond, inputs_embeds_image_only, inputs_embeds]).clone()
631
+ else:
632
+ input_embeddings_input = torch.cat([inputs_embeds_uncond, inputs_embeds_uncond_enc, inputs_embeds]).clone()
633
+ xt_input = torch.cat([model_xt, model_xt, model_xt])
634
+ new_token_mask = is_gen.repeat(3, 1)
635
+ fixed_prefix_routing = fixed_prefix_mask.repeat(3, 1)
636
+ is_gen_enc_null = torch.zeros_like(is_gen_enc, dtype=torch.bool)
637
+ if edit_guidance_mode == 'ip2p':
638
+ is_gen_enc_mask = torch.cat([is_gen_enc_null, is_gen_enc, is_gen_enc])
639
+ else:
640
+ is_gen_enc_mask = torch.cat([is_gen_enc_null, is_gen_enc_ccc, is_gen_enc])
641
+ timesteps = timesteps.repeat(3)
642
+ else:
643
+ input_embeddings_input = torch.cat([inputs_embeds_uncond, inputs_embeds]).clone()
644
+ xt_input = torch.cat([model_xt, model_xt])
645
+ new_token_mask = is_gen.repeat(2, 1)
646
+ fixed_prefix_routing = fixed_prefix_mask.repeat(2, 1)
647
+ is_gen_enc_mask = is_gen_enc.repeat(2, 1)
648
+ is_gen_enc_mask[0, :] = False
649
+ timesteps = timesteps.repeat(2)
650
+ else:
651
+ input_embeddings_input = inputs_embeds.clone()
652
+ new_token_mask = is_gen
653
+ fixed_prefix_routing = fixed_prefix_mask
654
+ xt_input = model_xt
655
+ is_gen_enc_mask = is_gen_enc
656
+ enc_use_image_branch = True
657
+ generation_attention_mask_input = fixed_prefix_routing | new_token_mask
658
+ if enc_use_image_branch:
659
+ modality_indices = generation_attention_mask_input | is_gen_enc_mask
660
+ else:
661
+ modality_indices = generation_attention_mask_input
662
+ t1 = time.time()
663
+ x_gen_input = xt_input
664
+ x_gen_child_embeddings = None
665
+ if xt_input.shape[0] % refinement_child_embeddings.shape[0] != 0:
666
+ raise RuntimeError('CFG batch does not align with the refinement state batch')
667
+ cfg_repeats = xt_input.shape[0] // refinement_child_embeddings.shape[0]
668
+ step_refinement_child_embeddings = refinement_child_embeddings
669
+ if source_padding_lock_mask is not None:
670
+ if source_padding_locked_embeddings.shape != refinement_child_embeddings.shape:
671
+ raise RuntimeError('source-padding embeddings do not align with the refinement state')
672
+ step_refinement_child_embeddings = refinement_child_embeddings.clone()
673
+ step_refinement_child_embeddings[source_padding_lock_mask] = source_padding_locked_embeddings[source_padding_lock_mask]
674
+ x_gen_input = None
675
+ x_gen_child_embeddings = step_refinement_child_embeddings.repeat(cfg_repeats, 1, 1)
676
+ (all_input_embeddings, new_token_mask) = _wte(model.get_model(), None, True, x_gen=x_gen_input, gen_shape=gen_shape, inputs_embeds_curr=input_embeddings_input, new_token_mask=new_token_mask, x_gen_child_embeddings=x_gen_child_embeddings)
677
+ t2 = time.time()
678
+ if use_ministral_prefix_cache:
679
+ if decode_step_idx == 0:
680
+ cache_cutoff = ministral_sbd_attention_window[0] if ministral_sbd_attention_window is not None else prompt_cutoff
681
+ if causal_context:
682
+ for layer in model_module.encoder.layers:
683
+ if hasattr(layer.self_attn, 'diffusion_lm'):
684
+ layer.self_attn.diffusion_lm = False
685
+ if cache_cutoff > 0:
686
+ output = model.get_model()(None, input_embeddings=all_input_embeddings[:, :cache_cutoff], modality_indices=modality_indices[:, :cache_cutoff], output_hidden_states=True, past_key_values=None, use_cache=True, overwrite_attn_impl='flash_attn')
687
+ past_key_values = output.past_key_values
688
+ cache_len = past_key_values.get_seq_length()
689
+ if cache_len != cache_cutoff:
690
+ raise RuntimeError(f'SBD prefix cache length does not match its generated-image boundary: {cache_len} != {cache_cutoff}')
691
+ else:
692
+ past_key_values = None
693
+ cache_len = 0
694
+ if causal_context:
695
+ for layer in model_module.encoder.layers:
696
+ if hasattr(layer.self_attn, 'diffusion_lm'):
697
+ layer.self_attn.diffusion_lm = True
698
+ else:
699
+ pass
700
+ else:
701
+ past_key_values = None
702
+ cache_len = 0
703
+ sampling_end = ministral_sbd_attention_window[1] if ministral_sbd_attention_window is not None and use_ministral_prefix_cache else all_input_embeddings.shape[1]
704
+ if not cache_len <= sampling_end <= all_input_embeddings.shape[1]:
705
+ raise RuntimeError(f'Invalid exact-image SBD sampling window: cache_len={cache_len}, sampling_end={sampling_end}, sequence_length={all_input_embeddings.shape[1]}')
706
+ logits = get_logits_ministral(model.get_model(), all_input_embeddings[:, cache_len:sampling_end], new_token_mask[:, cache_len:sampling_end], True, gen_shape=gen_shape, input_modality_indices=modality_indices[:, cache_len:sampling_end], timesteps=timesteps, past_key_values=past_key_values, generation_attention_mask=generation_attention_mask_input[:, cache_len:sampling_end], sbd_diffusion_sampling=use_ministral_sbd_sampling, full_attention_approx=use_exact_ministral_flash, loop_k=None)
707
+ t3 = time.time()
708
+ if run_cfg_branches:
709
+ if edit_image is not None:
710
+ (new_token_mask, _, _) = new_token_mask.chunk(3)
711
+ (logits_un, logits_middle, logits) = logits.chunk(3)
712
+ if do_cfg:
713
+ logits_is_ninf = logits == -np.inf
714
+ logits = _combine_edit_guidance_logits(logits, logits_un, logits_middle if edit_guidance_mode != 'ip2p' else None, guidance_scale=guidance_scale_for_step, guidance_scale_image=guidance_scale_image, edit_mode=edit_mode, guidance_mode=edit_guidance_mode, logits_image_only=logits_middle if edit_guidance_mode == 'ip2p' else None)
715
+ logits[logits_is_ninf] = -np.inf
716
+ else:
717
+ (new_token_mask, _) = new_token_mask.chunk(2)
718
+ (logits_un, logits) = logits.chunk(2)
719
+ if do_cfg:
720
+ logits_is_ninf = logits == -np.inf
721
+ if use_optional_guidance_scale:
722
+ active_guidance_scale = guidance_scale
723
+ logits = (1 + active_guidance_scale) * logits - active_guidance_scale * logits_un
724
+ else:
725
+ logits = (1 + guidance_scale) * logits - guidance_scale * logits_un
726
+ logits[logits_is_ninf] = -np.inf
727
+ t4 = time.time()
728
+ if top_p is not None or top_k is not None:
729
+ (_b, _l, _v) = logits.shape
730
+ logits = logits.view(_b * _l, _v)
731
+ logits = top_k_top_p_filtering(logits, top_k=top_k, top_p=top_p, filter_value=-np.inf, min_tokens_to_keep=1)
732
+ logits = logits.view(_b, _l, _v)
733
+ probs = logits.softmax(dim=-1)
734
+ trace_top_ids = None
735
+ trace_top_logits = None
736
+ trace_top_probs = None
737
+ _temperature = temperature
738
+ sampling_distribution = dists.Categorical(logits=logits / _temperature)
739
+ x0 = sampling_distribution.sample()
740
+ del sampling_distribution
741
+ x0_p = torch.gather(probs, -1, x0.long()[..., None]).squeeze(-1)
742
+ if edit_threshold <= 0:
743
+ x0 = torch.where(hard_mask_idx, x0, xt)
744
+ if decode_step_idx >= activation_steps:
745
+ select_index = torch.empty(0, dtype=torch.long, device=x0.device)
746
+ elif confidence_policy == 'mask_git':
747
+ _alg_temp = alg_temp
748
+ if dynamic_temperature:
749
+ _alg_temp = _alg_temp * local_temp
750
+ confidence = x0_p / _alg_temp
751
+ confidence = torch.where(mask_idx, confidence, -np.inf)
752
+ confidence = torch.softmax(confidence, dim=-1)
753
+ select_index = _select_within_unstarted(confidence, mask_idx, num_transfer, multinomial=True)
754
+ elif confidence_policy == 'mmada':
755
+ _alg_temp = alg_temp
756
+ if dynamic_temperature:
757
+ _alg_temp = _alg_temp * local_temp
758
+ confidence = torch.log(x0_p.clamp(1e-20)) + _alg_temp * gumbel_noise(x0_p, generator=None)
759
+ confidence = torch.where(mask_idx, confidence, -np.inf)
760
+ select_index = _select_within_unstarted(confidence, mask_idx, num_transfer)
761
+ elif confidence_policy == 'stratified':
762
+ start = stratified_token_count - int(n_mask.item())
763
+ select_index = torch.tensor(unmask_order[start:start + int(num_transfer)], device=x0.device, dtype=torch.long)
764
+ if structural_mask is not None:
765
+ select_index = content_positions[select_index]
766
+ else:
767
+ raise NotImplementedError(f'Unknown confidence_policy: {confidence_policy}')
768
+ transfer_index = torch.zeros_like(x0, dtype=torch.bool, device=x0.device)
769
+ j = 0
770
+ transfer_index[j, select_index] = True
771
+ proposal_child_embeddings = None
772
+ activation_index = transfer_index & (refinement_stage < 0)
773
+ refinement_stage[activation_index] = 0
774
+ semantic_next_refinement_round[activation_index] = decode_step_idx + 0
775
+ pending_index = (refinement_stage >= 0) & (refinement_stage < image_embedding_refinement_steps)
776
+ proposal_child_embeddings = model.get_model().call_gen_token_embedding(x0)
777
+ pending_index &= semantic_tree_refinement_due(refinement_stage, semantic_next_refinement_round, decode_round=decode_step_idx, refinement_steps=image_embedding_refinement_steps)
778
+ commit_index = torch.zeros_like(pending_index)
779
+ if pending_index.any():
780
+ semantic_advance = advance_revisable_semantic_tree(semantic_representatives[pending_index], x0[pending_index], refinement_stage[pending_index], semantic_tree, steps=image_embedding_refinement_steps)
781
+ semantic_representatives[pending_index] = semantic_advance.representatives
782
+ refinement_stage[pending_index] = semantic_advance.ages
783
+ semantic_next_refinement_round[pending_index] = decode_step_idx + 0 + 1
784
+ commit_index[pending_index] = semantic_advance.committed
785
+ semantic_noise_levels = semantic_tree_noise_for_ages(refinement_stage.clamp_min(0), steps=image_embedding_refinement_steps)
786
+ refinement_child_embeddings = build_semantic_tree_embeddings(semantic_representatives, semantic_noise_levels, model.get_model().call_gen_token_embedding, img_mask_id)
787
+ xt[commit_index] = semantic_representatives[commit_index]
788
+ transfer_index = commit_index
789
+ xt_is_mask = xt == img_mask_id
790
+ edit_progress = (decode_step_idx + 1) / decode_num_transfer_tokens.shape[1]
791
+ edits_enabled_this_round = edit_threshold > 0 and 0.0 <= edit_progress <= 1.0 and (image_embedding_refinement_steps == 1 or decode_step_idx < activation_steps)
792
+ if edits_enabled_this_round:
793
+ editable_position = ~xt_is_mask & ~transfer_index
794
+ if structural_mask is not None:
795
+ editable_position &= ~structural_mask
796
+ editing_confidence = torch.where(editable_position, x0_p, -torch.inf)
797
+ high_conf_editing = editing_confidence > edit_threshold
798
+ margin_accepted = torch.ones_like(editable_position)
799
+ proposal_logit_margin = None
800
+ token_changed = (x0 != xt) & high_conf_editing & margin_accepted
801
+ num_edited = token_changed.sum()
802
+ if num_edited > 0:
803
+ xt[token_changed] = x0[token_changed]
804
+ last_edit_step[token_changed] = decode_step_idx
805
+ refinement_child_embeddings[token_changed] = proposal_child_embeddings[token_changed]
806
+ refinement_stage[token_changed] = image_embedding_refinement_steps
807
+ total_edited += num_edited.item()
808
+ t5 = time.time()
809
+ cat_cfg_time += t1 - t0
810
+ post_cfg_time += t2 - t1
811
+ wte_time += t3 - t2
812
+ fwd_time += t4 - t3
813
+ sample_time += t5 - t4
814
+ all_time += t5 - t0
815
+ n_c += 1
816
+ unresolved_refinement = refinement_stage < image_embedding_refinement_steps
817
+ if unresolved_refinement.any() or (xt == img_mask_id).any():
818
+ stage_counts = {stage: (refinement_stage == stage).sum().item() for stage in range(-1, image_embedding_refinement_steps + 1)}
819
+ raise RuntimeError(f'image embedding refinement ended with unresolved tokens: unfinished_stages={unresolved_refinement.sum().item()}, committed_mask_tokens={(xt == img_mask_id).sum().item()}, stage_counts={stage_counts}')
820
+ xt = _restore_source_padding_vq(xt, source_padding_lock_mask, source_padding_locked_codes)
821
+ _assert_source_padding_vq_locked(xt, source_padding_lock_mask, source_padding_locked_codes)
822
+ if structural_mask is not None:
823
+ expected_row_id = int(row_marker_id)
824
+ expected_end_id = int(image_end_id)
825
+ marker_grid = xt.reshape(xt.shape[0], *gen_shape)
826
+ if not bool((marker_grid[:, :-1, -markers_per_row:] == expected_row_id).all() and (marker_grid[:, -1:, -markers_per_row:] == expected_end_id).all()):
827
+ raise RuntimeError('structural generation image markers changed during sampling')
828
+ xt = strip_image_row_markers(xt, content_gen_shape, markers_per_row=markers_per_row)
829
+ x0_img = xt
830
+ result = Image.fromarray(model.decode_image_gen(x0_img, image_resolution, image_resolution)[0])
831
+ return result
sbd_attention.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import torch
4
+
5
+ def build_image_attention_doc_ids(image_token_mask: torch.Tensor, *, valid_tokens: torch.Tensor | None=None) -> torch.Tensor:
6
+ if image_token_mask.ndim != 2:
7
+ raise ValueError('image_token_mask must be a rank-2 [batch, length] tensor')
8
+ if valid_tokens is None:
9
+ valid_tokens = torch.ones_like(image_token_mask, dtype=torch.bool)
10
+ elif tuple(valid_tokens.shape) != tuple(image_token_mask.shape):
11
+ raise ValueError('valid_tokens must align with image_token_mask')
12
+ image_token_mask = image_token_mask.to(dtype=torch.bool)
13
+ valid_tokens = valid_tokens.to(dtype=torch.bool)
14
+ image_token_mask = image_token_mask & valid_tokens
15
+ previous_image = torch.cat((torch.zeros_like(image_token_mask[:, :1]), image_token_mask[:, :-1]), dim=1)
16
+ document_starts = image_token_mask & ~previous_image
17
+ return torch.cumsum(document_starts.long(), dim=1) * image_token_mask
18
+
19
+ def generated_image_attention_window(generated_image_token_mask: torch.Tensor, *, valid_tokens: torch.Tensor | None=None) -> tuple[int, int]:
20
+ if generated_image_token_mask.ndim != 2:
21
+ raise ValueError('generated_image_token_mask must be a rank-2 [batch, length] tensor')
22
+ if valid_tokens is None:
23
+ valid_tokens = torch.ones_like(generated_image_token_mask, dtype=torch.bool)
24
+ elif tuple(valid_tokens.shape) != tuple(generated_image_token_mask.shape):
25
+ raise ValueError('valid_tokens must align with generated_image_token_mask')
26
+ generated_image_token_mask = generated_image_token_mask.to(dtype=torch.bool) & valid_tokens.to(dtype=torch.bool)
27
+ windows = []
28
+ for row in generated_image_token_mask:
29
+ active = torch.where(row)[0]
30
+ if active.numel() == 0:
31
+ raise ValueError('SBD sampling requires at least one image token per row')
32
+ start = int(active[0].item())
33
+ end = int(active[-1].item()) + 1
34
+ if not bool(row[start:end].all()):
35
+ raise ValueError('Dense SBD FlashAttention requires one contiguous generated-image block')
36
+ windows.append((start, end))
37
+ if any((window != windows[0] for window in windows[1:])):
38
+ raise ValueError('Dense SBD FlashAttention requires the same generated-image block for every CFG batch row')
39
+ return windows[0]
schedules.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADOBE CONFIDENTIAL
2
+ # Copyright 2025 Adobe
3
+ # All Rights Reserved.
4
+ # NOTICE: All information contained herein is, and remains
5
+ # the property of Adobe and its suppliers, if any. The intellectual
6
+ # and technical concepts contained herein are proprietary to Adobe
7
+ # and its suppliers and are protected by all applicable intellectual
8
+ # property laws, including trade secret and copyright laws.
9
+ # Dissemination of this information or reproduction of this material
10
+ # is strictly forbidden unless prior written permission is obtained
11
+ # from Adobe.
12
+
13
+ from __future__ import annotations
14
+ import numpy as np
15
+
16
+ def cosine_schedule_2(x):
17
+ x = 1 - np.clip(x, 0, 1)
18
+ return np.cos(np.pi * x / 2)
19
+
20
+ def logit_normal_schedule(shift, sigmas):
21
+ sigmas = shift * sigmas / (1 + (shift - 1) * sigmas)
22
+ return sigmas
special_tokens_map.json ADDED
@@ -0,0 +1,1061 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ "<LOC_0>",
4
+ "<LOC_1>",
5
+ "<LOC_2>",
6
+ "<LOC_3>",
7
+ "<LOC_4>",
8
+ "<LOC_5>",
9
+ "<LOC_6>",
10
+ "<LOC_7>",
11
+ "<LOC_8>",
12
+ "<LOC_9>",
13
+ "<LOC_10>",
14
+ "<LOC_11>",
15
+ "<LOC_12>",
16
+ "<LOC_13>",
17
+ "<LOC_14>",
18
+ "<LOC_15>",
19
+ "<LOC_16>",
20
+ "<LOC_17>",
21
+ "<LOC_18>",
22
+ "<LOC_19>",
23
+ "<LOC_20>",
24
+ "<LOC_21>",
25
+ "<LOC_22>",
26
+ "<LOC_23>",
27
+ "<LOC_24>",
28
+ "<LOC_25>",
29
+ "<LOC_26>",
30
+ "<LOC_27>",
31
+ "<LOC_28>",
32
+ "<LOC_29>",
33
+ "<LOC_30>",
34
+ "<LOC_31>",
35
+ "<LOC_32>",
36
+ "<LOC_33>",
37
+ "<LOC_34>",
38
+ "<LOC_35>",
39
+ "<LOC_36>",
40
+ "<LOC_37>",
41
+ "<LOC_38>",
42
+ "<LOC_39>",
43
+ "<LOC_40>",
44
+ "<LOC_41>",
45
+ "<LOC_42>",
46
+ "<LOC_43>",
47
+ "<LOC_44>",
48
+ "<LOC_45>",
49
+ "<LOC_46>",
50
+ "<LOC_47>",
51
+ "<LOC_48>",
52
+ "<LOC_49>",
53
+ "<LOC_50>",
54
+ "<LOC_51>",
55
+ "<LOC_52>",
56
+ "<LOC_53>",
57
+ "<LOC_54>",
58
+ "<LOC_55>",
59
+ "<LOC_56>",
60
+ "<LOC_57>",
61
+ "<LOC_58>",
62
+ "<LOC_59>",
63
+ "<LOC_60>",
64
+ "<LOC_61>",
65
+ "<LOC_62>",
66
+ "<LOC_63>",
67
+ "<LOC_64>",
68
+ "<LOC_65>",
69
+ "<LOC_66>",
70
+ "<LOC_67>",
71
+ "<LOC_68>",
72
+ "<LOC_69>",
73
+ "<LOC_70>",
74
+ "<LOC_71>",
75
+ "<LOC_72>",
76
+ "<LOC_73>",
77
+ "<LOC_74>",
78
+ "<LOC_75>",
79
+ "<LOC_76>",
80
+ "<LOC_77>",
81
+ "<LOC_78>",
82
+ "<LOC_79>",
83
+ "<LOC_80>",
84
+ "<LOC_81>",
85
+ "<LOC_82>",
86
+ "<LOC_83>",
87
+ "<LOC_84>",
88
+ "<LOC_85>",
89
+ "<LOC_86>",
90
+ "<LOC_87>",
91
+ "<LOC_88>",
92
+ "<LOC_89>",
93
+ "<LOC_90>",
94
+ "<LOC_91>",
95
+ "<LOC_92>",
96
+ "<LOC_93>",
97
+ "<LOC_94>",
98
+ "<LOC_95>",
99
+ "<LOC_96>",
100
+ "<LOC_97>",
101
+ "<LOC_98>",
102
+ "<LOC_99>",
103
+ "<LOC_100>",
104
+ "<LOC_101>",
105
+ "<LOC_102>",
106
+ "<LOC_103>",
107
+ "<LOC_104>",
108
+ "<LOC_105>",
109
+ "<LOC_106>",
110
+ "<LOC_107>",
111
+ "<LOC_108>",
112
+ "<LOC_109>",
113
+ "<LOC_110>",
114
+ "<LOC_111>",
115
+ "<LOC_112>",
116
+ "<LOC_113>",
117
+ "<LOC_114>",
118
+ "<LOC_115>",
119
+ "<LOC_116>",
120
+ "<LOC_117>",
121
+ "<LOC_118>",
122
+ "<LOC_119>",
123
+ "<LOC_120>",
124
+ "<LOC_121>",
125
+ "<LOC_122>",
126
+ "<LOC_123>",
127
+ "<LOC_124>",
128
+ "<LOC_125>",
129
+ "<LOC_126>",
130
+ "<LOC_127>",
131
+ "<LOC_128>",
132
+ "<LOC_129>",
133
+ "<LOC_130>",
134
+ "<LOC_131>",
135
+ "<LOC_132>",
136
+ "<LOC_133>",
137
+ "<LOC_134>",
138
+ "<LOC_135>",
139
+ "<LOC_136>",
140
+ "<LOC_137>",
141
+ "<LOC_138>",
142
+ "<LOC_139>",
143
+ "<LOC_140>",
144
+ "<LOC_141>",
145
+ "<LOC_142>",
146
+ "<LOC_143>",
147
+ "<LOC_144>",
148
+ "<LOC_145>",
149
+ "<LOC_146>",
150
+ "<LOC_147>",
151
+ "<LOC_148>",
152
+ "<LOC_149>",
153
+ "<LOC_150>",
154
+ "<LOC_151>",
155
+ "<LOC_152>",
156
+ "<LOC_153>",
157
+ "<LOC_154>",
158
+ "<LOC_155>",
159
+ "<LOC_156>",
160
+ "<LOC_157>",
161
+ "<LOC_158>",
162
+ "<LOC_159>",
163
+ "<LOC_160>",
164
+ "<LOC_161>",
165
+ "<LOC_162>",
166
+ "<LOC_163>",
167
+ "<LOC_164>",
168
+ "<LOC_165>",
169
+ "<LOC_166>",
170
+ "<LOC_167>",
171
+ "<LOC_168>",
172
+ "<LOC_169>",
173
+ "<LOC_170>",
174
+ "<LOC_171>",
175
+ "<LOC_172>",
176
+ "<LOC_173>",
177
+ "<LOC_174>",
178
+ "<LOC_175>",
179
+ "<LOC_176>",
180
+ "<LOC_177>",
181
+ "<LOC_178>",
182
+ "<LOC_179>",
183
+ "<LOC_180>",
184
+ "<LOC_181>",
185
+ "<LOC_182>",
186
+ "<LOC_183>",
187
+ "<LOC_184>",
188
+ "<LOC_185>",
189
+ "<LOC_186>",
190
+ "<LOC_187>",
191
+ "<LOC_188>",
192
+ "<LOC_189>",
193
+ "<LOC_190>",
194
+ "<LOC_191>",
195
+ "<LOC_192>",
196
+ "<LOC_193>",
197
+ "<LOC_194>",
198
+ "<LOC_195>",
199
+ "<LOC_196>",
200
+ "<LOC_197>",
201
+ "<LOC_198>",
202
+ "<LOC_199>",
203
+ "<LOC_200>",
204
+ "<LOC_201>",
205
+ "<LOC_202>",
206
+ "<LOC_203>",
207
+ "<LOC_204>",
208
+ "<LOC_205>",
209
+ "<LOC_206>",
210
+ "<LOC_207>",
211
+ "<LOC_208>",
212
+ "<LOC_209>",
213
+ "<LOC_210>",
214
+ "<LOC_211>",
215
+ "<LOC_212>",
216
+ "<LOC_213>",
217
+ "<LOC_214>",
218
+ "<LOC_215>",
219
+ "<LOC_216>",
220
+ "<LOC_217>",
221
+ "<LOC_218>",
222
+ "<LOC_219>",
223
+ "<LOC_220>",
224
+ "<LOC_221>",
225
+ "<LOC_222>",
226
+ "<LOC_223>",
227
+ "<LOC_224>",
228
+ "<LOC_225>",
229
+ "<LOC_226>",
230
+ "<LOC_227>",
231
+ "<LOC_228>",
232
+ "<LOC_229>",
233
+ "<LOC_230>",
234
+ "<LOC_231>",
235
+ "<LOC_232>",
236
+ "<LOC_233>",
237
+ "<LOC_234>",
238
+ "<LOC_235>",
239
+ "<LOC_236>",
240
+ "<LOC_237>",
241
+ "<LOC_238>",
242
+ "<LOC_239>",
243
+ "<LOC_240>",
244
+ "<LOC_241>",
245
+ "<LOC_242>",
246
+ "<LOC_243>",
247
+ "<LOC_244>",
248
+ "<LOC_245>",
249
+ "<LOC_246>",
250
+ "<LOC_247>",
251
+ "<LOC_248>",
252
+ "<LOC_249>",
253
+ "<LOC_250>",
254
+ "<LOC_251>",
255
+ "<LOC_252>",
256
+ "<LOC_253>",
257
+ "<LOC_254>",
258
+ "<LOC_255>",
259
+ "<LOC_256>",
260
+ "<LOC_257>",
261
+ "<LOC_258>",
262
+ "<LOC_259>",
263
+ "<LOC_260>",
264
+ "<LOC_261>",
265
+ "<LOC_262>",
266
+ "<LOC_263>",
267
+ "<LOC_264>",
268
+ "<LOC_265>",
269
+ "<LOC_266>",
270
+ "<LOC_267>",
271
+ "<LOC_268>",
272
+ "<LOC_269>",
273
+ "<LOC_270>",
274
+ "<LOC_271>",
275
+ "<LOC_272>",
276
+ "<LOC_273>",
277
+ "<LOC_274>",
278
+ "<LOC_275>",
279
+ "<LOC_276>",
280
+ "<LOC_277>",
281
+ "<LOC_278>",
282
+ "<LOC_279>",
283
+ "<LOC_280>",
284
+ "<LOC_281>",
285
+ "<LOC_282>",
286
+ "<LOC_283>",
287
+ "<LOC_284>",
288
+ "<LOC_285>",
289
+ "<LOC_286>",
290
+ "<LOC_287>",
291
+ "<LOC_288>",
292
+ "<LOC_289>",
293
+ "<LOC_290>",
294
+ "<LOC_291>",
295
+ "<LOC_292>",
296
+ "<LOC_293>",
297
+ "<LOC_294>",
298
+ "<LOC_295>",
299
+ "<LOC_296>",
300
+ "<LOC_297>",
301
+ "<LOC_298>",
302
+ "<LOC_299>",
303
+ "<LOC_300>",
304
+ "<LOC_301>",
305
+ "<LOC_302>",
306
+ "<LOC_303>",
307
+ "<LOC_304>",
308
+ "<LOC_305>",
309
+ "<LOC_306>",
310
+ "<LOC_307>",
311
+ "<LOC_308>",
312
+ "<LOC_309>",
313
+ "<LOC_310>",
314
+ "<LOC_311>",
315
+ "<LOC_312>",
316
+ "<LOC_313>",
317
+ "<LOC_314>",
318
+ "<LOC_315>",
319
+ "<LOC_316>",
320
+ "<LOC_317>",
321
+ "<LOC_318>",
322
+ "<LOC_319>",
323
+ "<LOC_320>",
324
+ "<LOC_321>",
325
+ "<LOC_322>",
326
+ "<LOC_323>",
327
+ "<LOC_324>",
328
+ "<LOC_325>",
329
+ "<LOC_326>",
330
+ "<LOC_327>",
331
+ "<LOC_328>",
332
+ "<LOC_329>",
333
+ "<LOC_330>",
334
+ "<LOC_331>",
335
+ "<LOC_332>",
336
+ "<LOC_333>",
337
+ "<LOC_334>",
338
+ "<LOC_335>",
339
+ "<LOC_336>",
340
+ "<LOC_337>",
341
+ "<LOC_338>",
342
+ "<LOC_339>",
343
+ "<LOC_340>",
344
+ "<LOC_341>",
345
+ "<LOC_342>",
346
+ "<LOC_343>",
347
+ "<LOC_344>",
348
+ "<LOC_345>",
349
+ "<LOC_346>",
350
+ "<LOC_347>",
351
+ "<LOC_348>",
352
+ "<LOC_349>",
353
+ "<LOC_350>",
354
+ "<LOC_351>",
355
+ "<LOC_352>",
356
+ "<LOC_353>",
357
+ "<LOC_354>",
358
+ "<LOC_355>",
359
+ "<LOC_356>",
360
+ "<LOC_357>",
361
+ "<LOC_358>",
362
+ "<LOC_359>",
363
+ "<LOC_360>",
364
+ "<LOC_361>",
365
+ "<LOC_362>",
366
+ "<LOC_363>",
367
+ "<LOC_364>",
368
+ "<LOC_365>",
369
+ "<LOC_366>",
370
+ "<LOC_367>",
371
+ "<LOC_368>",
372
+ "<LOC_369>",
373
+ "<LOC_370>",
374
+ "<LOC_371>",
375
+ "<LOC_372>",
376
+ "<LOC_373>",
377
+ "<LOC_374>",
378
+ "<LOC_375>",
379
+ "<LOC_376>",
380
+ "<LOC_377>",
381
+ "<LOC_378>",
382
+ "<LOC_379>",
383
+ "<LOC_380>",
384
+ "<LOC_381>",
385
+ "<LOC_382>",
386
+ "<LOC_383>",
387
+ "<LOC_384>",
388
+ "<LOC_385>",
389
+ "<LOC_386>",
390
+ "<LOC_387>",
391
+ "<LOC_388>",
392
+ "<LOC_389>",
393
+ "<LOC_390>",
394
+ "<LOC_391>",
395
+ "<LOC_392>",
396
+ "<LOC_393>",
397
+ "<LOC_394>",
398
+ "<LOC_395>",
399
+ "<LOC_396>",
400
+ "<LOC_397>",
401
+ "<LOC_398>",
402
+ "<LOC_399>",
403
+ "<LOC_400>",
404
+ "<LOC_401>",
405
+ "<LOC_402>",
406
+ "<LOC_403>",
407
+ "<LOC_404>",
408
+ "<LOC_405>",
409
+ "<LOC_406>",
410
+ "<LOC_407>",
411
+ "<LOC_408>",
412
+ "<LOC_409>",
413
+ "<LOC_410>",
414
+ "<LOC_411>",
415
+ "<LOC_412>",
416
+ "<LOC_413>",
417
+ "<LOC_414>",
418
+ "<LOC_415>",
419
+ "<LOC_416>",
420
+ "<LOC_417>",
421
+ "<LOC_418>",
422
+ "<LOC_419>",
423
+ "<LOC_420>",
424
+ "<LOC_421>",
425
+ "<LOC_422>",
426
+ "<LOC_423>",
427
+ "<LOC_424>",
428
+ "<LOC_425>",
429
+ "<LOC_426>",
430
+ "<LOC_427>",
431
+ "<LOC_428>",
432
+ "<LOC_429>",
433
+ "<LOC_430>",
434
+ "<LOC_431>",
435
+ "<LOC_432>",
436
+ "<LOC_433>",
437
+ "<LOC_434>",
438
+ "<LOC_435>",
439
+ "<LOC_436>",
440
+ "<LOC_437>",
441
+ "<LOC_438>",
442
+ "<LOC_439>",
443
+ "<LOC_440>",
444
+ "<LOC_441>",
445
+ "<LOC_442>",
446
+ "<LOC_443>",
447
+ "<LOC_444>",
448
+ "<LOC_445>",
449
+ "<LOC_446>",
450
+ "<LOC_447>",
451
+ "<LOC_448>",
452
+ "<LOC_449>",
453
+ "<LOC_450>",
454
+ "<LOC_451>",
455
+ "<LOC_452>",
456
+ "<LOC_453>",
457
+ "<LOC_454>",
458
+ "<LOC_455>",
459
+ "<LOC_456>",
460
+ "<LOC_457>",
461
+ "<LOC_458>",
462
+ "<LOC_459>",
463
+ "<LOC_460>",
464
+ "<LOC_461>",
465
+ "<LOC_462>",
466
+ "<LOC_463>",
467
+ "<LOC_464>",
468
+ "<LOC_465>",
469
+ "<LOC_466>",
470
+ "<LOC_467>",
471
+ "<LOC_468>",
472
+ "<LOC_469>",
473
+ "<LOC_470>",
474
+ "<LOC_471>",
475
+ "<LOC_472>",
476
+ "<LOC_473>",
477
+ "<LOC_474>",
478
+ "<LOC_475>",
479
+ "<LOC_476>",
480
+ "<LOC_477>",
481
+ "<LOC_478>",
482
+ "<LOC_479>",
483
+ "<LOC_480>",
484
+ "<LOC_481>",
485
+ "<LOC_482>",
486
+ "<LOC_483>",
487
+ "<LOC_484>",
488
+ "<LOC_485>",
489
+ "<LOC_486>",
490
+ "<LOC_487>",
491
+ "<LOC_488>",
492
+ "<LOC_489>",
493
+ "<LOC_490>",
494
+ "<LOC_491>",
495
+ "<LOC_492>",
496
+ "<LOC_493>",
497
+ "<LOC_494>",
498
+ "<LOC_495>",
499
+ "<LOC_496>",
500
+ "<LOC_497>",
501
+ "<LOC_498>",
502
+ "<LOC_499>",
503
+ "<LOC_500>",
504
+ "<LOC_501>",
505
+ "<LOC_502>",
506
+ "<LOC_503>",
507
+ "<LOC_504>",
508
+ "<LOC_505>",
509
+ "<LOC_506>",
510
+ "<LOC_507>",
511
+ "<LOC_508>",
512
+ "<LOC_509>",
513
+ "<LOC_510>",
514
+ "<LOC_511>",
515
+ "<LOC_512>",
516
+ "<LOC_513>",
517
+ "<LOC_514>",
518
+ "<LOC_515>",
519
+ "<LOC_516>",
520
+ "<LOC_517>",
521
+ "<LOC_518>",
522
+ "<LOC_519>",
523
+ "<LOC_520>",
524
+ "<LOC_521>",
525
+ "<LOC_522>",
526
+ "<LOC_523>",
527
+ "<LOC_524>",
528
+ "<LOC_525>",
529
+ "<LOC_526>",
530
+ "<LOC_527>",
531
+ "<LOC_528>",
532
+ "<LOC_529>",
533
+ "<LOC_530>",
534
+ "<LOC_531>",
535
+ "<LOC_532>",
536
+ "<LOC_533>",
537
+ "<LOC_534>",
538
+ "<LOC_535>",
539
+ "<LOC_536>",
540
+ "<LOC_537>",
541
+ "<LOC_538>",
542
+ "<LOC_539>",
543
+ "<LOC_540>",
544
+ "<LOC_541>",
545
+ "<LOC_542>",
546
+ "<LOC_543>",
547
+ "<LOC_544>",
548
+ "<LOC_545>",
549
+ "<LOC_546>",
550
+ "<LOC_547>",
551
+ "<LOC_548>",
552
+ "<LOC_549>",
553
+ "<LOC_550>",
554
+ "<LOC_551>",
555
+ "<LOC_552>",
556
+ "<LOC_553>",
557
+ "<LOC_554>",
558
+ "<LOC_555>",
559
+ "<LOC_556>",
560
+ "<LOC_557>",
561
+ "<LOC_558>",
562
+ "<LOC_559>",
563
+ "<LOC_560>",
564
+ "<LOC_561>",
565
+ "<LOC_562>",
566
+ "<LOC_563>",
567
+ "<LOC_564>",
568
+ "<LOC_565>",
569
+ "<LOC_566>",
570
+ "<LOC_567>",
571
+ "<LOC_568>",
572
+ "<LOC_569>",
573
+ "<LOC_570>",
574
+ "<LOC_571>",
575
+ "<LOC_572>",
576
+ "<LOC_573>",
577
+ "<LOC_574>",
578
+ "<LOC_575>",
579
+ "<LOC_576>",
580
+ "<LOC_577>",
581
+ "<LOC_578>",
582
+ "<LOC_579>",
583
+ "<LOC_580>",
584
+ "<LOC_581>",
585
+ "<LOC_582>",
586
+ "<LOC_583>",
587
+ "<LOC_584>",
588
+ "<LOC_585>",
589
+ "<LOC_586>",
590
+ "<LOC_587>",
591
+ "<LOC_588>",
592
+ "<LOC_589>",
593
+ "<LOC_590>",
594
+ "<LOC_591>",
595
+ "<LOC_592>",
596
+ "<LOC_593>",
597
+ "<LOC_594>",
598
+ "<LOC_595>",
599
+ "<LOC_596>",
600
+ "<LOC_597>",
601
+ "<LOC_598>",
602
+ "<LOC_599>",
603
+ "<LOC_600>",
604
+ "<LOC_601>",
605
+ "<LOC_602>",
606
+ "<LOC_603>",
607
+ "<LOC_604>",
608
+ "<LOC_605>",
609
+ "<LOC_606>",
610
+ "<LOC_607>",
611
+ "<LOC_608>",
612
+ "<LOC_609>",
613
+ "<LOC_610>",
614
+ "<LOC_611>",
615
+ "<LOC_612>",
616
+ "<LOC_613>",
617
+ "<LOC_614>",
618
+ "<LOC_615>",
619
+ "<LOC_616>",
620
+ "<LOC_617>",
621
+ "<LOC_618>",
622
+ "<LOC_619>",
623
+ "<LOC_620>",
624
+ "<LOC_621>",
625
+ "<LOC_622>",
626
+ "<LOC_623>",
627
+ "<LOC_624>",
628
+ "<LOC_625>",
629
+ "<LOC_626>",
630
+ "<LOC_627>",
631
+ "<LOC_628>",
632
+ "<LOC_629>",
633
+ "<LOC_630>",
634
+ "<LOC_631>",
635
+ "<LOC_632>",
636
+ "<LOC_633>",
637
+ "<LOC_634>",
638
+ "<LOC_635>",
639
+ "<LOC_636>",
640
+ "<LOC_637>",
641
+ "<LOC_638>",
642
+ "<LOC_639>",
643
+ "<LOC_640>",
644
+ "<LOC_641>",
645
+ "<LOC_642>",
646
+ "<LOC_643>",
647
+ "<LOC_644>",
648
+ "<LOC_645>",
649
+ "<LOC_646>",
650
+ "<LOC_647>",
651
+ "<LOC_648>",
652
+ "<LOC_649>",
653
+ "<LOC_650>",
654
+ "<LOC_651>",
655
+ "<LOC_652>",
656
+ "<LOC_653>",
657
+ "<LOC_654>",
658
+ "<LOC_655>",
659
+ "<LOC_656>",
660
+ "<LOC_657>",
661
+ "<LOC_658>",
662
+ "<LOC_659>",
663
+ "<LOC_660>",
664
+ "<LOC_661>",
665
+ "<LOC_662>",
666
+ "<LOC_663>",
667
+ "<LOC_664>",
668
+ "<LOC_665>",
669
+ "<LOC_666>",
670
+ "<LOC_667>",
671
+ "<LOC_668>",
672
+ "<LOC_669>",
673
+ "<LOC_670>",
674
+ "<LOC_671>",
675
+ "<LOC_672>",
676
+ "<LOC_673>",
677
+ "<LOC_674>",
678
+ "<LOC_675>",
679
+ "<LOC_676>",
680
+ "<LOC_677>",
681
+ "<LOC_678>",
682
+ "<LOC_679>",
683
+ "<LOC_680>",
684
+ "<LOC_681>",
685
+ "<LOC_682>",
686
+ "<LOC_683>",
687
+ "<LOC_684>",
688
+ "<LOC_685>",
689
+ "<LOC_686>",
690
+ "<LOC_687>",
691
+ "<LOC_688>",
692
+ "<LOC_689>",
693
+ "<LOC_690>",
694
+ "<LOC_691>",
695
+ "<LOC_692>",
696
+ "<LOC_693>",
697
+ "<LOC_694>",
698
+ "<LOC_695>",
699
+ "<LOC_696>",
700
+ "<LOC_697>",
701
+ "<LOC_698>",
702
+ "<LOC_699>",
703
+ "<LOC_700>",
704
+ "<LOC_701>",
705
+ "<LOC_702>",
706
+ "<LOC_703>",
707
+ "<LOC_704>",
708
+ "<LOC_705>",
709
+ "<LOC_706>",
710
+ "<LOC_707>",
711
+ "<LOC_708>",
712
+ "<LOC_709>",
713
+ "<LOC_710>",
714
+ "<LOC_711>",
715
+ "<LOC_712>",
716
+ "<LOC_713>",
717
+ "<LOC_714>",
718
+ "<LOC_715>",
719
+ "<LOC_716>",
720
+ "<LOC_717>",
721
+ "<LOC_718>",
722
+ "<LOC_719>",
723
+ "<LOC_720>",
724
+ "<LOC_721>",
725
+ "<LOC_722>",
726
+ "<LOC_723>",
727
+ "<LOC_724>",
728
+ "<LOC_725>",
729
+ "<LOC_726>",
730
+ "<LOC_727>",
731
+ "<LOC_728>",
732
+ "<LOC_729>",
733
+ "<LOC_730>",
734
+ "<LOC_731>",
735
+ "<LOC_732>",
736
+ "<LOC_733>",
737
+ "<LOC_734>",
738
+ "<LOC_735>",
739
+ "<LOC_736>",
740
+ "<LOC_737>",
741
+ "<LOC_738>",
742
+ "<LOC_739>",
743
+ "<LOC_740>",
744
+ "<LOC_741>",
745
+ "<LOC_742>",
746
+ "<LOC_743>",
747
+ "<LOC_744>",
748
+ "<LOC_745>",
749
+ "<LOC_746>",
750
+ "<LOC_747>",
751
+ "<LOC_748>",
752
+ "<LOC_749>",
753
+ "<LOC_750>",
754
+ "<LOC_751>",
755
+ "<LOC_752>",
756
+ "<LOC_753>",
757
+ "<LOC_754>",
758
+ "<LOC_755>",
759
+ "<LOC_756>",
760
+ "<LOC_757>",
761
+ "<LOC_758>",
762
+ "<LOC_759>",
763
+ "<LOC_760>",
764
+ "<LOC_761>",
765
+ "<LOC_762>",
766
+ "<LOC_763>",
767
+ "<LOC_764>",
768
+ "<LOC_765>",
769
+ "<LOC_766>",
770
+ "<LOC_767>",
771
+ "<LOC_768>",
772
+ "<LOC_769>",
773
+ "<LOC_770>",
774
+ "<LOC_771>",
775
+ "<LOC_772>",
776
+ "<LOC_773>",
777
+ "<LOC_774>",
778
+ "<LOC_775>",
779
+ "<LOC_776>",
780
+ "<LOC_777>",
781
+ "<LOC_778>",
782
+ "<LOC_779>",
783
+ "<LOC_780>",
784
+ "<LOC_781>",
785
+ "<LOC_782>",
786
+ "<LOC_783>",
787
+ "<LOC_784>",
788
+ "<LOC_785>",
789
+ "<LOC_786>",
790
+ "<LOC_787>",
791
+ "<LOC_788>",
792
+ "<LOC_789>",
793
+ "<LOC_790>",
794
+ "<LOC_791>",
795
+ "<LOC_792>",
796
+ "<LOC_793>",
797
+ "<LOC_794>",
798
+ "<LOC_795>",
799
+ "<LOC_796>",
800
+ "<LOC_797>",
801
+ "<LOC_798>",
802
+ "<LOC_799>",
803
+ "<LOC_800>",
804
+ "<LOC_801>",
805
+ "<LOC_802>",
806
+ "<LOC_803>",
807
+ "<LOC_804>",
808
+ "<LOC_805>",
809
+ "<LOC_806>",
810
+ "<LOC_807>",
811
+ "<LOC_808>",
812
+ "<LOC_809>",
813
+ "<LOC_810>",
814
+ "<LOC_811>",
815
+ "<LOC_812>",
816
+ "<LOC_813>",
817
+ "<LOC_814>",
818
+ "<LOC_815>",
819
+ "<LOC_816>",
820
+ "<LOC_817>",
821
+ "<LOC_818>",
822
+ "<LOC_819>",
823
+ "<LOC_820>",
824
+ "<LOC_821>",
825
+ "<LOC_822>",
826
+ "<LOC_823>",
827
+ "<LOC_824>",
828
+ "<LOC_825>",
829
+ "<LOC_826>",
830
+ "<LOC_827>",
831
+ "<LOC_828>",
832
+ "<LOC_829>",
833
+ "<LOC_830>",
834
+ "<LOC_831>",
835
+ "<LOC_832>",
836
+ "<LOC_833>",
837
+ "<LOC_834>",
838
+ "<LOC_835>",
839
+ "<LOC_836>",
840
+ "<LOC_837>",
841
+ "<LOC_838>",
842
+ "<LOC_839>",
843
+ "<LOC_840>",
844
+ "<LOC_841>",
845
+ "<LOC_842>",
846
+ "<LOC_843>",
847
+ "<LOC_844>",
848
+ "<LOC_845>",
849
+ "<LOC_846>",
850
+ "<LOC_847>",
851
+ "<LOC_848>",
852
+ "<LOC_849>",
853
+ "<LOC_850>",
854
+ "<LOC_851>",
855
+ "<LOC_852>",
856
+ "<LOC_853>",
857
+ "<LOC_854>",
858
+ "<LOC_855>",
859
+ "<LOC_856>",
860
+ "<LOC_857>",
861
+ "<LOC_858>",
862
+ "<LOC_859>",
863
+ "<LOC_860>",
864
+ "<LOC_861>",
865
+ "<LOC_862>",
866
+ "<LOC_863>",
867
+ "<LOC_864>",
868
+ "<LOC_865>",
869
+ "<LOC_866>",
870
+ "<LOC_867>",
871
+ "<LOC_868>",
872
+ "<LOC_869>",
873
+ "<LOC_870>",
874
+ "<LOC_871>",
875
+ "<LOC_872>",
876
+ "<LOC_873>",
877
+ "<LOC_874>",
878
+ "<LOC_875>",
879
+ "<LOC_876>",
880
+ "<LOC_877>",
881
+ "<LOC_878>",
882
+ "<LOC_879>",
883
+ "<LOC_880>",
884
+ "<LOC_881>",
885
+ "<LOC_882>",
886
+ "<LOC_883>",
887
+ "<LOC_884>",
888
+ "<LOC_885>",
889
+ "<LOC_886>",
890
+ "<LOC_887>",
891
+ "<LOC_888>",
892
+ "<LOC_889>",
893
+ "<LOC_890>",
894
+ "<LOC_891>",
895
+ "<LOC_892>",
896
+ "<LOC_893>",
897
+ "<LOC_894>",
898
+ "<LOC_895>",
899
+ "<LOC_896>",
900
+ "<LOC_897>",
901
+ "<LOC_898>",
902
+ "<LOC_899>",
903
+ "<LOC_900>",
904
+ "<LOC_901>",
905
+ "<LOC_902>",
906
+ "<LOC_903>",
907
+ "<LOC_904>",
908
+ "<LOC_905>",
909
+ "<LOC_906>",
910
+ "<LOC_907>",
911
+ "<LOC_908>",
912
+ "<LOC_909>",
913
+ "<LOC_910>",
914
+ "<LOC_911>",
915
+ "<LOC_912>",
916
+ "<LOC_913>",
917
+ "<LOC_914>",
918
+ "<LOC_915>",
919
+ "<LOC_916>",
920
+ "<LOC_917>",
921
+ "<LOC_918>",
922
+ "<LOC_919>",
923
+ "<LOC_920>",
924
+ "<LOC_921>",
925
+ "<LOC_922>",
926
+ "<LOC_923>",
927
+ "<LOC_924>",
928
+ "<LOC_925>",
929
+ "<LOC_926>",
930
+ "<LOC_927>",
931
+ "<LOC_928>",
932
+ "<LOC_929>",
933
+ "<LOC_930>",
934
+ "<LOC_931>",
935
+ "<LOC_932>",
936
+ "<LOC_933>",
937
+ "<LOC_934>",
938
+ "<LOC_935>",
939
+ "<LOC_936>",
940
+ "<LOC_937>",
941
+ "<LOC_938>",
942
+ "<LOC_939>",
943
+ "<LOC_940>",
944
+ "<LOC_941>",
945
+ "<LOC_942>",
946
+ "<LOC_943>",
947
+ "<LOC_944>",
948
+ "<LOC_945>",
949
+ "<LOC_946>",
950
+ "<LOC_947>",
951
+ "<LOC_948>",
952
+ "<LOC_949>",
953
+ "<LOC_950>",
954
+ "<LOC_951>",
955
+ "<LOC_952>",
956
+ "<LOC_953>",
957
+ "<LOC_954>",
958
+ "<LOC_955>",
959
+ "<LOC_956>",
960
+ "<LOC_957>",
961
+ "<LOC_958>",
962
+ "<LOC_959>",
963
+ "<LOC_960>",
964
+ "<LOC_961>",
965
+ "<LOC_962>",
966
+ "<LOC_963>",
967
+ "<LOC_964>",
968
+ "<LOC_965>",
969
+ "<LOC_966>",
970
+ "<LOC_967>",
971
+ "<LOC_968>",
972
+ "<LOC_969>",
973
+ "<LOC_970>",
974
+ "<LOC_971>",
975
+ "<LOC_972>",
976
+ "<LOC_973>",
977
+ "<LOC_974>",
978
+ "<LOC_975>",
979
+ "<LOC_976>",
980
+ "<LOC_977>",
981
+ "<LOC_978>",
982
+ "<LOC_979>",
983
+ "<LOC_980>",
984
+ "<LOC_981>",
985
+ "<LOC_982>",
986
+ "<LOC_983>",
987
+ "<LOC_984>",
988
+ "<LOC_985>",
989
+ "<LOC_986>",
990
+ "<LOC_987>",
991
+ "<LOC_988>",
992
+ "<LOC_989>",
993
+ "<LOC_990>",
994
+ "<LOC_991>",
995
+ "<LOC_992>",
996
+ "<LOC_993>",
997
+ "<LOC_994>",
998
+ "<LOC_995>",
999
+ "<LOC_996>",
1000
+ "<LOC_997>",
1001
+ "<LOC_998>",
1002
+ "<LOC_999>",
1003
+ "<LOC_1000>",
1004
+ "<LOC_1001>",
1005
+ "<LOC_1002>",
1006
+ "<LOC_1003>",
1007
+ "<LOC_1004>",
1008
+ "<LOC_1005>",
1009
+ "<LOC_1006>",
1010
+ "<LOC_1007>",
1011
+ "<LOC_1008>",
1012
+ "<LOC_1009>",
1013
+ "<LOC_1010>",
1014
+ "<LOC_1011>",
1015
+ "<LOC_1012>",
1016
+ "<LOC_1013>",
1017
+ "<LOC_1014>",
1018
+ "<LOC_1015>",
1019
+ "<LOC_1016>",
1020
+ "<LOC_1017>",
1021
+ "<LOC_1018>",
1022
+ "<LOC_1019>",
1023
+ "<LOC_1020>",
1024
+ "<LOC_1021>",
1025
+ "<LOC_1022>",
1026
+ "<LOC_1023>",
1027
+ "<LOC_1024>",
1028
+ "<box_p>",
1029
+ "</box_p>",
1030
+ "<LOC_BEGIN>",
1031
+ "<LOC_END>"
1032
+ ],
1033
+ "bos_token": {
1034
+ "content": "<s>",
1035
+ "lstrip": false,
1036
+ "normalized": false,
1037
+ "rstrip": false,
1038
+ "single_word": false
1039
+ },
1040
+ "eos_token": {
1041
+ "content": "<|im_end|>",
1042
+ "lstrip": false,
1043
+ "normalized": false,
1044
+ "rstrip": false,
1045
+ "single_word": false
1046
+ },
1047
+ "pad_token": {
1048
+ "content": "<|im_end|>",
1049
+ "lstrip": false,
1050
+ "normalized": false,
1051
+ "rstrip": false,
1052
+ "single_word": false
1053
+ },
1054
+ "unk_token": {
1055
+ "content": "<unk>",
1056
+ "lstrip": false,
1057
+ "normalized": false,
1058
+ "rstrip": false,
1059
+ "single_word": false
1060
+ }
1061
+ }
token_constants.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ IMAGE_TOKEN_INDEX = -200
2
+ IMAGE_PAD_TOKEN_INDEX = -500
3
+ DEFAULT_IMAGE_TOKEN = '<image>'
4
+ DEFAULT_IMAGE_PAD_TOKEN = '<image_padding>'
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f9ad3482369ba91711ff939f9eeb761d618b3157fcbfc0715f18e34b918eca97
3
+ size 17268792
tokenizer_config.json ADDED
The diff for this file is too large to render. See raw diff
 
tree.py ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import annotations
3
+ import hashlib
4
+ import math
5
+ import os
6
+ from collections.abc import Callable, Mapping
7
+ from dataclasses import dataclass
8
+ from numbers import Integral, Real
9
+ from pathlib import Path
10
+ import torch
11
+ import torch.nn.functional as F
12
+ PINNED_ARTIFACT_VERSION = 1
13
+ PINNED_ARTIFACT_ALGORITHM = 'recursive_centered_pca_rank_median_v1'
14
+ PINNED_ARTIFACT_METRIC = 'normalized_squared_l2_tree_ultrametric'
15
+ PINNED_PRODUCTION_VOCAB_SIZE = 131072
16
+ PINNED_PRODUCTION_DEPTH = 17
17
+ DEFAULT_SEMANTIC_TREE_STEPS = 4
18
+ DEFAULT_SEMANTIC_TREE_SCHEDULE = 'shift'
19
+ DEFAULT_SEMANTIC_TREE_SHIFT = 5.0
20
+ MAX_SEMANTIC_TREE_REFINEMENT_GAP = 2
21
+ SUPPORTED_SEMANTIC_TREE_INFERENCE_SCHEDULES = frozenset({'linear', 'shift', 'logit_normal', 'cosine', 'cosine2', 'exp'})
22
+
23
+ def _plain_positive_int(value: object, *, name: str) -> int:
24
+ if isinstance(value, bool) or not isinstance(value, Integral):
25
+ raise TypeError(f'{name} must be a positive integer')
26
+ value = int(value)
27
+ if value < 1:
28
+ raise ValueError(f'{name} must be a positive integer')
29
+ return value
30
+
31
+ def _plain_nonnegative_int(value: object, *, name: str) -> int:
32
+ if isinstance(value, bool) or not isinstance(value, Integral):
33
+ raise TypeError(f'{name} must be a non-negative integer')
34
+ value = int(value)
35
+ if value < 0:
36
+ raise ValueError(f'{name} must be a non-negative integer')
37
+ return value
38
+
39
+ def _plain_positive_float(value: object, *, name: str) -> float:
40
+ if isinstance(value, bool) or not isinstance(value, Real):
41
+ raise TypeError(f'{name} must be a finite positive number')
42
+ value = float(value)
43
+ if not math.isfinite(value) or value <= 0.0:
44
+ raise ValueError(f'{name} must be a finite positive number')
45
+ return value
46
+
47
+ def _is_power_of_two(value: int) -> bool:
48
+ return value > 0 and value & value - 1 == 0
49
+
50
+ def resolve_semantic_tree_steps(config, override=None):
51
+ steps = 4 if override is None else override
52
+ if isinstance(steps, bool) or steps not in (1, 4, 8, 16):
53
+ raise ValueError('refinement_steps must be 1, 4, 8, or 16')
54
+ return int(steps)
55
+
56
+ @dataclass(frozen=True, slots=True)
57
+ class SemanticTreeArtifactContract:
58
+ path: str | os.PathLike[str]
59
+ bytes: int | None = None
60
+ sha256: str | None = None
61
+ algorithm: str | None = PINNED_ARTIFACT_ALGORITHM
62
+
63
+ def __post_init__(self) -> None:
64
+ if not isinstance(self.path, (str, os.PathLike)):
65
+ raise TypeError('semantic-tree artifact path must be path-like')
66
+ raw_path = os.fspath(self.path)
67
+ if not isinstance(raw_path, str) or not raw_path.strip():
68
+ raise ValueError('semantic-tree artifact path must be nonempty')
69
+ object.__setattr__(self, 'path', Path(raw_path).expanduser())
70
+ if self.bytes is not None:
71
+ object.__setattr__(self, 'bytes', _plain_positive_int(self.bytes, name='semantic-tree artifact bytes'))
72
+ if self.sha256 is not None:
73
+ if not isinstance(self.sha256, str):
74
+ raise TypeError('semantic-tree artifact sha256 must be a string')
75
+ digest = self.sha256.strip().lower()
76
+ if len(digest) != 64 or any((character not in '0123456789abcdef' for character in digest)):
77
+ raise ValueError('semantic-tree artifact sha256 must be 64 hexadecimal characters')
78
+ object.__setattr__(self, 'sha256', digest)
79
+ if self.algorithm not in (None, PINNED_ARTIFACT_ALGORITHM):
80
+ raise ValueError(f'Unsupported semantic-tree algorithm: {self.algorithm!r}')
81
+
82
+ def production_semantic_tree_contract(path: str | os.PathLike[str]) -> SemanticTreeArtifactContract:
83
+ return SemanticTreeArtifactContract(path=path, sha256='4b7ee94fbb10fd4146a4ad167b595b037e3f591eaa12ecf3f0b411c82384a714', algorithm=PINNED_ARTIFACT_ALGORITHM)
84
+
85
+ def _sha256_file(path: Path) -> str:
86
+ digest = hashlib.sha256()
87
+ with path.open('rb') as artifact_file:
88
+ for block in iter(lambda : artifact_file.read(1024 * 1024), b''):
89
+ digest.update(block)
90
+ return digest.hexdigest()
91
+
92
+ class BalancedSemanticTree:
93
+
94
+ def __init__(self, leaf_to_token: torch.Tensor) -> None:
95
+ if not torch.is_tensor(leaf_to_token):
96
+ raise TypeError('leaf_to_token must be a tensor')
97
+ if leaf_to_token.ndim != 1:
98
+ raise ValueError('leaf_to_token must be one-dimensional')
99
+ if leaf_to_token.dtype == torch.bool or leaf_to_token.is_floating_point() or leaf_to_token.is_complex():
100
+ raise TypeError('leaf_to_token must contain integer token IDs')
101
+ vocab_size = int(leaf_to_token.numel())
102
+ if not _is_power_of_two(vocab_size):
103
+ raise ValueError('semantic-tree vocabulary size must be a power of two')
104
+ permutation = leaf_to_token.to(dtype=torch.long).contiguous()
105
+ expected = torch.arange(vocab_size, device=permutation.device)
106
+ if not torch.equal(torch.sort(permutation).values, expected):
107
+ raise ValueError('leaf_to_token must be a permutation of [0, V)')
108
+ token_to_leaf = torch.empty_like(permutation)
109
+ token_to_leaf.scatter_(0, permutation, expected)
110
+ self.vocab_size = vocab_size
111
+ self.depth = int(math.log2(vocab_size))
112
+ self.leaf_to_token = permutation
113
+ self.token_to_leaf = token_to_leaf
114
+
115
+ @classmethod
116
+ def _from_validated(cls, leaf_to_token: torch.Tensor, token_to_leaf: torch.Tensor) -> BalancedSemanticTree:
117
+ tree = cls.__new__(cls)
118
+ tree.vocab_size = int(leaf_to_token.numel())
119
+ tree.depth = int(math.log2(tree.vocab_size))
120
+ tree.leaf_to_token = leaf_to_token
121
+ tree.token_to_leaf = token_to_leaf
122
+ return tree
123
+
124
+ @classmethod
125
+ def from_artifact(cls, contract: SemanticTreeArtifactContract, expected_vocab_size: int=PINNED_PRODUCTION_VOCAB_SIZE) -> BalancedSemanticTree:
126
+ if not isinstance(contract, SemanticTreeArtifactContract):
127
+ raise TypeError('contract must be a SemanticTreeArtifactContract')
128
+ expected_vocab_size = _plain_positive_int(expected_vocab_size, name='expected_vocab_size')
129
+ if not _is_power_of_two(expected_vocab_size):
130
+ raise ValueError('expected_vocab_size must be a power of two')
131
+ path = contract.path
132
+ assert isinstance(path, Path)
133
+ if not path.is_file():
134
+ raise FileNotFoundError(f'semantic-tree artifact is not a file: {path}')
135
+ actual_bytes = path.stat().st_size
136
+ if contract.bytes is not None and actual_bytes != contract.bytes:
137
+ raise ValueError(f'semantic-tree artifact byte count mismatch: expected {contract.bytes}, got {actual_bytes}')
138
+ if contract.sha256 is not None:
139
+ actual_sha256 = _sha256_file(path)
140
+ if actual_sha256 != contract.sha256:
141
+ raise ValueError(f'semantic-tree artifact sha256 mismatch: expected {contract.sha256}, got {actual_sha256}')
142
+ artifact = torch.load(path, map_location='cpu', weights_only=True)
143
+ if not isinstance(artifact, Mapping):
144
+ raise TypeError('semantic-tree artifact must contain a mapping')
145
+ algorithm = artifact.get('algorithm')
146
+ allowed_algorithms = (contract.algorithm,) if contract.algorithm is not None else (PINNED_ARTIFACT_ALGORITHM,)
147
+ if algorithm not in allowed_algorithms:
148
+ raise ValueError(f'semantic-tree artifact algorithm mismatch: expected one of {allowed_algorithms!r}, got {algorithm!r}')
149
+ pinned_values = {'version': PINNED_ARTIFACT_VERSION, 'metric': PINNED_ARTIFACT_METRIC, 'vocab_size': expected_vocab_size, 'depth': int(math.log2(expected_vocab_size)), 'radii_monotone': True}
150
+ for (field_name, expected_value) in pinned_values.items():
151
+ if artifact.get(field_name) != expected_value:
152
+ raise ValueError(f'semantic-tree artifact {field_name} mismatch: expected {expected_value!r}, got {artifact.get(field_name)!r}')
153
+ leaf_to_token = artifact.get('leaf_to_token')
154
+ heap_radii = artifact.get('heap_radii')
155
+ if not torch.is_tensor(leaf_to_token) or leaf_to_token.dtype != torch.int32:
156
+ raise TypeError('semantic-tree leaf_to_token must be torch.int32')
157
+ if tuple(leaf_to_token.shape) != (expected_vocab_size,):
158
+ raise ValueError('semantic-tree leaf_to_token shape disagrees with vocabulary')
159
+ if not torch.is_tensor(heap_radii) or heap_radii.dtype != torch.float32:
160
+ raise TypeError('semantic-tree heap_radii must be torch.float32')
161
+ if tuple(heap_radii.shape) != (expected_vocab_size - 1,):
162
+ raise ValueError('semantic-tree heap_radii shape disagrees with vocabulary')
163
+ if not bool(torch.isfinite(heap_radii).all()) or bool((heap_radii < 0).any()):
164
+ raise ValueError('semantic-tree heap_radii must be finite and nonnegative')
165
+ return cls(leaf_to_token)
166
+
167
+ @property
168
+ def device(self) -> torch.device:
169
+ return self.leaf_to_token.device
170
+
171
+ def to(self, device: torch.device | str) -> BalancedSemanticTree:
172
+ resolved = torch.device(device)
173
+ if resolved == self.device:
174
+ return self
175
+ return type(self)._from_validated(self.leaf_to_token.to(resolved), self.token_to_leaf.to(resolved))
176
+
177
+ def _check_tokens(self, tokens: torch.Tensor, *, name: str) -> None:
178
+ if not torch.is_tensor(tokens):
179
+ raise TypeError(f'{name} must be a tensor')
180
+ if tokens.dtype == torch.bool or tokens.is_floating_point() or tokens.is_complex():
181
+ raise TypeError(f'{name} must contain integer code IDs')
182
+ if tokens.device != self.device:
183
+ raise ValueError(f'{name} and semantic-tree lookups must share a device')
184
+ if tokens.numel() and bool(((tokens < 0) | (tokens >= self.vocab_size)).any()):
185
+ raise ValueError(f'{name} contains code IDs outside [0, V)')
186
+
187
+ def _levels(self, levels: int | torch.Tensor, shape: torch.Size, device: torch.device) -> torch.Tensor:
188
+ if isinstance(levels, bool) or (not isinstance(levels, Integral) and (not torch.is_tensor(levels))):
189
+ raise TypeError('levels must contain integers')
190
+ level_tensor = torch.as_tensor(levels, device=device)
191
+ if level_tensor.dtype == torch.bool or level_tensor.is_floating_point() or level_tensor.is_complex():
192
+ raise TypeError('levels must contain integers')
193
+ if level_tensor.ndim < len(shape):
194
+ level_tensor = level_tensor.reshape(level_tensor.shape + (1,) * (len(shape) - level_tensor.ndim))
195
+ try:
196
+ level_tensor = torch.broadcast_to(level_tensor, shape).long()
197
+ except RuntimeError as error:
198
+ raise ValueError('levels are not broadcastable to endpoint shape') from error
199
+ if bool((level_tensor < 0).any()) or bool((level_tensor > self.depth).any()):
200
+ raise ValueError(f'levels must lie in [0, {self.depth}]')
201
+ return level_tensor
202
+
203
+ def node_ids(self, tokens: torch.Tensor, levels: int | torch.Tensor) -> torch.Tensor:
204
+ self._check_tokens(tokens, name='tokens')
205
+ level_tensor = self._levels(levels, tokens.shape, tokens.device)
206
+ leaves = self.token_to_leaf[tokens.long()]
207
+ return torch.bitwise_right_shift(leaves, self.depth - level_tensor)
208
+
209
+ @torch.no_grad()
210
+ def sample_representatives(self, endpoints: torch.Tensor, levels: int | torch.Tensor, generator: torch.Generator | None=None) -> torch.Tensor:
211
+ self._check_tokens(endpoints, name='endpoints')
212
+ level_tensor = self._levels(levels, endpoints.shape, endpoints.device)
213
+ leaves = self.token_to_leaf[endpoints.long()]
214
+ noisy = level_tensor < self.depth
215
+ if not bool(noisy.any()):
216
+ return endpoints.clone()
217
+ noisy_leaves = leaves[noisy]
218
+ noisy_levels = level_tensor[noisy]
219
+ shifts = self.depth - noisy_levels
220
+ subtree_starts = torch.bitwise_left_shift(torch.bitwise_right_shift(noisy_leaves, shifts), shifts)
221
+ subtree_sizes = torch.bitwise_left_shift(torch.ones_like(shifts), shifts)
222
+ random_bits = torch.randint(self.vocab_size, (int(noisy.sum().item()),), device=endpoints.device, dtype=torch.long, generator=generator)
223
+ sampled_leaves = subtree_starts + torch.bitwise_and(random_bits, subtree_sizes - 1)
224
+ result = endpoints.clone()
225
+ result[noisy] = self.leaf_to_token[sampled_leaves].to(endpoints.dtype)
226
+ return result
227
+
228
+ def _validate_ages(ages: torch.Tensor, *, steps: int) -> tuple[torch.Tensor, int]:
229
+ steps = _plain_positive_int(steps, name='steps')
230
+ if not torch.is_tensor(ages):
231
+ raise TypeError('ages must be a tensor')
232
+ if ages.dtype == torch.bool or ages.is_floating_point() or ages.is_complex():
233
+ raise TypeError('ages must contain integers')
234
+ if bool((ages < 0).any()) or bool((ages > steps).any()):
235
+ raise ValueError(f'ages must lie in [0, {steps}]')
236
+ return (ages.long(), steps)
237
+
238
+ def semantic_tree_levels_for_ages(ages: torch.Tensor, steps: int=DEFAULT_SEMANTIC_TREE_STEPS, depth: int=PINNED_PRODUCTION_DEPTH) -> torch.Tensor:
239
+ (ages, steps) = _validate_ages(ages, steps=steps)
240
+ depth = _plain_positive_int(depth, name='depth')
241
+ if steps > depth:
242
+ raise ValueError('steps cannot exceed tree depth')
243
+ return torch.div(ages * depth, steps, rounding_mode='floor')
244
+
245
+ def semantic_tree_noise_for_ages(ages: torch.Tensor, steps: int=DEFAULT_SEMANTIC_TREE_STEPS) -> torch.Tensor:
246
+ (ages, steps) = _validate_ages(ages, steps=steps)
247
+ return 1.0 - ages.to(dtype=torch.float32) / float(steps)
248
+
249
+ def semantic_tree_activation_counts(content_tokens: int, *, activation_steps: int, schedule: str=DEFAULT_SEMANTIC_TREE_SCHEDULE, shift: float=DEFAULT_SEMANTIC_TREE_SHIFT, device: torch.device | str | None=None) -> torch.Tensor:
250
+ content_tokens = _plain_positive_int(content_tokens, name='content_tokens')
251
+ activation_steps = min(_plain_positive_int(activation_steps, name='activation_steps'), content_tokens)
252
+ if not isinstance(schedule, str):
253
+ raise TypeError('schedule must be a string')
254
+ schedule = schedule.strip().lower()
255
+ if schedule not in SUPPORTED_SEMANTIC_TREE_INFERENCE_SCHEDULES:
256
+ allowed = ', '.join(sorted(SUPPORTED_SEMANTIC_TREE_INFERENCE_SCHEDULES))
257
+ raise ValueError(f'unsupported semantic-tree inference schedule {schedule!r}; expected one of: {allowed}')
258
+ shift = _plain_positive_float(shift, name='shift')
259
+ sample_times = torch.linspace(0.0, 1.0, activation_steps + 1, dtype=torch.float32)
260
+ if schedule == 'linear':
261
+ sigmas = sample_times
262
+ elif schedule == 'shift':
263
+ sigmas = shift * sample_times / (1.0 + (shift - 1.0) * sample_times)
264
+ elif schedule == 'logit_normal':
265
+ sigmas = 0.5 * (1.0 + torch.erf(torch.logit(sample_times) / math.sqrt(2.0)))
266
+ elif schedule == 'cosine':
267
+ sigmas = 1.0 - 0.5 * (1.0 + torch.cos(math.pi * sample_times))
268
+ elif schedule == 'cosine2':
269
+ sigmas = torch.sin(0.5 * math.pi * sample_times)
270
+ else:
271
+ sigmas = (1.0 - torch.exp(-5.0 * sample_times)) / (1.0 - math.exp(-5.0))
272
+ sigmas = sigmas.clamp(0.0001, 1.0)
273
+ boundaries = (sigmas * content_tokens).to(dtype=torch.long)
274
+ counts = (boundaries[1:] - boundaries[:-1]).clamp_min(1)
275
+ excess = int(counts.sum().item()) - content_tokens
276
+ cursor = 0
277
+ while excess > 0:
278
+ cursor %= counts.numel()
279
+ if int(counts[cursor].item()) == 1:
280
+ cursor += 1
281
+ continue
282
+ counts[cursor] -= 1
283
+ excess -= 1
284
+ cursor += 1
285
+ if int(counts.sum().item()) != content_tokens:
286
+ raise RuntimeError('semantic-tree activation counts do not cover content')
287
+ return counts.flip(0).to(device=device)
288
+
289
+ def resolve_semantic_tree_atomic_block_size(value: object=1) -> int:
290
+ block_size = _plain_positive_int(value, name='semantic_tree_atomic_block_size')
291
+ if block_size not in {1, 2, 4, 8}:
292
+ raise ValueError('semantic_tree_atomic_block_size currently supports 1, 2, 4, or 8')
293
+ return block_size
294
+
295
+ def resolve_semantic_tree_refinement_gap(value: object=0) -> int:
296
+ gap = _plain_nonnegative_int(value, name='semantic_tree_refinement_gap')
297
+ if gap > MAX_SEMANTIC_TREE_REFINEMENT_GAP:
298
+ raise ValueError('semantic_tree_refinement_gap currently supports only 0, 1, or 2')
299
+ return gap
300
+
301
+ def semantic_tree_decode_schedule(activation_counts: torch.Tensor, *, refinement_steps: int, refinement_gap: int=0) -> torch.Tensor:
302
+ if not torch.is_tensor(activation_counts):
303
+ raise TypeError('activation_counts must be a tensor')
304
+ if activation_counts.ndim != 2:
305
+ raise ValueError('activation_counts must have shape [batch, rounds]')
306
+ if activation_counts.dtype not in {torch.uint8, torch.int8, torch.int16, torch.int32, torch.int64}:
307
+ raise TypeError('activation_counts must use an integer dtype')
308
+ if activation_counts.shape[1] == 0:
309
+ raise ValueError('activation_counts must contain at least one round')
310
+ if bool((activation_counts < 0).any()):
311
+ raise ValueError('activation_counts must be non-negative')
312
+ refinement_steps = _plain_positive_int(refinement_steps, name='refinement_steps')
313
+ refinement_gap = resolve_semantic_tree_refinement_gap(refinement_gap)
314
+ flush_rounds = refinement_steps - 1 + refinement_steps * refinement_gap
315
+ if flush_rounds == 0:
316
+ return activation_counts
317
+ flush = torch.zeros(activation_counts.shape[0], flush_rounds, dtype=activation_counts.dtype, device=activation_counts.device)
318
+ return torch.cat((activation_counts, flush), dim=1)
319
+
320
+ def semantic_tree_refinement_due(ages: torch.Tensor, next_refinement_round: torch.Tensor, *, decode_round: int, refinement_steps: int) -> torch.Tensor:
321
+ if not torch.is_tensor(ages) or not torch.is_tensor(next_refinement_round):
322
+ raise TypeError('ages and next_refinement_round must be tensors')
323
+ if ages.shape != next_refinement_round.shape:
324
+ raise ValueError('ages and next_refinement_round must align')
325
+ if ages.device != next_refinement_round.device:
326
+ raise ValueError('ages and next_refinement_round must share a device')
327
+ for (tensor, name) in ((ages, 'ages'), (next_refinement_round, 'next_refinement_round')):
328
+ if tensor.dtype == torch.bool or tensor.is_floating_point():
329
+ raise TypeError(f'{name} must use an integer dtype')
330
+ decode_round = _plain_nonnegative_int(decode_round, name='decode_round')
331
+ refinement_steps = _plain_positive_int(refinement_steps, name='refinement_steps')
332
+ return ages.ge(0) & ages.lt(refinement_steps) & next_refinement_round.le(decode_round)
333
+ EmbeddingSource = torch.Tensor | Callable[[torch.Tensor], torch.Tensor]
334
+
335
+ def _embed_ids(source: EmbeddingSource, token_ids: torch.Tensor) -> torch.Tensor:
336
+ if torch.is_tensor(source):
337
+ if source.ndim != 2 or not source.is_floating_point():
338
+ raise TypeError('embedding weight must be a floating-point matrix')
339
+ if source.device != token_ids.device:
340
+ raise ValueError('embedding weight and token IDs must share a device')
341
+ if token_ids.numel() and bool(((token_ids < 0) | (token_ids >= source.shape[0])).any()):
342
+ raise ValueError('token ID lies outside the embedding weight')
343
+ return F.embedding(token_ids.long(), source)
344
+ if not callable(source):
345
+ raise TypeError('embedding source must be a weight tensor or callable')
346
+ embedded = source(token_ids)
347
+ if not torch.is_tensor(embedded):
348
+ raise TypeError('embedding callback must return a tensor')
349
+ return embedded
350
+
351
+ def build_semantic_tree_embeddings(representatives: torch.Tensor, noise_levels: float | torch.Tensor, embedding_callback: EmbeddingSource, mask_token_id: int) -> torch.Tensor:
352
+ if not torch.is_tensor(representatives):
353
+ raise TypeError('representatives must be a tensor')
354
+ if representatives.dtype == torch.bool or representatives.is_floating_point() or representatives.is_complex():
355
+ raise TypeError('representatives must contain integer code IDs')
356
+ if isinstance(mask_token_id, bool) or not isinstance(mask_token_id, Integral):
357
+ raise TypeError('mask_token_id must be an integer')
358
+ mask_token_id = int(mask_token_id)
359
+ if mask_token_id < 0:
360
+ raise ValueError('mask_token_id must be nonnegative')
361
+ representative_embeddings = _embed_ids(embedding_callback, representatives)
362
+ expected_prefix = tuple(representatives.shape)
363
+ if representative_embeddings.ndim != representatives.ndim + 1 or tuple(representative_embeddings.shape[:-1]) != expected_prefix or (not representative_embeddings.is_floating_point()):
364
+ raise ValueError('representative embeddings must have shape representatives.shape + [H]')
365
+ mask_ids = torch.tensor([mask_token_id], dtype=representatives.dtype, device=representatives.device)
366
+ mask_embedding = _embed_ids(embedding_callback, mask_ids)
367
+ if mask_embedding.shape != (1, representative_embeddings.shape[-1]):
368
+ raise ValueError('MASK embedding must have shape [1, H]')
369
+ if mask_embedding.device != representative_embeddings.device or mask_embedding.dtype != representative_embeddings.dtype:
370
+ raise ValueError('representative and MASK embeddings must share dtype/device')
371
+ noise = torch.as_tensor(noise_levels, device=representatives.device, dtype=torch.float32)
372
+ if noise.ndim < representatives.ndim:
373
+ noise = noise.reshape(noise.shape + (1,) * (representatives.ndim - noise.ndim))
374
+ try:
375
+ noise = torch.broadcast_to(noise, representatives.shape)
376
+ except RuntimeError as error:
377
+ raise ValueError('noise_levels are not broadcastable to representatives') from error
378
+ if not bool(torch.isfinite(noise).all()) or bool((noise < 0).any()) or bool((noise > 1).any()):
379
+ raise ValueError('noise_levels must be finite and lie in [0, 1]')
380
+ noise_in_embedding_dtype = noise.to(dtype=representative_embeddings.dtype)
381
+ combined = representative_embeddings + noise_in_embedding_dtype.unsqueeze(-1) * mask_embedding
382
+ return torch.where(noise.eq(0).unsqueeze(-1), representative_embeddings, combined)
383
+
384
+ @dataclass(frozen=True, slots=True)
385
+ class SemanticTreeAdvance:
386
+ representatives: torch.Tensor
387
+ ages: torch.Tensor
388
+ levels: torch.Tensor
389
+ noise_levels: torch.Tensor
390
+ committed: torch.Tensor
391
+
392
+ @torch.no_grad()
393
+ def advance_revisable_semantic_tree(current_representatives: torch.Tensor, x0_proposals: torch.Tensor, ages: torch.Tensor, tree: BalancedSemanticTree, steps: int=DEFAULT_SEMANTIC_TREE_STEPS, generator: torch.Generator | None=None) -> SemanticTreeAdvance:
394
+ if not isinstance(tree, BalancedSemanticTree):
395
+ raise TypeError('tree must be a BalancedSemanticTree')
396
+ tree._check_tokens(current_representatives, name='current_representatives')
397
+ tree._check_tokens(x0_proposals, name='x0_proposals')
398
+ if current_representatives.shape != x0_proposals.shape:
399
+ raise ValueError('current_representatives and x0_proposals must align')
400
+ if current_representatives.dtype != x0_proposals.dtype:
401
+ raise ValueError('current_representatives and x0_proposals must share dtype')
402
+ if not torch.is_tensor(ages) or ages.shape != current_representatives.shape:
403
+ raise ValueError('ages must align with representative tokens')
404
+ (validated_ages, steps) = _validate_ages(ages, steps=steps)
405
+ if validated_ages.device != current_representatives.device:
406
+ raise ValueError('ages and representative tokens must share a device')
407
+ if steps > tree.depth:
408
+ raise ValueError('steps cannot exceed tree depth')
409
+ unfinished = validated_ages < steps
410
+ next_ages = torch.where(unfinished, validated_ages + 1, validated_ages)
411
+ next_levels = semantic_tree_levels_for_ages(next_ages, steps=steps, depth=tree.depth)
412
+ proposal_representatives = tree.sample_representatives(x0_proposals, next_levels, generator=generator)
413
+ next_representatives = torch.where(unfinished, proposal_representatives, current_representatives)
414
+ return SemanticTreeAdvance(representatives=next_representatives, ages=next_ages.to(dtype=ages.dtype), levels=next_levels, noise_levels=semantic_tree_noise_for_ages(next_ages, steps=steps), committed=next_ages.eq(steps))
tree_metadata.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "filename": "pca_tree.pt",
3
+ "algorithm": "recursive_centered_pca_rank_median_v1",
4
+ "sha256": "4b7ee94fbb10fd4146a4ad167b595b037e3f591eaa12ecf3f0b411c82384a714",
5
+ "vocab_size": 131072,
6
+ "depth": 17
7
+ }
utils.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ADOBE CONFIDENTIAL
2
+ # Copyright 2025 Adobe
3
+ # All Rights Reserved.
4
+ # NOTICE: All information contained herein is, and remains
5
+ # the property of Adobe and its suppliers, if any. The intellectual
6
+ # and technical concepts contained herein are proprietary to Adobe
7
+ # and its suppliers and are protected by all applicable intellectual
8
+ # property laws, including trade secret and copyright laws.
9
+ # Dissemination of this information or reproduction of this material
10
+ # is strictly forbidden unless prior written permission is obtained
11
+ # from Adobe.
12
+
13
+ from __future__ import annotations
14
+ import torch
15
+
16
+ def pad_along_last_dim(x, size):
17
+ pad_size = size - x.shape[-1]
18
+ if pad_size == 0:
19
+ return x
20
+ padding = torch.zeros(*x.shape[:-1], pad_size, dtype=x.dtype, device=x.device)
21
+ x_padded = torch.cat([x, padding], dim=-1)
22
+ return x_padded
23
+
24
+ def maybe_truncate_last_dim(x, size):
25
+ if size == x.shape[-1]:
26
+ return x
27
+ return x[..., :size]
vision.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from types import SimpleNamespace
3
+ import numpy as np
4
+ import torch
5
+ from torch import nn
6
+ from timm.models.vision_transformer import Block
7
+ from .radio_patch import ViTPatchGenerator
8
+ from .radio_cls import ClsToken as _bundle_radio_cls
9
+
10
+ class RadioBackbone(nn.Module):
11
+ def __init__(self):
12
+ super().__init__()
13
+ self.patch_generator = ViTPatchGenerator(16,1280,224,cls_token=True,max_input_dims=2048,num_cls_tokens=4,register_multiple=10)
14
+ self.blocks = nn.Sequential(*[Block(1280,16,mlp_ratio=4,qkv_bias=True) for _ in range(32)])
15
+ def forward(self, pixels):
16
+ return self.blocks(self.patch_generator(pixels))[:,10:]
17
+
18
+ class RadioModel(nn.Module):
19
+ def __init__(self):
20
+ super().__init__()
21
+ self.model = RadioBackbone()
22
+ self.register_buffer('summary_idxs',torch.tensor([0,1,2],dtype=torch.int64))
23
+ def forward(self, pixels):
24
+ return self.model(pixels)
25
+
26
+ class RadioWrapper(nn.Module):
27
+ def __init__(self):
28
+ super().__init__()
29
+ self.radio_model = RadioModel()
30
+ def forward(self, pixels):
31
+ return self.radio_model(pixels)
32
+
33
+ class RadioVisionTower(nn.Module):
34
+ def __init__(self):
35
+ super().__init__()
36
+ self.vision_tower = RadioWrapper()
37
+ self.image_processor = RadioImageProcessor()
38
+ self.is_loaded = True
39
+ self.config = SimpleNamespace(hidden_size=1280,patch_size=16)
40
+ def forward(self, images):
41
+ reference = next(self.parameters())
42
+ if isinstance(images, (tuple,list)):
43
+ return torch.cat([self.vision_tower(x.to(reference)) for x in images], dim=1)
44
+ return self.vision_tower(images.to(reference))
45
+
46
+ class RadioImageProcessor:
47
+ radio_downsample_ratio = 0.5
48
+ def __call__(self, images, return_tensors='pt'):
49
+ if len(images)!=1:
50
+ raise ValueError('Process one image at a time')
51
+ image = images[0].convert('RGB')
52
+ ph,pw = round(image.height/16+0.5), round(image.width/16+0.5)
53
+ factor=min(math.sqrt(12000/(ph*pw)),1.)
54
+ h,w=math.floor(factor*ph),math.floor(factor*pw)
55
+ if h*w<1024:
56
+ up=math.sqrt(1024/(h*w)); h,w=math.ceil(up*h),math.ceil(up*w)
57
+ if h%2:h=h+1 if (h+1)*w<=12000 else max(2,h-1)
58
+ if w%2:w=w+1 if h*(w+1)<=12000 else max(2,w-1)
59
+ pixels=torch.from_numpy(np.asarray(image,dtype=np.uint8).copy()).permute(2,0,1).unsqueeze(0).float()
60
+ if pixels.shape[-2:]!=(h*16,w*16):
61
+ pixels=torch.nn.functional.interpolate(pixels,size=(h*16,w*16),mode='bicubic',align_corners=False,antialias=True)
62
+ mean=torch.tensor([.48145466,.4578275,.40821073]).view(1,3,1,1)
63
+ std=torch.tensor([.26862954,.26130258,.27577711]).view(1,3,1,1)
64
+ return SimpleNamespace(pixel_values=(pixels/255.-mean)/std)
vq.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from types import SimpleNamespace
2
+ import numpy as np
3
+ import torch
4
+ from torch import nn
5
+ from .vq_model import Encoder, Decoder
6
+
7
+ class Codebook(nn.Module):
8
+ def __init__(self):
9
+ super().__init__()
10
+ self.embedding = nn.Embedding(131072, 256)
11
+ def get_codebook_entry(self, indices, shape=None):
12
+ result = self.embedding(indices)
13
+ if shape is not None:
14
+ result = result.view(shape).permute(0,3,1,2).contiguous()
15
+ return result
16
+ def forward(self, z):
17
+ # Identical argmax to the IBQ softmax; chunking bounds scratch memory.
18
+ b,c,h,w = z.shape
19
+ flat = z.permute(0,2,3,1).reshape(-1,c)
20
+ ids = torch.cat([(part @ self.embedding.weight.T).argmax(-1) for part in flat.split(256)])
21
+ quant = self.embedding(ids).reshape(b,h,w,c).permute(0,3,1,2).contiguous()
22
+ return quant, 0.0, (None,None,ids)
23
+
24
+ class Emu3VQ(nn.Module):
25
+ def __init__(self):
26
+ super().__init__()
27
+ architecture = dict(double_z=False,z_channels=256,resolution=256,in_channels=3,out_ch=3,ch=256,ch_mult=[1,1,2,2,4],num_res_blocks=4,attn_resolutions=[16],dropout=0.0)
28
+ self.encoder = Encoder(**architecture)
29
+ self.decoder = Decoder(**architecture)
30
+ self.quantize = Codebook()
31
+ self.quant_conv = nn.Conv2d(256,256,1)
32
+ self.post_quant_conv = nn.Conv2d(256,256,1)
33
+ self.config = SimpleNamespace(num_vq_embeddings=131072,vq_embedding_dim=256)
34
+ def encode(self, images, mini_batch_size=None):
35
+ return self.quantize(self.quant_conv(self.encoder(images)))
36
+ def decode(self, quant, mini_batch_size=None):
37
+ return self.decoder(self.post_quant_conv(quant))
38
+
39
+ class Emu3ImageProcessor:
40
+ def preprocess(self, image):
41
+ pixels = np.asarray(image.convert('RGB'), dtype=np.float32) / 127.5 - 1.0
42
+ return torch.from_numpy(pixels).permute(2,0,1).unsqueeze(0)
vq_model.py ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pytorch_diffusion + derived encoder decoder
2
+ from __future__ import annotations
3
+ import torch
4
+ import torch.nn as nn
5
+
6
+ def nonlinearity(x):
7
+ return x * torch.sigmoid(x)
8
+
9
+ def Normalize(in_channels):
10
+ return torch.nn.GroupNorm(num_groups=32, num_channels=in_channels, eps=1e-06, affine=True)
11
+
12
+ class Upsample(nn.Module):
13
+
14
+ def __init__(self, in_channels, with_conv):
15
+ super().__init__()
16
+ self.with_conv = with_conv
17
+ if self.with_conv:
18
+ self.conv = torch.nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=1, padding=1)
19
+
20
+ def forward(self, x):
21
+ x = torch.nn.functional.interpolate(x, scale_factor=2.0, mode='nearest')
22
+ if self.with_conv:
23
+ x = self.conv(x)
24
+ return x
25
+
26
+ class Downsample(nn.Module):
27
+
28
+ def __init__(self, in_channels, with_conv):
29
+ super().__init__()
30
+ self.with_conv = with_conv
31
+ if self.with_conv:
32
+ self.conv = torch.nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=2, padding=0)
33
+
34
+ def forward(self, x):
35
+ if self.with_conv:
36
+ pad = (0, 1, 0, 1)
37
+ x = torch.nn.functional.pad(x, pad, mode='constant', value=0)
38
+ x = self.conv(x)
39
+ else:
40
+ x = torch.nn.functional.avg_pool2d(x, kernel_size=2, stride=2)
41
+ return x
42
+
43
+ class ResnetBlock(nn.Module):
44
+
45
+ def __init__(self, *, in_channels, out_channels=None, conv_shortcut=False, dropout, temb_channels=512):
46
+ super().__init__()
47
+ self.in_channels = in_channels
48
+ out_channels = in_channels if out_channels is None else out_channels
49
+ self.out_channels = out_channels
50
+ self.use_conv_shortcut = conv_shortcut
51
+ self.norm1 = Normalize(in_channels)
52
+ self.conv1 = torch.nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1)
53
+ if temb_channels > 0:
54
+ self.temb_proj = torch.nn.Linear(temb_channels, out_channels)
55
+ self.norm2 = Normalize(out_channels)
56
+ self.dropout = torch.nn.Dropout(dropout)
57
+ self.conv2 = torch.nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
58
+ if self.in_channels != self.out_channels:
59
+ if self.use_conv_shortcut:
60
+ self.conv_shortcut = torch.nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1)
61
+ else:
62
+ self.nin_shortcut = torch.nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0)
63
+
64
+ def forward(self, x, temb):
65
+ h = x
66
+ h = self.norm1(h)
67
+ h = nonlinearity(h)
68
+ h = self.conv1(h)
69
+ if temb is not None:
70
+ h = h + self.temb_proj(nonlinearity(temb))[:, :, None, None]
71
+ h = self.norm2(h)
72
+ h = nonlinearity(h)
73
+ h = self.dropout(h)
74
+ h = self.conv2(h)
75
+ if self.in_channels != self.out_channels:
76
+ if self.use_conv_shortcut:
77
+ x = self.conv_shortcut(x)
78
+ else:
79
+ x = self.nin_shortcut(x)
80
+ return x + h
81
+
82
+ class AttnBlock(nn.Module):
83
+
84
+ def __init__(self, in_channels):
85
+ super().__init__()
86
+ self.in_channels = in_channels
87
+ self.norm = Normalize(in_channels)
88
+ self.q = torch.nn.Conv2d(in_channels, in_channels, kernel_size=1, stride=1, padding=0)
89
+ self.k = torch.nn.Conv2d(in_channels, in_channels, kernel_size=1, stride=1, padding=0)
90
+ self.v = torch.nn.Conv2d(in_channels, in_channels, kernel_size=1, stride=1, padding=0)
91
+ self.proj_out = torch.nn.Conv2d(in_channels, in_channels, kernel_size=1, stride=1, padding=0)
92
+
93
+ def forward(self, x):
94
+ h_ = x
95
+ h_ = self.norm(h_)
96
+ q = self.q(h_)
97
+ k = self.k(h_)
98
+ v = self.v(h_)
99
+ (b, c, h, w) = q.shape
100
+ q = q.reshape(b, c, h * w)
101
+ q = q.permute(0, 2, 1)
102
+ k = k.reshape(b, c, h * w)
103
+ w_ = torch.bmm(q, k)
104
+ w_ = w_ * int(c) ** -0.5
105
+ w_ = torch.nn.functional.softmax(w_, dim=2)
106
+ v = v.reshape(b, c, h * w)
107
+ w_ = w_.permute(0, 2, 1)
108
+ h_ = torch.bmm(v, w_)
109
+ h_ = h_.reshape(b, c, h, w)
110
+ h_ = self.proj_out(h_)
111
+ return x + h_
112
+
113
+ class Encoder(nn.Module):
114
+
115
+ def __init__(self, *, ch, out_ch, ch_mult=(1, 2, 4, 8), num_res_blocks, attn_resolutions, dropout=0.0, resamp_with_conv=True, in_channels, resolution, z_channels, double_z=True, **ignore_kwargs):
116
+ super().__init__()
117
+ self.ch = ch
118
+ self.temb_ch = 0
119
+ self.num_resolutions = len(ch_mult)
120
+ self.num_res_blocks = num_res_blocks
121
+ self.resolution = resolution
122
+ self.in_channels = in_channels
123
+ self.conv_in = torch.nn.Conv2d(in_channels, self.ch, kernel_size=3, stride=1, padding=1)
124
+ curr_res = resolution
125
+ in_ch_mult = (1,) + tuple(ch_mult)
126
+ self.down = nn.ModuleList()
127
+ for i_level in range(self.num_resolutions):
128
+ block = nn.ModuleList()
129
+ attn = nn.ModuleList()
130
+ block_in = ch * in_ch_mult[i_level]
131
+ block_out = ch * ch_mult[i_level]
132
+ for i_block in range(self.num_res_blocks):
133
+ block.append(ResnetBlock(in_channels=block_in, out_channels=block_out, temb_channels=self.temb_ch, dropout=dropout))
134
+ block_in = block_out
135
+ if curr_res in attn_resolutions:
136
+ attn.append(AttnBlock(block_in))
137
+ down = nn.Module()
138
+ down.block = block
139
+ down.attn = attn
140
+ if i_level != self.num_resolutions - 1:
141
+ down.downsample = Downsample(block_in, resamp_with_conv)
142
+ curr_res = curr_res // 2
143
+ self.down.append(down)
144
+ self.mid = nn.Module()
145
+ self.mid.block_1 = ResnetBlock(in_channels=block_in, out_channels=block_in, temb_channels=self.temb_ch, dropout=dropout)
146
+ self.mid.attn_1 = AttnBlock(block_in)
147
+ self.mid.block_2 = ResnetBlock(in_channels=block_in, out_channels=block_in, temb_channels=self.temb_ch, dropout=dropout)
148
+ self.norm_out = Normalize(block_in)
149
+ self.conv_out = torch.nn.Conv2d(block_in, 2 * z_channels if double_z else z_channels, kernel_size=3, stride=1, padding=1)
150
+
151
+ def forward(self, x):
152
+ temb = None
153
+ hs = [self.conv_in(x)]
154
+ for i_level in range(self.num_resolutions):
155
+ for i_block in range(self.num_res_blocks):
156
+ h = self.down[i_level].block[i_block](hs[-1], temb)
157
+ if len(self.down[i_level].attn) > 0:
158
+ h = self.down[i_level].attn[i_block](h)
159
+ hs.append(h)
160
+ if i_level != self.num_resolutions - 1:
161
+ hs.append(self.down[i_level].downsample(hs[-1]))
162
+ h = hs[-1]
163
+ h = self.mid.block_1(h, temb)
164
+ h = self.mid.attn_1(h)
165
+ h = self.mid.block_2(h, temb)
166
+ h = self.norm_out(h)
167
+ h = nonlinearity(h)
168
+ h = self.conv_out(h)
169
+ return h
170
+
171
+ class Decoder(nn.Module):
172
+
173
+ def __init__(self, *, ch, out_ch, ch_mult=(1, 2, 4, 8), num_res_blocks, attn_resolutions, dropout=0.0, resamp_with_conv=True, in_channels, resolution, z_channels, give_pre_end=False, **ignorekwargs):
174
+ super().__init__()
175
+ self.ch = ch
176
+ self.temb_ch = 0
177
+ self.num_resolutions = len(ch_mult)
178
+ self.num_res_blocks = num_res_blocks
179
+ self.resolution = resolution
180
+ self.in_channels = in_channels
181
+ self.give_pre_end = give_pre_end
182
+ in_ch_mult = (1,) + tuple(ch_mult)
183
+ block_in = ch * ch_mult[self.num_resolutions - 1]
184
+ curr_res = resolution // 2 ** (self.num_resolutions - 1)
185
+ self.z_shape = (1, z_channels, curr_res, curr_res)
186
+ self.conv_in = torch.nn.Conv2d(z_channels, block_in, kernel_size=3, stride=1, padding=1)
187
+ self.mid = nn.Module()
188
+ self.mid.block_1 = ResnetBlock(in_channels=block_in, out_channels=block_in, temb_channels=self.temb_ch, dropout=dropout)
189
+ self.mid.attn_1 = AttnBlock(block_in)
190
+ self.mid.block_2 = ResnetBlock(in_channels=block_in, out_channels=block_in, temb_channels=self.temb_ch, dropout=dropout)
191
+ self.up = nn.ModuleList()
192
+ for i_level in reversed(range(self.num_resolutions)):
193
+ block = nn.ModuleList()
194
+ attn = nn.ModuleList()
195
+ block_out = ch * ch_mult[i_level]
196
+ for i_block in range(self.num_res_blocks + 1):
197
+ block.append(ResnetBlock(in_channels=block_in, out_channels=block_out, temb_channels=self.temb_ch, dropout=dropout))
198
+ block_in = block_out
199
+ if curr_res in attn_resolutions:
200
+ attn.append(AttnBlock(block_in))
201
+ up = nn.Module()
202
+ up.block = block
203
+ up.attn = attn
204
+ if i_level != 0:
205
+ up.upsample = Upsample(block_in, resamp_with_conv)
206
+ curr_res = curr_res * 2
207
+ self.up.insert(0, up)
208
+ self.norm_out = Normalize(block_in)
209
+ self.conv_out = torch.nn.Conv2d(block_in, out_ch, kernel_size=3, stride=1, padding=1)
210
+
211
+ def forward(self, z, return_intermediate_feature=False):
212
+ self.last_z_shape = z.shape
213
+ temb = None
214
+ h = self.conv_in(z)
215
+ h = self.mid.block_1(h, temb)
216
+ h = self.mid.attn_1(h)
217
+ h = self.mid.block_2(h, temb)
218
+ im_feat_list = []
219
+ for i_level in reversed(range(self.num_resolutions)):
220
+ for i_block in range(self.num_res_blocks + 1):
221
+ h = self.up[i_level].block[i_block](h, temb)
222
+ if len(self.up[i_level].attn) > 0:
223
+ h = self.up[i_level].attn[i_block](h)
224
+ if i_level != 0:
225
+ h = self.up[i_level].upsample(h)
226
+ im_feat_list.append(h)
227
+ if self.give_pre_end:
228
+ return h
229
+ h = self.norm_out(h)
230
+ h = nonlinearity(h)
231
+ h = self.conv_out(h)
232
+ if return_intermediate_feature:
233
+ return (h, im_feat_list)
234
+ return h