Add recognition context support for Qwen3-ASR - #144
Conversation
|
To be honest, this isn't going to be pulled in unless it supports all of the other families that also support similar kinds of things. We need to have a very good API for this that's exposed to users that's not really model specific. So I need someone to think about this more concretely before I pull it in. This is something I'm also thinking about. I just don't have time to write the code at the moment |
|
@cjpais I initially limited the implementation to Qwen3-ASR because the other “similar kinds of things” have different model contracts. Some accept recognition background, some accept hotword lists, and others consume transcript text associated with previous or current audio. Treating all of them as one string would hide those differences. I reviewed the relevant model and publisher interfaces:
General task instructions are intentionally excluded. Voxtral audio understanding prompts and MOSS custom prompts can change the task or output format. Canary-Qwen does not document a free form recognition context in ASR mode. NeMo also provides decoder phrase boosting for Canary and Parakeet. However, transcribe.cpp uses its own decoders and does not implement NeMo’s boosting tree or score fusion. Supporting those families requires a new decoder feature, so I propose leaving them out of the initial implementation. They can use the same public hotword field later. The remaining supported families expose only existing controls such as language, translation, PNC, ITN, timestamps, and diarization, or have no comparable text input. A single string is insufficient because these inputs carry different information. In particular, hotword boundaries cannot be recovered from a value such as I propose the following flat fields:
Cstruct transcribe_context {
uint64_t struct_size;
const char * prompt;
const char * const * hotwords;
size_t n_hotwords;
const char * previous_transcript;
const char * transcript_prefix;
};
TRANSCRIBE_API void transcribe_context_init(
struct transcribe_context * context
);
struct transcribe_run_params {
/* existing fields */
const struct transcribe_context * context;
};Capabilities would be defined for each field: TRANSCRIBE_FEATURE_CONTEXT_PROMPT
TRANSCRIBE_FEATURE_CONTEXT_HOTWORDS
TRANSCRIBE_FEATURE_CONTEXT_PREVIOUS_TRANSCRIPT
TRANSCRIBE_FEATURE_CONTEXT_TRANSCRIPT_PREFIXTypeScriptexport interface TranscriptionContext {
prompt?: string;
hotwords?: readonly string[];
previousTranscript?: string;
transcriptPrefix?: string;
}
export interface TranscribeOptions {
context?: TranscriptionContext;
}Whisper’s existing If this direction seems useful, I am happy to continue with it. If you already have another API direction in mind, or would prefer that I wait for your design, I am also happy to pause here. I have not pushed any redesign yet. |
|
Wouldn't it be simpler to expose two top-level options and leave everything else as family extensions?
Does the end user of transcribe.cpp really care about the distinction between previousTranscript vs transcriptPrefix vs recognitionPrompt? In practice those all reduce to "here's some text to condition on". The details can be explained in the documentation. |
|
@moribm Thanks, that is a valid option. My concern is that a future model could support both a recognition prompt and a transcript prefix. If that distinction exists only in family extensions, the meaning of the common |
Adds a shared recognition-context option across the public API, CLI, and language bindings, with Qwen3-ASR as the only model family that currently advertises and consumes it.
Why
Qwen3-ASR can use background text such as names, jargon, and domain terminology to improve recognition, but transcribe.cpp did not expose a way to provide that context. Reusing Whisper's
initial_promptwould conflate two model-specific semantics and would not provide a consistent option across single, batch, and streaming APIs.What
Core API and Qwen3-ASR
contexttotranscribe_run_paramsand add the independentTRANSCRIBE_FEATURE_CONTEXTcapability while preserving size-aware ABI compatibility.CLI and bindings
--context TEXTto the CLI.Tests and documentation
Notes
contextis intentionally separate from Whisper'sinitialPrompt/initial_prompt. Whisper's option is a Whisper-specific decoder prompt: it conditions decoding as transcript text preceding the current audio and can carry vocabulary, capitalization, punctuation, or style into the output. Qwen3-ASR recognition context is background information placed in the chat template's system turn to bias recognition toward names, jargon, and domain terminology. It is not prior transcript text, and it does not promise instruction following, translation, output formatting, punctuation, or style control.contextis implemented in the commontranscribe_run_paramsAPI rather than as a Qwen3-ASR-specific extension. This follows the earlier review discussion on PR #83, which noted that multiple model families have analogous recognition-context capabilities and that the option therefore belongs in the main API. Qwen3-ASR is currently the only family that advertises and consumes the capability; unsupported families warn and ignore it.