#!/usr/bin/env python3 import argparse import json import shutil import struct from pathlib import Path def load_json(path: Path): with open(path, "r", encoding="utf-8") as handle: return json.load(handle) def save_json(path: Path, value): with open(path, "w", encoding="utf-8") as handle: json.dump(value, handle, indent=2, ensure_ascii=False) handle.write("\n") def load_safetensors_header(path: Path): with open(path, "rb") as handle: header_len = struct.unpack(" int: start, end = entry["data_offsets"] return end - start def tensor_element_count(entry: dict) -> int: count = 1 for dim in entry["shape"]: count *= dim return count def build_vision_shard( original_model_dir: Path, original_index: dict, output_path: Path, ): weight_map = original_index["weight_map"] visual_keys = sorted(key for key in weight_map if key.startswith("model.visual")) if not visual_keys: raise ValueError("original model has no model.visual tensors") source_headers = {} output_header = {} output_payload = bytearray() parameter_count = 0 for key in visual_keys: shard_name = weight_map[key] shard_path = original_model_dir / shard_name if shard_path not in source_headers: source_headers[shard_path] = load_safetensors_header(shard_path) _, source_header = source_headers[shard_path] entry = source_header[key] data_start, data_end = entry["data_offsets"] renamed_key = key.replace("model.visual", "vision_tower", 1) parameter_count += tensor_element_count(entry) with open(shard_path, "rb") as handle: payload_base = 8 + source_headers[shard_path][0] handle.seek(payload_base + data_start) tensor_bytes = handle.read(data_end - data_start) new_start = len(output_payload) output_payload.extend(tensor_bytes) new_end = len(output_payload) output_header[renamed_key] = { "dtype": entry["dtype"], "shape": entry["shape"], "data_offsets": [new_start, new_end], } header_bytes = json.dumps(output_header, separators=(",", ":"), ensure_ascii=False).encode( "utf-8" ) with open(output_path, "wb") as handle: handle.write(struct.pack("