Views
No views yet
S(x) = α₁·H_acoustic(x) + α₂·H_phonetic(x) + α₃·H_linguistic(x) + α₄·H_contextual(x) + β·MI(x, D)H_acoustic(x): Spectral/MFCC entropy measuring acoustic diversityH_phonetic(x): Phoneme distribution entropy capturing phonetic complexityH_linguistic(x): Vocabulary and syntax entropy measuring linguistic richnessH_contextual(x): Domain and discourse entropyMI(x, D): Mutual information contribution relative to datasetα₁...α₄, β: Configurable weights (default: 0.25, 0.20, 0.25, 0.15, 0.15)I(x, y) = Σ_{j,ℓ} p(f_j, y_ℓ) log [p(f_j, y_ℓ) / (p(f_j)·p(y_ℓ))]D' = {x ∈ D : S(x) > τ}τ_{k+1} = τ_k · growth_factorS'(x) = S(x) + λ_err·ErrorRelevance(x, errors_k) + λ_cross·CrossLingualOverlap(x)Algorithm: HEEP Data Curation with Error-Aware Adaptation
Input: Dataset D, initial threshold τ₀, growth factor g
Output: Curated dataset D*
1. Initialize scorer with entropy estimators
2. Fit scorer to D (compute normalization stats, fit MI estimator)
3. D* ← D
4. k ← 0
5. While |D*| > min_samples AND k < max_rounds:
a. For each x in D*:
Compute S(x) = Σᵢ αᵢ·Hᵢ(x) + β·MI(x, D)
b. If error_patterns available:
Adjust S'(x) = S(x) + λ_err·ErrorRelevance(x) + λ_cross·CrossLingualOverlap(x)
c. D* ← {x ∈ D* : S'(x) > τₖ}
d. If train_callback: Train model on D*
e. If eval_callback: Analyze errors, update error_patterns
f. τₖ₊₁ ← τₖ · g
g. k ← k + 1
6. Return D*| Dataset | Bengali | Bhojpuri | Chhattisgarhi | Gujarati | Hindi | Kannada | Magahi | Maithili | Malayalam | Marathi | Odia | Punjabi | Sanskrit | Tamil | Telugu | Urdu | Avg |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Kathbath | 14.6 | – | – | 17.4 | 8.5 | 23 | – | – | 39.3 | 19.2 | 25.4 | 15.8 | 41.4 | 30.3 | 29 | 12.1 | 23 |
| Kathbath Hard | 15.7 | – | – | 18.5 | 9 | 25.1 | – | – | 41.2 | 20.4 | 27.7 | 16.6 | 43.6 | 32.6 | 30.3 | 11.9 | 24.4 |
| CommonVoice | 21 | – | – | – | 9.96 | – | – | – | 46 | 21.5 | 34.6 | 17.5 | – | 34 | – | 20.6 | 25.7 |
| FLEURS | 22.4 | – | – | 23.3 | 11 | 23.1 | – | – | 34.4 | 25.5 | 33.3 | 25 | – | 35.1 | 31.9 | 22.4 | 26.1 |
| IndicTTS | 15.8 | – | – | 16.9 | 6.6 | 19.6 | – | – | 26.4 | 14.5 | 14.8 | – | – | 22.6 | 31.3 | – | 18.7 |
| Gramvaani | – | – | – | – | 26 | – | – | – | – | – | – | – | – | – | – | – | 26 |
| RESPIN | 32.5 | 21.3 | 21.6 | – | 12.1 | 45.6 | 27.7 | 41.1 | – | 32.7 | – | – | – | – | 37.5 | – | 30.2 |
| Average | 20.4 | 21.3 | 21.6 | 19 | 11.9 | 27.3 | 27.7 | 41.1 | 37.5 | 22.3 | 27.2 | 18.7 | 42.5 | 30.9 | 32 | 16.7 | 24.6 |
| Model | Kathbath | Kathbath Noisy | CommonVoice | FLEURS | IndicTTS | RESPIN | Gramvaani | Average |
|---|---|---|---|---|---|---|---|---|
| Google STT | 14.3 | 16.7 | 20.8 | 19.4 | 18.3 | – | 59.9 | 24.9 |
| IndicWav2Vec | 12.2 | 16.2 | 20.2 | 18.3 | 15 | – | 42.1 | 20.7 |
| Azure STT | 13.6 | 15.1 | 14.6 | 24.3 | 15.2 | – | 42.3 | 20.8 |
| Nvidia Conformer-CTC Medium | 14 | 15.6 | 20.4 | 19.4 | 12.3 | – | 41.3 | 20.5 |
| Nvidia Conformer-CTC Large | 12.7 | 14.2 | 21.2 | 15.7 | 12.2 | – | 42.6 | 19.8 |
| IndicWhisper | 10.3 | 12 | 15 | 11.4 | 7.6 | – | 26.8 | 13.8 |
| HEEP Indic | 8.53 | 8.97 | 9.96 | 11.04 | 6.59 | 12.05 | 25.98 | 11.9 |
pip install qwen-asr[vllm]1from qwen_asr import Qwen3ASRModel
2
3# Load model with vLLM backend
4asr = Qwen3ASRModel.LLM(
5 model="bc7ec356/heep-indic",
6 gpu_memory_utilization=0.8,
7 max_new_tokens=4096,
8)
9
10# Transcribe from file path
11results = asr.transcribe(
12 audio="path/to/audio.wav",
13 language="Hindi",
14)
15print(results[0].text)
16print(results[0].language)1import torch
2from qwen_asr import Qwen3ASRModel
3
4# Load model with Transformers backend
5asr = Qwen3ASRModel.from_pretrained(
6 "bc7ec356/heep-indic",
7 dtype=torch.bfloat16,
8 device_map="cuda:0",
9)
10
11# Transcribe
12results = asr.transcribe(
13 audio="path/to/audio.wav",
14 language="Hindi",
15)
16print(results[0].text)1# Transcribe multiple files at once
2results = asr.transcribe(
3 audio=["audio1.wav", "audio2.wav", "audio3.wav"],
4 language=["Hindi", "Tamil", "Bengali"],
5)
6for r in results:
7 print(f"[{r.language}] {r.text}")1# Pass language=None to auto-detect
2results = asr.transcribe(
3 audio="path/to/audio.wav",
4 language=None,
5)
6print(f"Detected: {results[0].language}")
7print(f"Text: {results[0].text}")1import numpy as np
2import soundfile as sf
3
4from qwen_asr import Qwen3ASRModel
5
6asr = Qwen3ASRModel.LLM(
7 model="bc7ec356/heep-indic",
8 gpu_memory_utilization=0.8,
9 max_new_tokens=4096,
10)
11
12# Load audio
13wav, sr = sf.read("path/to/audio.wav", dtype="float32")
14
15# Initialize streaming state
16state = asr.init_streaming_state(
17 language="Hindi",
18 chunk_size_sec=2.0,
19 unfixed_chunk_num=2,
20 unfixed_token_num=5,
21)
22
23# Feed audio in 1-second chunks
24step = sr # 1 second of samples
25for pos in range(0, len(wav), step):
26 chunk = wav[pos : pos + step]
27 asr.streaming_transcribe(chunk, state)
28 print(f"Partial: {state.text}")
29
30# Finalize
31asr.finish_streaming_transcribe(state)
32print(f"Final: {state.text}")1import numpy as np
2
3# From a numpy array + sample rate
4audio_array = np.random.randn(16000).astype(np.float32) # 1 second at 16kHz
5results = asr.transcribe(
6 audio=(audio_array, 16000),
7 language="English",
8)device="cuda" for significantly faster inferencetorch_dtype=torch.float16 for optimal speed on modern GPUs1@article{anonymous2026heep,
2 title={HEEP: High Entropy Exponential Pruning for State-of-the-Art ASR Through Strategic Data Curation},
3 author={Anonymous},
4 journal={Under Review},
5 year={2026}
6}