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,1138 @@
|
|
|
1
|
+
# Adapted from: https://github.com/ctlllll/axolotl/blob/f86767e/src/axolotl/monkeypatch/medusa_utils.py
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
16
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
17
|
+
#
|
|
18
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
19
|
+
# you may not use this file except in compliance with the License.
|
|
20
|
+
# You may obtain a copy of the License at
|
|
21
|
+
#
|
|
22
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
23
|
+
#
|
|
24
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
25
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
26
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
27
|
+
# See the License for the specific language governing permissions and
|
|
28
|
+
# limitations under the License.
|
|
29
|
+
|
|
30
|
+
"""Support speculative decoding for huggingface models."""
|
|
31
|
+
|
|
32
|
+
import contextlib
|
|
33
|
+
import copy
|
|
34
|
+
from typing import Any
|
|
35
|
+
|
|
36
|
+
import torch
|
|
37
|
+
from torch import nn
|
|
38
|
+
from torch.nn import CrossEntropyLoss
|
|
39
|
+
from transformers import Cache, DynamicCache, PretrainedConfig, PreTrainedModel
|
|
40
|
+
from transformers.models.llama.modeling_llama import (
|
|
41
|
+
LlamaAttention,
|
|
42
|
+
LlamaDecoderLayer,
|
|
43
|
+
LlamaRMSNorm,
|
|
44
|
+
LlamaRotaryEmbedding,
|
|
45
|
+
)
|
|
46
|
+
from transformers.trainer_pt_utils import LabelSmoother
|
|
47
|
+
from transformers.utils import ModelOutput
|
|
48
|
+
|
|
49
|
+
from ..eagle.conversion import EagleDMRegistry, OfflineEagleDMRegistry
|
|
50
|
+
from ..eagle.eagle_model import EagleModel
|
|
51
|
+
from ..eagle.utils import RMSNorm, expand_mask, make_causal_mask
|
|
52
|
+
from ..medusa.conversion import MedusaDMRegistry
|
|
53
|
+
from ..medusa.medusa_model import MedusaModel
|
|
54
|
+
from ..utils import AcceptanceRateValidation, ResBlock
|
|
55
|
+
|
|
56
|
+
IGNORE_TOKEN_ID = LabelSmoother.ignore_index
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@MedusaDMRegistry.register({PreTrainedModel: "hf.PreTrainedModel"})
|
|
60
|
+
class HFMedusaModel(MedusaModel):
|
|
61
|
+
"""Medusa Model Class for huggingface models."""
|
|
62
|
+
|
|
63
|
+
def modify(self, medusa_num_heads=0, medusa_num_layers=0):
|
|
64
|
+
"""Constructor.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
medusa_num_heads: number of medusa heads.
|
|
68
|
+
medusa_num_layers: number of ResBlock layers in each head.
|
|
69
|
+
"""
|
|
70
|
+
super().modify(medusa_num_heads=medusa_num_heads, medusa_num_layers=medusa_num_layers)
|
|
71
|
+
self.config.medusa = {
|
|
72
|
+
"num_medusa_heads": medusa_num_heads,
|
|
73
|
+
"num_medusa_layers": medusa_num_layers,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
hidden_size = self.lm_head.weight.shape[-1]
|
|
77
|
+
vocab_size = self.lm_head.weight.shape[0]
|
|
78
|
+
|
|
79
|
+
# Create a list of Medusa heads
|
|
80
|
+
self.medusa_heads = nn.ModuleList(
|
|
81
|
+
[
|
|
82
|
+
nn.Sequential(
|
|
83
|
+
*([ResBlock(hidden_size)] * self.medusa_num_layers),
|
|
84
|
+
nn.Linear(hidden_size, vocab_size, bias=False),
|
|
85
|
+
)
|
|
86
|
+
for _ in range(self.medusa_num_heads)
|
|
87
|
+
]
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Ensure medusa_head's dtype and device align with the base_model
|
|
91
|
+
self.medusa_heads.to(self.lm_head.weight.dtype).to(self.lm_head.weight.device)
|
|
92
|
+
self.medusa_heads.device = self.lm_head.weight.device
|
|
93
|
+
if hasattr(self, "hf_device_map") and "lm_head" in self.hf_device_map:
|
|
94
|
+
self.hf_device_map["medusa_heads"] = self.hf_device_map["lm_head"]
|
|
95
|
+
|
|
96
|
+
def forward(
|
|
97
|
+
self,
|
|
98
|
+
input_ids: torch.LongTensor | None = None,
|
|
99
|
+
attention_mask: torch.Tensor | None = None,
|
|
100
|
+
position_ids: torch.LongTensor | None = None,
|
|
101
|
+
past_key_values: Cache | None = None,
|
|
102
|
+
inputs_embeds: torch.FloatTensor | None = None,
|
|
103
|
+
labels: torch.LongTensor | None = None,
|
|
104
|
+
use_cache: bool | None = None,
|
|
105
|
+
output_attentions: bool | None = None,
|
|
106
|
+
output_hidden_states: bool | None = None,
|
|
107
|
+
cache_position: torch.LongTensor | None = None,
|
|
108
|
+
logits_to_keep: int | torch.Tensor = 0,
|
|
109
|
+
freeze_base_model: bool = True,
|
|
110
|
+
medusa_heads_coefficient: float | None = 0.2,
|
|
111
|
+
medusa_decay_coefficient: float | None = 0.8,
|
|
112
|
+
**kwargs,
|
|
113
|
+
) -> Any:
|
|
114
|
+
"""Forward pass of the MedusaModel.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
torch.Tensor: A tensor containing predictions from all Medusa heads.
|
|
118
|
+
"""
|
|
119
|
+
# Pass input through the base model
|
|
120
|
+
with torch.no_grad() if freeze_base_model else contextlib.nullcontext():
|
|
121
|
+
outputs = self.model(
|
|
122
|
+
input_ids=input_ids,
|
|
123
|
+
attention_mask=attention_mask,
|
|
124
|
+
position_ids=position_ids,
|
|
125
|
+
past_key_values=past_key_values,
|
|
126
|
+
inputs_embeds=inputs_embeds,
|
|
127
|
+
use_cache=use_cache,
|
|
128
|
+
output_attentions=output_attentions,
|
|
129
|
+
output_hidden_states=output_hidden_states,
|
|
130
|
+
rcache_position=cache_position,
|
|
131
|
+
**kwargs,
|
|
132
|
+
)
|
|
133
|
+
hidden_states = outputs.last_hidden_state
|
|
134
|
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
|
135
|
+
slice_indices = (
|
|
136
|
+
slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
|
137
|
+
)
|
|
138
|
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
|
139
|
+
|
|
140
|
+
medusa_logits = [
|
|
141
|
+
self.medusa_heads[i](hidden_states[:, slice_indices, :])
|
|
142
|
+
for i in range(self.medusa_num_heads)
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
if labels is not None:
|
|
146
|
+
loss = 0
|
|
147
|
+
loss_fct = CrossEntropyLoss()
|
|
148
|
+
# Base model loss
|
|
149
|
+
if not freeze_base_model:
|
|
150
|
+
loss_logits = logits.view(-1, logits.shape[-1])
|
|
151
|
+
loss_labels = labels.view(-1)
|
|
152
|
+
base_model_loss = loss_fct(loss_logits, loss_labels)
|
|
153
|
+
loss += base_model_loss
|
|
154
|
+
# Medusa loss
|
|
155
|
+
for i in range(self.medusa_num_heads):
|
|
156
|
+
labels = labels[..., 1:].contiguous()
|
|
157
|
+
loss_logits = medusa_logits[i][:, : -(1 + i)].contiguous()
|
|
158
|
+
loss_logits = loss_logits.view(-1, loss_logits.shape[-1])
|
|
159
|
+
loss_labels = labels.view(-1)
|
|
160
|
+
loss += (
|
|
161
|
+
loss_fct(loss_logits, loss_labels)
|
|
162
|
+
* medusa_decay_coefficient**i
|
|
163
|
+
* medusa_heads_coefficient
|
|
164
|
+
)
|
|
165
|
+
else:
|
|
166
|
+
loss = None
|
|
167
|
+
|
|
168
|
+
return ModelOutput(
|
|
169
|
+
loss=loss,
|
|
170
|
+
logits=logits,
|
|
171
|
+
medusa_logits=medusa_logits,
|
|
172
|
+
past_key_values=outputs.past_key_values,
|
|
173
|
+
hidden_states=outputs.hidden_states,
|
|
174
|
+
attentions=outputs.attentions,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class EagleModule(nn.Module):
|
|
179
|
+
"""Eagle module used in EAGLE model."""
|
|
180
|
+
|
|
181
|
+
def __init__(self, config, decoder_layer_cls, bias=False):
|
|
182
|
+
"""Init function for EagleModule."""
|
|
183
|
+
super().__init__()
|
|
184
|
+
self.config = config
|
|
185
|
+
|
|
186
|
+
# NOTE:This is a temporary fix to support Qwen and Mixtral in current release.
|
|
187
|
+
# This is refactored in following MR.
|
|
188
|
+
config_overwrite = {
|
|
189
|
+
"mlp_bias": False,
|
|
190
|
+
"attention_bias": False,
|
|
191
|
+
"head_dim": self.config.hidden_size // self.config.num_attention_heads,
|
|
192
|
+
}
|
|
193
|
+
for key, value in config_overwrite.items():
|
|
194
|
+
setattr(self.config, key, value)
|
|
195
|
+
|
|
196
|
+
self.layers = nn.ModuleList(
|
|
197
|
+
[decoder_layer_cls(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
|
198
|
+
)
|
|
199
|
+
if config.use_last_layernorm:
|
|
200
|
+
self.norm = RMSNorm(config.hidden_size, config.rms_norm_eps)
|
|
201
|
+
|
|
202
|
+
# Optionally, we use a smaller vocab table for eagle module
|
|
203
|
+
if config.draft_vocab_size != config.vocab_size or config.has_lm_head:
|
|
204
|
+
# Need an extra lm_head for eagle module since vocab size is reduced.
|
|
205
|
+
assert config.draft_vocab_size <= config.vocab_size, (
|
|
206
|
+
"EAGLE module's vocab size should be <= base model vocab size!"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Initialize the buffers to zero.
|
|
210
|
+
# Their values depend on specific tokenzier and calibrate dataset, and should be set in training script.
|
|
211
|
+
if config.draft_vocab_size < config.vocab_size:
|
|
212
|
+
self.register_buffer("d2t", torch.zeros(config.draft_vocab_size, dtype=torch.int64))
|
|
213
|
+
self.eagle_lm_head = nn.Linear(
|
|
214
|
+
config.hidden_size,
|
|
215
|
+
config.draft_vocab_size,
|
|
216
|
+
bias=False,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
if not config.use_aux_hidden_state:
|
|
220
|
+
# In Eagle-1, the FC concentrate input embeddings and hidden states
|
|
221
|
+
self.fc = nn.Linear(2 * config.hidden_size, config.hidden_size, bias=bias)
|
|
222
|
+
else:
|
|
223
|
+
# In EAGLE-3, the FC concentrate hidden states from multiple base model layers
|
|
224
|
+
self.fc = nn.Linear(
|
|
225
|
+
len(config.eagle_aux_hidden_state_layer_ids) * config.hidden_size,
|
|
226
|
+
config.hidden_size,
|
|
227
|
+
bias=bias,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
first_layer_attn = self.layers[0].self_attn
|
|
231
|
+
if not isinstance(first_layer_attn, LlamaAttention):
|
|
232
|
+
raise ValueError("EAGLE-3 only support LlamaAttention.")
|
|
233
|
+
|
|
234
|
+
# EAGLE-3's first attention require [input_layernorm_output, aux_hidden_states]
|
|
235
|
+
first_layer_attn.register_forward_pre_hook(
|
|
236
|
+
self._eagle3_attention_forward_pre_hook, with_kwargs=True
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
# Modify qkv projection in first layer to accept 2h hidden size.
|
|
240
|
+
first_layer_attn.q_proj = nn.Linear(
|
|
241
|
+
first_layer_attn.q_proj.in_features * 2,
|
|
242
|
+
first_layer_attn.q_proj.out_features,
|
|
243
|
+
bias=first_layer_attn.config.attention_bias,
|
|
244
|
+
)
|
|
245
|
+
first_layer_attn.k_proj = nn.Linear(
|
|
246
|
+
first_layer_attn.k_proj.in_features * 2,
|
|
247
|
+
first_layer_attn.k_proj.out_features,
|
|
248
|
+
bias=first_layer_attn.config.attention_bias,
|
|
249
|
+
)
|
|
250
|
+
first_layer_attn.v_proj = nn.Linear(
|
|
251
|
+
first_layer_attn.v_proj.in_features * 2,
|
|
252
|
+
first_layer_attn.v_proj.out_features,
|
|
253
|
+
bias=first_layer_attn.config.attention_bias,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# In EAGLE-3, input_embeds and hidden_states are normalized separately before concatenation.
|
|
257
|
+
self.input_embeds_norm = LlamaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
|
258
|
+
self.hidden_norm = LlamaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
|
259
|
+
|
|
260
|
+
# Disable input norm in first layer. We normed embeds and h individually before.
|
|
261
|
+
self.layers[0].input_layernorm = nn.Identity()
|
|
262
|
+
|
|
263
|
+
def _eagle3_attention_forward_pre_hook(self, module, args, kwargs):
|
|
264
|
+
"""Concat input_embeds and hidden_states for EAGLE-3's first attention layer."""
|
|
265
|
+
if "hidden_states" not in kwargs:
|
|
266
|
+
raise ValueError("hidden_states not found in kwargs")
|
|
267
|
+
if self._input_embeds is None:
|
|
268
|
+
raise ValueError("self._input_embeds is None")
|
|
269
|
+
|
|
270
|
+
input_embeds = self._input_embeds
|
|
271
|
+
self._input_embeds = None
|
|
272
|
+
kwargs["hidden_states"] = torch.cat(
|
|
273
|
+
(input_embeds, self.hidden_norm(kwargs["hidden_states"])), dim=-1
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
return args, kwargs
|
|
277
|
+
|
|
278
|
+
def forward(
|
|
279
|
+
self,
|
|
280
|
+
hidden_states: torch.Tensor,
|
|
281
|
+
inputs_embeds: torch.Tensor,
|
|
282
|
+
attention_mask: torch.Tensor,
|
|
283
|
+
loss_mask: torch.Tensor | None = None,
|
|
284
|
+
logits: torch.Tensor | None = None,
|
|
285
|
+
position_ids: torch.LongTensor | None = None,
|
|
286
|
+
past_key_values: Cache | None = None,
|
|
287
|
+
use_cache: bool | None = None,
|
|
288
|
+
output_attentions: bool | None = False,
|
|
289
|
+
position_embeddings: torch.Tensor | None = None,
|
|
290
|
+
):
|
|
291
|
+
"""Forward function for EagleModule."""
|
|
292
|
+
batch_size, seq_length, _ = hidden_states.shape
|
|
293
|
+
seq_length_with_past = seq_length
|
|
294
|
+
past_key_values_length = 0
|
|
295
|
+
|
|
296
|
+
if past_key_values is not None:
|
|
297
|
+
past_key_values_length = past_key_values.get_seq_length()
|
|
298
|
+
seq_length_with_past = seq_length_with_past + past_key_values_length
|
|
299
|
+
if position_ids is None:
|
|
300
|
+
device = hidden_states.device if hidden_states is not None else inputs_embeds.device
|
|
301
|
+
position_ids = torch.arange(
|
|
302
|
+
past_key_values_length,
|
|
303
|
+
seq_length + past_key_values_length,
|
|
304
|
+
dtype=torch.long,
|
|
305
|
+
device=device,
|
|
306
|
+
)
|
|
307
|
+
position_ids = position_ids.unsqueeze(0).view(-1, seq_length)
|
|
308
|
+
else:
|
|
309
|
+
position_ids = position_ids.view(-1, seq_length).long()
|
|
310
|
+
|
|
311
|
+
inputs_embeds = inputs_embeds.to(hidden_states.dtype).to(hidden_states.device)
|
|
312
|
+
if self.config.use_aux_hidden_state:
|
|
313
|
+
# In EAGLE-3, we save input embeddings to attribute, and use it in first decoder layer by hook function
|
|
314
|
+
# Also, we normalize input embeddings and hidden states before concatenating them.
|
|
315
|
+
# The default input norm in first layer attn will be disabled.
|
|
316
|
+
self._input_embeds = self.input_embeds_norm(inputs_embeds)
|
|
317
|
+
else: # EAGLE-1
|
|
318
|
+
hidden_states = self.fc(torch.cat((inputs_embeds, hidden_states), dim=-1))
|
|
319
|
+
|
|
320
|
+
for decoder_layer in self.layers:
|
|
321
|
+
layer_outputs = decoder_layer(
|
|
322
|
+
hidden_states,
|
|
323
|
+
attention_mask=attention_mask,
|
|
324
|
+
position_ids=position_ids,
|
|
325
|
+
past_key_value=past_key_values,
|
|
326
|
+
output_attentions=output_attentions,
|
|
327
|
+
use_cache=use_cache,
|
|
328
|
+
position_embeddings=position_embeddings,
|
|
329
|
+
)
|
|
330
|
+
# For HF>= 4.54.0, the layer_outputs is a tensor, for older, it is a tuple.
|
|
331
|
+
if isinstance(layer_outputs, tuple):
|
|
332
|
+
hidden_states = layer_outputs[0]
|
|
333
|
+
else:
|
|
334
|
+
hidden_states = layer_outputs
|
|
335
|
+
|
|
336
|
+
pre_norm_h = hidden_states
|
|
337
|
+
|
|
338
|
+
post_norm_h = self.norm(hidden_states) if hasattr(self, "norm") else hidden_states
|
|
339
|
+
|
|
340
|
+
return post_norm_h, pre_norm_h, past_key_values
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
@EagleDMRegistry.register({PreTrainedModel: "hf.PreTrainedModel"})
|
|
344
|
+
class HFEagleModel(EagleModel):
|
|
345
|
+
"""Eagle Model Class for huggingface models."""
|
|
346
|
+
|
|
347
|
+
def _set_default_aux_hidden_state_layers(self):
|
|
348
|
+
num_layers = self.config.num_hidden_layers
|
|
349
|
+
self.eagle_config.eagle_aux_hidden_state_layer_ids = [
|
|
350
|
+
1,
|
|
351
|
+
max(0, num_layers // 2 - 1),
|
|
352
|
+
max(0, num_layers - 4),
|
|
353
|
+
]
|
|
354
|
+
self.eagle_config.eagle_aux_hidden_state_layer_ids = list(
|
|
355
|
+
set(self.eagle_config.eagle_aux_hidden_state_layer_ids)
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
def _collect_aux_hidden_states_forward_hook(self, module, input, output) -> None:
|
|
359
|
+
"""Collect auxiliary hidden states from base model intermediate layers, save them in attribute."""
|
|
360
|
+
hidden_states = (
|
|
361
|
+
output.clone().detach()
|
|
362
|
+
if isinstance(output, torch.Tensor)
|
|
363
|
+
else output[0].clone().detach()
|
|
364
|
+
)
|
|
365
|
+
self._aux_hidden_states.append(hidden_states)
|
|
366
|
+
|
|
367
|
+
def pop_aux_hidden_states(self):
|
|
368
|
+
"""Return aux hidden states from base model, and clear the list."""
|
|
369
|
+
# In PTQ, forward method will be called with try and except to find max batch size.
|
|
370
|
+
# This leads to uncleared aux hidden states in the front of the list.
|
|
371
|
+
# To fix it, we only return the last num_aux_h items in the list.
|
|
372
|
+
num_aux_h = len(self.eagle_config.eagle_aux_hidden_state_layer_ids)
|
|
373
|
+
aux_h_list = self._aux_hidden_states[-num_aux_h:]
|
|
374
|
+
self._aux_hidden_states.clear()
|
|
375
|
+
|
|
376
|
+
return aux_h_list
|
|
377
|
+
|
|
378
|
+
def modify(
|
|
379
|
+
self,
|
|
380
|
+
eagle_offline,
|
|
381
|
+
eagle_hidden_state_distillation,
|
|
382
|
+
eagle_self_logit_distillation,
|
|
383
|
+
eagle_freeze_base_model,
|
|
384
|
+
eagle_report_acc,
|
|
385
|
+
eagle_reuse_base_decoder,
|
|
386
|
+
eagle_loss_decay_factor,
|
|
387
|
+
eagle_architecture_config,
|
|
388
|
+
):
|
|
389
|
+
"""Constructor.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
config: The config for eagle decoder layers.
|
|
393
|
+
"""
|
|
394
|
+
super().modify(
|
|
395
|
+
eagle_offline=eagle_offline,
|
|
396
|
+
eagle_hidden_state_distillation=eagle_hidden_state_distillation,
|
|
397
|
+
eagle_self_logit_distillation=eagle_self_logit_distillation,
|
|
398
|
+
eagle_freeze_base_model=eagle_freeze_base_model,
|
|
399
|
+
eagle_report_acc=eagle_report_acc,
|
|
400
|
+
eagle_reuse_base_decoder=eagle_reuse_base_decoder,
|
|
401
|
+
eagle_loss_decay_factor=eagle_loss_decay_factor,
|
|
402
|
+
eagle_architecture_config=eagle_architecture_config,
|
|
403
|
+
)
|
|
404
|
+
self.eagle_config = PretrainedConfig.from_dict(eagle_architecture_config)
|
|
405
|
+
self.eagle_config._attn_implementation = "sdpa"
|
|
406
|
+
decoder_cls = (
|
|
407
|
+
type(self.model.layers[-1]) if self.eagle_reuse_base_decoder else LlamaDecoderLayer
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Use default aux_hidden_state layers if use_aux_hidden_state is True
|
|
411
|
+
# but no layer id is given
|
|
412
|
+
if (
|
|
413
|
+
self.eagle_config.use_aux_hidden_state
|
|
414
|
+
and len(self.eagle_config.eagle_aux_hidden_state_layer_ids) == 0
|
|
415
|
+
):
|
|
416
|
+
self._set_default_aux_hidden_state_layers()
|
|
417
|
+
|
|
418
|
+
if self.config.hidden_size != self.eagle_config.hidden_size:
|
|
419
|
+
raise ValueError(
|
|
420
|
+
"EAGLE module hidden size "
|
|
421
|
+
f"{self.eagle_config.hidden_size} must match base model hidden size "
|
|
422
|
+
f"{self.config.hidden_size}!"
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
self.eagle_module = EagleModule(
|
|
426
|
+
self.eagle_config,
|
|
427
|
+
decoder_cls,
|
|
428
|
+
)
|
|
429
|
+
self.eagle_rotary_emb = LlamaRotaryEmbedding(config=self.eagle_config)
|
|
430
|
+
|
|
431
|
+
if hasattr(self.model.layers[-1].self_attn, "o_proj"):
|
|
432
|
+
device = self.model.layers[-1].self_attn.o_proj.weight.device
|
|
433
|
+
elif hasattr(self.model.layers[-1].self_attn, "q_proj"):
|
|
434
|
+
device = self.model.layers[-1].self_attn.q_proj.weight.device
|
|
435
|
+
elif hasattr(self.model.layers[-1].self_attn, "qkv_proj"):
|
|
436
|
+
device = self.model.layers[-1].self_attn.qkv_proj.weight.device
|
|
437
|
+
self.eagle_module.to(self.dtype).to(device)
|
|
438
|
+
|
|
439
|
+
# Make sure self.model.embed_tokens and self.lm_head are frozen
|
|
440
|
+
for param in self.model.embed_tokens.parameters():
|
|
441
|
+
param.requires_grad = False
|
|
442
|
+
for param in self.lm_head.parameters():
|
|
443
|
+
param.requires_grad = False
|
|
444
|
+
|
|
445
|
+
# EAGLE-3 auxiliary hidden_states
|
|
446
|
+
if self.eagle_config.use_aux_hidden_state:
|
|
447
|
+
self._aux_hidden_states = []
|
|
448
|
+
for layer_idx, layer in enumerate(self.model.layers):
|
|
449
|
+
if layer_idx in self.eagle_config.eagle_aux_hidden_state_layer_ids:
|
|
450
|
+
layer.register_forward_hook(self._collect_aux_hidden_states_forward_hook)
|
|
451
|
+
|
|
452
|
+
def _prepare_decoder_attention_mask(
|
|
453
|
+
self, attention_mask, input_shape, inputs_embeds, past_key_values_length
|
|
454
|
+
):
|
|
455
|
+
"""Expand the 2-D attention mask to 4-D and apply causal mask."""
|
|
456
|
+
# create causal mask
|
|
457
|
+
# [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
|
|
458
|
+
combined_attention_mask = None
|
|
459
|
+
if input_shape[-1] > 1:
|
|
460
|
+
combined_attention_mask = make_causal_mask(
|
|
461
|
+
input_shape,
|
|
462
|
+
inputs_embeds.dtype,
|
|
463
|
+
device=inputs_embeds.device,
|
|
464
|
+
past_key_values_length=past_key_values_length,
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
if attention_mask is not None:
|
|
468
|
+
# [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
|
|
469
|
+
expanded_attn_mask = expand_mask(
|
|
470
|
+
attention_mask, inputs_embeds.dtype, tgt_len=input_shape[-1]
|
|
471
|
+
).to(inputs_embeds.device)
|
|
472
|
+
combined_attention_mask = (
|
|
473
|
+
expanded_attn_mask
|
|
474
|
+
if combined_attention_mask is None
|
|
475
|
+
else expanded_attn_mask + combined_attention_mask
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
return combined_attention_mask
|
|
479
|
+
|
|
480
|
+
def _get_eagle_module_inputs(
|
|
481
|
+
self,
|
|
482
|
+
input_ids,
|
|
483
|
+
eagle_input_hidden_states,
|
|
484
|
+
attention_mask,
|
|
485
|
+
position_ids,
|
|
486
|
+
eagle_cache,
|
|
487
|
+
):
|
|
488
|
+
"""Helper function to prepare eagle inputs for the 0th eagle forward pass."""
|
|
489
|
+
b, seq_length, _ = eagle_input_hidden_states.shape
|
|
490
|
+
past_key_values_length = eagle_cache.get_seq_length() if eagle_cache is not None else 0
|
|
491
|
+
seq_length_with_past = seq_length + past_key_values_length
|
|
492
|
+
|
|
493
|
+
# Prepare eagle_input_ids: Shift left 1 token
|
|
494
|
+
zeropadding = torch.zeros(
|
|
495
|
+
input_ids.shape[0], 1, dtype=input_ids.dtype, device=input_ids.device
|
|
496
|
+
)
|
|
497
|
+
eagle_input_ids = torch.cat((input_ids[:, 1:], zeropadding), dim=1)
|
|
498
|
+
|
|
499
|
+
# Prepare attention_mask
|
|
500
|
+
if attention_mask is not None: # Shift left 1 token for attention_mask
|
|
501
|
+
zeropadding = torch.zeros(
|
|
502
|
+
attention_mask.shape[0], 1, dtype=attention_mask.dtype, device=attention_mask.device
|
|
503
|
+
)
|
|
504
|
+
attention_mask = torch.cat((attention_mask[:, 1:], zeropadding), dim=1)
|
|
505
|
+
else:
|
|
506
|
+
attention_mask = torch.ones( # Initialize default attention_mask
|
|
507
|
+
(b, seq_length_with_past), dtype=torch.bool, device=eagle_input_hidden_states.device
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
# Expand the 2-D attention mask to 4-D and apply causal mask.
|
|
511
|
+
attention_mask = self._prepare_decoder_attention_mask(
|
|
512
|
+
attention_mask, (b, seq_length), eagle_input_hidden_states, past_key_values_length
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
# Prepare position_ids
|
|
516
|
+
if position_ids is None:
|
|
517
|
+
position_ids = torch.arange(
|
|
518
|
+
past_key_values_length,
|
|
519
|
+
seq_length + past_key_values_length,
|
|
520
|
+
dtype=torch.long,
|
|
521
|
+
device=eagle_input_hidden_states.device,
|
|
522
|
+
)
|
|
523
|
+
position_ids = position_ids.unsqueeze(0).view(-1, seq_length)
|
|
524
|
+
else:
|
|
525
|
+
position_ids = position_ids.view(-1, seq_length).long()
|
|
526
|
+
|
|
527
|
+
return eagle_input_ids, attention_mask, position_ids
|
|
528
|
+
|
|
529
|
+
def _concat_eagle_inputs(
|
|
530
|
+
self,
|
|
531
|
+
input_ids_0,
|
|
532
|
+
eagle_input_hidden_states_0,
|
|
533
|
+
attention_mask_0,
|
|
534
|
+
position_ids_0,
|
|
535
|
+
eagle_generated_hs,
|
|
536
|
+
):
|
|
537
|
+
"""Helper function to prepare eagle inputs for second-fourth eagle forward pass during training-time-testing.
|
|
538
|
+
|
|
539
|
+
This is a slow version, focusing on the correctness only. TODO: optimize this.
|
|
540
|
+
Parameters:
|
|
541
|
+
input_ids_0: [b, seq_length], input_ids from the 0th eagle step
|
|
542
|
+
base_model_hidden_states: [b, seq_length, h]
|
|
543
|
+
eagle_input_hidden_states_0: [b, seq_length, h]
|
|
544
|
+
attention_mask_0: [b, seq_length, seq_length], from the 0th eagle step.
|
|
545
|
+
position_ids_0: [b, seq_length], from the 0th eagle step.
|
|
546
|
+
eagle_generated_hs: [b, seq_length * n_steps, h], from the LAST eagle step.
|
|
547
|
+
"""
|
|
548
|
+
b, seq_length, h = eagle_input_hidden_states_0.shape
|
|
549
|
+
dtypemin = torch.finfo(attention_mask_0.dtype).min
|
|
550
|
+
|
|
551
|
+
if eagle_generated_hs.shape[1] == seq_length:
|
|
552
|
+
# This is the second step of eagle forward
|
|
553
|
+
|
|
554
|
+
# Concat input_ids
|
|
555
|
+
cat_input_ids = torch.cat((input_ids_0, input_ids_0), dim=-1)
|
|
556
|
+
|
|
557
|
+
# Concat hidden_states
|
|
558
|
+
cat_eagle_input_hidden_states = torch.cat(
|
|
559
|
+
(
|
|
560
|
+
eagle_input_hidden_states_0,
|
|
561
|
+
torch.zeros(
|
|
562
|
+
(b, 1, h),
|
|
563
|
+
dtype=eagle_input_hidden_states_0.dtype,
|
|
564
|
+
device=eagle_input_hidden_states_0.device,
|
|
565
|
+
),
|
|
566
|
+
eagle_generated_hs[:, :-1, :],
|
|
567
|
+
),
|
|
568
|
+
dim=1,
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# Expand attn_mask
|
|
572
|
+
zero_mask = torch.ones_like(attention_mask_0).bool()
|
|
573
|
+
mask_2_1 = attention_mask_0.clone().detach()
|
|
574
|
+
mask_2_1[:, :, :, :-1] = mask_2_1[:, :, :, 1:]
|
|
575
|
+
mask_2_2 = torch.ones_like(attention_mask_0).bool()
|
|
576
|
+
for i in range(1, seq_length - 1):
|
|
577
|
+
mask_2_2[:, :, i, i] = False
|
|
578
|
+
cat_attention_mask = torch.cat(
|
|
579
|
+
(
|
|
580
|
+
torch.cat((attention_mask_0, zero_mask), dim=-1),
|
|
581
|
+
torch.cat((mask_2_1, mask_2_2), dim=-1),
|
|
582
|
+
),
|
|
583
|
+
dim=-2,
|
|
584
|
+
)
|
|
585
|
+
cat_attention_mask = cat_attention_mask.masked_fill(cat_attention_mask == 1, dtypemin)
|
|
586
|
+
|
|
587
|
+
# Concat position_ids
|
|
588
|
+
cat_position_ids = torch.cat((position_ids_0, position_ids_0), dim=-1)
|
|
589
|
+
|
|
590
|
+
elif eagle_generated_hs.shape[1] == seq_length * 2:
|
|
591
|
+
cat_input_ids = torch.cat((input_ids_0, input_ids_0, input_ids_0), dim=-1)
|
|
592
|
+
cat_eagle_input_hidden_states = torch.cat(
|
|
593
|
+
(
|
|
594
|
+
eagle_input_hidden_states_0,
|
|
595
|
+
torch.zeros(
|
|
596
|
+
(b, 1, h),
|
|
597
|
+
dtype=eagle_input_hidden_states_0.dtype,
|
|
598
|
+
device=eagle_input_hidden_states_0.device,
|
|
599
|
+
),
|
|
600
|
+
eagle_generated_hs[:, :-1, :],
|
|
601
|
+
),
|
|
602
|
+
dim=1,
|
|
603
|
+
)
|
|
604
|
+
zero_mask = torch.ones_like(attention_mask_0).bool()
|
|
605
|
+
mask_2_1 = attention_mask_0.clone().detach()
|
|
606
|
+
mask_2_1[:, :, :, :-1] = mask_2_1[:, :, :, 1:]
|
|
607
|
+
mask_2_2 = torch.ones_like(attention_mask_0).bool()
|
|
608
|
+
for i in range(1, seq_length - 1):
|
|
609
|
+
mask_2_2[:, :, i, i] = False
|
|
610
|
+
|
|
611
|
+
mask_3_1 = mask_2_1.clone().detach()
|
|
612
|
+
mask_3_1[:, :, :, :-1] = mask_3_1[:, :, :, 1:]
|
|
613
|
+
mask_3_2 = mask_2_2.clone().detach()
|
|
614
|
+
mask_3_2[:, :, :, :-1] = mask_3_2[:, :, :, 1:]
|
|
615
|
+
mask_3_2[:, :, 1, 0] = True
|
|
616
|
+
mask_3_3 = mask_2_2.clone().detach()
|
|
617
|
+
mask_3_3[:, :, 1, 1] = True
|
|
618
|
+
cat_attention_mask = torch.cat(
|
|
619
|
+
(
|
|
620
|
+
torch.cat((attention_mask_0, zero_mask, zero_mask), dim=-1),
|
|
621
|
+
torch.cat((mask_2_1, mask_2_2, zero_mask), dim=-1),
|
|
622
|
+
torch.cat((mask_3_1, mask_3_2, mask_3_3), dim=-1),
|
|
623
|
+
),
|
|
624
|
+
dim=-2,
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
cat_attention_mask = cat_attention_mask.masked_fill(cat_attention_mask == 1, dtypemin)
|
|
628
|
+
cat_position_ids = torch.cat((position_ids_0, position_ids_0, position_ids_0), dim=-1)
|
|
629
|
+
|
|
630
|
+
elif eagle_generated_hs.shape[1] == seq_length * 3:
|
|
631
|
+
cat_input_ids = torch.cat((input_ids_0, input_ids_0, input_ids_0, input_ids_0), dim=-1)
|
|
632
|
+
cat_eagle_input_hidden_states = torch.cat(
|
|
633
|
+
(
|
|
634
|
+
eagle_input_hidden_states_0,
|
|
635
|
+
torch.zeros(
|
|
636
|
+
(b, 1, h),
|
|
637
|
+
dtype=eagle_input_hidden_states_0.dtype,
|
|
638
|
+
device=eagle_input_hidden_states_0.device,
|
|
639
|
+
),
|
|
640
|
+
eagle_generated_hs[:, :-1, :],
|
|
641
|
+
),
|
|
642
|
+
dim=1,
|
|
643
|
+
)
|
|
644
|
+
zero_mask = torch.ones_like(attention_mask_0).bool()
|
|
645
|
+
mask_2_1 = attention_mask_0.clone().detach()
|
|
646
|
+
mask_2_1[:, :, :, :-1] = mask_2_1[:, :, :, 1:]
|
|
647
|
+
mask_2_2 = torch.ones_like(attention_mask_0).bool()
|
|
648
|
+
for i in range(1, seq_length - 1):
|
|
649
|
+
mask_2_2[:, :, i, i] = False
|
|
650
|
+
|
|
651
|
+
mask_3_1 = mask_2_1.clone().detach()
|
|
652
|
+
mask_3_1[:, :, :, :-1] = mask_3_1[:, :, :, 1:]
|
|
653
|
+
mask_3_2 = mask_2_2.clone().detach()
|
|
654
|
+
mask_3_2[:, :, :, :-1] = mask_3_2[:, :, :, 1:]
|
|
655
|
+
mask_3_2[:, :, 1, 0] = True
|
|
656
|
+
mask_3_3 = mask_2_2.clone().detach()
|
|
657
|
+
mask_3_3[:, :, 1, 1] = True
|
|
658
|
+
|
|
659
|
+
mask_4_1 = mask_3_1.clone().detach()
|
|
660
|
+
mask_4_1[:, :, :, :-1] = mask_4_1[:, :, :, 1:]
|
|
661
|
+
mask_4_2 = mask_3_2.clone().detach()
|
|
662
|
+
mask_4_2[:, :, :, :-1] = mask_4_2[:, :, :, 1:]
|
|
663
|
+
mask_4_2[:, :, 2, 0] = True
|
|
664
|
+
mask_4_3 = mask_3_3.clone().detach()
|
|
665
|
+
mask_4_3[:, :, :, :-1] = mask_4_3[:, :, :, 1:]
|
|
666
|
+
mask_4_3[:, :, 2, 1] = True
|
|
667
|
+
mask_4_4 = mask_3_3.clone().detach()
|
|
668
|
+
mask_4_4[:, :, 2, 2] = True
|
|
669
|
+
|
|
670
|
+
cat_attention_mask = torch.cat(
|
|
671
|
+
(
|
|
672
|
+
torch.cat((attention_mask_0, zero_mask, zero_mask, zero_mask), dim=-1),
|
|
673
|
+
torch.cat((mask_2_1, mask_2_2, zero_mask, zero_mask), dim=-1),
|
|
674
|
+
torch.cat((mask_3_1, mask_3_2, mask_3_3, zero_mask), dim=-1),
|
|
675
|
+
torch.cat((mask_4_1, mask_4_2, mask_4_3, mask_4_4), dim=-1),
|
|
676
|
+
),
|
|
677
|
+
dim=-2,
|
|
678
|
+
)
|
|
679
|
+
cat_attention_mask = cat_attention_mask.masked_fill(cat_attention_mask == 1, dtypemin)
|
|
680
|
+
cat_position_ids = torch.cat(
|
|
681
|
+
(position_ids_0, position_ids_0, position_ids_0, position_ids_0), dim=-1
|
|
682
|
+
)
|
|
683
|
+
|
|
684
|
+
else:
|
|
685
|
+
raise ValueError(
|
|
686
|
+
f"EAGLE generated hidden states shape {eagle_generated_hs.shape} is not supported"
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
return cat_eagle_input_hidden_states, cat_input_ids, cat_attention_mask, cat_position_ids
|
|
690
|
+
|
|
691
|
+
def _base_model_forward(
|
|
692
|
+
self,
|
|
693
|
+
input_ids,
|
|
694
|
+
attention_mask,
|
|
695
|
+
position_ids,
|
|
696
|
+
past_key_values,
|
|
697
|
+
freeze_base_model,
|
|
698
|
+
labels,
|
|
699
|
+
kwargs,
|
|
700
|
+
):
|
|
701
|
+
with torch.no_grad() if freeze_base_model else contextlib.nullcontext():
|
|
702
|
+
outputs = super().forward(
|
|
703
|
+
input_ids=input_ids,
|
|
704
|
+
attention_mask=attention_mask,
|
|
705
|
+
position_ids=position_ids,
|
|
706
|
+
past_key_values=past_key_values,
|
|
707
|
+
output_hidden_states=True,
|
|
708
|
+
**kwargs,
|
|
709
|
+
)
|
|
710
|
+
past_key_values = outputs.past_key_values
|
|
711
|
+
if not isinstance(past_key_values, Cache):
|
|
712
|
+
past_key_values = DynamicCache.from_legacy_cache(past_key_values)
|
|
713
|
+
base_model_hidden_states = outputs.hidden_states[-1]
|
|
714
|
+
base_model_logits = outputs.logits
|
|
715
|
+
|
|
716
|
+
# Optionally, compute base model loss when we want to tune the base model.
|
|
717
|
+
base_model_loss = None
|
|
718
|
+
if not freeze_base_model and labels is not None: # Base model loss
|
|
719
|
+
loss_fct = CrossEntropyLoss()
|
|
720
|
+
loss_logits = base_model_logits.view(-1, base_model_logits.shape[-1])
|
|
721
|
+
labels = labels.view(-1)
|
|
722
|
+
base_model_loss = loss_fct(loss_logits, labels)
|
|
723
|
+
|
|
724
|
+
# Map the base model logits to the draft vocab
|
|
725
|
+
if self.eagle_config.draft_vocab_size != self.eagle_config.vocab_size and self.training:
|
|
726
|
+
reverse_mapping = (
|
|
727
|
+
torch.arange(len(self.eagle_module.d2t)).to(self.eagle_module.d2t.device)
|
|
728
|
+
+ self.eagle_module.d2t
|
|
729
|
+
)
|
|
730
|
+
base_model_logits = base_model_logits[:, :, reverse_mapping]
|
|
731
|
+
|
|
732
|
+
return base_model_hidden_states, base_model_logits, base_model_loss, past_key_values
|
|
733
|
+
|
|
734
|
+
def _eagle_forward(
|
|
735
|
+
self,
|
|
736
|
+
eagle_input_hidden_states,
|
|
737
|
+
inputs_embeds,
|
|
738
|
+
attention_mask,
|
|
739
|
+
position_ids,
|
|
740
|
+
position_embeddings,
|
|
741
|
+
):
|
|
742
|
+
eagle_postnorm_h, eagle_prenorm_h, eagle_cache = self.eagle_module(
|
|
743
|
+
eagle_input_hidden_states,
|
|
744
|
+
inputs_embeds,
|
|
745
|
+
attention_mask=attention_mask,
|
|
746
|
+
position_ids=position_ids,
|
|
747
|
+
use_cache=True,
|
|
748
|
+
position_embeddings=position_embeddings,
|
|
749
|
+
)
|
|
750
|
+
eagle_lm_head = (
|
|
751
|
+
self.eagle_module.eagle_lm_head
|
|
752
|
+
if hasattr(self.eagle_module, "eagle_lm_head")
|
|
753
|
+
else self.lm_head
|
|
754
|
+
)
|
|
755
|
+
eagle_logits = eagle_lm_head(eagle_postnorm_h)
|
|
756
|
+
|
|
757
|
+
return eagle_postnorm_h, eagle_prenorm_h, eagle_logits, eagle_cache
|
|
758
|
+
|
|
759
|
+
def forward(
|
|
760
|
+
self,
|
|
761
|
+
input_ids: torch.LongTensor,
|
|
762
|
+
attention_mask: torch.Tensor | None = None,
|
|
763
|
+
position_ids: torch.LongTensor | None = None,
|
|
764
|
+
past_key_values: Cache | None = None,
|
|
765
|
+
inputs_embeds: torch.FloatTensor | None = None,
|
|
766
|
+
labels: torch.LongTensor | None = None,
|
|
767
|
+
use_cache: bool | None = None,
|
|
768
|
+
output_attentions: bool | None = None,
|
|
769
|
+
output_hidden_states: bool | None = None,
|
|
770
|
+
cache_position: torch.LongTensor | None = None,
|
|
771
|
+
logits_to_keep: int = 0,
|
|
772
|
+
loss_mask: torch.Tensor | None = None,
|
|
773
|
+
classification_loss_coefficient: float | None = 1,
|
|
774
|
+
regression_loss_coefficient: float | None = 0,
|
|
775
|
+
**kwargs,
|
|
776
|
+
) -> Any:
|
|
777
|
+
"""Forward pass of the EagleModel.
|
|
778
|
+
|
|
779
|
+
Returns:
|
|
780
|
+
hidden_states: The hidden state from the base model.
|
|
781
|
+
logits: logits from the base model.
|
|
782
|
+
eagle_hidden_states: The hidden state from eagle_module.
|
|
783
|
+
eagle_logits: logits from the eagle_module.
|
|
784
|
+
"""
|
|
785
|
+
if past_key_values is not None and hasattr(past_key_values, "eagle_cache"):
|
|
786
|
+
eagle_cache = past_key_values.eagle_cache
|
|
787
|
+
else:
|
|
788
|
+
eagle_cache = None
|
|
789
|
+
|
|
790
|
+
if self.training:
|
|
791
|
+
assert eagle_cache is None, "eagle_cache should be None in training"
|
|
792
|
+
assert past_key_values is None, "past_key_values should be None in training"
|
|
793
|
+
|
|
794
|
+
if loss_mask is None:
|
|
795
|
+
loss_mask = torch.ones_like(input_ids, dtype=torch.bool, device=input_ids.device)
|
|
796
|
+
|
|
797
|
+
# ====First, we run base model forward====
|
|
798
|
+
base_model_hidden_states, base_model_logits, base_model_loss, past_key_values = (
|
|
799
|
+
self._base_model_forward(
|
|
800
|
+
input_ids,
|
|
801
|
+
attention_mask,
|
|
802
|
+
position_ids,
|
|
803
|
+
past_key_values,
|
|
804
|
+
self.eagle_freeze_base_model,
|
|
805
|
+
labels,
|
|
806
|
+
kwargs,
|
|
807
|
+
)
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
# ====Run eagle forward====
|
|
811
|
+
eagle_loss = None
|
|
812
|
+
if self.training:
|
|
813
|
+
# In EAGLE-3, we have an additional FC layer to concentrate hidden states from multiple base model layers
|
|
814
|
+
batch_size, seq_length, _ = base_model_hidden_states.shape
|
|
815
|
+
if self.eagle_config.use_aux_hidden_state:
|
|
816
|
+
eagle_input_hidden_states = self.eagle_module.fc(
|
|
817
|
+
torch.cat(self.pop_aux_hidden_states(), dim=-1)
|
|
818
|
+
)
|
|
819
|
+
else:
|
|
820
|
+
eagle_input_hidden_states = base_model_hidden_states
|
|
821
|
+
|
|
822
|
+
# Get eagle inputs for the first eagle forward pass
|
|
823
|
+
eagle_input_ids, attention_mask_0, position_ids = self._get_eagle_module_inputs(
|
|
824
|
+
input_ids,
|
|
825
|
+
eagle_input_hidden_states,
|
|
826
|
+
attention_mask,
|
|
827
|
+
position_ids,
|
|
828
|
+
eagle_cache,
|
|
829
|
+
)
|
|
830
|
+
with torch.no_grad():
|
|
831
|
+
inputs_embeds = self.model.embed_tokens(eagle_input_ids)
|
|
832
|
+
position_embeddings = self.eagle_rotary_emb(eagle_input_hidden_states, position_ids)
|
|
833
|
+
|
|
834
|
+
# Then, we run eagle forward
|
|
835
|
+
eagle_postnorm_h, eagle_prenorm_h, eagle_logits, eagle_cache = self._eagle_forward(
|
|
836
|
+
eagle_input_hidden_states,
|
|
837
|
+
inputs_embeds,
|
|
838
|
+
attention_mask_0,
|
|
839
|
+
position_ids,
|
|
840
|
+
position_embeddings,
|
|
841
|
+
)
|
|
842
|
+
|
|
843
|
+
if not isinstance(eagle_cache, Cache):
|
|
844
|
+
eagle_cache = DynamicCache.from_legacy_cache(eagle_cache)
|
|
845
|
+
past_key_values.eagle_cache = eagle_cache
|
|
846
|
+
|
|
847
|
+
# Compute loss on the eagle modules
|
|
848
|
+
regression_loss, classification_loss = self._eagle_loss(
|
|
849
|
+
base_model_hidden_states[:, 1:],
|
|
850
|
+
base_model_logits[:, 1:],
|
|
851
|
+
eagle_postnorm_h[:, :-1],
|
|
852
|
+
eagle_logits[:, :-1],
|
|
853
|
+
loss_mask[:, 1:],
|
|
854
|
+
)
|
|
855
|
+
eagle_loss = (
|
|
856
|
+
regression_loss_coefficient * regression_loss
|
|
857
|
+
+ classification_loss_coefficient * classification_loss
|
|
858
|
+
)
|
|
859
|
+
|
|
860
|
+
# ====Perform training-time-testing with 3 extra eagle forward passes====
|
|
861
|
+
# ====Second step of eagle forward====
|
|
862
|
+
eagle_input_hidden_states_1, eagle_input_ids_1, attention_mask_1, position_ids_1 = (
|
|
863
|
+
self._concat_eagle_inputs(
|
|
864
|
+
eagle_input_ids,
|
|
865
|
+
eagle_input_hidden_states,
|
|
866
|
+
attention_mask_0,
|
|
867
|
+
position_ids,
|
|
868
|
+
eagle_prenorm_h,
|
|
869
|
+
)
|
|
870
|
+
)
|
|
871
|
+
with torch.no_grad():
|
|
872
|
+
inputs_embeds = self.model.embed_tokens(eagle_input_ids_1)
|
|
873
|
+
position_embeddings = self.eagle_rotary_emb(eagle_input_hidden_states_1, position_ids_1)
|
|
874
|
+
eagle_postnorm_h, eagle_prenorm_h, eagle_logits, eagle_cache = self._eagle_forward(
|
|
875
|
+
eagle_input_hidden_states_1,
|
|
876
|
+
inputs_embeds,
|
|
877
|
+
attention_mask_1,
|
|
878
|
+
position_ids_1,
|
|
879
|
+
position_embeddings,
|
|
880
|
+
)
|
|
881
|
+
|
|
882
|
+
regression_loss, classification_loss = self._eagle_loss(
|
|
883
|
+
# base model predict +1 tok, while eagle predict +2
|
|
884
|
+
# so we shift base model outputs compared to eagle outputs
|
|
885
|
+
base_model_hidden_states[:, 1:],
|
|
886
|
+
base_model_logits[:, 1:],
|
|
887
|
+
eagle_postnorm_h[
|
|
888
|
+
:,
|
|
889
|
+
-seq_length:-1,
|
|
890
|
+
],
|
|
891
|
+
eagle_logits[
|
|
892
|
+
:,
|
|
893
|
+
-seq_length:-1,
|
|
894
|
+
],
|
|
895
|
+
# additionally, we mask the first n tok of eagle outputs at nth TTT step
|
|
896
|
+
torch.cat(
|
|
897
|
+
(
|
|
898
|
+
torch.zeros(batch_size, 1, dtype=loss_mask.dtype, device=loss_mask.device),
|
|
899
|
+
loss_mask[:, 2:],
|
|
900
|
+
),
|
|
901
|
+
dim=1,
|
|
902
|
+
),
|
|
903
|
+
)
|
|
904
|
+
eagle_loss += (
|
|
905
|
+
regression_loss_coefficient * regression_loss
|
|
906
|
+
+ classification_loss_coefficient * classification_loss
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
# ====Third step of eagle forward====
|
|
910
|
+
eagle_input_hidden_states_2, eagle_input_ids_2, attention_mask_2, position_ids_2 = (
|
|
911
|
+
self._concat_eagle_inputs(
|
|
912
|
+
eagle_input_ids,
|
|
913
|
+
eagle_input_hidden_states,
|
|
914
|
+
attention_mask_0,
|
|
915
|
+
position_ids,
|
|
916
|
+
eagle_prenorm_h,
|
|
917
|
+
)
|
|
918
|
+
)
|
|
919
|
+
with torch.no_grad():
|
|
920
|
+
inputs_embeds = self.model.embed_tokens(eagle_input_ids_2)
|
|
921
|
+
position_embeddings = self.eagle_rotary_emb(eagle_input_hidden_states_2, position_ids_2)
|
|
922
|
+
eagle_postnorm_h, eagle_prenorm_h, eagle_logits, eagle_cache = self._eagle_forward(
|
|
923
|
+
eagle_input_hidden_states_2,
|
|
924
|
+
inputs_embeds,
|
|
925
|
+
attention_mask_2,
|
|
926
|
+
position_ids_2,
|
|
927
|
+
position_embeddings,
|
|
928
|
+
)
|
|
929
|
+
|
|
930
|
+
regression_loss, classification_loss = self._eagle_loss(
|
|
931
|
+
base_model_hidden_states[:, 1:],
|
|
932
|
+
base_model_logits[:, 1:],
|
|
933
|
+
eagle_postnorm_h[:, -seq_length:-1, :],
|
|
934
|
+
eagle_logits[
|
|
935
|
+
:,
|
|
936
|
+
-seq_length:-1,
|
|
937
|
+
],
|
|
938
|
+
torch.cat(
|
|
939
|
+
(
|
|
940
|
+
torch.zeros(batch_size, 2, dtype=loss_mask.dtype, device=loss_mask.device),
|
|
941
|
+
loss_mask[:, 3:],
|
|
942
|
+
),
|
|
943
|
+
dim=1,
|
|
944
|
+
),
|
|
945
|
+
)
|
|
946
|
+
eagle_loss += (
|
|
947
|
+
regression_loss_coefficient * regression_loss
|
|
948
|
+
+ classification_loss_coefficient * classification_loss
|
|
949
|
+
)
|
|
950
|
+
|
|
951
|
+
# ====Fourth step of eagle forward====
|
|
952
|
+
eagle_input_hidden_states_3, eagle_input_ids_3, attention_mask_3, position_ids_3 = (
|
|
953
|
+
self._concat_eagle_inputs(
|
|
954
|
+
eagle_input_ids,
|
|
955
|
+
eagle_input_hidden_states,
|
|
956
|
+
attention_mask_0,
|
|
957
|
+
position_ids,
|
|
958
|
+
eagle_prenorm_h,
|
|
959
|
+
)
|
|
960
|
+
)
|
|
961
|
+
with torch.no_grad():
|
|
962
|
+
inputs_embeds = self.model.embed_tokens(eagle_input_ids_3)
|
|
963
|
+
position_embeddings = self.eagle_rotary_emb(eagle_input_hidden_states_3, position_ids_3)
|
|
964
|
+
eagle_postnorm_h, _, eagle_logits, eagle_cache = self._eagle_forward(
|
|
965
|
+
eagle_input_hidden_states_3,
|
|
966
|
+
inputs_embeds,
|
|
967
|
+
attention_mask_3,
|
|
968
|
+
position_ids_3,
|
|
969
|
+
position_embeddings,
|
|
970
|
+
)
|
|
971
|
+
|
|
972
|
+
regression_loss, classification_loss = self._eagle_loss(
|
|
973
|
+
base_model_hidden_states[:, 1:],
|
|
974
|
+
base_model_logits[:, 1:],
|
|
975
|
+
eagle_postnorm_h[
|
|
976
|
+
:,
|
|
977
|
+
-seq_length:-1,
|
|
978
|
+
],
|
|
979
|
+
eagle_logits[
|
|
980
|
+
:,
|
|
981
|
+
-seq_length:-1,
|
|
982
|
+
],
|
|
983
|
+
torch.cat(
|
|
984
|
+
(
|
|
985
|
+
torch.zeros(batch_size, 3, dtype=loss_mask.dtype, device=loss_mask.device),
|
|
986
|
+
loss_mask[:, 4:],
|
|
987
|
+
),
|
|
988
|
+
dim=1,
|
|
989
|
+
),
|
|
990
|
+
)
|
|
991
|
+
eagle_loss += (
|
|
992
|
+
regression_loss_coefficient * regression_loss
|
|
993
|
+
+ classification_loss_coefficient * classification_loss
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
# Finally, we merge base model loss and eagle loss, raise error if both are None
|
|
997
|
+
if base_model_loss is not None and eagle_loss is not None:
|
|
998
|
+
loss = base_model_loss + eagle_loss
|
|
999
|
+
elif base_model_loss is not None:
|
|
1000
|
+
loss = base_model_loss
|
|
1001
|
+
elif eagle_loss is not None:
|
|
1002
|
+
loss = eagle_loss
|
|
1003
|
+
else:
|
|
1004
|
+
loss = None
|
|
1005
|
+
assert not self.training, ValueError(
|
|
1006
|
+
"Both base_model_loss and eagle_loss are skipped. At least one loss must be computed."
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
return ModelOutput(
|
|
1010
|
+
loss=loss,
|
|
1011
|
+
logits=base_model_logits,
|
|
1012
|
+
past_key_values=past_key_values,
|
|
1013
|
+
hidden_states=base_model_hidden_states,
|
|
1014
|
+
)
|
|
1015
|
+
|
|
1016
|
+
def _eagle_loss(
|
|
1017
|
+
self,
|
|
1018
|
+
base_model_hidden_states,
|
|
1019
|
+
base_model_logits,
|
|
1020
|
+
eagle_hidden_states,
|
|
1021
|
+
eagle_logits,
|
|
1022
|
+
loss_mask,
|
|
1023
|
+
):
|
|
1024
|
+
"""Function for EAGLE loss computing."""
|
|
1025
|
+
loss_mask = loss_mask[:, :, None]
|
|
1026
|
+
criterion = nn.SmoothL1Loss(reduction="none")
|
|
1027
|
+
classification_loss = nn.Softmax(dim=2)(base_model_logits) * nn.LogSoftmax(dim=2)(
|
|
1028
|
+
eagle_logits
|
|
1029
|
+
)
|
|
1030
|
+
classification_loss = -torch.sum(torch.sum(loss_mask * classification_loss, 2)) / (
|
|
1031
|
+
loss_mask.sum() + 1e-5
|
|
1032
|
+
)
|
|
1033
|
+
regression_loss = criterion(eagle_hidden_states, base_model_hidden_states)
|
|
1034
|
+
regression_loss = torch.sum(torch.mean(loss_mask * regression_loss, 2)) / (
|
|
1035
|
+
loss_mask.sum() + 1e-5
|
|
1036
|
+
)
|
|
1037
|
+
return regression_loss, classification_loss
|
|
1038
|
+
|
|
1039
|
+
@torch.no_grad()
|
|
1040
|
+
def pseudo_speculative_generate(
|
|
1041
|
+
self,
|
|
1042
|
+
input_ids: torch.Tensor,
|
|
1043
|
+
steps: int = 1,
|
|
1044
|
+
):
|
|
1045
|
+
"""Pseudo generate of the EAGLE GPTModel.
|
|
1046
|
+
|
|
1047
|
+
Returns:
|
|
1048
|
+
base_token (torch.Tensor): token from base model
|
|
1049
|
+
draft_tokens (torch.Tensor): draft tokens from eagle module
|
|
1050
|
+
"""
|
|
1051
|
+
base_model_outputs = super().forward(
|
|
1052
|
+
input_ids=input_ids,
|
|
1053
|
+
output_hidden_states=True,
|
|
1054
|
+
)
|
|
1055
|
+
|
|
1056
|
+
base_model_hidden_states = base_model_outputs.hidden_states[-1]
|
|
1057
|
+
base_model_logits = base_model_outputs.logits
|
|
1058
|
+
base_token = base_model_logits[:, -1:, :].argmax(dim=-1)
|
|
1059
|
+
|
|
1060
|
+
# Early return
|
|
1061
|
+
if steps < 1:
|
|
1062
|
+
if hasattr(self, "_aux_hidden_states"):
|
|
1063
|
+
_ = self.pop_aux_hidden_states()
|
|
1064
|
+
return base_token, None
|
|
1065
|
+
|
|
1066
|
+
eagle_ids = torch.cat((input_ids[:, 1:], base_token), dim=-1)
|
|
1067
|
+
|
|
1068
|
+
if self.eagle_config.use_aux_hidden_state:
|
|
1069
|
+
# EAGLE-3
|
|
1070
|
+
# Only the first iteration input_hidden_states are from aux_hidden_state layers
|
|
1071
|
+
# Gather _aux_hidden_states from all devices before concatenation
|
|
1072
|
+
gathered_aux_hidden_states = self.pop_aux_hidden_states()
|
|
1073
|
+
gathered_aux_hidden_states = [
|
|
1074
|
+
h.to(input_ids.device) for h in gathered_aux_hidden_states
|
|
1075
|
+
]
|
|
1076
|
+
eagle_input_hidden_states = self.eagle_module.fc(
|
|
1077
|
+
torch.cat(gathered_aux_hidden_states, dim=-1)
|
|
1078
|
+
)
|
|
1079
|
+
|
|
1080
|
+
else:
|
|
1081
|
+
eagle_input_hidden_states = base_model_hidden_states
|
|
1082
|
+
|
|
1083
|
+
draft_tokens = []
|
|
1084
|
+
for _ in range(steps):
|
|
1085
|
+
# Get eagle inputs for the first eagle forward pass
|
|
1086
|
+
_, eagle_attention_mask, eagle_position_ids = self._get_eagle_module_inputs(
|
|
1087
|
+
input_ids,
|
|
1088
|
+
eagle_input_hidden_states,
|
|
1089
|
+
None,
|
|
1090
|
+
None,
|
|
1091
|
+
None,
|
|
1092
|
+
)
|
|
1093
|
+
position_embeddings = self.eagle_rotary_emb(
|
|
1094
|
+
eagle_input_hidden_states, eagle_position_ids
|
|
1095
|
+
)
|
|
1096
|
+
|
|
1097
|
+
_, eagle_prenorm_h, eagle_logits, _ = self._eagle_forward(
|
|
1098
|
+
eagle_input_hidden_states,
|
|
1099
|
+
self.model.embed_tokens(eagle_ids),
|
|
1100
|
+
eagle_attention_mask,
|
|
1101
|
+
eagle_position_ids,
|
|
1102
|
+
position_embeddings,
|
|
1103
|
+
)
|
|
1104
|
+
|
|
1105
|
+
draft_token = eagle_logits[:, -1:, :].argmax(dim=-1)
|
|
1106
|
+
if self.eagle_config.draft_vocab_size != self.eagle_config.vocab_size:
|
|
1107
|
+
draft_token += self.eagle_module.d2t[draft_token]
|
|
1108
|
+
draft_tokens.append(draft_token)
|
|
1109
|
+
|
|
1110
|
+
eagle_ids = torch.cat((eagle_ids, draft_token.to(eagle_ids.device)), dim=-1)
|
|
1111
|
+
eagle_input_hidden_states = torch.cat(
|
|
1112
|
+
(eagle_input_hidden_states, eagle_prenorm_h[:, -1:, :]), dim=1
|
|
1113
|
+
)
|
|
1114
|
+
|
|
1115
|
+
draft_tokens = torch.cat(draft_tokens, dim=-1).to(base_token.device)
|
|
1116
|
+
|
|
1117
|
+
return base_token, draft_tokens
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
@OfflineEagleDMRegistry.register({PreTrainedModel: "hf.PreTrainedModel"})
|
|
1121
|
+
class DetachedHFEagleModel(HFEagleModel):
|
|
1122
|
+
"""A wrapper for detached Eagle module."""
|
|
1123
|
+
|
|
1124
|
+
# TODO: Implement DetachedHFEagleModel class for offline eagle.
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
class HFARValidation(AcceptanceRateValidation):
|
|
1128
|
+
"""This is the subclass for HF model AR validation."""
|
|
1129
|
+
|
|
1130
|
+
def get_ground_truth(self, input_ids, osl):
|
|
1131
|
+
"""This function returns ground truth output tokens from the base model."""
|
|
1132
|
+
input_ids = copy.deepcopy(input_ids).to(torch.cuda.current_device())
|
|
1133
|
+
for _ in range(osl):
|
|
1134
|
+
input_id, _ = self.model.pseudo_speculative_generate(input_ids, steps=0)
|
|
1135
|
+
input_ids = torch.cat((input_ids, input_id), dim=-1)
|
|
1136
|
+
if input_id[0, 0] == self.end_token:
|
|
1137
|
+
break
|
|
1138
|
+
return input_ids
|