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.
- modelopt/__init__.py +20 -0
- modelopt/deploy/__init__.py +16 -0
- modelopt/deploy/llm/__init__.py +30 -0
- modelopt/deploy/llm/generate.py +345 -0
- modelopt/onnx/__init__.py +34 -0
- modelopt/onnx/autocast/__init__.py +19 -0
- modelopt/onnx/autocast/__main__.py +187 -0
- modelopt/onnx/autocast/convert.py +202 -0
- modelopt/onnx/autocast/graphsanitizer.py +422 -0
- modelopt/onnx/autocast/logging_config.py +78 -0
- modelopt/onnx/autocast/nodeclassifier.py +416 -0
- modelopt/onnx/autocast/precisionconverter.py +1032 -0
- modelopt/onnx/autocast/referencerunner.py +159 -0
- modelopt/onnx/autocast/utils.py +117 -0
- modelopt/onnx/llm_export_utils/__init__.py +16 -0
- modelopt/onnx/llm_export_utils/export_utils.py +162 -0
- modelopt/onnx/llm_export_utils/quantization_utils.py +122 -0
- modelopt/onnx/llm_export_utils/surgeon_utils.py +120 -0
- modelopt/onnx/logging_config.py +77 -0
- modelopt/onnx/op_types.py +300 -0
- modelopt/onnx/quantization/__init__.py +20 -0
- modelopt/onnx/quantization/__main__.py +291 -0
- modelopt/onnx/quantization/calib_utils.py +178 -0
- modelopt/onnx/quantization/extensions.py +35 -0
- modelopt/onnx/quantization/fp8.py +375 -0
- modelopt/onnx/quantization/graph_utils.py +1479 -0
- modelopt/onnx/quantization/gs_patching.py +112 -0
- modelopt/onnx/quantization/int4.py +1347 -0
- modelopt/onnx/quantization/int8.py +283 -0
- modelopt/onnx/quantization/operators.py +121 -0
- modelopt/onnx/quantization/ort_patching.py +1766 -0
- modelopt/onnx/quantization/ort_utils.py +346 -0
- modelopt/onnx/quantization/partitioning.py +439 -0
- modelopt/onnx/quantization/qdq_utils.py +1349 -0
- modelopt/onnx/quantization/quant_utils.py +283 -0
- modelopt/onnx/quantization/quantize.py +528 -0
- modelopt/onnx/quantization/src/modelopt_round_and_pack_ext.cpp +127 -0
- modelopt/onnx/trt_utils.py +424 -0
- modelopt/onnx/utils.py +753 -0
- modelopt/torch/__init__.py +41 -0
- modelopt/torch/_deploy/__init__.py +23 -0
- modelopt/torch/_deploy/_runtime/__init__.py +29 -0
- modelopt/torch/_deploy/_runtime/common.py +72 -0
- modelopt/torch/_deploy/_runtime/ort_client.py +193 -0
- modelopt/torch/_deploy/_runtime/registry.py +83 -0
- modelopt/torch/_deploy/_runtime/runtime_client.py +154 -0
- modelopt/torch/_deploy/_runtime/tensorrt/constants.py +108 -0
- modelopt/torch/_deploy/_runtime/tensorrt/engine_builder.py +324 -0
- modelopt/torch/_deploy/_runtime/tensorrt/hw_param_config.py +51 -0
- modelopt/torch/_deploy/_runtime/tensorrt/layerwise_profiling.py +178 -0
- modelopt/torch/_deploy/_runtime/tensorrt/parse_trtexec_log.py +151 -0
- modelopt/torch/_deploy/_runtime/tensorrt/tensorrt_utils.py +200 -0
- modelopt/torch/_deploy/_runtime/trt_client.py +219 -0
- modelopt/torch/_deploy/compilation.py +142 -0
- modelopt/torch/_deploy/device_model.py +157 -0
- modelopt/torch/_deploy/profiling.py +193 -0
- modelopt/torch/_deploy/utils/__init__.py +18 -0
- modelopt/torch/_deploy/utils/onnx_optimizer.py +120 -0
- modelopt/torch/_deploy/utils/onnx_utils.py +58 -0
- modelopt/torch/_deploy/utils/torch_onnx.py +593 -0
- modelopt/torch/distill/__init__.py +28 -0
- modelopt/torch/distill/config.py +130 -0
- modelopt/torch/distill/distillation.py +84 -0
- modelopt/torch/distill/distillation_model.py +318 -0
- modelopt/torch/distill/loss_balancers.py +140 -0
- modelopt/torch/distill/losses.py +275 -0
- modelopt/torch/distill/mode.py +223 -0
- modelopt/torch/distill/plugins/__init__.py +24 -0
- modelopt/torch/distill/plugins/huggingface.py +110 -0
- modelopt/torch/distill/plugins/megatron.py +476 -0
- modelopt/torch/distill/registry.py +23 -0
- modelopt/torch/export/__init__.py +24 -0
- modelopt/torch/export/convert_hf_config.py +117 -0
- modelopt/torch/export/distribute.py +300 -0
- modelopt/torch/export/hf_config_map.py +84 -0
- modelopt/torch/export/layer_utils.py +1893 -0
- modelopt/torch/export/mcore_config_map.py +25 -0
- modelopt/torch/export/model_config.py +623 -0
- modelopt/torch/export/model_config_export.py +552 -0
- modelopt/torch/export/model_config_utils.py +392 -0
- modelopt/torch/export/model_utils.py +71 -0
- modelopt/torch/export/plugins/__init__.py +21 -0
- modelopt/torch/export/plugins/mcore_common.py +67 -0
- modelopt/torch/export/plugins/mcore_custom.py +530 -0
- modelopt/torch/export/plugins/mcore_deepseek.py +143 -0
- modelopt/torch/export/plugins/mcore_gptoss.py +71 -0
- modelopt/torch/export/plugins/mcore_llama.py +164 -0
- modelopt/torch/export/plugins/mcore_nemotron.py +90 -0
- modelopt/torch/export/plugins/mcore_qwen.py +99 -0
- modelopt/torch/export/plugins/megatron_importer.py +647 -0
- modelopt/torch/export/postprocess.py +847 -0
- modelopt/torch/export/quant_utils.py +1069 -0
- modelopt/torch/export/tensorrt_llm_type.py +42 -0
- modelopt/torch/export/tensorrt_llm_utils.py +405 -0
- modelopt/torch/export/transformer_engine.py +94 -0
- modelopt/torch/export/unified_export_hf.py +537 -0
- modelopt/torch/export/unified_export_megatron.py +1164 -0
- modelopt/torch/nas/__init__.py +27 -0
- modelopt/torch/nas/algorithms.py +856 -0
- modelopt/torch/nas/autonas.py +808 -0
- modelopt/torch/nas/conversion.py +119 -0
- modelopt/torch/nas/hparams/__init__.py +19 -0
- modelopt/torch/nas/hparams/concat.py +319 -0
- modelopt/torch/nas/hparams/container.py +48 -0
- modelopt/torch/nas/modules/__init__.py +21 -0
- modelopt/torch/nas/modules/container.py +99 -0
- modelopt/torch/nas/modules/conv.py +254 -0
- modelopt/torch/nas/modules/linear.py +76 -0
- modelopt/torch/nas/modules/norm.py +193 -0
- modelopt/torch/nas/modules/utils.py +61 -0
- modelopt/torch/nas/patch.py +261 -0
- modelopt/torch/nas/plugins/__init__.py +29 -0
- modelopt/torch/nas/plugins/megatron.py +1497 -0
- modelopt/torch/nas/plugins/torch.py +71 -0
- modelopt/torch/nas/plugins/transformer_engine.py +42 -0
- modelopt/torch/nas/plugins/transformers.py +210 -0
- modelopt/torch/nas/registry.py +23 -0
- modelopt/torch/nas/search_space.py +260 -0
- modelopt/torch/nas/traced_hp.py +149 -0
- modelopt/torch/nas/utils.py +408 -0
- modelopt/torch/opt/__init__.py +41 -0
- modelopt/torch/opt/_hooks.py +98 -0
- modelopt/torch/opt/config.py +383 -0
- modelopt/torch/opt/conversion.py +620 -0
- modelopt/torch/opt/dynamic.py +1367 -0
- modelopt/torch/opt/hparam.py +275 -0
- modelopt/torch/opt/mode.py +353 -0
- modelopt/torch/opt/plugins/__init__.py +38 -0
- modelopt/torch/opt/plugins/diffusers.py +40 -0
- modelopt/torch/opt/plugins/huggingface.py +162 -0
- modelopt/torch/opt/plugins/mcore_dist_checkpointing.py +211 -0
- modelopt/torch/opt/plugins/megatron.py +142 -0
- modelopt/torch/opt/plugins/peft.py +108 -0
- modelopt/torch/opt/plugins/transformers.py +160 -0
- modelopt/torch/opt/searcher.py +363 -0
- modelopt/torch/opt/utils.py +125 -0
- modelopt/torch/prune/__init__.py +26 -0
- modelopt/torch/prune/fastnas.py +376 -0
- modelopt/torch/prune/gradnas.py +349 -0
- modelopt/torch/prune/plugins/__init__.py +24 -0
- modelopt/torch/prune/plugins/mcore_minitron.py +263 -0
- modelopt/torch/prune/plugins/transformers.py +41 -0
- modelopt/torch/prune/pruning.py +211 -0
- modelopt/torch/quantization/__init__.py +26 -0
- modelopt/torch/quantization/algorithms.py +671 -0
- modelopt/torch/quantization/backends/__init__.py +20 -0
- modelopt/torch/quantization/backends/fp8_per_tensor_gemm.py +204 -0
- modelopt/torch/quantization/backends/gemm_registry.py +156 -0
- modelopt/torch/quantization/backends/nvfp4_gemm.py +201 -0
- modelopt/torch/quantization/backends/utils.py +28 -0
- modelopt/torch/quantization/calib/__init__.py +25 -0
- modelopt/torch/quantization/calib/bias.py +172 -0
- modelopt/torch/quantization/calib/calibrator.py +63 -0
- modelopt/torch/quantization/calib/histogram.py +434 -0
- modelopt/torch/quantization/calib/max.py +110 -0
- modelopt/torch/quantization/compress.py +227 -0
- modelopt/torch/quantization/config.py +1180 -0
- modelopt/torch/quantization/conversion.py +389 -0
- modelopt/torch/quantization/export_onnx.py +639 -0
- modelopt/torch/quantization/extensions.py +89 -0
- modelopt/torch/quantization/mode.py +428 -0
- modelopt/torch/quantization/model_calib.py +949 -0
- modelopt/torch/quantization/model_quant.py +477 -0
- modelopt/torch/quantization/nn/__init__.py +26 -0
- modelopt/torch/quantization/nn/functional.py +109 -0
- modelopt/torch/quantization/nn/modules/__init__.py +16 -0
- modelopt/torch/quantization/nn/modules/quant_activations.py +22 -0
- modelopt/torch/quantization/nn/modules/quant_batchnorm.py +24 -0
- modelopt/torch/quantization/nn/modules/quant_conv.py +123 -0
- modelopt/torch/quantization/nn/modules/quant_instancenorm.py +39 -0
- modelopt/torch/quantization/nn/modules/quant_linear.py +258 -0
- modelopt/torch/quantization/nn/modules/quant_module.py +211 -0
- modelopt/torch/quantization/nn/modules/quant_pooling.py +99 -0
- modelopt/torch/quantization/nn/modules/quant_rnn.py +527 -0
- modelopt/torch/quantization/nn/modules/tensor_quantizer.py +1293 -0
- modelopt/torch/quantization/plugins/__init__.py +73 -0
- modelopt/torch/quantization/plugins/accelerate.py +214 -0
- modelopt/torch/quantization/plugins/apex.py +52 -0
- modelopt/torch/quantization/plugins/attention.py +312 -0
- modelopt/torch/quantization/plugins/custom.py +192 -0
- modelopt/torch/quantization/plugins/diffusers.py +237 -0
- modelopt/torch/quantization/plugins/fairscale.py +45 -0
- modelopt/torch/quantization/plugins/huggingface.py +736 -0
- modelopt/torch/quantization/plugins/megatron.py +462 -0
- modelopt/torch/quantization/plugins/peft.py +148 -0
- modelopt/torch/quantization/plugins/transformer_engine.py +60 -0
- modelopt/torch/quantization/plugins/transformers.py +52 -0
- modelopt/torch/quantization/plugins/transformers_trainer.py +426 -0
- modelopt/torch/quantization/plugins/trl.py +27 -0
- modelopt/torch/quantization/plugins/vllm.py +199 -0
- modelopt/torch/quantization/qtensor/__init__.py +24 -0
- modelopt/torch/quantization/qtensor/base_qtensor.py +370 -0
- modelopt/torch/quantization/qtensor/fp8_tensor.py +151 -0
- modelopt/torch/quantization/qtensor/int4_tensor.py +130 -0
- modelopt/torch/quantization/qtensor/int8_tensor.py +124 -0
- modelopt/torch/quantization/qtensor/mxfp4_tensor.py +144 -0
- modelopt/torch/quantization/qtensor/nf4_tensor.py +199 -0
- modelopt/torch/quantization/qtensor/nvfp4_tensor.py +295 -0
- modelopt/torch/quantization/src/tensor_quant.cpp +77 -0
- modelopt/torch/quantization/src/tensor_quant.h +69 -0
- modelopt/torch/quantization/src/tensor_quant_fp8.cpp +48 -0
- modelopt/torch/quantization/src/tensor_quant_gpu.cu +361 -0
- modelopt/torch/quantization/src/tensor_quant_gpu_fp8.cu +122 -0
- modelopt/torch/quantization/src/tensor_quant_mx.cu +411 -0
- modelopt/torch/quantization/src/tensor_quant_mx.h +247 -0
- modelopt/torch/quantization/tensor_quant.py +816 -0
- modelopt/torch/quantization/triton/__init__.py +36 -0
- modelopt/torch/quantization/triton/fp4_kernel.py +303 -0
- modelopt/torch/quantization/utils.py +443 -0
- modelopt/torch/sparsity/__init__.py +19 -0
- modelopt/torch/sparsity/config.py +51 -0
- modelopt/torch/sparsity/magnitude.py +148 -0
- modelopt/torch/sparsity/mode.py +203 -0
- modelopt/torch/sparsity/module.py +87 -0
- modelopt/torch/sparsity/plugins/__init__.py +27 -0
- modelopt/torch/sparsity/plugins/megatron.py +93 -0
- modelopt/torch/sparsity/searcher.py +84 -0
- modelopt/torch/sparsity/sparsegpt.py +276 -0
- modelopt/torch/sparsity/sparsification.py +123 -0
- modelopt/torch/speculative/__init__.py +20 -0
- modelopt/torch/speculative/config.py +100 -0
- modelopt/torch/speculative/eagle/__init__.py +20 -0
- modelopt/torch/speculative/eagle/conversion.py +67 -0
- modelopt/torch/speculative/eagle/default_config.py +50 -0
- modelopt/torch/speculative/eagle/eagle_model.py +51 -0
- modelopt/torch/speculative/eagle/utils.py +91 -0
- modelopt/torch/speculative/medusa/__init__.py +19 -0
- modelopt/torch/speculative/medusa/conversion.py +59 -0
- modelopt/torch/speculative/medusa/medusa_model.py +32 -0
- modelopt/torch/speculative/mode.py +86 -0
- modelopt/torch/speculative/plugins/__init__.py +33 -0
- modelopt/torch/speculative/plugins/megatron_eagle.py +2119 -0
- modelopt/torch/speculative/plugins/megatron_medusa.py +312 -0
- modelopt/torch/speculative/plugins/transformers.py +1138 -0
- modelopt/torch/speculative/speculative_decoding.py +59 -0
- modelopt/torch/speculative/utils.py +364 -0
- modelopt/torch/trace/__init__.py +25 -0
- modelopt/torch/trace/analyzer.py +1368 -0
- modelopt/torch/trace/modules/__init__.py +19 -0
- modelopt/torch/trace/modules/concat.py +384 -0
- modelopt/torch/trace/modules/nn.py +153 -0
- modelopt/torch/trace/plugins/__init__.py +34 -0
- modelopt/torch/trace/plugins/megatron.py +36 -0
- modelopt/torch/trace/plugins/transformers.py +58 -0
- modelopt/torch/trace/symbols.py +545 -0
- modelopt/torch/trace/tracer.py +331 -0
- modelopt/torch/utils/__init__.py +28 -0
- modelopt/torch/utils/_pytree.py +133 -0
- modelopt/torch/utils/cpp_extension.py +91 -0
- modelopt/torch/utils/dataset_utils.py +484 -0
- modelopt/torch/utils/distributed.py +311 -0
- modelopt/torch/utils/graph.py +123 -0
- modelopt/torch/utils/image_processor.py +112 -0
- modelopt/torch/utils/import_utils.py +35 -0
- modelopt/torch/utils/list.py +54 -0
- modelopt/torch/utils/logging.py +127 -0
- modelopt/torch/utils/memory_monitor.py +146 -0
- modelopt/torch/utils/network.py +658 -0
- modelopt/torch/utils/perf.py +174 -0
- modelopt/torch/utils/plugins/__init__.py +27 -0
- modelopt/torch/utils/plugins/megatron_generate.py +299 -0
- modelopt/torch/utils/plugins/megatron_mmlu.py +152 -0
- modelopt/torch/utils/plugins/megatron_preprocess_data.py +200 -0
- modelopt/torch/utils/random.py +163 -0
- modelopt/torch/utils/speech_dataset_utils.py +134 -0
- modelopt/torch/utils/tensor.py +87 -0
- modelopt/torch/utils/vlm_dataset_utils.py +110 -0
- nvidia_modelopt-0.35.0.dist-info/METADATA +171 -0
- nvidia_modelopt-0.35.0.dist-info/RECORD +272 -0
- nvidia_modelopt-0.35.0.dist-info/WHEEL +5 -0
- nvidia_modelopt-0.35.0.dist-info/licenses/LICENSE +14 -0
- nvidia_modelopt-0.35.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 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
|
+
"""Reference runner module for ONNX model execution.
|
|
17
|
+
|
|
18
|
+
This module provides functionality for running ONNX models using ONNXRuntime as a reference
|
|
19
|
+
implementation. It supports both random input generation and user-provided inputs through
|
|
20
|
+
NPZ or Polygraphy JSON files. The runner is used to analyze model behavior and validate
|
|
21
|
+
outputs during precision conversion.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import copy
|
|
25
|
+
import io
|
|
26
|
+
import sys
|
|
27
|
+
from collections import OrderedDict
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
import onnx
|
|
31
|
+
|
|
32
|
+
from modelopt.onnx.autocast.logging_config import configure_logging, logger
|
|
33
|
+
from modelopt.onnx.quantization.ort_utils import _prepare_ep_list
|
|
34
|
+
|
|
35
|
+
configure_logging()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ReferenceRunner:
|
|
39
|
+
"""A class to run ONNX models with ONNXRuntime for reference inference."""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self, model: onnx.ModelProto, providers: list[str] = ["cpu"], trt_plugins: list[str] = []
|
|
43
|
+
):
|
|
44
|
+
"""Initialize with ONNX model path."""
|
|
45
|
+
self.model = model
|
|
46
|
+
self.input_names = [input.name for input in self.model.graph.input]
|
|
47
|
+
self.providers = self._prepare_ep_list_with_trt_plugin_path(providers, trt_plugins)
|
|
48
|
+
|
|
49
|
+
def _prepare_ep_list_with_trt_plugin_path(self, providers, trt_plugins):
|
|
50
|
+
providers = _prepare_ep_list(providers) or providers
|
|
51
|
+
if "TensorrtExecutionProvider" in providers:
|
|
52
|
+
providers.remove("TensorrtExecutionProvider")
|
|
53
|
+
# Ensure that the TRT EP is the first in the providers list to avoid fallback issues
|
|
54
|
+
trt_ep_options = (
|
|
55
|
+
{"trt_extra_plugin_lib_paths": ";".join(trt_plugins)} if trt_plugins else {}
|
|
56
|
+
)
|
|
57
|
+
providers.insert(0, ("TensorrtExecutionProvider", trt_ep_options))
|
|
58
|
+
logger.info(f"Successfully updated EPs for ORT: {providers}")
|
|
59
|
+
return providers
|
|
60
|
+
|
|
61
|
+
def _load_inputs_from_json(self, input_data_path):
|
|
62
|
+
"""Load inputs from Polygraphy JSON format."""
|
|
63
|
+
from polygraphy.json import load_json
|
|
64
|
+
|
|
65
|
+
return load_json(input_data_path, description="input data")
|
|
66
|
+
|
|
67
|
+
def _load_inputs_from_npz(self, input_data_path):
|
|
68
|
+
"""Load inputs from NPZ format."""
|
|
69
|
+
return [np.load(input_data_path)]
|
|
70
|
+
|
|
71
|
+
def _validate_inputs(self, data_loader):
|
|
72
|
+
"""Validate that input names match the model."""
|
|
73
|
+
if isinstance(data_loader, list) and (
|
|
74
|
+
isinstance(data_loader[0], (dict, np.lib.npyio.NpzFile))
|
|
75
|
+
):
|
|
76
|
+
if sorted(self.input_names) != sorted(data_loader[0].keys()):
|
|
77
|
+
raise ValueError("Input names from ONNX model do not match provided input names.")
|
|
78
|
+
else:
|
|
79
|
+
raise ValueError("Invalid input file.")
|
|
80
|
+
|
|
81
|
+
def _load_inputs(self, inputs):
|
|
82
|
+
"""Get data loader from inputs or create random data loader if no inputs provided."""
|
|
83
|
+
from polygraphy.comparator import DataLoader
|
|
84
|
+
|
|
85
|
+
# If no inputs are provided, use random inputs
|
|
86
|
+
data_loader = DataLoader(val_range={"": (-1, 1)})
|
|
87
|
+
|
|
88
|
+
if inputs is not None:
|
|
89
|
+
if isinstance(inputs, str):
|
|
90
|
+
if inputs.endswith(".json"):
|
|
91
|
+
data_loader = self._load_inputs_from_json(inputs)
|
|
92
|
+
elif inputs.endswith(".npz"):
|
|
93
|
+
data_loader = self._load_inputs_from_npz(inputs)
|
|
94
|
+
else:
|
|
95
|
+
raise ValueError(
|
|
96
|
+
f"Invalid input file: {inputs}. Supported input file types: .json (Polygraphy JSON format), "
|
|
97
|
+
".npz (Numpy)"
|
|
98
|
+
)
|
|
99
|
+
elif isinstance(inputs, (dict, OrderedDict)):
|
|
100
|
+
data_loader = [inputs]
|
|
101
|
+
else:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
f"Invalid input type: {type(inputs)}. Supported input types: dict, OrderedDict, or a path to a "
|
|
104
|
+
"JSON or NPZ file."
|
|
105
|
+
)
|
|
106
|
+
self._validate_inputs(data_loader)
|
|
107
|
+
|
|
108
|
+
return data_loader
|
|
109
|
+
|
|
110
|
+
def run(self, inputs=None):
|
|
111
|
+
"""Run FP32 inference with provided or random inputs."""
|
|
112
|
+
import onnxruntime as ort
|
|
113
|
+
from polygraphy import constants
|
|
114
|
+
from polygraphy.backend.onnx import BytesFromOnnx
|
|
115
|
+
from polygraphy.backend.onnx import ModifyOutputs as ModifyOnnxOutputs
|
|
116
|
+
from polygraphy.backend.onnxrt import OnnxrtRunner, SessionFromOnnx
|
|
117
|
+
from polygraphy.comparator import Comparator
|
|
118
|
+
|
|
119
|
+
logger.info("Running ONNX Runtime to obtain reference outputs (this may take a while)...")
|
|
120
|
+
# Set ONNX Runtime log level to ERROR to suppress warnings
|
|
121
|
+
ort.set_default_logger_severity(3)
|
|
122
|
+
|
|
123
|
+
model_copy = copy.deepcopy(self.model)
|
|
124
|
+
modify_outputs = ModifyOnnxOutputs(model_copy, outputs=constants.MARK_ALL)
|
|
125
|
+
serialize_onnx = BytesFromOnnx(modify_outputs)
|
|
126
|
+
build_onnxrt_session = SessionFromOnnx(serialize_onnx, providers=self.providers)
|
|
127
|
+
runners = [OnnxrtRunner(build_onnxrt_session)]
|
|
128
|
+
|
|
129
|
+
# Comparator is used despite the fact that we are using ONNXRuntime
|
|
130
|
+
# because it provides the ability to generate random inputs using DataLoader
|
|
131
|
+
data_loader = self._load_inputs(inputs)
|
|
132
|
+
|
|
133
|
+
# Temporarily redirect stdout to suppress Comparator.run() output
|
|
134
|
+
stdout = sys.stdout
|
|
135
|
+
string_buffer = io.StringIO()
|
|
136
|
+
sys.stdout = string_buffer
|
|
137
|
+
try:
|
|
138
|
+
results = Comparator.run(runners, data_loader=data_loader)
|
|
139
|
+
finally:
|
|
140
|
+
# Capture the output before restoring stdout
|
|
141
|
+
captured_output = string_buffer.getvalue()
|
|
142
|
+
sys.stdout = stdout
|
|
143
|
+
|
|
144
|
+
if not results:
|
|
145
|
+
logger.error(f"ONNXRuntime execution failed with output:\n{captured_output}")
|
|
146
|
+
raise Exception("ONNXRuntime failed to run, see logs for details")
|
|
147
|
+
|
|
148
|
+
# Get the output results
|
|
149
|
+
output_dict = OrderedDict(results[0][1][0])
|
|
150
|
+
|
|
151
|
+
# Include input data for completeness
|
|
152
|
+
input_data = next(iter(data_loader))
|
|
153
|
+
|
|
154
|
+
# Combine inputs and outputs in the returned dictionary
|
|
155
|
+
combined_dict = OrderedDict()
|
|
156
|
+
combined_dict.update(input_data)
|
|
157
|
+
combined_dict.update(output_dict)
|
|
158
|
+
|
|
159
|
+
return combined_dict
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 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
|
+
"""Utility functions for AutoCast.
|
|
17
|
+
|
|
18
|
+
This module provides common utility functions used across the AutoCast package.
|
|
19
|
+
It includes functions for graph traversal, tensor type inference, model validation,
|
|
20
|
+
and mapping setup between nodes, initializers, and value info. These utilities
|
|
21
|
+
support the core functionality of model precision conversion.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import onnx
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def setup_mappings(model: onnx.ModelProto) -> tuple[dict, dict, dict]:
|
|
28
|
+
"""Setup and return mappings for model components.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
model: ONNX model to create mappings for.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Tuple containing:
|
|
35
|
+
- value_info_map: Mapping of names to value infos.
|
|
36
|
+
- initializer_map: Mapping of names to initializers.
|
|
37
|
+
- node_to_init_map: Mapping of node names to their initializer inputs.
|
|
38
|
+
"""
|
|
39
|
+
value_info_map = {}
|
|
40
|
+
for container in (model.graph.value_info, model.graph.input, model.graph.output):
|
|
41
|
+
value_info_map.update((vi.name, vi) for vi in container)
|
|
42
|
+
|
|
43
|
+
initializer_map = {init.name: init for init in model.graph.initializer}
|
|
44
|
+
|
|
45
|
+
node_to_init_map = {
|
|
46
|
+
node.name: [
|
|
47
|
+
initializer_map[input_name]
|
|
48
|
+
for input_name in node.input
|
|
49
|
+
if input_name in initializer_map
|
|
50
|
+
]
|
|
51
|
+
for node in model.graph.node
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return value_info_map, initializer_map, node_to_init_map
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_consumer_nodes(model: onnx.ModelProto, tensor_name: str) -> list[onnx.NodeProto]:
|
|
58
|
+
"""Get all consumer nodes for a given tensor name.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
model: The ONNX model to search.
|
|
62
|
+
tensor_name: Name of the tensor to find consumers for.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
list[onnx.NodeProto]: List of nodes that consume the tensor.
|
|
66
|
+
"""
|
|
67
|
+
return [n for n in model.graph.node if tensor_name in n.input]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_producer_nodes(model: onnx.ModelProto, tensor_name: str) -> list[onnx.NodeProto]:
|
|
71
|
+
"""Get all producer nodes for a given tensor name.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
model: The ONNX model to search.
|
|
75
|
+
tensor_name: Name of the tensor to find producers for.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
list[onnx.NodeProto]: List of nodes that produce the tensor.
|
|
79
|
+
"""
|
|
80
|
+
return [n for n in model.graph.node if tensor_name in n.output]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_unique_consumer_node(model: onnx.ModelProto, tensor_name: str) -> onnx.NodeProto:
|
|
84
|
+
"""Get a single consumer node and raise exception if there are multiple consumers.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
model: The ONNX model to search.
|
|
88
|
+
tensor_name: Name of the tensor to find consumer for.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
onnx.NodeProto: The single consumer node.
|
|
92
|
+
|
|
93
|
+
Raises:
|
|
94
|
+
Exception: If there is not exactly one consumer node.
|
|
95
|
+
"""
|
|
96
|
+
consumers = get_consumer_nodes(model, tensor_name)
|
|
97
|
+
if len(consumers) != 1:
|
|
98
|
+
raise Exception(f"Expected single consumer for {tensor_name}, found {len(consumers)}")
|
|
99
|
+
return consumers[0]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_cast_to_type(cast_node: onnx.NodeProto) -> int:
|
|
103
|
+
"""Get the target type from a Cast node.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
cast_node: The Cast node to extract type from.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
int: The target type value from the Cast node's 'to' attribute.
|
|
110
|
+
|
|
111
|
+
Raises:
|
|
112
|
+
ValueError: If the Cast node does not have a 'to' attribute.
|
|
113
|
+
"""
|
|
114
|
+
for attr in cast_node.attribute:
|
|
115
|
+
if attr.name == "to":
|
|
116
|
+
return attr.i
|
|
117
|
+
raise ValueError("Cast node does not have 'to' attribute")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2023-2025 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
|
+
"""Utilities for exporting LLM models to ONNX."""
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2023-2025 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
|
+
"""Utilities for exporting LLM models to ONNX."""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
import time
|
|
21
|
+
from enum import Enum
|
|
22
|
+
|
|
23
|
+
import torch
|
|
24
|
+
from transformers import DynamicCache
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RopeType(Enum):
|
|
28
|
+
"""Rope type enum."""
|
|
29
|
+
|
|
30
|
+
K_NONE = 0
|
|
31
|
+
K_ROPE_ROTATE_GPTJ = 1
|
|
32
|
+
K_ROPE_ROTATE_NEOX = 2
|
|
33
|
+
K_MROPE = 3
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ModelLoader:
|
|
37
|
+
"""A class to handle HuggingFace model loading and configuration."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, torch_dir, config_path):
|
|
40
|
+
"""Initialize the ModelLoader."""
|
|
41
|
+
self.config_path = config_path
|
|
42
|
+
self.torch_dir = torch_dir
|
|
43
|
+
self.model_type = self.get_model_type()
|
|
44
|
+
self.hf_model = None
|
|
45
|
+
self.rope_type = RopeType.K_ROPE_ROTATE_NEOX
|
|
46
|
+
|
|
47
|
+
def get_model_type(self):
|
|
48
|
+
"""Get model type from config file."""
|
|
49
|
+
with open(self.config_path) as f:
|
|
50
|
+
return json.load(f).get("model_type")
|
|
51
|
+
|
|
52
|
+
def load_model(self):
|
|
53
|
+
"""Load HuggingFace model based on model type."""
|
|
54
|
+
print(f"Loading HF model from {self.torch_dir} with model type {self.model_type}")
|
|
55
|
+
from transformers import AutoModelForCausalLM
|
|
56
|
+
|
|
57
|
+
self.hf_model = AutoModelForCausalLM.from_pretrained(
|
|
58
|
+
self.torch_dir, torch_dtype=torch.float16, trust_remote_code=True
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return self.hf_model.eval().cuda()
|
|
62
|
+
|
|
63
|
+
def get_rope_type(self):
|
|
64
|
+
"""Get rope type."""
|
|
65
|
+
return self.rope_type
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class WrapperModelForCausalLM(torch.nn.Module):
|
|
69
|
+
"""Wrapper Model to ensure all models have the same I/O."""
|
|
70
|
+
|
|
71
|
+
def __init__(self, model):
|
|
72
|
+
"""Initialize the WrapperModelForCausalLM."""
|
|
73
|
+
super().__init__()
|
|
74
|
+
try:
|
|
75
|
+
self.model = model.model
|
|
76
|
+
except Exception:
|
|
77
|
+
self.model = model
|
|
78
|
+
self.lm_head = model.lm_head
|
|
79
|
+
self.config = model.config
|
|
80
|
+
|
|
81
|
+
def forward(
|
|
82
|
+
self,
|
|
83
|
+
input_ids,
|
|
84
|
+
past_key_values,
|
|
85
|
+
):
|
|
86
|
+
"""Forward pass."""
|
|
87
|
+
past_key_values = DynamicCache.from_legacy_cache(past_key_values)
|
|
88
|
+
outputs = self.model(input_ids=input_ids, past_key_values=past_key_values, use_cache=True)
|
|
89
|
+
hidden_states = outputs[0]
|
|
90
|
+
past_key_values = outputs.past_key_values.to_legacy_cache()
|
|
91
|
+
logits = self.lm_head(hidden_states)
|
|
92
|
+
return logits, past_key_values
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def llm_to_onnx(model, output_dir, extra_inputs={}, extra_dyn_axes={}):
|
|
96
|
+
"""Export the WrapperModelForCausalLM to ONNX with fixed I/O names and shape definitions and save to `output_dir`.
|
|
97
|
+
|
|
98
|
+
Parameters:
|
|
99
|
+
model: torch.Module
|
|
100
|
+
output_dir: str, the output_dir of the original ONNX.
|
|
101
|
+
extra_inputs: dict, append additional inputs after kv_cache. Usually for VL models
|
|
102
|
+
extra_dyn_axes: dict. Usually for VL models
|
|
103
|
+
"""
|
|
104
|
+
start_time = time.time()
|
|
105
|
+
config = model.config
|
|
106
|
+
num_layers = config.num_hidden_layers
|
|
107
|
+
num_attention_heads = config.num_attention_heads
|
|
108
|
+
num_key_value_heads = config.num_key_value_heads
|
|
109
|
+
hidden_size = config.hidden_size
|
|
110
|
+
hidden_size_per_layer = hidden_size // num_attention_heads
|
|
111
|
+
|
|
112
|
+
dummy_bs = 1
|
|
113
|
+
dummy_len = 10
|
|
114
|
+
dummy_input_ids = torch.randint(100, (dummy_bs, dummy_len), dtype=torch.int64).cuda()
|
|
115
|
+
input_names = ["input_ids"]
|
|
116
|
+
output_names = ["logits"]
|
|
117
|
+
dynamic_axes = {"input_ids": {0: "batch_size", 1: "seq_len"}}
|
|
118
|
+
dummy_kv_cache = ()
|
|
119
|
+
for i in range(num_layers):
|
|
120
|
+
dummy_k = torch.rand(
|
|
121
|
+
(dummy_bs, num_key_value_heads, dummy_len, hidden_size_per_layer), dtype=torch.float16
|
|
122
|
+
).cuda()
|
|
123
|
+
dummy_v = torch.rand(
|
|
124
|
+
(dummy_bs, num_key_value_heads, dummy_len, hidden_size_per_layer), dtype=torch.float16
|
|
125
|
+
).cuda()
|
|
126
|
+
dummy_kv_cache = (*dummy_kv_cache, (dummy_k, dummy_v))
|
|
127
|
+
input_names.extend([f"past_key_values.{i}.key", f"past_key_values.{i}.value"])
|
|
128
|
+
output_names.extend([f"present_key_values.{i}.key", f"present_key_values.{i}.value"])
|
|
129
|
+
input_dynamic_axes = {0: "batch_size", 2: "past_len"}
|
|
130
|
+
dynamic_axes[f"past_key_values.{i}.key"] = input_dynamic_axes
|
|
131
|
+
dynamic_axes[f"past_key_values.{i}.value"] = input_dynamic_axes
|
|
132
|
+
|
|
133
|
+
torch_to_onnx(
|
|
134
|
+
model,
|
|
135
|
+
(dummy_input_ids, {"past_key_values": dummy_kv_cache, **extra_inputs}),
|
|
136
|
+
output_dir,
|
|
137
|
+
"model.onnx",
|
|
138
|
+
input_names=input_names + list(extra_inputs.keys()),
|
|
139
|
+
output_names=output_names,
|
|
140
|
+
dynamic_axes=dynamic_axes | extra_dyn_axes,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
end_time = time.time()
|
|
144
|
+
print(
|
|
145
|
+
f"Native ONNX Export from torch completed in {end_time - start_time}s. ONNX file is saved to {output_dir}."
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def torch_to_onnx(model, inputs, onnx_dir, onnx_name, input_names, output_names, dynamic_axes):
|
|
150
|
+
"""Export the model to ONNX."""
|
|
151
|
+
os.makedirs(onnx_dir, exist_ok=True)
|
|
152
|
+
with torch.inference_mode():
|
|
153
|
+
torch.onnx.export(
|
|
154
|
+
model,
|
|
155
|
+
inputs,
|
|
156
|
+
f"{onnx_dir}/{onnx_name}",
|
|
157
|
+
input_names=input_names,
|
|
158
|
+
output_names=output_names,
|
|
159
|
+
dynamic_axes=dynamic_axes,
|
|
160
|
+
opset_version=19,
|
|
161
|
+
do_constant_folding=True,
|
|
162
|
+
)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2023-2025 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
|
+
"""Quantization utilities for LLM models."""
|
|
17
|
+
|
|
18
|
+
import time
|
|
19
|
+
|
|
20
|
+
import modelopt.torch.quantization as mtq
|
|
21
|
+
from modelopt.torch.utils.dataset_utils import get_dataset_dataloader
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _quantize_model(model, quant_config, calib_dataloader=None):
|
|
25
|
+
"""The calibration loop for the model can be setup using the modelopt API.
|
|
26
|
+
|
|
27
|
+
Example usage:
|
|
28
|
+
from modelopt.torch.utils.dataset_utils import create_forward_loop
|
|
29
|
+
model = ... # Initialize the model
|
|
30
|
+
tokenizer = ... # Initialize the tokenizer
|
|
31
|
+
quant_cfg = ... # Setup quantization configuration
|
|
32
|
+
forward_loop = create_forward_loop(model=model, dataset_name="cnn_dailymail", tokenizer=tokenizer)
|
|
33
|
+
mtq.quantize(model, quant_cfg, forward_loop=forward_loop)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def calibrate_loop(model):
|
|
37
|
+
"""Adjusts weights and scaling factors based on selected algorithms."""
|
|
38
|
+
for idx, data in enumerate(calib_dataloader):
|
|
39
|
+
if idx % 10 == 0:
|
|
40
|
+
print(f"Calibrating batch {idx}...")
|
|
41
|
+
if isinstance(data, dict):
|
|
42
|
+
data = {k: v.to(model.device) for k, v in data.items()}
|
|
43
|
+
model(**data)
|
|
44
|
+
else:
|
|
45
|
+
data = data.to(model.device)
|
|
46
|
+
model(data)
|
|
47
|
+
|
|
48
|
+
print("Starting quantization...")
|
|
49
|
+
start_time = time.time()
|
|
50
|
+
mtq.quantize(model, quant_config, forward_loop=calibrate_loop)
|
|
51
|
+
end_time = time.time()
|
|
52
|
+
print(f"Quantization finishes in {end_time - start_time}s.")
|
|
53
|
+
|
|
54
|
+
return model
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_quant_config(precision, lm_head_precision="fp16"):
|
|
58
|
+
"""Get the quantization configuration."""
|
|
59
|
+
if precision == "fp8":
|
|
60
|
+
quant_cfg = mtq.FP8_DEFAULT_CFG
|
|
61
|
+
|
|
62
|
+
elif precision == "nvfp4":
|
|
63
|
+
quant_cfg = mtq.NVFP4_DEFAULT_CFG
|
|
64
|
+
|
|
65
|
+
elif precision == "int4_awq":
|
|
66
|
+
quant_cfg = mtq.INT4_AWQ_CFG
|
|
67
|
+
|
|
68
|
+
else:
|
|
69
|
+
raise ValueError(f"Unsupported precision: {precision}")
|
|
70
|
+
|
|
71
|
+
config_dict = quant_cfg["quant_cfg"] # type: dict
|
|
72
|
+
|
|
73
|
+
if lm_head_precision == "fp8":
|
|
74
|
+
config_dict["*lm_head.input_quantizer"] = {"num_bits": (4, 3), "axis": None}
|
|
75
|
+
config_dict["*lm_head.weight_quantizer"] = {"num_bits": (4, 3), "axis": None}
|
|
76
|
+
elif lm_head_precision == "nvfp4":
|
|
77
|
+
config_dict["*lm_head.input_quantizer"] = {
|
|
78
|
+
"num_bits": (2, 1),
|
|
79
|
+
"block_sizes": {-1: 16, "type": "dynamic", "scale_bits": (4, 3)},
|
|
80
|
+
"axis": None,
|
|
81
|
+
"enable": True,
|
|
82
|
+
}
|
|
83
|
+
config_dict["*lm_head.weight_quantizer"] = {
|
|
84
|
+
"num_bits": (2, 1),
|
|
85
|
+
"block_sizes": {-1: 16, "type": "dynamic", "scale_bits": (4, 3)},
|
|
86
|
+
"axis": None,
|
|
87
|
+
"enable": True,
|
|
88
|
+
}
|
|
89
|
+
return quant_cfg
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def quantize(
|
|
93
|
+
model, tokenizer, precision, lm_head_precision="fp16", dataset_dir=None, calib_size=512
|
|
94
|
+
):
|
|
95
|
+
"""Quantize the PyTorch model to fp8 or int4_awq."""
|
|
96
|
+
assert precision in [
|
|
97
|
+
"fp8",
|
|
98
|
+
"int4_awq",
|
|
99
|
+
"nvfp4",
|
|
100
|
+
], (
|
|
101
|
+
f"Only fp8(W8A8), int4_awq(W4A16), nvfp4(W4A4) is supported. You passed an unsupported precision: {precision}."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
assert lm_head_precision in ["fp16"], (
|
|
105
|
+
f"Only fp16(unquantized) is supported for lm_head. You passed an unsupported precision: {lm_head_precision}."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if tokenizer.pad_token != "<unk>": # nosec B105
|
|
109
|
+
tokenizer.pad_token = tokenizer.eos_token
|
|
110
|
+
if tokenizer.pad_token is None:
|
|
111
|
+
tokenizer.pad_token = tokenizer.eos_token
|
|
112
|
+
if not dataset_dir:
|
|
113
|
+
dataset_dir = "cnn_dailymail"
|
|
114
|
+
|
|
115
|
+
batch_size = 1
|
|
116
|
+
data_loader = get_dataset_dataloader(
|
|
117
|
+
dataset_name=dataset_dir, tokenizer=tokenizer, batch_size=batch_size, num_samples=calib_size
|
|
118
|
+
)
|
|
119
|
+
quant_config = get_quant_config(precision, lm_head_precision)
|
|
120
|
+
quantized_model = _quantize_model(model, quant_config, data_loader)
|
|
121
|
+
mtq.print_quant_summary(quantized_model)
|
|
122
|
+
return quantized_model
|