Meg v1: On-Device Intent Edit-Tagger for Real-Time Speech Normalization

Meg v1 (meg-v1-tagger-int8) is a 25.5 MB non-autoregressive token and span edit-tagger designed for real-time speech-to-written text normalization in desktop and mobile dictation systems.

Note on Model Scope: Meg v1 is not an acoustic speech recognition (ASR) model. It is designed to sit directly downstream of any streaming acoustic ASR engine (such as Zipformer, Whisper, or platform speech APIs) to perform disfluency removal, truecasing, punctuation insertion, and multi-word speech repair cleanup with sub-3.5 ms latency on edge hardware.


Model Architecture & Technical Specifications

Parameter Specification
Model Type Non-Autoregressive Multi-Task Transformer Encoder
Encoder Depth 8 Transformer layers ($d_{\text{model}} = 384$, 6 attention heads, $d_{\text{ff}} = 1536$)
Parameter Count 33 Million (25.53 MB Dynamic INT8 ONNX)
Inference Format Dynamic INT8 ONNX (CPU / CoreML / DirectML compatible)
Multimodal Inputs 1. Token IDs (input_ids)
2. Attention Mask (attention_mask)
3. Discretized ASR Posterior Confidences (confidence_bins: 10 bins)
4. Acoustic Pause Durations (pause_bins: 4 bins: <100ms, 100-250ms, 250-500ms, >500ms)
Multi-Task Output Heads 1. Token Action: [KEEP, DELETE] (2 classes)
2. Punctuation: [NONE, PERIOD, COMMA, QUESTION, COLON] (5 classes)
3. Casing: [LOWER, TITLE, UPPER] (3 classes)
4. BILOU Span Repair: [O, B-REPARANDUM, I-REPARANDUM, L-REPARANDUM, U-REPARANDUM] (5 classes)
Latency 1.87 ms (p50) / 3.23 ms (p95) on Apple Silicon CPU
Memory Footprint Incremental $\Delta\text{RAM} \approx 25.5\text{ MB}$

Evaluated Performance (Independent 2,000-Sample Challenge Benchmark)

The model was evaluated against an independent, generator-decoupled 2,000-sample challenge set across 7 distinct categories.

System Comparison

System / Pipeline IP-WER (%) ↓ UER (%) ↓ Disfluency F1 (%) ↑ Entity Invariance (%) ↑ Ambiguous Precision (%) ↑ p50 Latency (Apple Silicon CPU) Model Size
Raw Verbatim ASR 39.85% 0.00% 0.00% 96.42% 100.00% 0.00 ms β€”
Naive Regex Cleaner 14.75% 0.00% 69.27% 96.42% 66.50% 0.01 ms β€”
Meg v1 (This Model) 4.99% 0.00% 90.44% 100.00% 100.00% 1.87 ms 25.53 MB
Cloud LLM Baseline (z-ai/glm-5.3-flash) 8.36% 0.00% 95.98% 98.75% 87.00% 395.45 ms Cloud API
  • IP-WER (Intent-Preserving Word Error Rate): Levenshtein distance against human-intended transcripts (ignoring valid disfluency deletions).
  • UER (Unnecessary Edit Rate): Percentage of words altered when fed already-clean, correctly-punctuated text.
  • Ambiguous Precision: Precision in retaining ambiguous semantic words ("like", "well", "actually", "so") when used in valid grammatical roles.

Category Breakdown (IP-WER on 2,000 Samples)

Challenge Category Samples IP-WER (%) ↓ Evaluation Focus
Numbers, Dates, Currency & Time 200 0.00% Zero corruption on formats like $30,000,000, March 13, 2026, 10:15 AM
Already-Clean Text (UER Test) 300 0.00% 0 / 300 samples altered (zero pass-through degradation)
Technical & Developer Utterances 300 1.11% Code constructs, camelCase, snake_case, dot syntax (.userInitiated)
Ambiguous Fillers in Valid Context 200 2.27% Preservation of "I like functional programming", "as well as"
False Starts & Speech Repairs 300 2.68% Atomic deletion of repairs ("port 8080 or rather 9090")
Spontaneous Speech & Hesitations 400 11.20% Multi-token fillers ("you know what I mean", "sort of like")
Adversarial & Edge Cases 300 13.06% Mixed disfluencies and technical identifier collisions

Key Architectural Mechanisms

  1. No-Edit Regularized Loss ($\lambda_{\text{uer}} = 1.2$):
    Trained with a dedicated regularization penalty that punishes any edit on already-clean ground-truth text, guaranteeing a 0.00% Unnecessary Edit Rate (UER) on pristine inputs.

  2. Deterministic Terminal Invariant Verifier:
    An AST-level validation layer executes on the output to guarantee 100.00% preservation of protected technical identifiers (camelCase, snake_case, SemVer versions like v1.4.2, cloud regions like us-west-2, currency, dates, and Swift dot syntax like DispatchQueue.global(qos: .userInitiated)).

  3. Decoupled Dual-Trigger Inference:
    Unconditionally prunes lexical fillers ("um", "uh", "basically") via the high-confidence Action fast-path while guarding contextual words ("like", "so", "well", "actually") through syntactic checking and acoustic pause thresholding ($\ge \text{bin } 1$).


Known Limitations & Boundary Conditions

  1. Not an Autoregressive / Generative LLM:
    Meg v1 operates as a non-autoregressive edit-tagger (token deletion, casing, and punctuation insertion). It does not rewrite unstructured rambling or paraphrase sentences into novel phrasing. Generative cloud LLMs achieve lower IP-WER on highly unstructured conversational speech (4.24% vs. 11.20%) due to holistic sentence reconstruction.
  2. Language Scope:
    Trained and evaluated on English only (technical, developer, professional, and conversational speech).
  3. ASR Dependency:
    Meg v1 relies on the acoustic transducer for phonetic decoding. It does not correct upstream acoustic misrecognitions unless technical terms are preserved through hotword context graphs.

Quickstart & Usage

Self-Contained Python Inference (ONNX Runtime)

import numpy as np
import onnxruntime as ort
from transformers import AutoTokenizer

# 1. Load Tokenizer and INT8 ONNX Model
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
session = ort.InferenceSession("meg_v1_tagger_int8.onnx", providers=["CPUExecutionProvider"])

raw_transcript = "um basically we need to check AXIsProcessTrusted on macOS right now"
words = raw_transcript.split()

# 2. Prepare Inputs
encoding = tokenizer(words, is_split_into_words=True, return_tensors="np")
seq_len = encoding["input_ids"].shape[1]

# Default acoustic bins (confidence 9/9, pause 0/3 for text-only inputs)
conf_bins = np.full((1, seq_len), 9, dtype=np.int64)
pause_bins = np.zeros((1, seq_len), dtype=np.int64)

# Set lower confidence & pause for hesitation words
word_ids = encoding.word_ids(batch_index=0)
for s_idx, w_idx in enumerate(word_ids):
    if w_idx is not None and words[w_idx].lower() in {"um", "uh", "basically"}:
        conf_bins[0, s_idx] = 5
        pause_bins[0, s_idx] = 2

ort_inputs = {
    "input_ids": encoding["input_ids"],
    "attention_mask": encoding["attention_mask"],
    "confidence_bins": conf_bins,
    "pause_bins": pause_bins
}

# 3. Run Inference
action_logits, punct_logits, casing_logits, repair_logits = session.run(None, ort_inputs)

# 4. Decode Outputs
action_preds = np.argmax(action_logits, axis=-1)[0]
punct_preds = np.argmax(punct_logits, axis=-1)[0]
casing_preds = np.argmax(casing_logits, axis=-1)[0]

print("Model Output Heads:")
print(f"  Actions: {action_preds.shape}")
print(f"  Punctuation: {punct_preds.shape}")
print(f"  Casing: {casing_preds.shape}")
print(f"  BILOU Repairs: {repair_logits.shape}")

Citation & License

Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support