|
1 | 1 | """ |
2 | | -Utility functions for checkpoint conversion operations. |
| 2 | +Utility functions for Eagle checkpoint conversion operations. |
3 | 3 | """ |
4 | 4 |
|
5 | 5 | from __future__ import annotations |
6 | 6 |
|
7 | 7 | import inspect |
8 | | -import json |
9 | | -from pathlib import Path |
10 | 8 | from typing import Any |
11 | 9 |
|
12 | 10 | import torch |
13 | | -from huggingface_hub import snapshot_download |
14 | 11 | from loguru import logger |
15 | | -from safetensors import safe_open |
16 | 12 | from transformers import LlamaConfig |
17 | 13 |
|
18 | 14 | _LLAMA_CONFIG_PARAMS = set(inspect.signature(LlamaConfig.__init__).parameters) |
@@ -69,139 +65,6 @@ def find_vocab_size(config_dict: dict) -> int | None: |
69 | 65 | return None |
70 | 66 |
|
71 | 67 |
|
72 | | -def download_checkpoint_from_hub(model_id: str, cache_dir: str | None = None) -> Path: |
73 | | - """ |
74 | | - Download a checkpoint from HuggingFace Hub. |
75 | | -
|
76 | | - :param model_id: HuggingFace model ID |
77 | | - :param cache_dir: Optional directory to cache downloads |
78 | | - :return: Local path to the downloaded checkpoint |
79 | | - :raises FileNotFoundError: If the checkpoint cannot be downloaded |
80 | | -
|
81 | | - :Example: |
82 | | -
|
83 | | - >>> path = download_checkpoint_from_hub("yuhuili/EAGLE-LLaMA3.1-Instruct-8B") |
84 | | - >>> print(path) |
85 | | - /home/user/.cache/huggingface/hub/models--yuhuili--EAGLE-LLaMA3.1-Instruct-8B/snapshots/... |
86 | | - """ |
87 | | - logger.info(f"Downloading checkpoint from HuggingFace: {model_id}") |
88 | | - try: |
89 | | - local_path = snapshot_download( |
90 | | - repo_id=model_id, |
91 | | - allow_patterns=["*.json", "*.safetensors", "*.bin", "*.index.json"], |
92 | | - cache_dir=cache_dir, |
93 | | - ) |
94 | | - logger.debug(f"Downloaded to: {local_path}") |
95 | | - return Path(local_path) |
96 | | - except Exception as hf_exception: |
97 | | - logger.error(f"Failed to download checkpoint: {hf_exception}") |
98 | | - raise FileNotFoundError(f"Checkpoint not found: {model_id}") from hf_exception |
99 | | - |
100 | | - |
101 | | -def ensure_checkpoint_is_local( |
102 | | - checkpoint_path: str | Path, cache_dir: str | Path | None = None |
103 | | -) -> Path: |
104 | | - """ |
105 | | - Ensure we have a local copy of the checkpoint. |
106 | | -
|
107 | | - If the path exists locally, return it. Otherwise, treat it as a |
108 | | - HuggingFace model ID and download it. |
109 | | -
|
110 | | - :param checkpoint_path: Local path or HuggingFace model ID |
111 | | - :param cache_dir: Optional cache directory for downloads |
112 | | - :return: Path to local checkpoint directory |
113 | | -
|
114 | | - :Example: |
115 | | -
|
116 | | - >>> # Local path - returned as-is |
117 | | - >>> local = ensure_checkpoint_is_local("./my_checkpoint") |
118 | | -
|
119 | | - >>> # HuggingFace ID - downloaded first |
120 | | - >>> downloaded = ensure_checkpoint_is_local( |
121 | | - ... "yuhuili/EAGLE-LLaMA3.1-Instruct-8B" |
122 | | - ... ) |
123 | | - """ |
124 | | - checkpoint_path = Path(checkpoint_path) |
125 | | - |
126 | | - if checkpoint_path.exists(): |
127 | | - logger.debug(f"Using local checkpoint: {checkpoint_path}") |
128 | | - return checkpoint_path |
129 | | - |
130 | | - return download_checkpoint_from_hub( |
131 | | - model_id=str(checkpoint_path), cache_dir=str(cache_dir) if cache_dir else None |
132 | | - ) |
133 | | - |
134 | | - |
135 | | -def load_checkpoint_config(checkpoint_dir: Path) -> dict: |
136 | | - """ |
137 | | - Load the config.json from a checkpoint directory. |
138 | | -
|
139 | | - :param checkpoint_dir: Path to checkpoint directory |
140 | | - :return: Config dictionary |
141 | | - :raises FileNotFoundError: If config.json is not found |
142 | | -
|
143 | | - :Example: |
144 | | -
|
145 | | - >>> config = load_checkpoint_config(Path("./checkpoint")) |
146 | | - >>> print(config["model_type"]) |
147 | | - llama |
148 | | - """ |
149 | | - config_path = checkpoint_dir / "config.json" |
150 | | - if not config_path.exists(): |
151 | | - raise FileNotFoundError(f"No config.json found at {checkpoint_dir}") |
152 | | - |
153 | | - logger.debug(f"Loading config from: {config_path}") |
154 | | - with config_path.open() as f: |
155 | | - return json.load(f) |
156 | | - |
157 | | - |
158 | | -def load_checkpoint_weights(checkpoint_dir: Path) -> dict[str, torch.Tensor]: |
159 | | - """ |
160 | | - Load model weights from a checkpoint directory. |
161 | | -
|
162 | | - Supports both safetensors and PyTorch bin formats. |
163 | | -
|
164 | | - :param checkpoint_dir: Path to checkpoint directory |
165 | | - :return: Dictionary mapping weight names to tensors |
166 | | - :raises FileNotFoundError: If no weights are found |
167 | | - :raises NotImplementedError: If checkpoint is sharded |
168 | | -
|
169 | | - :Example: |
170 | | -
|
171 | | - >>> weights = load_checkpoint_weights(Path("./checkpoint")) |
172 | | - >>> print(f"Loaded {len(weights)} weights") |
173 | | - Loaded 50 weights |
174 | | - """ |
175 | | - weights = {} |
176 | | - |
177 | | - safetensors_path = checkpoint_dir / "model.safetensors" |
178 | | - if safetensors_path.exists(): |
179 | | - logger.debug(f"Loading safetensors weights from: {safetensors_path}") |
180 | | - with safe_open(safetensors_path, framework="pt") as f: |
181 | | - # safetensors requires iterating over keys() method |
182 | | - for key in f.keys(): # noqa: SIM118 |
183 | | - weights[key] = f.get_tensor(key) |
184 | | - return weights |
185 | | - |
186 | | - pytorch_path = checkpoint_dir / "pytorch_model.bin" |
187 | | - if pytorch_path.exists(): |
188 | | - logger.debug(f"Loading PyTorch weights from: {pytorch_path}") |
189 | | - return torch.load(pytorch_path, map_location="cpu") |
190 | | - |
191 | | - index_paths = [ |
192 | | - checkpoint_dir / "model.safetensors.index.json", |
193 | | - checkpoint_dir / "pytorch_model.bin.index.json", |
194 | | - ] |
195 | | - for index_path in index_paths: |
196 | | - if index_path.exists(): |
197 | | - raise NotImplementedError( |
198 | | - f"Sharded checkpoint detected: {index_path}. " |
199 | | - "Please use a single-file checkpoint." |
200 | | - ) |
201 | | - |
202 | | - raise FileNotFoundError(f"No weights found at {checkpoint_dir}") |
203 | | - |
204 | | - |
205 | 68 | def detect_fusion_bias_and_layernorms( |
206 | 69 | weights: dict[str, torch.Tensor], |
207 | 70 | ) -> tuple[bool, bool]: |
|
0 commit comments