Instructions to use hshispeech/Ruby-ASR-1.7B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use hshispeech/Ruby-ASR-1.7B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="hshispeech/Ruby-ASR-1.7B")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("hshispeech/Ruby-ASR-1.7B", device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 8,918 Bytes
47075fe 608d187 47075fe 608d187 22839f9 608d187 7add96f 608d187 7add96f 608d187 22839f9 608d187 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | ---
license: apache-2.0
language:
- ja
base_model: Qwen/Qwen3-ASR-1.7B
pipeline_tag: automatic-speech-recognition
library_name: transformers
tags:
- automatic-speech-recognition
- japanese
- furigana
- ruby
- ctc
- qwen3-asr
---
# Ruby-ASR-1.7B: Japanese ASR with inline furigana + a CTC mora-reading head
π Paper: [arXiv:2609.27289](https://arxiv.org/abs/2609.27289) Β·
π» Code: [hshi-speech/Ruby-ASR-1.7B](https://github.com/hshi-speech/Ruby-ASR-1.7B)
Ruby-ASR-1.7B is a pair of Japanese fine-tunes of
[Qwen/Qwen3-ASR-1.7B](https://huggingface.co/Qwen/Qwen3-ASR-1.7B), shipped as
two variants in this repo:
| model | subfolder | style |
|---|---|---|
| **Ruby-ASR-sub** | `subtitle/` | subtitle-style transcription |
| **Ruby-ASR-ver** | `verbatim/` | verbatim-style transcription |
Use `subtitle` when prioritizing concise, readable orthographic transcription;
use `verbatim` when prioritizing script-aware and lexical-reading accuracy
(see [Evaluation](#evaluation)).
Both variants share the same architecture, mora vocab, and layout, and each
adds **two complementary outputs**:
1. **Ruby (furigana) transcription** β the standard Qwen3-ASR seq2seq decoder
emits the transcript with inline bracket furigana:
`δΈ[γͺγͺ]εΉ΄ι[γγγγ]γ§γγΉγ«γει[γ¨γγ γ‘]γ§γγγγ`
Every annotated word carries its reading, so downstream text display
(HTML `<ruby>`), reading-aware subtitling, and pronunciation-controlled TTS
all get the reading for free.
2. **Mora reading (CTC)** β an auxiliary branch on the audio encoder
(2-layer Transformer adapter + linear head, trained jointly with CTC loss)
that outputs the **actual pronunciation** as kana morae directly from the
encoder, without running the LLM decoder:
`γγγγ³γ«γ³γγγΉγγ’γγ’γγγγγΏγ·`
Each variant's sharded main weights are a **stock Qwen3-ASR checkpoint** (the
CTC branch is stored separately under `ctc/`), so Mode 2 works with unmodified
vLLM and the official [`qwen-asr`](https://github.com/QwenLM/Qwen3-ASR)
toolkit. Mode 1 is provided by the
[`ruby_asr`](https://github.com/hshi-speech/Ruby-ASR-1.7B) package.
## Repo layout
```
subtitle/ verbatim/ (same layout in both)
βββ model-0000x-of-00003.safetensors sharded Qwen3-ASR weights (CTC stripped) β Mode 2
βββ model.safetensors.index.json
βββ config.json, generation_config.json
βββ tokenizer.json, tokenizer_config.json, vocab.json, merges.txt,
β added_tokens.json, special_tokens_map.json, chat_template.json,
β preprocessor_config.json
βββ ctc/
βββ model.safetensors the CTC branch (ctc_adapter.* + ctc_head.*) β Mode 1
βββ config.json adapter hyper-params (transformer, 2 layers, nhead 8), blank id
βββ mora_vocab.json {mora: id}; id 0 = <blank>, ids 1-26 = a-z, then morae
```
## Mode 1 β mora reading via encoder + CTC
No LLM decoding: audio β encoder frames β CTC adapter β head β greedy collapse.
Fast, and reflects the *actual pronunciation* (e.g. numbers and kanji resolved
to what was said). Loads straight from this repo:
```python
# pip install git+https://github.com/hshi-speech/Ruby-ASR-1.7B.git
from ruby_asr import MoraCTCRecognizer
rec = MoraCTCRecognizer.from_pretrained("hshispeech/Ruby-ASR-1.7B",
subfolder="subtitle") # or "verbatim"
print(rec.transcribe("audio.wav")[0])
# γγγγ³γ«γ³γγγΉγγ’γγ’γγγγγΏγ·
```
Output alphabet: katakana morae (`γγ§`, `γ`, `γ³`, `γΌ` are single tokens)
plus `a`β`z` for embedded English. Long vowels are unified to `γΌ`
(`γγ¦γγ§γ¦` β `γγΌγγ§γΌ`), matching the pyopenjtalk `g2p(kana=True)`
convention the training targets were built with.
## Mode 2 β ruby transcription (transformers)
Download the variant you need, then load it like stock Qwen3-ASR:
```python
# pip install qwen-asr
import torch
from huggingface_hub import snapshot_download
from qwen_asr import Qwen3ASRModel
root = snapshot_download("hshispeech/Ruby-ASR-1.7B", allow_patterns=["subtitle/*"])
model = Qwen3ASRModel.from_pretrained(f"{root}/subtitle",
dtype=torch.bfloat16, device_map="cuda")
print(model.transcribe(audio="audio.wav")[0].text)
# δΈ[γͺγͺ]εΉ΄ι[γγγγ]γ§γγΉγ«γει[γ¨γγ γ‘]γ§γγγγ
```
Post-process the bracket output (surface / reading / HTML `<ruby>`) with the
`ruby_asr` helpers:
```python
from ruby_asr import to_surface, to_reading, to_html, brackets_to_parens
text = "δΈ[γͺγͺ]εΉ΄ι[γγγγ]γ§γγΉγ«γει[γ¨γγ γ‘]γ§γγγγ"
to_surface(text) # δΈεΉ΄ιγ§γγΉγ«γειγ§γγγγ
to_reading(text) # γͺγͺγγγγγ§γγΉγ«γγ¨γγ γ‘γ§γγγγ
to_html(brackets_to_parens(text)) # <ruby><rb>δΈ</rb><rt>γͺγͺ</rt></ruby>β¦
```
## Mode 2 β ruby transcription (vLLM)
```bash
pip install "qwen-asr[vllm]" # or your own vLLM >= 0.14 install
hf download hshispeech/Ruby-ASR-1.7B --include "subtitle/*" --local-dir Ruby-ASR-1.7B
vllm serve Ruby-ASR-1.7B/subtitle --served-model-name ruby-asr --max-model-len 8192
```
```python
import base64
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="EMPTY")
audio_b64 = base64.b64encode(open("audio.wav", "rb").read()).decode()
resp = client.chat.completions.create(
model="ruby-asr",
messages=[
{"role": "system", "content": ""},
{"role": "user", "content": [
{"type": "input_audio",
"input_audio": {"data": audio_b64, "format": "wav"}}]},
],
temperature=0.0, max_tokens=512)
print(resp.choices[0].message.content)
# language Japanese<asr_text>δΈ[γͺγͺ]εΉ΄ι[γγγγ]γ§γγΉγ«γει[γ¨γγ γ‘]γ§γγγγ
```
> **Use `/v1/chat/completions`, not `/v1/audio/transcriptions`.** The furigana
> is the model's learned behaviour under the standard Qwen3-ASR chat prompt
> (empty system + audio). The transcriptions endpoint builds a different
> internal prompt and returns plain text without brackets.
## Training objective
Fine-tuned from Qwen3-ASR-1.7B with a joint loss `0.3 Β· CTC + 0.7 Β· CE`: the
standard cross-entropy over the seq2seq ruby transcript plus a CTC loss over
mora targets from the auxiliary encoder branch. The seq2seq path never sees
the CTC adapter, so ruby decoding is bit-identical to a checkpoint without
the branch.
## Evaluation
Character-count-weighted averages (W.Avg.) over five Japanese benchmarks β
B5K, CSJ, JSUT-Book, Common Voice 8, and TEDx β weighted by the number of
reference characters per test set. All values are percentages; lower is
better.
| Model | Raw CER | SA-CER | Kana CER |
| --------------- | -------: | -------: | -------: |
| ReazonSpeech-k2 | 10.35 | 8.51 | 5.64 |
| Qwen3-ASR-1.7B | 10.78 | 8.59 | 5.74 |
| Kana-Whisper | N/A | N/A | 4.66 |
| Ruby-ASR-ver | 9.10 | **6.59** | **3.75** |
| Ruby-ASR-sub | **8.51** | 6.64 | 4.01 |
On this weighted aggregate, **Ruby-ASR-sub** achieves the best Raw CER
(8.51%, a 21.1% relative reduction over Qwen3-ASR), and **Ruby-ASR-ver** the
best SA-CER (6.59%) and Kana CER (3.75%) β relative reductions of 23.3% and
34.7% over Qwen3-ASR. Compared with Kana-Whisper, Ruby-ASR-ver reduces
weighted Kana CER from 4.66% to 3.75%, a 19.5% relative reduction.
Metrics:
- **Raw CER** β normalized orthographic transcription, with the original
script preserved.
- **SA-CER** β script-aware: kana regions are scored by reading, kanji
regions by orthography.
- **Kana CER** β lexical-reading transcription.
- Ruby-ASR and Kana-Whisper are scored on their direct reading outputs; the
orthographic baselines are converted through the shared G2P pipeline.
## Limitations
- Japanese-focused fine-tune; other Qwen3-ASR languages were not part of
training and quality on them is untested.
- Mode 1 output is pronunciation kana only β no kanji, punctuation, or word
boundaries.
- Furigana brackets are learned behaviour, not constrained decoding: rare
formatting slips (e.g. an empty `[]` on numbers) are possible; the parser in
the code repo handles them.
## Citation
```bibtex
@misc{shi2026rubyasrevidencepreservingsupervisionjoint,
title = {Ruby-ASR: Evidence-Preserving Supervision for Joint Orthographic and Lexical-Reading Recognition},
author = {Hao Shi and Yun Liu and Xuehao Yang and Jun Liu and Chuanbo Hua and Xuanjun Chen and Lianbo Liu and Shiao Zhu and Zixiong Su},
year = {2026},
eprint = {2609.27289},
archivePrefix = {arXiv},
primaryClass = {cs.CL},
url = {https://arxiv.org/abs/2609.27289},
}
```
## License
Apache-2.0, same as the Qwen3-ASR base model.
|