Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
36767d1
CanaryConverter draft
eustlb Sep 8, 2025
403a6df
init: Add files (canary-1b-v2)
harshaljanjani Jun 22, 2026
c9a82bf
fix: Resolve Bandit warning
harshaljanjani Jun 23, 2026
86a5cf1
fix: Make CI green 1
harshaljanjani Jun 23, 2026
210d2ee
Merge branch 'main' into add-canary
harshaljanjani Jul 8, 2026
9c2e8b3
refactor: Address review round 1 - 1
harshaljanjani Jul 9, 2026
769b816
Merge branch 'main' into add-canary
harshaljanjani Jul 9, 2026
d471d82
refactor: Address review round 1 - 2
harshaljanjani Jul 9, 2026
4537446
Merge branch 'main' into add-canary
harshaljanjani Jul 16, 2026
e4bd5a9
refactor: Address review round 2
harshaljanjani Jul 16, 2026
5784717
DIrectly create config file since doesn't need modular.
ebezzam Jul 29, 2026
11a160a
Testing nits/refactor.
ebezzam Jul 29, 2026
e029972
Refactor common processing utillities.
ebezzam Jul 29, 2026
3afbfaa
Merge branch 'main' into add-canary
harshaljanjani Jul 29, 2026
60c4ffc
refactor: Address review round 3
harshaljanjani Jul 29, 2026
43b3a1a
Nits
ebezzam Aug 3, 2026
f9cfb7e
Merge branch 'main' into add-canary
harshaljanjani Aug 3, 2026
65e9ecb
refactor: Address review round 4
harshaljanjani Aug 3, 2026
3a59a9e
Merge branch 'main' into add-canary
harshaljanjani Aug 4, 2026
a0c120e
refactor: Address review round 5
harshaljanjani Aug 4, 2026
26d6acb
Modular nits
ebezzam Aug 4, 2026
aa463c9
Merge remote-tracking branch 'upstream/main' into add-canary
harshaljanjani Aug 4, 2026
7fbcd26
Merge branch 'main' into add-canary
harshaljanjani Aug 24, 2026
bc48e52
fix: CI issue
harshaljanjani Aug 24, 2026
2ae352f
Merge branch 'main' into add-canary
harshaljanjani Aug 25, 2026
b18b94c
Address comments on docs.
ebezzam Aug 25, 2026
1af705d
Merge branch 'add-canary' of github.com:harshaljanjani/transformers i…
ebezzam Aug 25, 2026
0240976
Apply suggestion from @vasqu
ebezzam Aug 25, 2026
aedeb7e
address config comment
ebezzam Aug 25, 2026
0993cdb
Merge branch 'add-canary' of github.com:harshaljanjani/transformers i…
ebezzam Aug 25, 2026
83af420
fix: Make changes
harshaljanjani Aug 25, 2026
1fa2ec6
Merge remote-tracking branch 'upstream/main' into add-canary
harshaljanjani Aug 25, 2026
e751207
address modular comments
ebezzam Aug 25, 2026
bec2944
fix: Make changes 2
harshaljanjani Aug 26, 2026
646fc61
Merge remote-tracking branch 'upstream/main' into add-canary
harshaljanjani Aug 26, 2026
f7b6e99
Merge branch 'main' into add-canary
ebezzam Aug 31, 2026
5dc16a3
Move dtype casting.
ebezzam Aug 31, 2026
cb50a15
Address comments
ebezzam Aug 31, 2026
3904da9
Add back decorators.
ebezzam Aug 31, 2026
88dd3d6
replace: NVIDIA Canary-1B-V2 repo
harshaljanjani Aug 31, 2026
077e790
Merge branch 'main' into add-canary
ebezzam Aug 31, 2026
5cfdb93
Merge branch 'main' into add-canary
ebezzam Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/en/_toctree.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,8 @@
title: Audio Spectrogram Transformer
- local: model_doc/bark
title: Bark
- local: model_doc/canary
title: Canary
- local: model_doc/clap
title: CLAP
- local: model_doc/cohere_asr
Expand Down
149 changes: 149 additions & 0 deletions docs/source/en/model_doc/canary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<!--Copyright 2026 The HuggingFace Team. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

⚠️ Note that this file is in Markdown but contains specific syntax for our doc-builder (similar to MDX) that may not be
rendered properly in your Markdown viewer.

-->
*This model was published in HF papers on 2025-09-17 and contributed to Hugging Face Transformers on 2026-07-29.*

<div class="flex flex-wrap space-x-1">
<img alt="SDPA" src="https://img.shields.io/badge/SDPA-DE3412?style=flat&logo=pytorch&logoColor=white">
</div>

# Canary

## Overview

Canary-1B-v2 was proposed in [Canary-1B-v2 & Parakeet-TDT-0.6B-v3: Efficient and High-Performance Models for Multilingual ASR and AST](https://huggingface.co/papers/2509.14128) by Monica Sekoyan, Nithin Rao Koluguri, Nune Tadevosyan, Piotr Zelasko, Travis Bartley, Nikolay Karpov, Jagadeesh Balam, and Boris Ginsburg.

The abstract from the paper is the following:

*This report introduces Canary-1B-v2, a fast, robust multilingual model for Automatic Speech Recognition (ASR) and Speech-to-Text Translation (AST). Built with a FastConformer encoder and Transformer decoder, it supports 25 European languages. The model was trained on 1.7M hours of total data samples, including Granary and NeMo ASR Set 3.0, with non-speech audio added to reduce hallucinations for ASR and AST. We describe its two-stage pre-training and fine-tuning process with dynamic data balancing, as well as experiments with an nGPT encoder. Results show nGPT scales well with massive data, while FastConformer excels after fine-tuning. For timestamps, Canary-1B-v2 uses the NeMo Forced Aligner (NFA) with an auxiliary CTC model, providing reliable segment-level timestamps for ASR and AST. Evaluations show Canary-1B-v2 outperforms Whisper-large-v3 on English ASR while being 10× faster, and delivers competitive multilingual ASR and AST performance against larger models like Seamless-M4T-v2-large and LLM-based systems. We also release Parakeet-TDT-0.6B-v3, a successor to v2, offering multilingual ASR across the same 25 languages with just 600M parameters.*

Canary reuses the [Fast Conformer](https://huggingface.co/papers/2305.05084) encoder from [Parakeet](./parakeet.md) (loaded through [`ParakeetEncoder`] / [`ParakeetEncoderConfig`]) and pairs it with a Transformer decoder that uses fixed sinusoidal positional embeddings, cross-attention to the encoder outputs and tied input/output embeddings. The task is selected through a decoder prompt prefix built by [`CanaryProcessor`] of the form `<|startofcontext|> <|startoftranscript|> <|emo:undefined|> <source_lang> <target_lang> <pnc|nopnc> <|noitn|> <|notimestamp|> <|nodiarize|>`, where `source_lang == target_lang` selects transcription and otherwise selects translation.

The original implementation can be found in [NVIDIA NeMo](https://github.com/NVIDIA/NeMo). A model checkpoint is available at [harshaljanjani/canary-1b-v2-hf](https://huggingface.co/harshaljanjani/canary-1b-v2-hf).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: let's check with NVIDIA about adding the Transformers checkpoint to their model card, as NeMo and Transformers files can exist in the same repo!

Can you open a PR on the HF Hub to add the Transformers file and usage? Like this and this as one PR. And if you can mention this PR + indicate that your HF PR is a draft so that they don't merge it just yet. Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yea what's the state here? Any response or should we use "revision" for now instead?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when we're ready to merge, we can ask @nithinraok!


Comment thread
ebezzam marked this conversation as resolved.
Resolved
This model was contributed by [Harshal Janjani](https://huggingface.co/harshaljanjani).

## Usage
Comment thread
ebezzam marked this conversation as resolved.
Resolved

### Transcription

The simplest way to transcribe audio is with `apply_transcription_request`, which builds the multitask decoder prompt for you (it is a convenience wrapper for `apply_chat_template`).

```python
from datasets import load_dataset, Audio
from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq

processor = AutoProcessor.from_pretrained("harshaljanjani/canary-1b-v2-hf")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO (when HF model merged): set checkpoint here and elsewhere to nvidia/canary-1b-v2

model = AutoModelForSpeechSeq2Seq.from_pretrained("harshaljanjani/canary-1b-v2-hf", device_map="auto")

ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
ds = ds.cast_column("audio", Audio(sampling_rate=processor.feature_extractor.sampling_rate))

inputs = processor.apply_transcription_request(audio=ds[0]["audio"]["array"], source_language="en").to(model.device)
generated_ids = model.generate(**inputs, max_new_tokens=128)
print(processor.decode(generated_ids, skip_special_tokens=True)[0])
```

### Translation

Set `target_language` to a different language than `source_language` for speech-to-text translation.

```python
inputs = processor.apply_transcription_request(
audio=ds[0]["audio"]["array"], source_language="en", target_language="de"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw more fmi but what are the defaults here? would it use en as default?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default for source_language is "en", and target_language is None (as default is to not translate)

).to(model.device)
generated_ids = model.generate(**inputs, max_new_tokens=128)
print(processor.decode(generated_ids, skip_special_tokens=True)[0])
```

### Batch inference

Pass a list of audios and, optionally, a list of `source_language` / `target_language`.

```python
audios = [ds[0]["audio"]["array"], ds[1]["audio"]["array"]]
inputs = processor.apply_transcription_request(
audio=audios, source_language="en", target_language=["en", "de"]
Comment thread
ebezzam marked this conversation as resolved.
Resolved
).to(model.device)
generated_ids = model.generate(**inputs, max_new_tokens=128)
for text in processor.decode(generated_ids, skip_special_tokens=True):
print(text)
```

### Torch compile

For autoregressive transcription, `torch.compile` accelerates the per-token forward passes inside `generate` by providing a `CompileConfig` object.

```python
from transformers import CompileConfig
Comment thread
ebezzam marked this conversation as resolved.
Resolved

inputs = processor.apply_transcription_request(audio=ds[0]["audio"]["array"], source_language="en").to(model.device)
compile_config = CompileConfig()

# Warmup
for _ in range(3):
_ = model.generate(**inputs, max_new_tokens=128, cache_implementation="static", compile_config=compile_config)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cache implementation is not necessary if we have compile config no?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think because my Qwen3 ASR example from here was copied, and because I probably saw that type of usage in the docstrings here.

@vasqu should we remove cache_implementation here and elsewhere? namely in Qwen3ASR and in the CompileConfig docstring

on another note: @harshaljanjani I'm getting the following warning when running a compile example

[transformers] You have set `compile_config`, but we are unable to meet the criteria for compilation. Compilation will be skipped.

can you look into it?

below is my script

from transformers import CompileConfig
from datasets import load_dataset, Audio
from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq

processor = AutoProcessor.from_pretrained("harshaljanjani/canary-1b-v2-hf")
model = AutoModelForSpeechSeq2Seq.from_pretrained("harshaljanjani/canary-1b-v2-hf", device_map="auto")

ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
ds = ds.cast_column("audio", Audio(sampling_rate=processor.feature_extractor.sampling_rate))
inputs = processor.apply_transcription_request(audio=ds[0]["audio"]["array"], source_language="en").to(model.device)

compile_config = CompileConfig()

# Warmup
for _ in range(3):
    # _ = model.generate(**inputs, max_new_tokens=128, cache_implementation="static", compile_config=compile_config)
    _ = model.generate(**inputs, max_new_tokens=128, compile_config=compile_config)


# Apply model
generated_ids = model.generate(**inputs, max_new_tokens=128, compile_config=compile_config)
# generated_ids = model.generate(**inputs, max_new_tokens=128, cache_implementation="static", compile_config=compile_config)

print(processor.decode(generated_ids, skip_special_tokens=True)[0])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's from removing cache_implementation="static". Given Canary's self and cross-attention caches are both DynamicCache, this check fails. Adding the line makes both StaticCache and it compiles; think plain Llama does the same (?) so keeping it here and elsewhere seems reasonable, would love to know if you think otherwise though!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep can confirm 👍

are you able to try with multi-GPU, e.g. running

CUDA_VISIBLE_DEVICES=0,1 python src/transformers/models/canary/compile_example.py

I get the following warning 4 times

skipping cudagraphs due to skipping cudagraphs due to multiple devices: device(type='cuda', index=1), device(type='cuda', index=0)

@harshaljanjani harshaljanjani Aug 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup here's the output I got 🤗
On 2× L4 I don't get that exact one, but I do get torch._dynamo hit config.recompile_limit (8)
twice, both pointing at accelerate/hooks.py. Doesn't happen pinned to a single GPU, so looks
like the same device_map="auto" cause, just worded differently on torch 2.13.
Script

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raised #48364

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this is weird, though I have no idea about where it's going. We also have the cache_config which allows override cache init kwargs for certain cache types, but also doesn't change cache_implemetation automatically

I think Cyril is cache maintainer so it's better to ask him

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @Cyrilvallez (sorry for all the pings 😬)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harshaljanjani thanks for the explanations and opening the other PR!

@vasqu how should we proceed with this PR so it isn't blocked: should we leave cache_implemetation="static" for now with a note? and in then in the other PR: remove from this example and others (Llama and Qwen3ASR)

@vasqu vasqu Aug 31, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't block this PR! We can keep the static cache docs etc (and only update when we change the logic if we decide to do it)


# Apply model
generated_ids = model.generate(**inputs, max_new_tokens=128, cache_implementation="static", compile_config=compile_config)
print(processor.decode(generated_ids, skip_special_tokens=True)[0])
```

### Training

Canary can be trained with the loss outputted by the model. Build the decoder sequence from the multitask prompt followed by the target text, and mask the prompt in the labels.

```python
import torch

model.train()
audio = ds[0]["audio"]["array"]
transcription = "mister Quilter is the apostle of the middle classes, and we are glad to welcome his gospel."

prompt = processor.apply_transcription_request(audio=audio, source_language="en").to(model.device)
target_ids = processor(audio=audio, text=transcription)["decoder_input_ids"].to(model.device)
decoder_input_ids = torch.cat([prompt["decoder_input_ids"], target_ids], dim=1)
labels = decoder_input_ids.clone()
labels[:, : prompt["decoder_input_ids"].shape[1]] = -100
Comment thread
ebezzam marked this conversation as resolved.
Resolved

outputs = model(
input_features=prompt["input_features"],
attention_mask=prompt["attention_mask"],
decoder_input_ids=decoder_input_ids,
labels=labels,
)
outputs.loss.backward()
```

> [!NOTE]
> Segment-level timestamps for Canary-1B-v2 are produced by the external NeMo Forced Aligner (NFA) with an auxiliary CTC model, not by the decoder, so they are not part of the `generate` output.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe would put it somewhere above close to the initial description. Feel like users would oftetimes not get to the end to see this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in b18b94c by @ebezzam, thank you :)


## CanaryConfig

[[autodoc]] CanaryConfig

## CanaryProcessor

[[autodoc]] CanaryProcessor

## CanaryModel

[[autodoc]] CanaryModel
- forward

## CanaryForConditionalGeneration

[[autodoc]] CanaryForConditionalGeneration
- forward
98 changes: 98 additions & 0 deletions src/transformers/audio_utils.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably cc @eustlb just in case

Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,104 @@ def make_list_of_audio_chat_template(
return make_list_of_audio(audio)


def make_audio_chat_template_content(audio_item) -> dict:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new utility to handle str input (for url or path) and array input

"""
Build a chat-template content dict for a single audio item.

Args:
audio_item (`str` or array-like):
A single audio item. Strings are treated as local paths or URLs; other values (numpy/torch arrays) are
forwarded directly.

Returns:
`dict`: A chat-template content dict, e.g. `{"type": "audio", "path": ...}` for strings or
`{"type": "audio", "audio": ...}` otherwise.
"""
if isinstance(audio_item, str):
return {"type": "audio", "path": audio_item}
return {"type": "audio", "audio": audio_item}


def resolve_language(language: str | None, code_to_name: dict[str, str], return_code: bool = True) -> str | None:
"""
Map a language code or name to its canonical form, with validation.

Accepts either a language code (e.g. ``"zh"``, ``"en"``) or a full name (e.g. ``"Chinese"``, ``"English"``) and
returns the canonical code or name depending on ``return_code``. ``None`` passes through unchanged (auto-detect).

Args:
language (`str` or `None`):
The language code or full name to resolve. ``None`` is returned unchanged.
code_to_name (`dict[str, str]`):
Mapping from language code to full language name for the model's supported languages.
return_code (`bool`, *optional*, defaults to `True`):
Whether to return the canonical language ``code``. If ``False``, returns the full language ``name``.

Returns:
`str` or `None`: The canonical language code or name, or ``None`` if ``language`` is ``None``.

Raises:
`ValueError`: If the language is not recognized.
"""
if language is None:
return None

language_lower = language.lower()
# Try code lookup first, then full-name lookup (both case-insensitive)
for code, name in code_to_name.items():
if language_lower == code.lower() or language_lower == name.lower():
return code if return_code else name

raise ValueError(
f"Unsupported language: {language!r}. Use a language code "
f"(e.g. 'en', 'zh') or full name (e.g. 'English', 'Chinese'). "
f"Supported codes: {sorted(code_to_name.keys())}. "
f"Supported names: {sorted(set(code_to_name.values()))}."
)


def prepare_language_inputs(
language: str | list[str] | None,
batch_size: int,
code_to_name: dict[str, str],
allow_broadcast: bool = False,
return_code: bool = True,
) -> list[str | None]:
"""
Broadcast and validate a language argument to match ``batch_size``.

Accepts language codes (e.g. ``"zh"``, ``"en"``) or full names (e.g. ``"Chinese"``, ``"English"``). Each value is
resolved to its canonical form via [`resolve_language`].

Args:
language (`str`, `list[str]`, or `None`):
The language hint(s). A single value is broadcast to the whole batch; a list must match ``batch_size``
(unless ``allow_broadcast`` is set). ``None`` disables language hints for the whole batch.
batch_size (`int`):
The number of samples in the batch.
code_to_name (`dict[str, str]`):
Mapping from language code to full language name for the model's supported languages.
allow_broadcast (`bool`, *optional*, defaults to `False`):
Whether a single-element list may be broadcast to the whole batch.
return_code (`bool`, *optional*, defaults to `True`):
Whether to return canonical language ``code``s. If ``False``, returns full language ``name``s.

Returns:
`list[str | None]`: The resolved language for each sample.
"""
if language is None:
return [None] * batch_size
if isinstance(language, str):
return [resolve_language(language, code_to_name, return_code)] * batch_size
if isinstance(language, (list, tuple)):
if allow_broadcast and len(language) == 1 and batch_size > 1:
return [resolve_language(language[0], code_to_name, return_code)] * batch_size
if len(language) != batch_size:
raise ValueError(f"Got {len(language)} language(s) for {batch_size} sample(s); counts must match.")
return [resolve_language(lang, code_to_name, return_code) for lang in language]
raise TypeError("`language` must be a string, a list of strings, or `None`.")


def hertz_to_mel(freq: float | np.ndarray, mel_scale: str = "htk") -> float | np.ndarray:
"""
Convert frequency from hertz to mels.
Expand Down
11 changes: 11 additions & 0 deletions src/transformers/convert_slow_tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,17 @@ def tokenizer(self, proto):
return tokenizer


class CanaryConverter(ParakeetConverter):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

def __init__(self, vocab_file=None, *args):
super().__init__(vocab_file, *args)
# Only the `<|...|>` (type 4) control tokens are special; other type-4 pieces (digits, `<pad>`) are plain text.
self.special_tokens = {
piece.piece
for piece in self.proto.pieces
if piece.type == 4 and piece.piece.startswith("<|") and piece.piece.endswith("|>")
}


def bytes_to_unicode():
"""
Returns list of utf-8 byte and a mapping to unicode strings. We specifically avoids mapping to whitespace/control
Expand Down
1 change: 1 addition & 0 deletions src/transformers/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
from .bros import *
from .byt5 import *
from .camembert import *
from .canary import *
from .canine import *
from .chameleon import *
from .chinese_clip import *
Expand Down

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so this is the simplification tied to the doc change? Would it change anything if we still passed the kwarg?

@ebezzam ebezzam Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no the docchange is something separate, just added a comment for the reason

this change is to create a this common utility shared across multiple processors

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import numpy as np

from ...audio_utils import AudioInput, make_list_of_audio_chat_template
from ...audio_utils import AudioInput, make_audio_chat_template_content, make_list_of_audio_chat_template
from ...feature_extraction_utils import BatchFeature
from ...processing_utils import ProcessingKwargs, ProcessorMixin, Unpack
from ...tokenization_utils_base import TextInput
Expand Down Expand Up @@ -236,9 +236,7 @@ def apply_transcription_request(
"role": "user",
"content": [
{"type": "text", "text": prompt_text},
{"type": "audio", "path": audio_item}
if isinstance(audio_item, str)
else {"type": "audio", "audio": audio_item},
make_audio_chat_template_content(audio_item),
],
}
]
Expand Down
2 changes: 2 additions & 0 deletions src/transformers/models/auto/auto_mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
("bridgetower_vision_model", "BridgeTowerVisionConfig"),
("bros", "BrosConfig"),
("camembert", "CamembertConfig"),
("canary", "CanaryConfig"),
("canine", "CanineConfig"),
("chameleon", "ChameleonConfig"),
("chameleon_vqgan", "ChameleonVQVAEConfig"),
Expand Down Expand Up @@ -1016,6 +1017,7 @@
("blip-2", "Blip2Processor"),
("bridgetower", "BridgeTowerProcessor"),
("bros", "BrosProcessor"),
("canary", "CanaryProcessor"),
("chameleon", "ChameleonProcessor"),
("chinese_clip", "ChineseCLIPProcessor"),
("clap", "ClapProcessor"),
Expand Down
1 change: 1 addition & 0 deletions src/transformers/models/auto/feature_extraction_auto.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
MISSING_FEATURE_EXTRACTOR_MAPPING_NAMES = OrderedDict(
[
("audioflamingo3", "WhisperFeatureExtractor"),
("canary", "ParakeetFeatureExtractor"),
("csm", "EncodecFeatureExtractor"),
("data2vec-audio", "Wav2Vec2FeatureExtractor"),
("glmasr", "WhisperFeatureExtractor"),
Expand Down
2 changes: 2 additions & 0 deletions src/transformers/models/auto/modeling_auto.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class _BaseModelWithGenerate(PreTrainedModel, GenerationMixin):
("bridgetower", "BridgeTowerModel"),
("bros", "BrosModel"),
("camembert", "CamembertModel"),
("canary", "CanaryModel"),
("canine", "CanineModel"),
("chameleon", "ChameleonModel"),
("chinese_clip", "ChineseCLIPModel"),
Expand Down Expand Up @@ -1314,6 +1315,7 @@ class _BaseModelWithGenerate(PreTrainedModel, GenerationMixin):

MODEL_FOR_SPEECH_SEQ_2_SEQ_MAPPING_NAMES = OrderedDict(
[
("canary", "CanaryForConditionalGeneration"),
("cohere_asr", "CohereAsrForConditionalGeneration"),
("dia", "DiaForConditionalGeneration"),
("granite_speech", "GraniteSpeechForConditionalGeneration"),
Expand Down
1 change: 1 addition & 0 deletions src/transformers/models/auto/tokenization_auto.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
("bros", "BertTokenizer" if is_tokenizers_available() else None),
("byt5", "ByT5Tokenizer"),
("camembert", "CamembertTokenizer" if is_tokenizers_available() else None),
("canary", "TokenizersBackend" if is_tokenizers_available() else None),
("canine", "CanineTokenizer"),
("chinese_clip", "BertTokenizer" if is_tokenizers_available() else None),
("clap", "RobertaTokenizer"),
Expand Down
28 changes: 28 additions & 0 deletions src/transformers/models/canary/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2026 The HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import TYPE_CHECKING

from ...utils import _LazyModule
from ...utils.import_utils import define_import_structure


if TYPE_CHECKING:
from .configuration_canary import *
from .modeling_canary import *
from .processing_canary import *
else:
import sys

_file = globals()["__file__"]
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
Loading
Loading