Spaces:
Running
Running
| import os | |
| import torch | |
| from safetensors.torch import safe_open | |
| import yaml | |
| # --- CONFIGURATION --- | |
| YAML_PATH = "B:/24B/karcher_stock_24b/mergekit_config.yml" | |
| FINAL_MERGE_DIR = "B:/24B/karcher_stock_24b" | |
| LAYERS_TO_SCAN =[ | |
| "model.layers.10.mlp.down_proj.weight" # "model.language_model.layers.10.mlp.gate_proj.weight" | |
| ] | |
| # --------------------- | |
| def load_tensor(model_dir, tensor_name): | |
| """Finds and loads a tensor from a directory of safetensors.""" | |
| for file in os.listdir(model_dir): | |
| if file.endswith(".safetensors"): | |
| filepath = os.path.join(model_dir, file) | |
| with safe_open(filepath, framework="pt", device="cpu") as f: | |
| if tensor_name in f.keys(): | |
| return f.get_tensor(tensor_name).float() | |
| raise ValueError(f"Tensor {tensor_name} not found in {model_dir}") | |
| def main(): | |
| print("Loading YAML config...") | |
| with open(YAML_PATH, 'r') as f: | |
| config = yaml.safe_load(f) | |
| base_path = config['base_model'] | |
| donor_paths = [m['model'] for m in config['models']] | |
| print(f"\nScanning {len(LAYERS_TO_SCAN)} MLP layers for structural influence...\n") | |
| for layer in LAYERS_TO_SCAN: | |
| print(f"--- Layer: {layer} ---") | |
| try: | |
| base_w = load_tensor(base_path, layer) | |
| final_w = load_tensor(FINAL_MERGE_DIR, layer) | |
| # Use float64 for norm calculations to prevent precision loss in energy ratios | |
| final_norm = torch.norm(final_w.double()).item() | |
| final_tv = final_w - base_w | |
| final_tv_norm = torch.norm(final_tv.double()).item() | |
| results = [] | |
| # 1. Collect raw magnitudes of the components | |
| base_norm = torch.norm(base_w.double()).item() | |
| donor_tvs = [] | |
| for donor in donor_paths: | |
| dw = load_tensor(donor, layer) | |
| donor_tvs.append(dw - base_w) | |
| donor_tv_norms = [torch.norm(dtv.double()).item() for dtv in donor_tvs] | |
| # 2. Calculate Total Component Energy (Base + all Donor Deltas) | |
| total_component_energy = base_norm + sum(donor_tv_norms) | |
| results = [] | |
| # 3. Assign Share to Base Model | |
| base_share = (base_norm / total_component_energy) * 100 | |
| results.append(("(Base Model)", -1.0, 0.0, base_share)) | |
| # 4. Assign Share to Donors | |
| for i, donor in enumerate(donor_paths): | |
| donor_tv = donor_tvs[i] | |
| cos_sim = torch.nn.functional.cosine_similarity( | |
| final_tv.flatten(), donor_tv.flatten(), dim=0 | |
| ).item() | |
| rel_mag = (torch.norm(donor_tv.double()).item() / final_tv_norm) | |
| # Compositional Share: How much of the total energy sum belongs to this donor's delta | |
| comp_share = (donor_tv_norms[i] / total_component_energy) * 100 | |
| name = donor.split("/")[-1][:50] | |
| results.append((name, cos_sim, rel_mag, comp_share)) | |
| # Sort by highest similarity (Donors first, Base at the very bottom) | |
| results.sort(key=lambda x: x[1], reverse=True) | |
| print(f"{'Model Name':<55} | {'Alignment {Cos}':<12} | {'Rel Mag (TV)':<12} | {'Merge Composition'}") | |
| print("-" * 105) | |
| for name, sim, mag, energy in results: | |
| sim_str = f"{sim:12.4f}" if sim >= 0 else " N/A " | |
| mag_str = f"{mag:11.2f}x" if mag > 0 else " N/A " | |
| print(f"{name:<55} | {sim_str} | {mag_str} | {energy:>13.2f}%") | |
| except Exception as e: | |
| print(f"Skipping layer due to error: {e}") | |
| if __name__ == "__main__": | |
| main() |