"""Lee solo el header de un archivo safetensors sin cargar los tensores en RAM.""" from __future__ import annotations import json import struct def safetensors_inspect(path: str) -> dict: """Lee el header de un archivo safetensors sin cargar los tensores. El formato safetensors almacena al inicio del archivo: - 8 bytes: uint64 little-endian con la longitud del header JSON (N). - N bytes: JSON con metadata y descriptores de tensores. Este enfoque evita cargar gigabytes de pesos en RAM para inspeccionar un checkpoint: solo se leen los primeros 8 + N bytes. Spec: https://github.com/huggingface/safetensors#format Args: path: ruta al archivo .safetensors (absoluta o relativa). Returns: dict con claves: path (str): ruta absoluta del archivo. metadata (dict): metadatos del modelo (campo "__metadata__" del header). tensors (list[dict]): lista de tensores, cada uno con: name (str): nombre del tensor. dtype (str): tipo de dato (F32, BF16, F16, I32, etc.). shape (list[int]): dimensiones del tensor. data_offsets (list[int]): [inicio, fin] en bytes dentro del bloque de datos (para acceso lazy si se necesita). total_size_bytes (int): tamano total del archivo en bytes. n_tensors (int): numero de tensores en el archivo. Raises: FileNotFoundError: si el archivo no existe. ValueError: si el archivo no es un safetensors valido. OSError: si no se puede leer el archivo. """ import os abs_path = os.path.abspath(path) if not os.path.isfile(abs_path): raise FileNotFoundError(f"safetensors_inspect: archivo no encontrado: {abs_path}") total_size = os.path.getsize(abs_path) with open(abs_path, "rb") as f: # Leer los 8 bytes del tamano del header raw_len = f.read(8) if len(raw_len) < 8: raise ValueError( f"safetensors_inspect: archivo demasiado corto para ser safetensors: {abs_path}" ) header_len = struct.unpack(" total_size: raise ValueError( f"safetensors_inspect: header_len invalido ({header_len}) en {abs_path}" ) raw_header = f.read(header_len) if len(raw_header) < header_len: raise ValueError( f"safetensors_inspect: no se pudo leer el header completo en {abs_path}" ) try: header = json.loads(raw_header.decode("utf-8")) except (json.JSONDecodeError, UnicodeDecodeError) as exc: raise ValueError( f"safetensors_inspect: header JSON invalido en {abs_path}: {exc}" ) from exc metadata = header.get("__metadata__", {}) tensors = [] for name, desc in header.items(): if name == "__metadata__": continue tensors.append( { "name": name, "dtype": desc.get("dtype", ""), "shape": desc.get("shape", []), "data_offsets": desc.get("data_offsets", []), } ) return { "path": abs_path, "metadata": metadata, "tensors": tensors, "total_size_bytes": total_size, "n_tensors": len(tensors), }