Views
No views yet
float32 to resolve typical Fourier Transform (rfft) cast exceptions with NumPy during processing.1# NOTE: Run this cell first, then restart the runtime before proceeding.
2%%capture
3import os, re
4if "COLAB_" not in "".join(os.environ.keys()):
5 !pip install unsloth
6else:
7 import torch
8 v = re.match(r'[\d]{1,}\.[\d]{1,}', str(torch.__version__)).group(0)
9 xformers = 'xformers==' + {
10 '2.10': '0.0.34', '2.9': '0.0.33.post1', '2.8': '0.0.32.post2'
11 }.get(v, "0.0.34")
12 !pip install sentencepiece protobuf "datasets==4.3.0" \
13 "huggingface_hub>=0.34.0" hf_transfer
14 !pip install --no-deps unsloth_zoo bitsandbytes accelerate \
15 {xformers} peft trl triton unsloth
16 !pip install --no-deps --upgrade "torchao>=0.16.0"
17!pip install --no-deps transformers==5.5.0 "tokenizers>=0.22.0,<=0.23.0"
18!pip install torchcodec # Audio codec support
19!pip install --no-deps --upgrade timm # Required for Gemma 4 audio/vision
20!pip install jiwer # WER / CER evaluation
21import torch; torch._dynamo.config.recompile_limit = 641import torch
2import numpy as np
3import librosa
4from unsloth import FastModel
5
6# 1. Define Model and Repository Name
7HF_REPO_NAME = "Sothay/gemm4-E2B-khmer-asr"
8TARGET_SAMPLE_RATE = 16000
9
10# 2. Load Model & Processor
11print("⏳ Loading model and processor...")
12model, processor = FastModel.from_pretrained(
13 model_name = HF_REPO_NAME,
14 max_seq_length = 8192,
15 dtype = torch.float16, # Force float16 for T4/GPU compatibility
16 load_in_4bit = True, # Enable 4-bit quantization for minimal VRAM
17)
18
19# 3. Enable Unsloth's optimized inference kernels
20FastModel.for_inference(model)
21print("✅ Model ready for inference.")
22
23# 4. Helper function to load and preprocess audio
24def load_audio(file_path: str) -> np.ndarray:
25 """Loads audio and resamples it to 16,000 Hz float32 array."""
26 # librosa automatically returns float32 arrays
27 audio, sr = librosa.load(file_path, sr=TARGET_SAMPLE_RATE)
28 return audio
29
30# 5. Define transcription function
31def transcribe_khmer(audio_array: np.ndarray) -> str:
32 """Runs inference on a processed float32 audio array."""
33 # Guarantee float32 to prevent numpy.fft.rfft casting errors
34 audio_array = np.asarray(audio_array, dtype=np.float32)
35
36 # Structure system and user prompts matching the training template
37 system_prompt = (
38 "You are an expert Khmer speech recognition assistant. "
39 "Transcribe the spoken audio accurately in Khmer script, "
40 "without translation or explanation."
41 )
42
43 messages = [
44 {
45 "role": "system",
46 "content": [{"type": "text", "text": system_prompt}],
47 },
48 {
49 "role": "user",
50 "content": [
51 {"type": "audio", "audio": audio_array},
52 {"type": "text", "text": "Please transcribe this Khmer audio."},
53 ],
54 },
55 ]
56
57 # Tokenize input sequence
58 inputs = processor.apply_chat_template(
59 messages,
60 add_generation_prompt = True,
61 tokenize = True,
62 return_dict = True,
63 return_tensors = "pt",
64 ).to("cuda")
65
66 # Generate transcript
67 output_ids = model.generate(
68 **inputs,
69 max_new_tokens = 256,
70 do_sample = False, # Greedy decoding: stable, fast & reproducible
71 )
72
73 # Decode and strip prompt tokens
74 prompt_len = inputs["input_ids"].shape[1]
75 transcript = processor.decode(
76 output_ids[0][prompt_len:],
77 skip_special_tokens = True
78 ).strip()
79
80 return transcript
81
82# ── Example Usage ──────────────────────────────────────────────────────────
83# Replace with the path to your local Khmer audio file (wav, mp3, flac, etc.)
84audio_path = "path_to_your_audio.wav"
85
86try:
87 print(f"🔊 Processing audio: {audio_path}...")
88 audio_data = load_audio(audio_path)
89
90 print("Transcribing...")
91 prediction = transcribe_khmer(audio_data)
92
93 print("\n Predicted Transcript:")
94 print(prediction)
95except Exception as e:
96 print(f" Error running inference: {e}")SFTTrainer from Hugging Face's trl library with the following memory-saving configuration to enable stable training on a single T4 (16 GB) GPU:torch.float16 (Mixed-precision fp16=True, bf16=False since T4 lacks native bf16 compute support).paged_adamw_8bit (cuts optimizer states footprint by ~75%).use_reentrant=False) to avoid autograd graph overheads.per_device_train_batch_size=2 with gradient_accumulation_steps=4 (effective batch size of 8).4096 tokens.float32), and prints the Khmer transcription.pip install unsloth librosa soundfile numpy torch1import torch
2import numpy as np
3import librosa
4from unsloth import FastModel
5
6# 1. Define Model Repository
7HF_REPO_NAME = "Sothay/gemm4-E2B-khmer-asr"
8TARGET_SAMPLE_RATE = 16000
9
10# 2. Load Model & Processor
11print("⏳ Loading model and processor...")
12model, processor = FastModel.from_pretrained(
13 model_name = HF_REPO_NAME,
14 max_seq_length = 4096,
15 dtype = torch.float16, # Force float16 for T4 GPU compatibility
16 load_in_4bit = True, # 4-bit quantization for low-VRAM environments
17)
18
19# Enable Unsloth's optimized inference mode
20FastModel.for_inference(model)
21print("✅ Model loaded successfully!")
22
23# 3. Define Inference Functions
24def transcribe_audio_file(file_path: str) -> str:
25 """Loads a local audio file, pre-processes it, and returns the transcription."""
26 # Load and automatically resample to 16,000 Hz float32
27 audio_array, sr = librosa.load(file_path, sr=TARGET_SAMPLE_RATE)
28
29 # Ensure float32 to prevent numpy.fft.rfft casting issues
30 audio_array = np.asarray(audio_array, dtype=np.float32)
31
32 # Format instruction messages
33 system_prompt = (
34 "You are an expert Khmer speech recognition assistant. "
35 "Transcribe the spoken audio accurately in Khmer script, "
36 "without translation or explanation."
37 )
38
39 messages = [
40 {
41 "role": "system",
42 "content": [{"type": "text", "text": system_prompt}],
43 },
44 {
45 "role": "user",
46 "content": [
47 {"type": "audio", "audio": audio_array},
48 {"type": "text", "text": "Please transcribe this Khmer audio."},
49 ],
50 },
51 ]
52
53 # Tokenize input context
54 inputs = processor.apply_chat_template(
55 messages,
56 add_generation_prompt = True,
57 tokenize = True,
58 return_dict = True,
59 return_tensors = "pt",
60 ).to("cuda")
61
62 # Generate output transcript using Greedy decoding
63 output_ids = model.generate(
64 **inputs,
65 max_new_tokens = 256,
66 do_sample = False, # Greedy decoding (deterministic ASR)
67 )
68
69 # Strip prompt tokens and decode prediction
70 prompt_len = inputs["input_ids"].shape[1]
71 transcript = processor.decode(
72 output_ids[0][prompt_len:],
73 skip_special_tokens = True
74 ).strip()
75
76 return transcript
77
78# ── Example Usage ──────────────────────────────────────────────────────────
79# Simply change this path to point to your local audio file
80my_audio_file = "my_voice_sample.wav"
81
82try:
83 print(f"\n🔊 Reading audio file: {my_audio_file}")
84 transcript = transcribe_audio_file(my_audio_file)
85 print("\n🎯 Transcription:")
86 print(transcript)
87except Exception as e:
88 print(f"❌ Error occurred: {e}")