Views
No views yet
KanaryPrompt formatter tuned for Korean text normalization and foreign-word rendering. Prompt controls for punctuation (pnc), inverse text normalization (itn), and foreign-word style (foreign) are passed via prompt tokens. This repo ships the .nemo checkpoint plus minimal inference scripts.kanary-1b-20260119.nemo: NeMo checkpoint.kanary_prompt: Python package that extends the Canary prompt format.infer.py: Example that builds a temporary manifest and prints transcriptions.Canary2PromptFormatter, KanaryPromptFormatter adds a new |foreign| prompt token to control foreign-word writing styles. We also fine-tuned Kanary to support extended |itn| tokens (itn, noitn, itn:undefined), which are not available in the original Canary."{CANARY2_BOCTX}|decodercontext|{CANARY_BOS}|emotion||source_lang||target_lang||pnc||itn||timestamp||diarize||foreign|"requirements.txt1# Install torch separately to match your CUDA version if needed.
2nemo_toolkit[asr]
3soundfile
4huggingface_hub>=0.22.0
5git+https://github.com/21jun/kanary_prompt.git
61import nemo.collections.asr as nemo_asr
2from kanary_prompt import kanary
3import json
4import tempfile
5import soundfile as sf
6
7# Initialize ASR model
8asr_model = nemo_asr.models.ASRModel.from_pretrained("lee1jun/kanary-1b-20260119")
9
10# Prepare your audio file paths
11
12audio_paths = ["path/to/your/audio1.wav", "path/to/your/audio2.wav", "path/to/your/audio3.wav"]
13
14
15def _get_duration_seconds(audio_path: str) -> float:
16 info = sf.info(audio_path)
17 if info.samplerate == 0:
18 raise ValueError(f"Sample rate is zero for {audio_path}")
19 return float(info.frames / info.samplerate)
20
21# Since the current NeMo EncDecMultiTaskModel (Canary) does not support prompt configuration directly in the `transcribe` method,
22# we create a wrapper function to handle the prompt configuration via a temporary JSON manifest file.
23def transcribe(audio_paths, show_manifest=False, **kwargs):
24 # Create tmp json file of audio paths and kwargs, then call asr_model.transcribe on it
25 tmp_json = tempfile.NamedTemporaryFile(mode='w+', delete=True, suffix=".json")
26 data = []
27 for audio_path in audio_paths:
28 entry = {"audio_filepath": audio_path}
29 entry.update(kwargs)
30 if "duration" not in entry:
31 try:
32 entry["duration"] = _get_duration_seconds(audio_path)
33 except Exception as exc:
34 print(f"Warning: unable to compute duration for {audio_path}: {exc}; defaulting to 0.0")
35 entry["duration"] = 0.0
36 data.append(entry)
37 for item in data:
38 tmp_json.write(json.dumps(item) + "\n")
39 tmp_json.flush()
40 if show_manifest:
41 with open(tmp_json.name, 'r') as f:
42 print(f.read())
43
44 transcriptions = asr_model.transcribe(tmp_json.name)
45 tmp_json.close()
46 return transcriptions
47
48
49# Example usage:
50
51transcriptions = transcribe(audio_paths, source_lang="ko", target_lang="ko", itn="itn", pnc="True", foreign="foreign:en")
52for transcription in transcriptions:
53 print(transcription.text)
54
55
56transcriptions = transcribe(audio_paths, source_lang="ko", target_lang="ko", itn="noitn", pnc="False", foreign="foreign:ko")
57for transcription in transcriptions:
58 print(transcription.text)
59source_lang / target_lang: Language codes in the manifest; currently only ko is supported.foreign: Foreign-word style, e.g., foreign:en, foreign:ko, or foreign:undefined if unused.itn : Inverse Text Normalization, e.g., itn, noitn, itn:undefined if unused.pnc: Use "True" or "False" strings as expected by the model.audio_filepath, duration, source_lang, target_lang, foreign, itn, pnc.1import nemo.collections.asr as nemo_asr
2from kanary_prompt import kanary
3import json
4import tempfile
5import soundfile as sf
6
7# Initialize ASR model
8asr_model = nemo_asr.models.ASRModel.from_pretrained("lee1jun/kanary-1b-20260119")
9# Example usage:
10transcriptions = asr_model.transcribe("path/to/your/manifest.json")| MODEL | ITN | PNC | FOREIGN | Transcription |
|---|---|---|---|---|
| whisper-large-v3-turbo | - | - | - | 그게 처음에 마이페이지를 들어가서 캐시를 버튼을 누르고 또 캐시 할인권 메뉴어 메뉴에서 쉐어링 캐시 그리고 충전하기 버튼을 누르면 |
| kanary | itn | True | foreign:en | 그게 처음에 my page를 들어가서 cash를 버튼을 누르고 또 cash 할인권 manu manu에서 sharing cash 그리고 충전하기 버튼을 누르면. |
| kanary | noitn | True | foreign:ko | 그게 처음에 마이 페이지를 들어가서 캐시를 버튼을 누르고 또 캐시 할인권 메뉴여 메뉴에서 셰어링 캐시 그리고 충전하기 버튼을 누르면. |
| kanary | itn:undefined | True | foreign:undefined | 그게 처음에 마이페이지를 들어가서 캐시를 버튼을 누르고 또 캐시 할인권 메뉴여 메뉴에서 쉐어링 캐시 그리고 충전하기 버튼을 누르면. |
| MODEL | ITN | PNC | FOREIGN | Transcription |
|---|---|---|---|---|
| whisper-large-v3-turbo | - | - | - | 유효기간 0622고요. CVC 번호가 333이네요. |
| kanary | noitn | True | foreign:en | 유효기간 공 육 이 이구요. cvc번호가 삼 삼 삼이네요. |
| kanary | itn | True | foreign:en | 유효기간 0622고요. cvc번호가 333이네요. |
| kanary | noitn | True | foreign:ko | 유효기간 공 육 이 이구요. 씨브이씨번호가 삼 삼 삼이네요. |
| kanary | itn | True | foreign:ko | 유효기간 0622고요. 씨브이씨번호가 333이네요. |
itn, pnc, and foreign prompts.model_config.yaml.itn:undefined token and 3 new foreign-handling tokens.model_config.yaml1tokenizer:
2 dir: null
3 type: agg
4 langs:
5 spl_tokens:
6 dir: null
7 type: bpe
8 model_path: nemo:7f3ebf9af63d49ca88c0929ccacd3bd9_tokenizer.model
9 vocab_path: nemo:e910c2757df4403b82d3f2e421ea5f0b_vocab.txt
10 spe_tokenizer_vocab: nemo:548dc4893ea64b92886055409f7e8713_tokenizer.vocab
11 ko:
12 dir: null
13 type: bpe
14 model_path: nemo:f29eefa5554e40848746cf1f81ee9421_tokenizer.model
15 vocab_path: nemo:01f79140103246f892ea17db8aed2985_vocab.txt
16 spe_tokenizer_vocab: nemo:34ed5c3872dc42cda8125930bae15efa_tokenizer.vocab
17 custom_tokenizer:
18 _target_: nemo.collections.common.tokenizers.canary_tokenizer.CanaryTokenizer
19 tokenizers: null