File size: 2,156 Bytes
a4362c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
"""Convert the pinned official Fun-ASR-Nano checkpoint to safetensors."""

from __future__ import annotations

import argparse
import hashlib
from pathlib import Path

import torch
from safetensors.torch import save_file


SOURCE_REVISION = "272c57b82523ada6fd87095e955f8e29100979ab"
SOURCE_SHA256 = "55ae0d2fee369f0f11cce0795f6927934ad17cf11b278a7e56a51272074160bb"
EXPECTED_TENSORS = 1261


def sha256(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as stream:
        for chunk in iter(lambda: stream.read(16 * 1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("source", type=Path, help="Pinned official model.pt")
    parser.add_argument("output", type=Path, help="Output model.safetensors")
    args = parser.parse_args()

    actual_source_hash = sha256(args.source)
    if actual_source_hash != SOURCE_SHA256:
        raise SystemExit(
            f"source SHA-256 mismatch: expected {SOURCE_SHA256}, got {actual_source_hash}"
        )

    checkpoint = torch.load(args.source, map_location="cpu", weights_only=True)
    state_dict = checkpoint.get("state_dict", checkpoint)
    if len(state_dict) != EXPECTED_TENSORS:
        raise SystemExit(
            f"tensor count mismatch: expected {EXPECTED_TENSORS}, got {len(state_dict)}"
        )
    if not all(isinstance(value, torch.Tensor) for value in state_dict.values()):
        raise SystemExit("checkpoint contains non-tensor state-dict values")

    lora_keys = [key for key in state_dict if "lora" in key.lower()]
    if lora_keys:
        raise SystemExit(f"unexpected LoRA tensors: {lora_keys[:10]}")

    args.output.parent.mkdir(parents=True, exist_ok=True)
    # Keep provenance in MODEL_PROVENANCE.json. safetensors serializes metadata
    # map keys in nondeterministic order, which would make whole-file hashes vary.
    save_file(state_dict, args.output)
    print(f"wrote {args.output}")
    print(f"sha256 {sha256(args.output)}")
    print(f"tensors {len(state_dict)}")


if __name__ == "__main__":
    main()