Configuration Parsing Warning:In adapter_config.json: "peft.task_type" must be a string

πŸŽ™οΈ NAMAA Saudi-Dialect ASR V1

A Saudi Arabic Speech Recognition Model for Arabic & Saudi Transcribe.

NAMAA Saudi-Dialect ASR V1

This is a lightweight LoRA adapter fine-tuned on approximately 30 hours of human-transcribed Saudi Podcast Speech.

On the reported Saudi Evaluation Set, the model acheives:

26.50% WER and 15.28% CER with a produced 22.5M trainable parameters Approximately of nearly 90 MB of adapter weights, used with the 2.07B-parameter base model.


At a glance

Property Details
Task Automatic speech recognition
Language Arabic β€” Saudi dialectal speech
Base model Cohere Transcribe Arabic
Adaptation LoRA
Training speech Approximately 30 hours across 2,400 source segments
Trainable parameters 22.5M β€” approximately 1.1% of the base parameter count
Adapter download Approximately 90 MB / 86 MiB
Audio input Mono, 16 kHz
Output Arabic transcription
Evaluated domain Saudi podcasts and interviews

The adapter file size is not the total inference memory requirement: the base model must also be loaded.

Evaluation

All systems were evaluated on the same 826 held-out segments containing approximately 10.8 hours of Saudi podcast speech.

Evaluation used human reference transcripts and identical Arabic orthographic normalization:

  • Diacritic removal.
  • Hamza, alef, and ta marbuta normalization.
  • Punctuation removal.

Lower WER and CER are better. These results describe performance on this evaluation set, rather than a general ranking across Arabic ASR tasks.

Model Base parameters WER ↓ CER ↓
Saudi-Dialect ASR β€” this adapter 2.07B + LoRA 26.50% 15.28%
Cohere Transcribe Arabic 2.07B 29.12% 16.32%
Whisper large-v3 1.55B 37.99% 21.29%
Whisper large-v3-turbo 0.81B 38.30% 21.14%
Nemotron 3.5 ASR streaming 0.64B 50.29% 29.92%
ArTST v3 0.15B 53.96% 33.22%

What changed relative to the base?

Measure Base Saudi adapter Change
WER 29.12% 26.50% βˆ’2.62 percentage points
CER 16.32% 15.28% βˆ’1.04 percentage points
Substitutions 15,126 13,562 βˆ’1,564
Insertions 5,505 4,401 βˆ’1,104
Deletions 2,938 3,487 +549

The adapter produces fewer substitutions and insertions, but more deletions. Overall WER improves despite this trade-off.

Segment-level analysis

  • 536 of 826 segments showed lower WER than the base model.
  • The reported 95% bootstrap confidence interval for the mean per-segment WER difference was [βˆ’3.00, βˆ’2.29] percentage points.
  • Negative differences favor the Saudi adapter.

This confidence interval concerns the mean per-segment difference. It should not be interpreted as a confidence interval for the corpus-level WER reduction, which weights segments by reference length.


Quick start

Install the dependencies:

pip install torch transformers peft accelerate soundfile scipy

The following example is for a regular Python environment with CPU or dedicated GPU access.

import math
import os

import numpy as np
import soundfile as sf
import torch
from peft import PeftModel
from scipy.signal import resample_poly
from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor


BASE = "CohereLabs/cohere-transcribe-arabic-07-2026"
ADAPTER = "NAMAA-Space/NAMAA-Saudi-ASR-V1"
TOKEN = os.environ.get("HF_TOKEN", "").strip()

if not TOKEN:
    raise RuntimeError(
        "Set HF_TOKEN with read access to the private adapter."
    )

device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = (
    torch.bfloat16
    if device == "cuda" and torch.cuda.is_bf16_supported()
    else torch.float32
)

processor = AutoProcessor.from_pretrained(
    BASE,
    token=TOKEN,
    trust_remote_code=True,
)

# Load and merge on CPU before moving to the inference device.
with torch.device("cpu"):
    model = AutoModelForSpeechSeq2Seq.from_pretrained(
        BASE,
        token=TOKEN,
        trust_remote_code=True,
        dtype=dtype,
    )

    model = PeftModel.from_pretrained(
        model,
        ADAPTER,
        token=TOKEN,
        torch_device="cpu",
    ).merge_and_unload()

model = model.to(device).eval()

# Replace this with your audio file.
audio, sample_rate = sf.read(
    "sample.wav",
    dtype="float32",
    always_2d=True,
)

audio = audio.mean(axis=1)

if audio.size == 0:
    raise ValueError("The audio file is empty.")

if not np.isfinite(audio).all():
    raise ValueError("The audio contains invalid sample values.")

if sample_rate != 16000:
    divisor = math.gcd(sample_rate, 16000)
    audio = resample_poly(
        audio,
        up=16000 // divisor,
        down=sample_rate // divisor,
    ).astype(np.float32)

inputs = processor(
    audio=audio,
    sampling_rate=16000,
    return_tensors="pt",
)

chunk_index = inputs.pop("audio_chunk_index", None)

prepared = {}
for key, value in inputs.items():
    if torch.is_tensor(value):
        if value.is_floating_point():
            value = value.to(device=device, dtype=dtype)
        else:
            value = value.to(device)
    prepared[key] = value

with torch.inference_mode():
    outputs = model.generate(
        **prepared,
        max_new_tokens=440,
    )

parts = [
    text.strip()
    for text in processor.batch_decode(
        outputs,
        skip_special_tokens=True,
    )
]

if chunk_index is not None:
    if torch.is_tensor(chunk_index):
        chunk_index = chunk_index.detach().cpu().tolist()

    if len(chunk_index) == len(parts):
        order = sorted(
            range(len(parts)),
            key=lambda index: chunk_index[index],
        )
        parts = [parts[index] for index in order]

transcript = " ".join(part for part in parts if part)
print(transcript)

Long recordings

The processor used in this project splits recordings longer than approximately 35 seconds into windows.

Decode every output row. Using only the first decoded result silently discards subsequent windows.

The example concatenates window transcriptions in order. It does not provide timestamps or explicit overlap reconciliation; inspect window boundaries for repetitions or omissions when processing long recordings.


Training

Setting Value
Base architecture FastConformer encoder + transformer decoder
Base parameters 2.07B, frozen during adaptation
LoRA rank 32
LoRA alpha 64
Target modules q_proj, k_proj, v_proj, o_proj, fc1, fc2
Trainable parameters Approximately 22.5M
Source training segments 2,400 β€” approximately 30 hours
Audio sample rate 16 kHz
Epochs 3
Reported optimizer steps 867
Effective batch size 16
Learning-rate schedule OneCycle, peak learning rate 1e-4
Precision bfloat16
Checkpoint selection WER measured from generated transcriptions

Source segments were divided into training windows. The source-segment count therefore differs from the number of chunked training examples.

Training insight: transcript boundaries matter

The source segments average approximately 45 seconds, exceeding the encoder's approximately 35-second training window.

In the reported diagnostic comparison, teacher-forcing cross-entropy increased from 0.71 to 3.18 outside that window. Chunking was therefore important, but the human transcripts did not include timestamps.

Why proportional splitting failed

An initial approach divided each transcript across audio windows in proportion to their duration.

This assumes a roughly uniform speaking rate. Pauses, fast speech, and uneven sentence lengths violate that assumption and can assign words to the wrong audio window.

The resulting model showed:

  • A 39% reduction in validation cross-entropy.
  • A 7-percentage-point increase in WER.
  • Generated text length falling to 88% of the reference length.

Lower teacher-forcing loss did not translate into better transcriptions.

The alignment-based approach

The improved workflow used ASR-assisted transcript alignment:

  1. Transcribe each audio window with the base model.
  2. Align the predicted word sequences with the human transcript.
  3. Use those alignments to locate transcript boundaries.
  4. Train on the corresponding portions of the human transcript.

This uses model predictions to estimate boundaries while retaining human-written text as the training target.

Teacher-forcing cross-entropy in the target-quality comparison decreased from 0.802 with proportional splitting to 0.530 with alignment-based splitting.

Practical lesson: evaluate generated transcriptions during training. Cross-entropy alone can favor a model that omits speech.


Intended use

The adapter is intended for experimentation and transcription workflows involving Saudi Arabic speech, particularly podcasts and interviews.

Review generated transcripts before using them in publications, datasets, or other settings where transcription accuracy matters.

Limitations

  • Domain coverage: training and evaluation focus on podcasts and interviews. Performance on broadcast news, call centers, read speech, and other domains has not been established.

  • Long-audio boundaries: concatenating independently decoded windows can require additional boundary handling.

Citation

@misc{nacar2026namaasaudiasr,
  author       = {Nacar, Omer},
  title        = {{NAMAA Saudi-Dialect ASR V1}},
  year         = {2026},
  howpublished = {Hugging Face model repository},
  url          = {https://huggingface.co/NAMAA-Space/NAMAA-Saudi-ASR-V1}
}
Downloads last month
11
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for NAMAA-Space/NAMAA-Saudi-ASR-V1

Space using NAMAA-Space/NAMAA-Saudi-ASR-V1 1