File size: 2,204 Bytes
9c98083
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""Inspect a LoRA .safetensors file: embedded training metadata + inferred
rank/target modules from tensor shapes. Read-only, no GPU/torch needed --
just parses the safetensors header, so it's fast and safe to run on any
LoRA file (including ones you didn't train yourself).

Usage:
    python_embeded\\python.exe dataset_builder\\inspect_lora.py path\\to\\lora.safetensors
"""
import argparse
import json
import re
from collections import Counter

from safetensors import safe_open


def parse_args():
    p = argparse.ArgumentParser(description="Inspect a LoRA safetensors file's metadata")
    p.add_argument("lora_path")
    return p.parse_args()


def infer_rank(keys, shapes):
    for k in keys:
        if k.endswith("lora_A.weight") or k.endswith("lora_down.weight"):
            return shapes[k][0]
    return None


def summarize_target_modules(keys):
    """Collapses per-block keys (blocks.0, blocks.1, ...) into module families
    so you can see what parts of the model were trained without a 800-line dump."""
    families = Counter()
    for k in keys:
        base = re.sub(r"\.(lora_A|lora_B|lora_down|lora_up|alpha)(\.weight)?$", "", k)
        base = re.sub(r"\.\d+\.", ".N.", base)
        families[base] += 1
    return families


def main():
    args = parse_args()
    with safe_open(args.lora_path, framework="pt") as f:
        meta = f.metadata() or {}
        keys = list(f.keys())
        shapes = {k: f.get_slice(k).get_shape() for k in keys}

    print(f"=== {args.lora_path} ===")
    print(f"Tensor count: {len(keys)}")
    print(f"Inferred rank (lora_A/lora_down first dim): {infer_rank(keys, shapes)}")

    print("\n--- Embedded metadata ---")
    if not meta:
        print("(none)")
    for k, v in meta.items():
        try:
            parsed = json.loads(v)
            print(f"{k}:")
            print(json.dumps(parsed, indent=2, ensure_ascii=False)[:3000])
        except (json.JSONDecodeError, TypeError):
            print(f"{k}: {v}")

    print("\n--- Target module families (per-block keys collapsed) ---")
    for base, count in summarize_target_modules(keys).most_common(30):
        print(f"  {base}  x{count}")


if __name__ == "__main__":
    main()