File size: 3,403 Bytes
10b603f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Strict, reproducible FP32 export using the upstream Parakeet converter."""
from pathlib import Path
import hashlib
import importlib.util
import json
import tarfile
import torch
import yaml
from transformers import ParakeetForTDT, AutoProcessor

import argparse
from huggingface_hub import hf_hub_download
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("output", type=Path)
parser.add_argument("--cache-dir")
args = parser.parse_args()
ROOT = args.output.resolve()
ROOT.mkdir(parents=True, exist_ok=True)
REVISION = "555136b50265a132d4cea0d35560c26fc4f657ab"
SOURCE_SHA = "031c8ddab4845aeced904a7cde8e8aa57993b2e344716cf83a545b079c473b56"
CONVERTER_REV = "6c6bac29f50c8aad5d1f06c72b2f892a6e335dd0"
source = Path(hf_hub_download("oruk/orukeet", "orukeet-v0.1.0.nemo", revision=REVISION, cache_dir=args.cache_dir))
with source.open("rb") as handle:
    assert hashlib.file_digest(handle, "sha256").hexdigest() == SOURCE_SHA
extracted = ROOT / ".nemo-source"
extracted.mkdir(exist_ok=True)
with tarfile.open(source) as archive:
    archive.extractall(extracted, filter="data")
config = yaml.safe_load((extracted / "model_config.yaml").read_text())
spec = importlib.util.spec_from_file_location("upstream_converter", Path(__file__).with_name("convert_nemo_to_hf.py"))
converter = importlib.util.module_from_spec(spec)
spec.loader.exec_module(converter)
files = {"model_weights": str(extracted / "model_weights.ckpt"),
         "tokenizer_model_file": str(extracted / config["tokenizer"]["model_path"].removeprefix("nemo:"))}
output = ROOT
output.mkdir(exist_ok=True)
converter.write_processor(config, files, str(output), "tdt")
model_config = converter.convert_tdt_config(config, converter.convert_encoder_config(config))
state_dict = converter.load_and_convert_tdt_state_dict(files, model_config.vocab_size)
with torch.device("meta"):
    model = ParakeetForTDT(model_config)
result = model.load_state_dict(state_dict, strict=True, assign=True)
assert not result.missing_keys and not result.unexpected_keys
model.eval()
model.generation_config.decoder_start_token_id = model.config.blank_token_id
model.generation_config.suppress_tokens = list(range(model.config.vocab_size, model.config.vocab_size + len(model.config.durations)))
model.save_pretrained(output, max_shard_size="4GB")
processor = AutoProcessor.from_pretrained(output, local_files_only=True)
assert processor.tokenizer.convert_tokens_to_ids("<blank>") == model.config.blank_token_id
assert len(processor.tokenizer) == model.config.vocab_size
proof = {
    "source_repo": "oruk/orukeet", "source_revision": REVISION,
    "source_filename": source.name, "source_sha256": SOURCE_SHA,
    "converter_url": f"https://github.com/huggingface/transformers/blob/{CONVERTER_REV}/src/transformers/models/parakeet/convert_nemo_to_hf.py",
    "dtype": str(next(model.parameters()).dtype), "strict_state_dict": True,
    "tensor_count": len(state_dict), "parameter_count": sum(p.numel() for p in model.parameters()),
    "vocab_size": model.config.vocab_size,
    "files": {}
}
for path in sorted(output.iterdir()):
    if path.is_file():
        with path.open("rb") as handle:
            proof["files"][path.name] = {"sha256": hashlib.file_digest(handle, "sha256").hexdigest(), "bytes": path.stat().st_size}
(ROOT / "export-provenance.json").write_text(json.dumps(proof, indent=2) + "\n")
print(json.dumps(proof, indent=2))