Coverage for  / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / components / checkpoint / load_groups.py: 83%

271 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-11-15 07:18 +0800

1# Copyright 2026 Huawei Technologies Co., Ltd 

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"""Hugging Face checkpoint names and layouts, mapped onto the tensors of a finalized model. 

16 

17Both pretrained loaders are built on what is here. :class:`HuggingFaceCheckpointer` reads whole checkpoint 

18tensors and converts them in memory, while :class:`HFLoadPlanner` plans the same conversions as 

19distributed checkpoint reads. Keys are renamed, converters are chosen and replacement conversions are 

20routed the same way in both, so the two load the same values under the same names. 

21""" 

22import json 

23import logging 

24from collections import Counter, OrderedDict, defaultdict 

25from collections.abc import Callable, Iterable, Sequence 

26from copy import deepcopy 

27from dataclasses import dataclass 

28from pathlib import Path 

29from typing import Any, Optional 

30 

31import torch 

32from huggingface_hub import snapshot_download 

33from safetensors import safe_open 

34from torch import nn 

35 

36from hyper_parallel import DTensor, Partial, distribute_tensor 

37from hyper_parallel.components.checkpoint.weight_conversion import ( 

38 WeightConverter, 

39 WeightRenaming, 

40 dot_natural_key, 

41 rename_source_key, 

42) 

43 

44logger = logging.getLogger(__name__) 

45 

46SAFE_WEIGHTS_NAME = "model.safetensors" 

47SAFE_WEIGHTS_INDEX_NAME = "model.safetensors.index.json" 

48_SNAPSHOT_PATTERNS = ("*.safetensors", "*.safetensors.index.json", "engram_host_rows.json") 

49 

50# Picks the converter a checkpoint key matched by ``source pattern`` belongs to, for the model tensor 

51# ``target name``, out of every converter with that source pattern. None when no single one fits. 

52ConverterSelector = Callable[[str, str, Sequence[WeightConverter]], Optional[WeightConverter]] 

53 

54 

55@dataclass(frozen=True) 

56class LoadReport: 

57 """Summary of one pretrained-weight load.""" 

58 

59 loaded_keys: tuple[str, ...] 

60 missing_keys: tuple[str, ...] 

61 unexpected_keys: tuple[str, ...] 

62 

63 

64@dataclass(frozen=True) 

65class CheckpointIndex: 

66 """Map checkpoint tensor names to their safetensors shard files.""" 

67 

68 files_by_key: dict[str, Path] 

69 

70 def keys(self) -> tuple[str, ...]: 

71 """Return checkpoint keys in deterministic natural order.""" 

72 return sorted_checkpoint_keys(self.files_by_key) 

73 

74 def load_tensor(self, key: str) -> torch.Tensor: 

75 """Materialize one checkpoint tensor on CPU.""" 

76 file_path = self.files_by_key.get(key) 

77 if file_path is None: 

78 raise ValueError(f"Checkpoint key is not indexed: {key}") 

79 with safe_open(str(file_path), framework="pt", device="cpu") as checkpoint: 

80 return checkpoint.get_tensor(key) 

81 

82 

83@dataclass 

84class LoadGroup: 

85 """Checkpoint tensors converted together, and the transform converting them.""" 

86 

87 first_target_name: str 

88 transform: WeightRenaming | WeightConverter 

89 

90 

91@dataclass(frozen=True) 

92class _TensorShape: 

93 """Shape of a model tensor, as shape-aware conversion operations ask for it.""" 

94 

95 shape: torch.Size 

96 

97 

98class SourceModelView: 

99 """Expose pre-replacement parameter shapes to Transformers conversion ops.""" 

100 

101 def __init__(self, model: nn.Module, shapes: dict[str, tuple[int, ...]]) -> None: 

102 """Build a lightweight model view from captured tensor shapes.""" 

103 self.config = getattr(model, "config", None) 

104 self.base_model_prefix = getattr(model, "base_model_prefix", None) 

105 self._targets = { 

106 name: _TensorShape(torch.Size(shape)) for name, shape in shapes.items() 

107 } 

108 

109 @property 

110 def targets(self) -> dict[str, _TensorShape]: 

111 """Shape of every pre-replacement tensor, by name.""" 

112 return self._targets 

113 

114 def get_parameter(self, name: str) -> _TensorShape: 

115 """Return source parameter metadata used by shape-aware converters.""" 

116 try: 

117 return self._targets[name] 

118 except KeyError as exc: 

119 raise AttributeError(f"source model has no parameter {name!r}") from exc 

120 

121 

122@dataclass 

123class ReplacementLoadGroup: 

124 """A replacement conversion waiting for the normalized tensors it is routed.""" 

125 

126 group: LoadGroup 

127 expected: Counter[str] 

128 received: Counter[str] 

129 completed: bool = False 

130 

131 

132def sorted_checkpoint_keys(keys: Iterable[str]) -> tuple[str, ...]: 

133 """Checkpoint keys in natural order, experts 2 before 10, which is the order loads collect them in.""" 

134 return tuple(sorted(keys, key=dot_natural_key)) 

135 

136 

137def _index_single_file(file_path: Path) -> CheckpointIndex: 

138 """Index every tensor of one safetensors file.""" 

139 with safe_open(str(file_path), framework="pt", device="cpu") as checkpoint: 

140 files_by_key = {key: file_path for key in checkpoint.keys()} 

141 return CheckpointIndex(files_by_key) 

142 

143 

144def _index_sharded_checkpoint(directory: Path, index_path: Path) -> CheckpointIndex: 

145 """Index tensors described by a sharded safetensors index file.""" 

146 try: 

147 index_data = json.loads(index_path.read_text(encoding="utf-8")) 

148 except (OSError, json.JSONDecodeError) as exc: 

149 raise ValueError(f"Failed to read safetensors index {index_path}: {exc}") from exc 

150 weight_map = index_data.get("weight_map") 

151 if not isinstance(weight_map, dict) or not weight_map: 

152 raise ValueError(f"Safetensors index has no non-empty weight_map: {index_path}") 

153 

154 files_by_key = {} 

155 for key, relative_path in weight_map.items(): 

156 file_path = directory / relative_path 

157 if not file_path.is_file(): 

158 raise ValueError(f"Safetensors shard for {key} does not exist: {file_path}") 

159 files_by_key[key] = file_path 

160 return CheckpointIndex(files_by_key) 

161 

162 

163def resolve_checkpoint_location(pretrained_path: str) -> Path: 

164 """ 

165 Resolve a pretrained path into a local safetensors file or checkpoint directory. 

166 

167 Args: 

168 pretrained_path (str): A ``.safetensors`` file, a checkpoint directory, or a Hub repository id, 

169 which is downloaded first. 

170 

171 Returns: 

172 Path: The file or the directory. 

173 

174 Raises: 

175 ValueError: If the path is a file of another kind. 

176 """ 

177 path = Path(pretrained_path).expanduser() 

178 if path.is_file(): 

179 if path.suffix != ".safetensors": 

180 raise ValueError(f"MVP only supports safetensors checkpoints, got: {path}") 

181 return path 

182 if path.is_dir(): 

183 return path 

184 return Path( 

185 snapshot_download( 

186 repo_id=pretrained_path, 

187 allow_patterns=list(_SNAPSHOT_PATTERNS), 

188 ) 

189 ) 

190 

191 

192def resolve_checkpoint_index(pretrained_path: str) -> CheckpointIndex: 

193 """Resolve a local or Hub checkpoint into a tensor-to-file index.""" 

194 location = resolve_checkpoint_location(pretrained_path) 

195 if location.is_file(): 

196 return _index_single_file(location) 

197 

198 index_path = location / SAFE_WEIGHTS_INDEX_NAME 

199 if index_path.is_file(): 

200 return _index_sharded_checkpoint(location, index_path) 

201 

202 single_file = location / SAFE_WEIGHTS_NAME 

203 if single_file.is_file(): 

204 return _index_single_file(single_file) 

205 raise ValueError( 

206 "MVP requires model.safetensors or model.safetensors.index.json under " 

207 f"{location}" 

208 ) 

209 

210 

211def join_fqn(module_name: str, tensor_name: str) -> str: 

212 """Name of a tensor registered on the module named ``module_name``.""" 

213 return f"{module_name}.{tensor_name}" if module_name else tensor_name 

214 

215 

216def build_load_targets(model: nn.Module) -> dict[str, torch.Tensor]: 

217 """Collect persistent parameters and buffers owned by the model.""" 

218 targets = {} 

219 # Direct module registries preserve tied aliases and let us exclude 

220 # non-persistent buffers without materializing an FSDP state_dict. 

221 for module_name, module in model.named_modules(remove_duplicate=False): 

222 for tensor_name, parameter in module._parameters.items(): # pylint: disable=W0212 

223 if parameter is not None: 

224 targets[join_fqn(module_name, tensor_name)] = parameter 

225 non_persistent = module._non_persistent_buffers_set # pylint: disable=W0212 

226 for tensor_name, buffer in module._buffers.items(): # pylint: disable=W0212 

227 if buffer is not None and tensor_name not in non_persistent: 

228 targets[join_fqn(module_name, tensor_name)] = buffer 

229 return targets 

230 

231 

232def checkpoint_logical_shapes(model: nn.Module) -> dict[str, tuple[int, ...]]: 

233 """Collect model-declared logical parameter shapes for trailing padding on any dimensions. 

234 

235 Modules may expose ``checkpoint_logical_shapes()`` returning logical shapes 

236 keyed by parameter names relative to that module. Undeclared parameters keep 

237 the normal strict checkpoint shape checks. 

238 

239 Args: 

240 model: Model whose modules declare logical checkpoint shapes. 

241 

242 Returns: 

243 Logical shapes keyed by fully qualified model parameter names. 

244 """ 

245 shapes = {} 

246 for module_name, module in model.named_modules(): 

247 provider = getattr(module, "checkpoint_logical_shapes", None) 

248 if not callable(provider): 

249 continue 

250 declared = provider() 

251 if not isinstance(declared, dict): 

252 raise ValueError(f"Invalid checkpoint padding declaration on {module_name}") 

253 for parameter_name, shape in declared.items(): 

254 parameter = module.get_parameter(parameter_name) 

255 if (not isinstance(shape, tuple) or len(shape) != parameter.ndim 

256 or any(not isinstance(size, int) or isinstance(size, bool) or size < 0 for size in shape)): 

257 raise ValueError(f"Invalid logical checkpoint shape on {module_name}: {shape}") 

258 name = join_fqn(module_name, parameter_name) 

259 if name in shapes and shapes[name] != shape: 

260 raise ValueError(f"Conflicting logical checkpoint shapes for {name}") 

261 shapes[name] = shape 

262 return shapes 

263 

264 

265def checkpoint_padding_boxes( 

266 logical_shape: tuple[int, ...], offsets: tuple[int, ...], sizes: tuple[int, ...], 

267) -> list[tuple[tuple[int, ...], tuple[int, ...]]]: 

268 """Partition a local shard's trailing padding into disjoint local boxes. 

269 

270 Args: 

271 logical_shape: Unpadded global checkpoint dimensions. 

272 offsets: Global origin of this rank's rectangular shard. 

273 sizes: Dimensions of this rank's local shard. 

274 

275 Returns: 

276 Local offsets and dimensions of non-overlapping padding boxes. 

277 """ 

278 if len(logical_shape) != len(offsets) or len(offsets) != len(sizes): 

279 raise ValueError("Logical shape and local shard must have the same number of dimensions") 

280 valid = tuple(max(0, min(size, logical - offset)) 

281 for logical, offset, size in zip(logical_shape, offsets, sizes)) 

282 boxes = [] 

283 for axis, (length, size) in enumerate(zip(valid, sizes)): 

284 lengths = valid[:axis] + (size - length,) + sizes[axis + 1:] 

285 if all(lengths): 

286 starts = (0,) * axis + (length,) + (0,) * (len(sizes) - axis - 1) 

287 boxes.append((starts, lengths)) 

288 return boxes 

289 

290 

291def make_tensor_loader(index: CheckpointIndex, source_key: str) -> Callable[[], torch.Tensor]: 

292 """A loader reading one checkpoint tensor when a conversion asks for it.""" 

293 return lambda: index.load_tensor(source_key) 

294 

295 

296def _scoped_candidates(candidates: Sequence[WeightConverter], target_name: str) -> list[WeightConverter]: 

297 """The candidates scoped to a module that holds ``target_name``.""" 

298 return [ 

299 converter 

300 for converter in candidates 

301 if converter.scope_prefix is not None 

302 and ( 

303 target_name == converter.scope_prefix 

304 or target_name.startswith(f"{converter.scope_prefix}.") 

305 ) 

306 ] 

307 

308 

309def select_unique_converter( 

310 source_pattern: str, 

311 target_name: str, 

312 candidates: Sequence[WeightConverter], 

313) -> Optional[WeightConverter]: 

314 """ 

315 Pick the converter a matched checkpoint key belongs to. 

316 

317 A converter scoped to a module holding the target wins when it is the only one. Otherwise the only 

318 unscoped converter does. 

319 

320 Args: 

321 source_pattern (str): The source pattern the key matched. 

322 target_name (str): The model tensor the key was renamed to. 

323 candidates (Sequence[WeightConverter]): Every converter with that source pattern. 

324 

325 Returns: 

326 Optional[WeightConverter]: The converter, or None when neither rule picks exactly one. 

327 """ 

328 del source_pattern 

329 scoped_candidates = _scoped_candidates(candidates, target_name) 

330 if len(scoped_candidates) == 1: 

331 return scoped_candidates[0] 

332 unscoped_candidates = [converter for converter in candidates if converter.scope_prefix is None] 

333 return unscoped_candidates[0] if len(unscoped_candidates) == 1 else None 

334 

335 

336def _split_transforms( 

337 transforms: Sequence[Any], 

338) -> tuple[list[WeightRenaming], list[WeightConverter], dict[str, list[WeightConverter]]]: 

339 """Renamings, converters, and the converters by each of their source patterns.""" 

340 renamings = [transform for transform in transforms if isinstance(transform, WeightRenaming)] 

341 converters = [transform for transform in transforms if isinstance(transform, WeightConverter)] 

342 converters_by_pattern = defaultdict(list) 

343 for converter in converters: 

344 for pattern in converter.source_patterns: 

345 converters_by_pattern[pattern].append(converter) 

346 return renamings, converters, converters_by_pattern 

347 

348 

349def build_load_groups( 

350 model: Any, 

351 source_keys: Iterable[str], 

352 targets: dict[str, Any], 

353 *, 

354 weights_mapping: list[WeightRenaming | WeightConverter], 

355 make_loader: Callable[[str], Any], 

356 select_converter: ConverterSelector = select_unique_converter, 

357) -> tuple[ 

358 tuple[LoadGroup, ...], 

359 tuple[str, ...], 

360 list[WeightRenaming | WeightConverter], 

361]: 

362 """ 

363 Build checkpoint conversion groups and report unmatched checkpoint keys. 

364 

365 Args: 

366 model (Any): The model, or the view of it the keys are renamed against. 

367 source_keys (Iterable[str]): Checkpoint keys, in the order their tensors are collected. 

368 targets (dict[str, Any]): Model tensors by name. 

369 weights_mapping (list[WeightRenaming | WeightConverter]): Rules renaming and converting keys. 

370 make_loader (Callable[[str], Any]): Called with a key, returns what the group collects for it. 

371 select_converter (ConverterSelector): Picks the converter of a matched key. 

372 Default :func:`select_unique_converter`. 

373 

374 Returns: 

375 tuple: The groups in order of their first key, the keys renamed to no target, and the mapping. 

376 """ 

377 unsupported = [ 

378 transform 

379 for transform in weights_mapping 

380 if not isinstance(transform, (WeightRenaming, WeightConverter)) 

381 ] 

382 if unsupported: 

383 names = ", ".join(type(transform).__name__ for transform in unsupported) 

384 raise ValueError(f"Unsupported Transformers weight transforms in MVP: {names}") 

385 

386 renamings, converters, converters_by_pattern = _split_transforms(weights_mapping) 

387 groups: OrderedDict[str, LoadGroup] = OrderedDict() 

388 unexpected_keys = [] 

389 base_model_prefix = getattr(model, "base_model_prefix", None) 

390 

391 for source_key in source_keys: 

392 target_name, source_pattern = rename_source_key( 

393 source_key, 

394 renamings, 

395 converters, 

396 base_model_prefix=base_model_prefix, 

397 meta_state_dict=targets, 

398 ) 

399 if target_name not in targets and source_key in targets: 

400 target_name, source_pattern = rename_source_key( 

401 source_key, 

402 [], 

403 [], 

404 base_model_prefix=base_model_prefix, 

405 meta_state_dict=targets, 

406 ) 

407 if target_name not in targets: 

408 unexpected_keys.append(source_key) 

409 continue 

410 

411 if source_pattern is None: 

412 source_pattern = source_key 

413 transform = WeightRenaming(source_patterns=source_key, target_patterns=target_name) 

414 else: 

415 converter = select_converter( 

416 source_pattern, target_name, converters_by_pattern.get(source_pattern, []) 

417 ) 

418 if converter is None: 

419 raise ValueError( 

420 "No unique WeightConverter found for matched source pattern " 

421 f"{source_pattern!r} and target {target_name!r}" 

422 ) 

423 transform = deepcopy(converter) 

424 

425 group = groups.setdefault( 

426 target_name, 

427 LoadGroup(first_target_name=target_name, transform=transform), 

428 ) 

429 group.transform.add_tensor(target_name, source_key, source_pattern, make_loader(source_key)) 

430 

431 return tuple(groups.values()), tuple(unexpected_keys), weights_mapping 

432 

433 

434def build_replacement_routes( 

435 model: nn.Module, 

436 source_names: tuple[str, ...], 

437 targets: dict[str, torch.Tensor], 

438 transforms: list[WeightRenaming | WeightConverter], 

439) -> dict[str, tuple[ReplacementLoadGroup, str, str]]: 

440 """Route normalized Transformers parameters into replacement converters.""" 

441 renamings, converters, converters_by_pattern = _split_transforms(deepcopy(transforms)) 

442 groups: OrderedDict[str, ReplacementLoadGroup] = OrderedDict() 

443 routes = {} 

444 base_model_prefix = getattr(model, "base_model_prefix", None) 

445 for source_name in source_names: 

446 target_name, source_pattern = rename_source_key( 

447 source_name, 

448 renamings, 

449 converters, 

450 base_model_prefix=base_model_prefix, 

451 meta_state_dict=targets, 

452 ) 

453 if source_pattern is None and target_name == source_name: 

454 continue 

455 if target_name not in targets: 

456 continue 

457 

458 if source_pattern is None: 

459 collected_pattern = source_name 

460 transform: WeightRenaming | WeightConverter = WeightRenaming( 

461 source_patterns=source_name, 

462 target_patterns=target_name, 

463 ) 

464 else: 

465 collected_pattern = source_pattern 

466 scoped_candidates = _scoped_candidates(converters_by_pattern.get(source_pattern, []), target_name) 

467 if len(scoped_candidates) != 1: 

468 raise ValueError( 

469 "No unique replacement WeightConverter found for source " 

470 f"{source_name!r} and target {target_name!r}" 

471 ) 

472 transform = deepcopy(scoped_candidates[0]) 

473 

474 state = groups.get(target_name) 

475 if state is None: 

476 state = ReplacementLoadGroup( 

477 group=LoadGroup(target_name, transform), 

478 expected=Counter(), 

479 received=Counter(), 

480 ) 

481 groups[target_name] = state 

482 state.expected[collected_pattern] += 1 

483 routes[source_name] = (state, target_name, collected_pattern) 

484 return routes 

485 

486 

487def base_weights_mapping( 

488 weights_mapping: list[WeightRenaming | WeightConverter], 

489 replacement_mapping: list[WeightRenaming | WeightConverter], 

490) -> list[WeightRenaming | WeightConverter]: 

491 """The rules of ``weights_mapping`` that are not replacement conversions.""" 

492 replacement_ids = {id(transform) for transform in replacement_mapping} 

493 return [transform for transform in weights_mapping if id(transform) not in replacement_ids] 

494 

495 

496def first_tensor(value: Any) -> Any: 

497 """The tensor a conversion returned under one name, which a renaming returns in a list.""" 

498 return value[0] if isinstance(value, list) else value 

499 

500 

501def convert_group(group: LoadGroup, model: Any) -> dict[str, Any]: 

502 """ 

503 Convert all checkpoint tensors belonging to one load group. 

504 

505 Args: 

506 group (LoadGroup): The group, its tensors already collected. 

507 model (Any): The model, or the view of it, handed to the conversion operations. 

508 

509 Returns: 

510 dict[str, Any]: Converted tensors by model tensor name. 

511 

512 Raises: 

513 RuntimeError: If the conversion fails, naming the group. 

514 """ 

515 try: 

516 return group.transform.convert( 

517 group.first_target_name, 

518 model=model, 

519 config=getattr(model, "config", None), 

520 hf_quantizer=None, 

521 loading_info=None, 

522 ) 

523 except Exception as exc: 

524 raise RuntimeError( 

525 f"Failed to convert checkpoint tensors for {group.first_target_name}: {exc}" 

526 ) from exc 

527 

528 

529def local_target_tensor(target: torch.Tensor) -> torch.Tensor: 

530 """The part of a model tensor held on this rank.""" 

531 return target.to_local() if isinstance(target, DTensor) else target 

532 

533 

534def target_layout(target: torch.Tensor) -> Any: 

535 """The layout a model tensor is sharded with, or None for a whole tensor.""" 

536 if isinstance(target, DTensor) and target.layout is not None: 

537 return target.layout 

538 return getattr(target, "_sharding_spec", None) 

539 

540 

541def reject_partial_layout(target_name: str, layout: Any) -> None: 

542 """Refuse a layout with a Partial placement, which pretrained loads do not support.""" 

543 if any(isinstance(placement, Partial) for placement in layout.placements): 

544 raise ValueError(f"Partial placement is not supported for pretrained loading: {target_name}") 

545 

546 

547def shard_for_target(target_name: str, full_tensor: torch.Tensor, target: torch.Tensor) -> torch.Tensor: 

548 """Shard a full checkpoint tensor according to its target layout.""" 

549 layout = target_layout(target) 

550 if layout is None: 

551 return full_tensor 

552 reject_partial_layout(target_name, layout) 

553 

554 local_dtensor = distribute_tensor( 

555 full_tensor, 

556 layout.mesh, 

557 layout.alias_placements, 

558 src_data_rank=None, 

559 ) 

560 return local_dtensor.to_local() 

561 

562 

563def copy_into_target( 

564 target_name: str, full_tensor: torch.Tensor, target: torch.Tensor, 

565 logical_shape: tuple[int, ...] | None = None, 

566) -> None: 

567 """Copy a checkpoint tensor into its materialized local target.""" 

568 layout = target_layout(target) 

569 target_shape = tuple(getattr(layout, "tensor_shape", None) or target.shape) 

570 if logical_shape is not None and tuple(full_tensor.shape) == logical_shape and target_shape != logical_shape: 

571 if (len(logical_shape) != len(target_shape) 

572 or any(logical > physical for logical, physical in zip(logical_shape, target_shape))): 

573 raise ValueError(f"Invalid checkpoint padding shape for {target_name}") 

574 padded = full_tensor.new_zeros(target_shape) 

575 padded[tuple(slice(0, size) for size in logical_shape)].copy_(full_tensor) 

576 full_tensor = padded 

577 local_tensor = shard_for_target(target_name, full_tensor, target) 

578 destination = local_target_tensor(target) 

579 if destination.is_meta: 

580 raise ValueError(f"Target must be materialized before loading: {target_name}") 

581 if tuple(local_tensor.shape) != tuple(destination.shape): 

582 raise ValueError( 

583 f"Local shape mismatch for {target_name}: checkpoint shard " 

584 f"{tuple(local_tensor.shape)} vs target {tuple(destination.shape)}" 

585 ) 

586 local_tensor = local_tensor.to(device=destination.device, dtype=destination.dtype) 

587 with torch.no_grad(): 

588 destination.copy_(local_tensor) 

589 target._is_hf_initialized = True # pylint: disable=W0212 

590 

591 

592def alias_names_by_target(targets: dict[str, torch.Tensor]) -> dict[int, set[str]]: 

593 """Every name each model tensor is registered under, by the identity of the tensor.""" 

594 aliases = defaultdict(set) 

595 for target_name, target in targets.items(): 

596 aliases[id(target)].add(target_name) 

597 return aliases 

598 

599 

600def validate_load_result( 

601 missing_keys: tuple[str, ...], 

602 unexpected_keys: tuple[str, ...], 

603 strict: bool, 

604) -> None: 

605 """Validate missing keys and report ignored checkpoint tensors.""" 

606 if strict and missing_keys: 

607 preview = ", ".join(missing_keys[:10]) 

608 raise RuntimeError( 

609 f"Checkpoint did not load {len(missing_keys)} owned model tensors; " 

610 f"first keys: {preview}" 

611 ) 

612 if unexpected_keys: 

613 logger.warning( 

614 "Ignored %d checkpoint tensors not owned by this model/rank; first keys: %s", 

615 len(unexpected_keys), 

616 ", ".join(unexpected_keys[:10]), 

617 )