| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import os |
| from typing import Dict, Optional, Union |
|
|
| import torch |
|
|
| __all__ = ["load_fp8_scales", "load_quantized_model", "save_quantized_model"] |
|
|
|
|
| def load_fp8_scales( |
| quant_scales: Optional[Union[str, Dict[str, torch.Tensor]]] |
| ) -> Dict[str, torch.Tensor]: |
| """Load FP8 quant scales from dict, file, or dir. Prefer .safetensors.""" |
| if quant_scales is None: |
| raise ValueError("quant_scales is required") |
|
|
| if isinstance(quant_scales, dict) and len(quant_scales) > 0: |
| |
| return quant_scales |
|
|
| if isinstance(quant_scales, str): |
| |
| if os.path.isfile(quant_scales): |
| if quant_scales.endswith(".safetensors"): |
| import safetensors.torch |
|
|
| print(f"Loaded scale map from {quant_scales}") |
| return safetensors.torch.load_file(quant_scales) |
| else: |
| print(f"Loaded scale map from {quant_scales}") |
| return torch.load(quant_scales) |
| |
| if os.path.isdir(quant_scales): |
| safetensors_path = os.path.join(quant_scales, "fp8_scales.safetensors") |
| pth_path = os.path.join(quant_scales, "fp8_scales.pth") |
| if os.path.isfile(safetensors_path): |
| import safetensors.torch |
|
|
| print(f"Loaded scale map from {safetensors_path}") |
| return safetensors.torch.load_file(safetensors_path) |
| if os.path.isfile(pth_path): |
| print(f"Loaded scale map from {pth_path}") |
| return torch.load(pth_path) |
| raise FileNotFoundError( |
| f"Quant scale file not found: {pth_path} or {safetensors_path}" |
| ) |
| raise FileNotFoundError(f"quant_scales path does not exist: {quant_scales}") |
|
|
| raise ValueError(f"Invalid quant_scales type: {type(quant_scales)}. Only str (path) or dict.") |
|
|
|
|
| def save_quantized_model(model: torch.nn.Module, save_path: str, fp8_scales_map: Dict): |
| """ |
| Save quantized model and scale dict to directory. |
| """ |
| import logging |
|
|
| logger = logging.getLogger(__name__) |
|
|
| if not os.path.exists(save_path): |
| try: |
| os.makedirs(save_path, exist_ok=True) |
| except Exception as e: |
| raise RuntimeError(f"Cannot create directory for save_path: {save_path}. Error: {e}") |
|
|
| try: |
| |
| if hasattr(model, "save_pretrained"): |
| model.save_pretrained(save_path) |
| logger.info(f"Saved quantized model to {save_path} via save_pretrained") |
| else: |
| |
| from safetensors.torch import save_file as safe_save |
|
|
| model_path = os.path.join(save_path, "model.safetensors") |
| safe_save(model.state_dict(), model_path) |
| logger.info(f"Saved state_dict to {model_path}") |
|
|
| |
| from safetensors.torch import save_file as safe_save |
|
|
| scale_save_path = os.path.join(save_path, "fp8_scales.safetensors") |
| safe_save(fp8_scales_map, scale_save_path) |
| logger.info(f"Saved scales map to {scale_save_path}") |
|
|
| except Exception as e: |
| raise RuntimeError(f"Failed to save model and scales map to {save_path}. Error: {e}") |
|
|
|
|
| def load_quantized_model(model_class, save_path: str, device: str = "cpu"): |
| """ |
| Load quantized model from directory. |
| """ |
| import logging |
|
|
| logger = logging.getLogger(__name__) |
|
|
| try: |
| |
| if hasattr(model_class, "from_pretrained"): |
| model = model_class.from_pretrained(save_path) |
| logger.info(f"Loaded Hugging Face model from {save_path}") |
| return model |
| except Exception as e: |
| logger.warning(f"Failed to load as Hugging Face model: {e}") |
|
|
| try: |
| |
| model_path = os.path.join(save_path, "model.safetensors") |
| if os.path.exists(model_path): |
| from safetensors.torch import load_file as safe_load |
|
|
| state_dict = safe_load(model_path, device=device) |
| model = model_class() |
| model.load_state_dict(state_dict) |
| model.to(device) |
| logger.info(f"Loaded model from {model_path} (safetensors)") |
| return model |
|
|
| |
| model_path = os.path.join(save_path, "pytorch_model.bin") |
| if os.path.exists(model_path): |
| state_dict = torch.load(model_path, map_location=device) |
| model = model_class() |
| model.load_state_dict(state_dict) |
| model.to(device) |
| logger.info(f"Loaded model from {model_path} (pytorch)") |
| return model |
| else: |
| raise FileNotFoundError( |
| f"Model file not found at {save_path}. " |
| "Expected 'model.safetensors' or 'pytorch_model.bin'" |
| ) |
|
|
| except Exception as e: |
| raise RuntimeError(f"Failed to load model from {save_path}. Error: {e}") |
|
|