nvidia-modelopt 0.35.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. modelopt/__init__.py +20 -0
  2. modelopt/deploy/__init__.py +16 -0
  3. modelopt/deploy/llm/__init__.py +30 -0
  4. modelopt/deploy/llm/generate.py +345 -0
  5. modelopt/onnx/__init__.py +34 -0
  6. modelopt/onnx/autocast/__init__.py +19 -0
  7. modelopt/onnx/autocast/__main__.py +187 -0
  8. modelopt/onnx/autocast/convert.py +202 -0
  9. modelopt/onnx/autocast/graphsanitizer.py +422 -0
  10. modelopt/onnx/autocast/logging_config.py +78 -0
  11. modelopt/onnx/autocast/nodeclassifier.py +416 -0
  12. modelopt/onnx/autocast/precisionconverter.py +1032 -0
  13. modelopt/onnx/autocast/referencerunner.py +159 -0
  14. modelopt/onnx/autocast/utils.py +117 -0
  15. modelopt/onnx/llm_export_utils/__init__.py +16 -0
  16. modelopt/onnx/llm_export_utils/export_utils.py +162 -0
  17. modelopt/onnx/llm_export_utils/quantization_utils.py +122 -0
  18. modelopt/onnx/llm_export_utils/surgeon_utils.py +120 -0
  19. modelopt/onnx/logging_config.py +77 -0
  20. modelopt/onnx/op_types.py +300 -0
  21. modelopt/onnx/quantization/__init__.py +20 -0
  22. modelopt/onnx/quantization/__main__.py +291 -0
  23. modelopt/onnx/quantization/calib_utils.py +178 -0
  24. modelopt/onnx/quantization/extensions.py +35 -0
  25. modelopt/onnx/quantization/fp8.py +375 -0
  26. modelopt/onnx/quantization/graph_utils.py +1479 -0
  27. modelopt/onnx/quantization/gs_patching.py +112 -0
  28. modelopt/onnx/quantization/int4.py +1347 -0
  29. modelopt/onnx/quantization/int8.py +283 -0
  30. modelopt/onnx/quantization/operators.py +121 -0
  31. modelopt/onnx/quantization/ort_patching.py +1766 -0
  32. modelopt/onnx/quantization/ort_utils.py +346 -0
  33. modelopt/onnx/quantization/partitioning.py +439 -0
  34. modelopt/onnx/quantization/qdq_utils.py +1349 -0
  35. modelopt/onnx/quantization/quant_utils.py +283 -0
  36. modelopt/onnx/quantization/quantize.py +528 -0
  37. modelopt/onnx/quantization/src/modelopt_round_and_pack_ext.cpp +127 -0
  38. modelopt/onnx/trt_utils.py +424 -0
  39. modelopt/onnx/utils.py +753 -0
  40. modelopt/torch/__init__.py +41 -0
  41. modelopt/torch/_deploy/__init__.py +23 -0
  42. modelopt/torch/_deploy/_runtime/__init__.py +29 -0
  43. modelopt/torch/_deploy/_runtime/common.py +72 -0
  44. modelopt/torch/_deploy/_runtime/ort_client.py +193 -0
  45. modelopt/torch/_deploy/_runtime/registry.py +83 -0
  46. modelopt/torch/_deploy/_runtime/runtime_client.py +154 -0
  47. modelopt/torch/_deploy/_runtime/tensorrt/constants.py +108 -0
  48. modelopt/torch/_deploy/_runtime/tensorrt/engine_builder.py +324 -0
  49. modelopt/torch/_deploy/_runtime/tensorrt/hw_param_config.py +51 -0
  50. modelopt/torch/_deploy/_runtime/tensorrt/layerwise_profiling.py +178 -0
  51. modelopt/torch/_deploy/_runtime/tensorrt/parse_trtexec_log.py +151 -0
  52. modelopt/torch/_deploy/_runtime/tensorrt/tensorrt_utils.py +200 -0
  53. modelopt/torch/_deploy/_runtime/trt_client.py +219 -0
  54. modelopt/torch/_deploy/compilation.py +142 -0
  55. modelopt/torch/_deploy/device_model.py +157 -0
  56. modelopt/torch/_deploy/profiling.py +193 -0
  57. modelopt/torch/_deploy/utils/__init__.py +18 -0
  58. modelopt/torch/_deploy/utils/onnx_optimizer.py +120 -0
  59. modelopt/torch/_deploy/utils/onnx_utils.py +58 -0
  60. modelopt/torch/_deploy/utils/torch_onnx.py +593 -0
  61. modelopt/torch/distill/__init__.py +28 -0
  62. modelopt/torch/distill/config.py +130 -0
  63. modelopt/torch/distill/distillation.py +84 -0
  64. modelopt/torch/distill/distillation_model.py +318 -0
  65. modelopt/torch/distill/loss_balancers.py +140 -0
  66. modelopt/torch/distill/losses.py +275 -0
  67. modelopt/torch/distill/mode.py +223 -0
  68. modelopt/torch/distill/plugins/__init__.py +24 -0
  69. modelopt/torch/distill/plugins/huggingface.py +110 -0
  70. modelopt/torch/distill/plugins/megatron.py +476 -0
  71. modelopt/torch/distill/registry.py +23 -0
  72. modelopt/torch/export/__init__.py +24 -0
  73. modelopt/torch/export/convert_hf_config.py +117 -0
  74. modelopt/torch/export/distribute.py +300 -0
  75. modelopt/torch/export/hf_config_map.py +84 -0
  76. modelopt/torch/export/layer_utils.py +1893 -0
  77. modelopt/torch/export/mcore_config_map.py +25 -0
  78. modelopt/torch/export/model_config.py +623 -0
  79. modelopt/torch/export/model_config_export.py +552 -0
  80. modelopt/torch/export/model_config_utils.py +392 -0
  81. modelopt/torch/export/model_utils.py +71 -0
  82. modelopt/torch/export/plugins/__init__.py +21 -0
  83. modelopt/torch/export/plugins/mcore_common.py +67 -0
  84. modelopt/torch/export/plugins/mcore_custom.py +530 -0
  85. modelopt/torch/export/plugins/mcore_deepseek.py +143 -0
  86. modelopt/torch/export/plugins/mcore_gptoss.py +71 -0
  87. modelopt/torch/export/plugins/mcore_llama.py +164 -0
  88. modelopt/torch/export/plugins/mcore_nemotron.py +90 -0
  89. modelopt/torch/export/plugins/mcore_qwen.py +99 -0
  90. modelopt/torch/export/plugins/megatron_importer.py +647 -0
  91. modelopt/torch/export/postprocess.py +847 -0
  92. modelopt/torch/export/quant_utils.py +1069 -0
  93. modelopt/torch/export/tensorrt_llm_type.py +42 -0
  94. modelopt/torch/export/tensorrt_llm_utils.py +405 -0
  95. modelopt/torch/export/transformer_engine.py +94 -0
  96. modelopt/torch/export/unified_export_hf.py +537 -0
  97. modelopt/torch/export/unified_export_megatron.py +1164 -0
  98. modelopt/torch/nas/__init__.py +27 -0
  99. modelopt/torch/nas/algorithms.py +856 -0
  100. modelopt/torch/nas/autonas.py +808 -0
  101. modelopt/torch/nas/conversion.py +119 -0
  102. modelopt/torch/nas/hparams/__init__.py +19 -0
  103. modelopt/torch/nas/hparams/concat.py +319 -0
  104. modelopt/torch/nas/hparams/container.py +48 -0
  105. modelopt/torch/nas/modules/__init__.py +21 -0
  106. modelopt/torch/nas/modules/container.py +99 -0
  107. modelopt/torch/nas/modules/conv.py +254 -0
  108. modelopt/torch/nas/modules/linear.py +76 -0
  109. modelopt/torch/nas/modules/norm.py +193 -0
  110. modelopt/torch/nas/modules/utils.py +61 -0
  111. modelopt/torch/nas/patch.py +261 -0
  112. modelopt/torch/nas/plugins/__init__.py +29 -0
  113. modelopt/torch/nas/plugins/megatron.py +1497 -0
  114. modelopt/torch/nas/plugins/torch.py +71 -0
  115. modelopt/torch/nas/plugins/transformer_engine.py +42 -0
  116. modelopt/torch/nas/plugins/transformers.py +210 -0
  117. modelopt/torch/nas/registry.py +23 -0
  118. modelopt/torch/nas/search_space.py +260 -0
  119. modelopt/torch/nas/traced_hp.py +149 -0
  120. modelopt/torch/nas/utils.py +408 -0
  121. modelopt/torch/opt/__init__.py +41 -0
  122. modelopt/torch/opt/_hooks.py +98 -0
  123. modelopt/torch/opt/config.py +383 -0
  124. modelopt/torch/opt/conversion.py +620 -0
  125. modelopt/torch/opt/dynamic.py +1367 -0
  126. modelopt/torch/opt/hparam.py +275 -0
  127. modelopt/torch/opt/mode.py +353 -0
  128. modelopt/torch/opt/plugins/__init__.py +38 -0
  129. modelopt/torch/opt/plugins/diffusers.py +40 -0
  130. modelopt/torch/opt/plugins/huggingface.py +162 -0
  131. modelopt/torch/opt/plugins/mcore_dist_checkpointing.py +211 -0
  132. modelopt/torch/opt/plugins/megatron.py +142 -0
  133. modelopt/torch/opt/plugins/peft.py +108 -0
  134. modelopt/torch/opt/plugins/transformers.py +160 -0
  135. modelopt/torch/opt/searcher.py +363 -0
  136. modelopt/torch/opt/utils.py +125 -0
  137. modelopt/torch/prune/__init__.py +26 -0
  138. modelopt/torch/prune/fastnas.py +376 -0
  139. modelopt/torch/prune/gradnas.py +349 -0
  140. modelopt/torch/prune/plugins/__init__.py +24 -0
  141. modelopt/torch/prune/plugins/mcore_minitron.py +263 -0
  142. modelopt/torch/prune/plugins/transformers.py +41 -0
  143. modelopt/torch/prune/pruning.py +211 -0
  144. modelopt/torch/quantization/__init__.py +26 -0
  145. modelopt/torch/quantization/algorithms.py +671 -0
  146. modelopt/torch/quantization/backends/__init__.py +20 -0
  147. modelopt/torch/quantization/backends/fp8_per_tensor_gemm.py +204 -0
  148. modelopt/torch/quantization/backends/gemm_registry.py +156 -0
  149. modelopt/torch/quantization/backends/nvfp4_gemm.py +201 -0
  150. modelopt/torch/quantization/backends/utils.py +28 -0
  151. modelopt/torch/quantization/calib/__init__.py +25 -0
  152. modelopt/torch/quantization/calib/bias.py +172 -0
  153. modelopt/torch/quantization/calib/calibrator.py +63 -0
  154. modelopt/torch/quantization/calib/histogram.py +434 -0
  155. modelopt/torch/quantization/calib/max.py +110 -0
  156. modelopt/torch/quantization/compress.py +227 -0
  157. modelopt/torch/quantization/config.py +1180 -0
  158. modelopt/torch/quantization/conversion.py +389 -0
  159. modelopt/torch/quantization/export_onnx.py +639 -0
  160. modelopt/torch/quantization/extensions.py +89 -0
  161. modelopt/torch/quantization/mode.py +428 -0
  162. modelopt/torch/quantization/model_calib.py +949 -0
  163. modelopt/torch/quantization/model_quant.py +477 -0
  164. modelopt/torch/quantization/nn/__init__.py +26 -0
  165. modelopt/torch/quantization/nn/functional.py +109 -0
  166. modelopt/torch/quantization/nn/modules/__init__.py +16 -0
  167. modelopt/torch/quantization/nn/modules/quant_activations.py +22 -0
  168. modelopt/torch/quantization/nn/modules/quant_batchnorm.py +24 -0
  169. modelopt/torch/quantization/nn/modules/quant_conv.py +123 -0
  170. modelopt/torch/quantization/nn/modules/quant_instancenorm.py +39 -0
  171. modelopt/torch/quantization/nn/modules/quant_linear.py +258 -0
  172. modelopt/torch/quantization/nn/modules/quant_module.py +211 -0
  173. modelopt/torch/quantization/nn/modules/quant_pooling.py +99 -0
  174. modelopt/torch/quantization/nn/modules/quant_rnn.py +527 -0
  175. modelopt/torch/quantization/nn/modules/tensor_quantizer.py +1293 -0
  176. modelopt/torch/quantization/plugins/__init__.py +73 -0
  177. modelopt/torch/quantization/plugins/accelerate.py +214 -0
  178. modelopt/torch/quantization/plugins/apex.py +52 -0
  179. modelopt/torch/quantization/plugins/attention.py +312 -0
  180. modelopt/torch/quantization/plugins/custom.py +192 -0
  181. modelopt/torch/quantization/plugins/diffusers.py +237 -0
  182. modelopt/torch/quantization/plugins/fairscale.py +45 -0
  183. modelopt/torch/quantization/plugins/huggingface.py +736 -0
  184. modelopt/torch/quantization/plugins/megatron.py +462 -0
  185. modelopt/torch/quantization/plugins/peft.py +148 -0
  186. modelopt/torch/quantization/plugins/transformer_engine.py +60 -0
  187. modelopt/torch/quantization/plugins/transformers.py +52 -0
  188. modelopt/torch/quantization/plugins/transformers_trainer.py +426 -0
  189. modelopt/torch/quantization/plugins/trl.py +27 -0
  190. modelopt/torch/quantization/plugins/vllm.py +199 -0
  191. modelopt/torch/quantization/qtensor/__init__.py +24 -0
  192. modelopt/torch/quantization/qtensor/base_qtensor.py +370 -0
  193. modelopt/torch/quantization/qtensor/fp8_tensor.py +151 -0
  194. modelopt/torch/quantization/qtensor/int4_tensor.py +130 -0
  195. modelopt/torch/quantization/qtensor/int8_tensor.py +124 -0
  196. modelopt/torch/quantization/qtensor/mxfp4_tensor.py +144 -0
  197. modelopt/torch/quantization/qtensor/nf4_tensor.py +199 -0
  198. modelopt/torch/quantization/qtensor/nvfp4_tensor.py +295 -0
  199. modelopt/torch/quantization/src/tensor_quant.cpp +77 -0
  200. modelopt/torch/quantization/src/tensor_quant.h +69 -0
  201. modelopt/torch/quantization/src/tensor_quant_fp8.cpp +48 -0
  202. modelopt/torch/quantization/src/tensor_quant_gpu.cu +361 -0
  203. modelopt/torch/quantization/src/tensor_quant_gpu_fp8.cu +122 -0
  204. modelopt/torch/quantization/src/tensor_quant_mx.cu +411 -0
  205. modelopt/torch/quantization/src/tensor_quant_mx.h +247 -0
  206. modelopt/torch/quantization/tensor_quant.py +816 -0
  207. modelopt/torch/quantization/triton/__init__.py +36 -0
  208. modelopt/torch/quantization/triton/fp4_kernel.py +303 -0
  209. modelopt/torch/quantization/utils.py +443 -0
  210. modelopt/torch/sparsity/__init__.py +19 -0
  211. modelopt/torch/sparsity/config.py +51 -0
  212. modelopt/torch/sparsity/magnitude.py +148 -0
  213. modelopt/torch/sparsity/mode.py +203 -0
  214. modelopt/torch/sparsity/module.py +87 -0
  215. modelopt/torch/sparsity/plugins/__init__.py +27 -0
  216. modelopt/torch/sparsity/plugins/megatron.py +93 -0
  217. modelopt/torch/sparsity/searcher.py +84 -0
  218. modelopt/torch/sparsity/sparsegpt.py +276 -0
  219. modelopt/torch/sparsity/sparsification.py +123 -0
  220. modelopt/torch/speculative/__init__.py +20 -0
  221. modelopt/torch/speculative/config.py +100 -0
  222. modelopt/torch/speculative/eagle/__init__.py +20 -0
  223. modelopt/torch/speculative/eagle/conversion.py +67 -0
  224. modelopt/torch/speculative/eagle/default_config.py +50 -0
  225. modelopt/torch/speculative/eagle/eagle_model.py +51 -0
  226. modelopt/torch/speculative/eagle/utils.py +91 -0
  227. modelopt/torch/speculative/medusa/__init__.py +19 -0
  228. modelopt/torch/speculative/medusa/conversion.py +59 -0
  229. modelopt/torch/speculative/medusa/medusa_model.py +32 -0
  230. modelopt/torch/speculative/mode.py +86 -0
  231. modelopt/torch/speculative/plugins/__init__.py +33 -0
  232. modelopt/torch/speculative/plugins/megatron_eagle.py +2119 -0
  233. modelopt/torch/speculative/plugins/megatron_medusa.py +312 -0
  234. modelopt/torch/speculative/plugins/transformers.py +1138 -0
  235. modelopt/torch/speculative/speculative_decoding.py +59 -0
  236. modelopt/torch/speculative/utils.py +364 -0
  237. modelopt/torch/trace/__init__.py +25 -0
  238. modelopt/torch/trace/analyzer.py +1368 -0
  239. modelopt/torch/trace/modules/__init__.py +19 -0
  240. modelopt/torch/trace/modules/concat.py +384 -0
  241. modelopt/torch/trace/modules/nn.py +153 -0
  242. modelopt/torch/trace/plugins/__init__.py +34 -0
  243. modelopt/torch/trace/plugins/megatron.py +36 -0
  244. modelopt/torch/trace/plugins/transformers.py +58 -0
  245. modelopt/torch/trace/symbols.py +545 -0
  246. modelopt/torch/trace/tracer.py +331 -0
  247. modelopt/torch/utils/__init__.py +28 -0
  248. modelopt/torch/utils/_pytree.py +133 -0
  249. modelopt/torch/utils/cpp_extension.py +91 -0
  250. modelopt/torch/utils/dataset_utils.py +484 -0
  251. modelopt/torch/utils/distributed.py +311 -0
  252. modelopt/torch/utils/graph.py +123 -0
  253. modelopt/torch/utils/image_processor.py +112 -0
  254. modelopt/torch/utils/import_utils.py +35 -0
  255. modelopt/torch/utils/list.py +54 -0
  256. modelopt/torch/utils/logging.py +127 -0
  257. modelopt/torch/utils/memory_monitor.py +146 -0
  258. modelopt/torch/utils/network.py +658 -0
  259. modelopt/torch/utils/perf.py +174 -0
  260. modelopt/torch/utils/plugins/__init__.py +27 -0
  261. modelopt/torch/utils/plugins/megatron_generate.py +299 -0
  262. modelopt/torch/utils/plugins/megatron_mmlu.py +152 -0
  263. modelopt/torch/utils/plugins/megatron_preprocess_data.py +200 -0
  264. modelopt/torch/utils/random.py +163 -0
  265. modelopt/torch/utils/speech_dataset_utils.py +134 -0
  266. modelopt/torch/utils/tensor.py +87 -0
  267. modelopt/torch/utils/vlm_dataset_utils.py +110 -0
  268. nvidia_modelopt-0.35.0.dist-info/METADATA +171 -0
  269. nvidia_modelopt-0.35.0.dist-info/RECORD +272 -0
  270. nvidia_modelopt-0.35.0.dist-info/WHEEL +5 -0
  271. nvidia_modelopt-0.35.0.dist-info/licenses/LICENSE +14 -0
  272. nvidia_modelopt-0.35.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,552 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """Code that export optimized models to the TensorRT-LLM checkpoint."""
17
+
18
+ import copy
19
+ import json
20
+ import math
21
+ import tempfile
22
+ from collections.abc import Iterator
23
+ from dataclasses import asdict
24
+ from pathlib import Path
25
+ from typing import Any
26
+ from warnings import warn
27
+
28
+ import torch
29
+ import torch.nn as nn
30
+ from safetensors.torch import save_file
31
+
32
+ from modelopt.torch.utils import distributed as dist
33
+ from modelopt.torch.utils import import_plugin
34
+
35
+ from .layer_utils import (
36
+ build_conv_config,
37
+ build_decoder_config,
38
+ build_embedding_config,
39
+ build_layernorm_config,
40
+ build_linear_config,
41
+ build_medusa_heads_config,
42
+ check_model_compatibility,
43
+ get_dtype,
44
+ get_enc_dec_models,
45
+ get_enc_dec_token_ids,
46
+ get_encoder_config,
47
+ get_transformer_layers,
48
+ is_conv,
49
+ is_decoder_list,
50
+ is_embedding,
51
+ is_layernorm,
52
+ is_linear,
53
+ model_type_is_enc_dec,
54
+ )
55
+ from .model_config import QUANTIZATION_INT4_AWQ, QUANTIZATION_W4A8_AWQ, ModelConfig
56
+ from .model_config_utils import (
57
+ merge_gate_fc,
58
+ merge_qkv,
59
+ model_config_to_dict,
60
+ pack_linear_weights,
61
+ split_config_and_weights,
62
+ )
63
+ from .postprocess import (
64
+ check_weight_shape_valid,
65
+ pad_embedding_lm_head,
66
+ postprocess_model_config,
67
+ postprocess_tensors,
68
+ update_lm_head_quantization,
69
+ )
70
+ from .quant_utils import get_quantization_format, process_layer_quant_config
71
+ from .tensorrt_llm_utils import (
72
+ convert_to_tensorrt_llm_config,
73
+ is_tensorrt_llm_0_8_or_9,
74
+ prepare_enc_dec_export_dir,
75
+ prepare_t5_decoder_layer,
76
+ )
77
+
78
+ has_mcore = False
79
+ with import_plugin("megatron", verbose=False):
80
+ from megatron.core.models.gpt import GPTModel as MCoreGPTModel
81
+ from megatron.core.transformer.module import MegatronModule
82
+
83
+ has_mcore = True
84
+
85
+ __all__ = ["export_tensorrt_llm_checkpoint", "torch_to_tensorrt_llm_checkpoint"]
86
+
87
+
88
+ def torch_to_tensorrt_llm_checkpoint(
89
+ model: nn.Module,
90
+ decoder_type: str,
91
+ dtype: torch.dtype | None = None,
92
+ inference_tensor_parallel: int = 0,
93
+ inference_pipeline_parallel: int = 1,
94
+ workspace_path: Path | str | None = None,
95
+ ) -> Iterator[tuple[dict[str, Any], dict[str, torch.Tensor], dict[str, Any]]]:
96
+ """Converts the torch model to the TensorRT-LLM checkpoint per GPU rank.
97
+
98
+ TensorRT-LLM checkpoint is the LLM model format that can be used by the TensorRT-LLM build API.
99
+ for the engine building process.
100
+ https://github.com/NVIDIA/TensorRT-LLM/blob/main/docs/source/architecture/checkpoint.md
101
+
102
+ Args:
103
+ model: the torch model.
104
+ decoder_type: the type of the decoder, e.g. gpt, gptj, llama.
105
+ Please see :mod:`modelopt.torch.export.model_utils` for the supported models.
106
+ dtype: the weights data type to export the unquantized layers or the default model data type if None.
107
+ inference_tensor_parallel: The target inference time tensor parallel.
108
+ We will merge or split the calibration tensor parallelism to inference.
109
+ Default is 0, meaning using the calibration without manual config merge or split.
110
+ inference_pipeline_parallel: The target inference time pipeline parallel.
111
+ We will merge or split the calibration pipeline parallelism to inference.
112
+ Default is 1, meaning no pipeline parallelism.
113
+ workspace_path: the path to the NFS directory for postprocess cross rank communication.
114
+
115
+ Yields:
116
+ A tuple of
117
+ tensorrt_llm_config: A dict that maps to the ``PretrainedConfig`` in TensorRT-LLM.
118
+ https://github.com/NVIDIA/TensorRT-LLM/blob/main/tensorrt_llm/models/modeling_utils.py
119
+ weights: A dict that stores all model weights and scaling factors for each rank.
120
+ per_layer_quantization: A dict that contains layer-wise quantization information for all quantized layers
121
+ for mixed_precision, empty dictionary otherwise.
122
+ """
123
+ if dtype is None:
124
+ dtype = get_dtype(model)
125
+
126
+ if dtype not in [torch.float16, torch.bfloat16]:
127
+ warn(
128
+ f"dtype {dtype} not fully compatible with TensorRT-LLM optimizations, Default to float16."
129
+ )
130
+ dtype = torch.float16
131
+
132
+ architecture = ""
133
+ hf_config = None
134
+ if has_mcore and isinstance(model, MegatronModule):
135
+ if not isinstance(model, MCoreGPTModel):
136
+ raise ValueError("Only megatron.core.models.gpt.GPTModel is supported!")
137
+ # MCoreGPTModel.config has type TransformerConfig
138
+ #
139
+ # We choose to deepcopy here since TransformerConfig deserialization is sensitive to
140
+ # additional attributes.
141
+ model_metadata_config = copy.deepcopy(model.config.__dict__)
142
+ vocab_size = model.vocab_size
143
+ model_metadata_config["max_position_embeddings"] = model.max_position_embeddings
144
+ model_metadata_config["rotary_percent"] = model.rotary_percent
145
+ model_metadata_config["rotary_base"] = getattr(model, "rotary_base", 10000)
146
+ rope_scaling = getattr(model, "rotary_scaling", False)
147
+ if rope_scaling:
148
+ model_metadata_config["rope_scaling"] = {"type": "llama3"}
149
+ elif hasattr(model, "config"):
150
+ # Huggingface models
151
+ model_metadata_config = model.config.__dict__
152
+ vocab_size = model.config.vocab_size
153
+ hf_config = model.config
154
+ architecture = model.config.architectures[0]
155
+
156
+ # For Baichuan 13B, we check if alibi is used with the alibi_mask property.
157
+ if hasattr(model, "model") and hasattr(model.model, "alibi_mask"):
158
+ model_metadata_config["alibi"] = True
159
+
160
+ # For MPT, DBRX
161
+ for config_key in ["attn_config", "ffn_config"]:
162
+ config_value = model_metadata_config.get(config_key, None)
163
+ if config_value:
164
+ model_metadata_config.update(
165
+ config_value if isinstance(config_value, dict) else config_value.to_dict()
166
+ )
167
+
168
+ elif hasattr(model, "cfg"):
169
+ # NeMo MegatronGPTModel
170
+ model_metadata_config = dict(model.cfg)
171
+ vocab_size = model.tokenizer.vocab_size
172
+ else:
173
+ raise ValueError("Cannot find valid model metadata config in model")
174
+
175
+ if (
176
+ "multi_query_group_num" in model_metadata_config
177
+ and model_metadata_config["multi_query_group_num"] % inference_tensor_parallel != 0
178
+ ):
179
+ raise ValueError(
180
+ "Cannot divide {} kv_heads into {} gpus".format(
181
+ model_metadata_config["multi_query_group_num"],
182
+ inference_tensor_parallel,
183
+ )
184
+ )
185
+
186
+ training_pipeline_parallel = model_metadata_config.get("pipeline_model_parallel_size", 1)
187
+ training_tensor_parallel = dist.size() // training_pipeline_parallel
188
+ model_metadata_config["training_pipeline_parallel"] = training_pipeline_parallel
189
+ model_metadata_config["training_tensor_parallel"] = training_tensor_parallel
190
+
191
+ if "make_vocab_size_divisible_by" in model_metadata_config:
192
+ # For some nemo models, the vocab_size is pre-padded.
193
+ # We calculate the pre-padded vocab_size with this config: make_vocab_size_divisible_by.
194
+ make_vocab_size_divisible_by = model_metadata_config["make_vocab_size_divisible_by"]
195
+ make_vocab_size_divisible_by_with_tp = (
196
+ make_vocab_size_divisible_by * training_tensor_parallel
197
+ )
198
+ vocab_size = int(
199
+ math.ceil(vocab_size / make_vocab_size_divisible_by_with_tp)
200
+ * make_vocab_size_divisible_by_with_tp
201
+ )
202
+ print(
203
+ f"the new vocab_size is updated: {vocab_size}, make_vocab_size_divisible_by"
204
+ f" {make_vocab_size_divisible_by}, training_tensor_parallel"
205
+ f" {training_tensor_parallel}."
206
+ )
207
+
208
+ models = [("decoder", model)]
209
+ is_enc_dec = model_type_is_enc_dec(decoder_type)
210
+ if is_enc_dec:
211
+ model_lm_head = model.proj_out if decoder_type in ["whisper"] else model.lm_head
212
+ # For Encoder-Decoder models, we process the checkpoint separately.
213
+ models = get_enc_dec_models(model, decoder_type)
214
+
215
+ for component_name, model in models: # noqa: PLR1704
216
+ transformer_layers = get_transformer_layers(model)
217
+ if training_pipeline_parallel == 1:
218
+ compatible, has_position_embedding, has_embedding_layernorm = check_model_compatibility(
219
+ transformer_layers
220
+ )
221
+ else:
222
+ # For Megatron models with more than one PP,
223
+ # we skip the compatibility check as not all ranks have the full model.
224
+ # For Megatron Core GPTModel, both nemotron and llama do not have position embedding
225
+ # nor embedding layernorm.
226
+ compatible = len(transformer_layers) > 0
227
+ has_position_embedding = False
228
+ has_embedding_layernorm = False
229
+ assert compatible, "The model is not supported"
230
+
231
+ config = ModelConfig(
232
+ architecture=architecture,
233
+ dtype=str(dtype).split(".")[1],
234
+ rank=dist.rank(),
235
+ tensor_parallel=training_tensor_parallel,
236
+ pipeline_parallel=training_pipeline_parallel,
237
+ vocab_size=vocab_size,
238
+ )
239
+
240
+ # For Encoder-Decoder Model
241
+ if is_enc_dec:
242
+ config.enc_dec = component_name
243
+ model_metadata_config["enc_dec"] = component_name
244
+
245
+ if decoder_type in ["bart"]:
246
+ # bart does not have final layernorm but has embedding layernorm.
247
+ has_embedding_layernorm = True
248
+ elif decoder_type in ["whisper"]:
249
+ has_position_embedding = True
250
+
251
+ # GLM has a different handling of word_embeddings.
252
+ if decoder_type == "glm":
253
+ model = model.glm
254
+ transformer_layers.insert(0, model.word_embeddings)
255
+
256
+ # Build the full model_config dict layer by layer.
257
+ for module in transformer_layers:
258
+ if is_embedding(module):
259
+ if config.vocab_embedding is None and not (
260
+ decoder_type == "whisper" and model_metadata_config["enc_dec"] == "enc"
261
+ ):
262
+ # We assume the first embedding in the list the vocab_embedding.
263
+ # For whisper encoder module, the only embedding is position embedding
264
+ normalization_constant = 1
265
+ # Normalize vocab embedding for gemma.
266
+ if (
267
+ decoder_type == "gemma" and is_tensorrt_llm_0_8_or_9()
268
+ ) or decoder_type == "recurrentgemma":
269
+ normalization_constant = model_metadata_config["hidden_size"] ** 0.5
270
+
271
+ config.vocab_embedding = build_embedding_config(
272
+ module, normalization_constant=normalization_constant
273
+ )
274
+ elif has_position_embedding and config.position_embedding is None:
275
+ config.position_embedding = build_embedding_config(module)
276
+ if decoder_type in ["bart"]:
277
+ # Special handling for TRTLLM bart model
278
+ # Huggingface bart-large-cnn offsets embedding ids by 2 (see modeling_bart.py)
279
+ config.position_embedding.weight = config.position_embedding.weight[2:]
280
+ elif decoder_type == "glm":
281
+ config.block_embedding = build_embedding_config(module)
282
+ elif is_decoder_list(module):
283
+ layers = []
284
+ for idx, layer in enumerate(module.children()):
285
+ # Special process due to T5 model structure's specialty
286
+ if decoder_type in ["t5"]:
287
+ layer = layer.layer
288
+ layer_config = build_decoder_config(
289
+ layer,
290
+ model_metadata_config,
291
+ decoder_type,
292
+ tp_size=inference_tensor_parallel,
293
+ )
294
+ if decoder_type in ["deci"]:
295
+ block_config = model_metadata_config["block_configs"][idx]
296
+ layer_config.block_config = asdict(block_config)
297
+ # Special process for each decoder layer of Encoder-Decoder Model
298
+ if decoder_type in ["t5"]:
299
+ prepare_t5_decoder_layer(
300
+ layer_config,
301
+ model.config,
302
+ model_metadata_config["enc_dec"],
303
+ layers,
304
+ )
305
+ layers.append(layer_config)
306
+ config.layers = layers
307
+ elif is_layernorm(module):
308
+ if has_embedding_layernorm and config.ln_embed is None:
309
+ # Assume embedding_layernorm is placed before the ln_f.
310
+ config.ln_embed = build_layernorm_config(module)
311
+ else:
312
+ config.ln_f = build_layernorm_config(module)
313
+ elif is_linear(module):
314
+ if model_metadata_config.get("share_embeddings_and_output_weights", False):
315
+ # NeMo/MCore models with shared embeddings - for example Gemma -
316
+ # the model head weight is None so we just skip processing
317
+ config.share_embedding_table = True
318
+ continue
319
+ # TRT LLM forces the embedding table to be shared for the following models.
320
+ force_share_embedding_table = decoder_type in ["gemma", "gemma2", "gemma3"]
321
+ if force_share_embedding_table and torch.equal(
322
+ module.weight, config.vocab_embedding.weight
323
+ ):
324
+ config.share_embedding_table = True
325
+ else:
326
+ # This will update lm_head quantization config according to constraints from TRT-LLM
327
+ update_lm_head_quantization(config, module, inference_pipeline_parallel)
328
+ config.lm_head = build_linear_config(module, "column")
329
+ elif is_conv(module) and decoder_type in ["whisper"]:
330
+ if config.conv1 is None:
331
+ config.conv1 = build_conv_config(module)
332
+ else:
333
+ config.conv2 = build_conv_config(module)
334
+
335
+ # For decoder of Encoder-Decoder model, it needs some encoder information
336
+ if is_enc_dec and model_metadata_config["enc_dec"] == "dec":
337
+ config.encoder_hidden_size, config.encoder_num_heads, config.encoder_head_size = (
338
+ get_encoder_config(models[0][1].config)
339
+ )
340
+ (
341
+ config.decoder_start_token_id,
342
+ config.eos_token_id,
343
+ config.bos_token_id,
344
+ config.pad_token_id,
345
+ ) = get_enc_dec_token_ids(models[1][1].config)
346
+
347
+ # For the training time PP, not all ranks will have the lm_head layer.
348
+ if config.lm_head is None:
349
+ if is_enc_dec:
350
+ if decoder_type not in ["whisper"]:
351
+ config.share_embedding_table = False
352
+ if model_metadata_config["enc_dec"] == "dec":
353
+ config.lm_head = build_linear_config(model_lm_head, "column")
354
+ elif training_pipeline_parallel == 1:
355
+ # Models that share weights for lm_head and vocab_embedding
356
+ assert decoder_type in [
357
+ "mpt",
358
+ "gpt2",
359
+ "gemma",
360
+ "gemma2",
361
+ "gemma3",
362
+ "glm",
363
+ "llama",
364
+ "mllama",
365
+ ], f"lm_head not available for decoder {decoder_type}"
366
+ config.share_embedding_table = True
367
+
368
+ # Handle Medusa Heads
369
+ # TODO (chenhany): post-processing is not implemented yet
370
+ config.medusa_heads = build_medusa_heads_config(model)
371
+
372
+ config.quantization = get_quantization_format(model)
373
+
374
+ if (
375
+ config.quantization in [QUANTIZATION_INT4_AWQ, QUANTIZATION_W4A8_AWQ]
376
+ and config.vocab_size % 64 != 0
377
+ ):
378
+ # TODO: Check if this works for Mixtral
379
+ assert training_tensor_parallel == 1, "We do not support padding for training time TP"
380
+ print("Padding vocab_embedding and lm_head for AWQ weights export")
381
+ pad_embedding_lm_head(config)
382
+ if hf_config is not None:
383
+ hf_config.vocab_size = config.vocab_size
384
+
385
+ check_weight_shape_valid(
386
+ config,
387
+ inference_tensor_parallel,
388
+ training_tensor_parallel,
389
+ )
390
+
391
+ # If inference_tensor_parallel or inference_pipeline_parallel is different from world_size,
392
+ # we try to merge or split the model configs based on the rank selected.
393
+ if (
394
+ inference_tensor_parallel > 0
395
+ or inference_pipeline_parallel > 0
396
+ or training_pipeline_parallel > 1
397
+ ):
398
+ model_configs = postprocess_model_config(
399
+ config,
400
+ inference_tensor_parallel,
401
+ inference_pipeline_parallel,
402
+ training_pipeline_parallel=training_pipeline_parallel,
403
+ workspace_path=workspace_path,
404
+ )
405
+ else:
406
+ model_configs = [config]
407
+
408
+ for model_config in model_configs:
409
+ assert model_config.rank >= 0, "Invalid model_config, postprocess_model_config fails."
410
+
411
+ merge_qkv(model_config)
412
+ merge_gate_fc(model_config)
413
+ pack_linear_weights(model_config)
414
+
415
+ weights = {}
416
+ # Layer config dict holds quantization format of each layer.
417
+ # It also holds awq_block_size information for applicable layers.
418
+ layer_config_dict = {}
419
+ model_config_dict = model_config_to_dict(model_config)
420
+ # We split the weights from model_config and save them separately as two files.
421
+ split_config_and_weights(model_config_dict, weights, "transformer", layer_config_dict)
422
+ # Process per layer quantization config dict
423
+ quant_config = process_layer_quant_config(layer_config_dict)
424
+ # We only export the json once across ranks as all jsons should be the same except for the rank.
425
+ tensorrt_llm_config = convert_to_tensorrt_llm_config(
426
+ model_config, quant_config, hf_config=hf_config
427
+ )
428
+
429
+ # Postprocess the tensors in the model_config.
430
+ # Exporting the safetensors also allows the tensor to be a view.
431
+ postprocess_tensors(
432
+ weights,
433
+ dtype=dtype,
434
+ force_cpu=True,
435
+ force_contiguous=True,
436
+ force_non_view=False,
437
+ )
438
+
439
+ yield tensorrt_llm_config, weights, quant_config
440
+
441
+
442
+ def export_tensorrt_llm_checkpoint(
443
+ model: nn.Module,
444
+ decoder_type: str,
445
+ dtype: torch.dtype | None = None,
446
+ export_dir: Path | str = tempfile.gettempdir(),
447
+ inference_tensor_parallel: int = 0,
448
+ inference_pipeline_parallel: int = 1,
449
+ use_nfs_workspace: bool = False,
450
+ ):
451
+ """Exports the torch model to the TensorRT-LLM checkpoint and save to the export_dir.
452
+
453
+ Args:
454
+ model: the torch model.
455
+ decoder_type: the type of the decoder, e.g. gpt, gptj, llama.
456
+ Please see the model_utils.py for the supported models.
457
+ dtype: the weights data type to export the unquantized layers or the default model data type if None.
458
+ export_dir: the target export path.
459
+ inference_tensor_parallel: The target inference time tensor parallel.
460
+ We will merge or split the calibration tensor parallelism to inference.
461
+ Default is 0, meaning using the calibration without manual config merge or split.
462
+ inference_pipeline_parallel: The target inference time pipeline parallel.
463
+ We will merge or split the calibration pipeline parallelism to inference.
464
+ Default is 1, meaning no pipeline parallelism.
465
+ inference_pipeline_parallel: The target inference time pipeline parallel.
466
+ use_nfs_workspace: if True, the an NFS workspace will be created under the export_dir and
467
+ used as a shared memory for cross process/node communication.
468
+
469
+ For tensorrt_llm deployment, save the representation under ``export_dir``.
470
+ We will save the model_config as two files:
471
+
472
+ * ``.json``: The nested dict that maps to the ``PretrainedConfig`` in TensorRT-LLM.
473
+ https://github.com/NVIDIA/TensorRT-LLM/blob/main/tensorrt_llm/models/modeling_utils.py.
474
+ * ``.safetensors``: The file for the list of weights as safetensors. Unique for each rank.
475
+ """
476
+ export_dir = Path(export_dir)
477
+ export_root = export_dir
478
+ export_dir.mkdir(parents=True, exist_ok=True)
479
+ # Create a NFS workspace under the export folder which is also assumed to be NFS.
480
+ workspace_path = None
481
+ if use_nfs_workspace:
482
+ workspace_path = export_dir.joinpath("workspace")
483
+ workspace_path.mkdir(parents=True, exist_ok=True)
484
+
485
+ try:
486
+ for (
487
+ tensorrt_llm_config,
488
+ weights,
489
+ quant_config,
490
+ ) in torch_to_tensorrt_llm_checkpoint(
491
+ model=model,
492
+ decoder_type=decoder_type,
493
+ dtype=dtype,
494
+ inference_tensor_parallel=inference_tensor_parallel,
495
+ inference_pipeline_parallel=inference_pipeline_parallel,
496
+ workspace_path=workspace_path,
497
+ ):
498
+ exclude_modules = set()
499
+ rank = tensorrt_llm_config["rank"]
500
+ world_size = tensorrt_llm_config["mapping"]["world_size"]
501
+ if tensorrt_llm_config["quantization"]:
502
+ excluded_modules_rank = tensorrt_llm_config["quantization"].get(
503
+ "exclude_modules", {}
504
+ )
505
+ if excluded_modules_rank:
506
+ exclude_modules.update(excluded_modules_rank)
507
+ # For Encoder-Decoder model
508
+ is_enc_dec = model_type_is_enc_dec(tensorrt_llm_config["decoder"])
509
+ if is_enc_dec:
510
+ export_dir = prepare_enc_dec_export_dir(tensorrt_llm_config, export_root)
511
+ export_dir = Path(export_dir)
512
+ export_dir.mkdir(parents=True, exist_ok=True)
513
+
514
+ if rank == world_size - 1:
515
+ # We only export the json once across ranks as all jsons should be the same except for the rank.
516
+ # If auto_quant is used, save per layer quantization information in quant_cfg.json
517
+ if "quantized_layers" in quant_config:
518
+ # Update auto quant related information for config.json export
519
+ # We remove group_size, has_zero_point, exclude_modules and pre_quant_scale information from config
520
+ tensorrt_llm_config["quantization"] = {
521
+ k: quant_config[k] for k in ("quant_algo", "kv_cache_quant_algo")
522
+ }
523
+ with open(export_dir / "quant_cfg.json", "w") as f:
524
+ json.dump(quant_config, f, indent=4)
525
+ else:
526
+ # Excluded modules information is only included in non auto_quant case
527
+ tensorrt_llm_config["quantization"]["exclude_modules"] = list(exclude_modules)
528
+
529
+ with open(export_dir / "config.json", "w") as f:
530
+ json.dump(tensorrt_llm_config, f, indent=4)
531
+
532
+ # Hacky implementation for Encoder-Decoder for now
533
+ if is_enc_dec:
534
+ new_weights = {}
535
+ for key in weights:
536
+ new_key = key
537
+ if key.endswith("rel_attn_table") and key.find(".0.") > 0:
538
+ # stores additional the relative attention for pre-compute feature in TRTLLM
539
+ new_weights["rel_attn_table"] = weights[key].clone()
540
+ new_weights[new_key] = weights[key]
541
+ weights = new_weights
542
+ # End of hacky implementation for Encoder-Decoder for now
543
+
544
+ weights_path = export_dir / f"rank{rank}.safetensors"
545
+ save_file(weights, weights_path)
546
+
547
+ except Exception as e:
548
+ warn(
549
+ "Cannot export model to the model_config. The modelopt-optimized model state_dict"
550
+ " can be saved with torch.save for further inspection."
551
+ )
552
+ raise e