BarathwajAnandan commited on
Commit
5e46086
·
verified ·
1 Parent(s): f64d1b9

Upload load_fp8.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. load_fp8.py +122 -0
load_fp8.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Load FP8-quantized cohere-transcribe model from safetensors.
2
+
3
+ Usage:
4
+ from load_fp8 import load_model
5
+ model, processor = load_model("path/to/repo", compile=True)
6
+ """
7
+ import torch
8
+ import torch._dynamo
9
+ import torch._inductor.config
10
+ import json
11
+ import os
12
+ from safetensors.torch import load_file
13
+ from transformers import CohereAsrForConditionalGeneration, AutoProcessor, AutoConfig
14
+
15
+ torch._inductor.config.triton.cudagraphs = False
16
+
17
+
18
+ def load_model(model_path, device="auto", native_fp8=True, compile=False):
19
+ """Load FP8-quantized cohere-transcribe model.
20
+
21
+ Args:
22
+ model_path: Path to the FP8 model directory
23
+ device: Device for model placement
24
+ native_fp8: Reconstruct torchao Float8Tensors for FP8 compute (requires torchao)
25
+ compile: Apply torch.compile to encoder layers for max throughput
26
+
27
+ Returns:
28
+ (model, processor) tuple
29
+ """
30
+ with open(os.path.join(model_path, "fp8_config.json")) as f:
31
+ fp8_config = json.load(f)
32
+ fp8_layers = set(fp8_config["fp8_layers"])
33
+ raw = load_file(os.path.join(model_path, "model.safetensors"))
34
+
35
+ # Build BF16 state dict (dequantize FP8 layers)
36
+ state_dict = {}
37
+ for layer_name in fp8_layers:
38
+ qdata = raw[layer_name + ".qdata"]
39
+ scale = raw[layer_name + ".scale"]
40
+ state_dict[layer_name] = (qdata.float() * scale).to(torch.bfloat16)
41
+ for key, tensor in raw.items():
42
+ if not key.endswith(".qdata") and not key.endswith(".scale"):
43
+ state_dict[key] = tensor
44
+
45
+ config = AutoConfig.from_pretrained(model_path)
46
+ model = CohereAsrForConditionalGeneration(config)
47
+ model.to(torch.bfloat16)
48
+ model.load_state_dict(state_dict, strict=False)
49
+
50
+ target_device = "cuda" if (device == "auto" and torch.cuda.is_available()) else device
51
+ model = model.to(target_device)
52
+ model.eval()
53
+
54
+ # Re-quantize to native FP8
55
+ if native_fp8:
56
+ from torchao.quantization import quantize_, Float8DynamicActivationFloat8WeightConfig
57
+ quantize_(model.model.encoder, Float8DynamicActivationFloat8WeightConfig())
58
+
59
+ # Compile encoder per-layer
60
+ if compile:
61
+ encoder = model.model.encoder
62
+ torch._dynamo.config.cache_size_limit = len(encoder.layers) + 4
63
+ for layer in encoder.layers:
64
+ layer.forward = torch.compile(layer.forward, dynamic=True, mode="max-autotune-no-cudagraphs")
65
+
66
+ processor = AutoProcessor.from_pretrained(model_path)
67
+ return model, processor
68
+
69
+
70
+ if __name__ == "__main__":
71
+ import argparse, time
72
+ import numpy as np
73
+ from transformers.audio_utils import load_audio
74
+
75
+ parser = argparse.ArgumentParser()
76
+ parser.add_argument("--model_path", required=True)
77
+ parser.add_argument("--audio", default=None)
78
+ parser.add_argument("--language", default="en")
79
+ parser.add_argument("--no-fp8", dest="native_fp8", action="store_false")
80
+ parser.add_argument("--compile", action="store_true")
81
+ args = parser.parse_args()
82
+
83
+ mode = []
84
+ if args.native_fp8: mode.append("FP8")
85
+ else: mode.append("BF16")
86
+ if args.compile: mode.append("+ compile")
87
+ print(f"Loading model ({' '.join(mode)})...")
88
+ t0 = time.time()
89
+ model, processor = load_model(args.model_path, native_fp8=args.native_fp8, compile=args.compile)
90
+ load_time = time.time() - t0
91
+
92
+ if args.audio:
93
+ audio = load_audio(args.audio, sampling_rate=16000)
94
+ else:
95
+ from huggingface_hub import hf_hub_download
96
+ audio_file = hf_hub_download(
97
+ repo_id="CohereLabs/cohere-transcribe-03-2026",
98
+ filename="demo/voxpopuli_test_en_demo.wav",
99
+ )
100
+ audio = load_audio(audio_file, sampling_rate=16000)
101
+
102
+ # Warmup (triggers compile if enabled)
103
+ inputs = processor(audio, sampling_rate=16000, return_tensors="pt", language=args.language)
104
+ inputs.to(model.device, dtype=model.dtype)
105
+ _ = model.generate(**inputs, max_new_tokens=256)
106
+ print(f"Loaded + warmup in {time.time()-t0:.1f}s")
107
+
108
+ dur = len(audio) / 16000
109
+ times = []
110
+ for _ in range(5):
111
+ inputs = processor(audio, sampling_rate=16000, return_tensors="pt", language=args.language)
112
+ inputs.to(model.device, dtype=model.dtype)
113
+ torch.cuda.synchronize()
114
+ t0 = time.perf_counter()
115
+ outputs = model.generate(**inputs, max_new_tokens=256)
116
+ torch.cuda.synchronize()
117
+ times.append(time.perf_counter() - t0)
118
+
119
+ text = processor.decode(outputs, skip_special_tokens=True)
120
+ avg = np.mean(times)
121
+ print(f"RTFx: {dur/avg:.1f} ({avg*1000:.1f}ms)")
122
+ print(f"Transcription: {text}")