Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 14 additions & 5 deletions bindings/python/src/transcribe_cpp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ def _stream_update_from(u) -> StreamUpdate:


def _build_run_params(task, language, target_language, timestamps,
keep_special_tags, spec_k_drafts):
keep_special_tags, spec_k_drafts, context=None):
if not isinstance(spec_k_drafts, int) or spec_k_drafts < -1:
raise InvalidArgument(
f"spec_k_drafts must be -1 (family default), 0 (disabled), or a "
Expand All @@ -596,6 +596,7 @@ def _build_run_params(task, language, target_language, timestamps,
params.target_language = target_language.encode("utf-8") if target_language else None
params.keep_special_tags = keep_special_tags
params.spec_k_drafts = spec_k_drafts
params.context = context.encode("utf-8") if context else None
return params


Expand Down Expand Up @@ -984,6 +985,7 @@ def run(self, pcm: PCMLike, *, task: Task = "transcribe",
timestamps: Timestamps = "auto",
keep_special_tags: bool = False,
spec_k_drafts: int = -1,
context: str | None = None,
family: FamilyExtension | None = None) -> Result:
"""Transcribe 16 kHz mono float32 PCM and return a materialized Result.

Expand All @@ -992,14 +994,18 @@ def run(self, pcm: PCMLike, *, task: Task = "transcribe",
``spec_k_drafts`` tunes speculative decoding on models whose
capabilities advertise ``supports_spec_decode`` (-1 = family default,
0 = disabled, >0 = draft length; silently ignored elsewhere).
``context`` is free text (names, jargon, prior transcript) that
biases recognition on models advertising the ``initial_prompt``
feature (whisper, qwen3_asr, funasr_nano); the output remains a
transcript, and unsupported models warn and ignore it.

On ``Aborted`` (via :meth:`cancel`) and ``OutputTruncated`` the
partial transcript is preserved and attached to the exception as
``partial_result``."""
self._cancel.clear()
array, n_samples = _pcm_to_carray(pcm)
params = _build_run_params(task, language, target_language, timestamps,
keep_special_tags, spec_k_drafts)
keep_special_tags, spec_k_drafts, context)
ext = self._resolve_family(family, "run") if family is not None else None
if ext is not None:
params.family = ctypes.cast(
Expand All @@ -1020,6 +1026,7 @@ def run_batch(self, pcms: Sequence[PCMLike], *, task: Task = "transcribe",
timestamps: Timestamps = "auto",
keep_special_tags: bool = False,
spec_k_drafts: int = -1,
context: str | None = None,
family: FamilyExtension | None = None,
return_exceptions: bool = False) -> list[Result | TranscribeError]:
"""Transcribe several utterances in one dispatch — one Result each.
Expand Down Expand Up @@ -1054,7 +1061,7 @@ def run_batch(self, pcms: Sequence[PCMLike], *, task: Task = "transcribe",
counts[k] = n

params = _build_run_params(task, language, target_language, timestamps,
keep_special_tags, spec_k_drafts)
keep_special_tags, spec_k_drafts, context)
ext = self._resolve_family(family, "run") if family is not None else None
if ext is not None:
params.family = ctypes.cast(
Expand Down Expand Up @@ -1107,6 +1114,7 @@ def stream(self, *, task: Task = "transcribe", language: str | None = None,
target_language: str | None = None, timestamps: Timestamps = "none",
keep_special_tags: bool = False, commit_policy: CommitPolicy = "auto",
stable_prefix_agreement_n: int = 0,
context: str | None = None,
family: FamilyExtension | None = None) -> Stream:
"""Begin streaming on this session and return a Stream to feed audio to.

Expand All @@ -1119,7 +1127,7 @@ def stream(self, *, task: Task = "transcribe", language: str | None = None,
# spec_k_drafts is an offline-decode knob; streaming always uses the
# family default (-1).
run_params = _build_run_params(task, language, target_language, timestamps,
keep_special_tags, -1)
keep_special_tags, -1, context)
sp = _StreamParams()
_lib.transcribe_stream_params_init(_byref(sp))
sp.commit_policy = _enum(_COMMIT_POLICIES, commit_policy, "commit_policy")
Expand Down Expand Up @@ -1348,6 +1356,7 @@ def transcribe(
timestamps: Timestamps = "auto",
keep_special_tags: bool = False,
spec_k_drafts: int = -1,
context: str | None = None,
family: FamilyExtension | None = None,
) -> Result:
"""Transcribe *pcm* in one call and return a materialized Result.
Expand All @@ -1362,7 +1371,7 @@ def transcribe(
session_opts = dict(n_threads=n_threads, kv_type=kv_type, n_ctx=n_ctx)
run_opts = dict(task=task, language=language, target_language=target_language,
timestamps=timestamps, keep_special_tags=keep_special_tags,
spec_k_drafts=spec_k_drafts, family=family)
spec_k_drafts=spec_k_drafts, context=context, family=family)

if isinstance(model, Model):
with model.session(**session_opts) as session:
Expand Down
6 changes: 3 additions & 3 deletions bindings/python/src/transcribe_cpp/_generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# Stable digest of the ABI surface below (structs, enums, macros, layout,
# prototypes). A native provider package echoes this back so the API
# package can reject an ABI-mismatched provider before dlopen.
PUBLIC_HEADER_HASH = "86b16dd97ad1cb58"
PUBLIC_HEADER_HASH = "3ba8dde028c487b6"

# === enum constants ===
TRANSCRIBE_OK = 0
Expand Down Expand Up @@ -152,7 +152,7 @@ class transcribe_whisper_chunk_trace(_c.Structure):
transcribe_backend_device._fields_ = [("struct_size", _c.c_uint64), ("name", _c.c_char_p), ("description", _c.c_char_p), ("kind", _c.c_char_p), ("device_id", _c.c_char_p), ("memory_total", _c.c_uint64), ("memory_free", _c.c_uint64), ("device_type", _c.c_int)]
transcribe_model_load_params._fields_ = [("struct_size", _c.c_uint64), ("backend", _c.c_int), ("gpu_device", _c.c_int)]
transcribe_session_params._fields_ = [("struct_size", _c.c_uint64), ("n_threads", _c.c_int), ("kv_type", _c.c_int), ("n_ctx", _c.c_int32)]
transcribe_run_params._fields_ = [("struct_size", _c.c_uint64), ("task", _c.c_int), ("timestamps", _c.c_int), ("pnc", _c.c_int), ("itn", _c.c_int), ("language", _c.c_char_p), ("target_language", _c.c_char_p), ("keep_special_tags", _c.c_bool), ("family", _c.POINTER(transcribe_ext)), ("spec_k_drafts", _c.c_int32)]
transcribe_run_params._fields_ = [("struct_size", _c.c_uint64), ("task", _c.c_int), ("timestamps", _c.c_int), ("pnc", _c.c_int), ("itn", _c.c_int), ("language", _c.c_char_p), ("target_language", _c.c_char_p), ("keep_special_tags", _c.c_bool), ("family", _c.POINTER(transcribe_ext)), ("spec_k_drafts", _c.c_int32), ("context", _c.c_char_p)]
transcribe_capabilities._fields_ = [("struct_size", _c.c_uint64), ("native_sample_rate", _c.c_int32), ("n_languages", _c.c_int), ("languages", _c.POINTER(_c.c_char_p)), ("max_timestamp_kind", _c.c_int), ("supports_language_detect", _c.c_bool), ("supports_translate", _c.c_bool), ("supports_streaming", _c.c_bool), ("supports_spec_decode", _c.c_bool), ("max_audio_ms", _c.c_int64), ("n_translate_target_languages", _c.c_int), ("translate_target_languages", _c.POINTER(_c.c_char_p))]
transcribe_session_limits._fields_ = [("struct_size", _c.c_uint64), ("effective_n_ctx", _c.c_int32), ("effective_max_audio_ms", _c.c_int64), ("max_kv_bytes", _c.c_int64)]
transcribe_stream_params._fields_ = [("struct_size", _c.c_uint64), ("family", _c.POINTER(transcribe_ext)), ("commit_policy", _c.c_int), ("stable_prefix_agreement_n", _c.c_uint32)]
Expand Down Expand Up @@ -194,7 +194,7 @@ class transcribe_whisper_chunk_trace(_c.Structure):
'transcribe_backend_device': {'size': 64, 'align': 8, 'offsets': {'struct_size': 0, 'name': 8, 'description': 16, 'kind': 24, 'device_id': 32, 'memory_total': 40, 'memory_free': 48, 'device_type': 56}},
'transcribe_model_load_params': {'size': 16, 'align': 8, 'offsets': {'struct_size': 0, 'backend': 8, 'gpu_device': 12}},
'transcribe_session_params': {'size': 24, 'align': 8, 'offsets': {'struct_size': 0, 'n_threads': 8, 'kv_type': 12, 'n_ctx': 16}},
'transcribe_run_params': {'size': 64, 'align': 8, 'offsets': {'struct_size': 0, 'task': 8, 'timestamps': 12, 'pnc': 16, 'itn': 20, 'language': 24, 'target_language': 32, 'keep_special_tags': 40, 'family': 48, 'spec_k_drafts': 56}},
'transcribe_run_params': {'size': 72, 'align': 8, 'offsets': {'struct_size': 0, 'task': 8, 'timestamps': 12, 'pnc': 16, 'itn': 20, 'language': 24, 'target_language': 32, 'keep_special_tags': 40, 'family': 48, 'spec_k_drafts': 56, 'context': 64}},
'transcribe_capabilities': {'size': 56, 'align': 8, 'offsets': {'struct_size': 0, 'native_sample_rate': 8, 'n_languages': 12, 'languages': 16, 'max_timestamp_kind': 24, 'supports_language_detect': 28, 'supports_translate': 29, 'supports_streaming': 30, 'supports_spec_decode': 31, 'max_audio_ms': 32, 'n_translate_target_languages': 40, 'translate_target_languages': 48}},
'transcribe_session_limits': {'size': 32, 'align': 8, 'offsets': {'struct_size': 0, 'effective_n_ctx': 8, 'effective_max_audio_ms': 16, 'max_kv_bytes': 24}},
'transcribe_stream_params': {'size': 24, 'align': 8, 'offsets': {'struct_size': 0, 'family': 8, 'commit_policy': 16, 'stable_prefix_agreement_n': 20}},
Expand Down
6 changes: 3 additions & 3 deletions bindings/python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions bindings/rust/sys/src/transcribe_sys.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// @generated by `cargo xtask bindgen` from include/transcribe/extensions.h
// DO NOT EDIT BY HAND. Regenerate: `cargo xtask bindgen`.
// Pinned to include/transcribe.abihash = 86b16dd97ad1cb58
// Pinned to include/transcribe.abihash = 3ba8dde028c487b6

/// The public-ABI digest these bindings were generated against
/// (sha256/16 over the normalized FFI surface). The load-time version
/// gate and the CI drift check both anchor on this value.
pub const PUBLIC_HEADER_HASH: &str = "86b16dd97ad1cb58";
pub const PUBLIC_HEADER_HASH: &str = "3ba8dde028c487b6";

/* automatically generated by rust-bindgen 0.72.1 */

Expand Down Expand Up @@ -329,10 +329,11 @@ pub struct transcribe_run_params {
pub keep_special_tags: bool,
pub family: *const transcribe_ext,
pub spec_k_drafts: i32,
pub context: *const ::std::os::raw::c_char,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of transcribe_run_params"][::std::mem::size_of::<transcribe_run_params>() - 64usize];
["Size of transcribe_run_params"][::std::mem::size_of::<transcribe_run_params>() - 72usize];
["Alignment of transcribe_run_params"]
[::std::mem::align_of::<transcribe_run_params>() - 8usize];
["Offset of field: transcribe_run_params::struct_size"]
Expand All @@ -355,6 +356,8 @@ const _: () = {
[::std::mem::offset_of!(transcribe_run_params, family) - 48usize];
["Offset of field: transcribe_run_params::spec_k_drafts"]
[::std::mem::offset_of!(transcribe_run_params, spec_k_drafts) - 56usize];
["Offset of field: transcribe_run_params::context"]
[::std::mem::offset_of!(transcribe_run_params, context) - 64usize];
};
unsafe extern "C" {
pub fn transcribe_run_params_init(params: *mut transcribe_run_params);
Expand Down
17 changes: 13 additions & 4 deletions bindings/rust/transcribe-cpp/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ pub struct RunOptions {
pub keep_special_tags: bool,
/// Speculative-decode draft length. `-1` = family default, `0` = disabled.
pub spec_k_drafts: i32,
/// Free-text recognition-biasing context (names, jargon, prior
/// transcript). Honored by models advertising the initial-prompt
/// feature (whisper, qwen3_asr, funasr_nano); the output remains a
/// transcript, and unsupported models warn and ignore it.
pub context: Option<String>,
/// Optional family-specific run extension (e.g. whisper decode knobs).
pub family: Option<RunExtension>,
}
Expand All @@ -53,6 +58,7 @@ impl Default for RunOptions {
target_language: None,
keep_special_tags: false,
spec_k_drafts: -1,
context: None,
family: None,
}
}
Expand Down Expand Up @@ -144,7 +150,7 @@ impl Session {
/// On an aborted or truncated decode the partial transcript is preserved
/// on the returned [`Error::Aborted`] / [`Error::OutputTruncated`].
pub fn run(&mut self, pcm: &[f32], options: &RunOptions) -> Result<Transcript> {
let (params, _lang, _target, _family) = build_run_params(options)?;
let (params, _lang, _target, _context, _family) = build_run_params(options)?;
let n = clamp_len(pcm.len())?;

// The compute path is serialized per model; hold the lock for the native
Expand Down Expand Up @@ -187,7 +193,7 @@ impl Session {
pcms: &[&[f32]],
options: &RunOptions,
) -> Result<Vec<Result<Transcript>>> {
let (params, _lang, _target, _family) = build_run_params(options)?;
let (params, _lang, _target, _context, _family) = build_run_params(options)?;
let ptrs: Vec<*const f32> = pcms.iter().map(|p| p.as_ptr()).collect();
let lens: Vec<i32> = pcms
.iter()
Expand Down Expand Up @@ -263,7 +269,7 @@ impl Session {
/// Dropping the returned `Stream` abandons it and returns the session to
/// idle.
pub fn stream(&mut self, run: &RunOptions, stream: &StreamOptions) -> Result<Stream<'_>> {
let (run_params, _lang, _target, _family) = build_run_params(run)?;
let (run_params, _lang, _target, _context, _family) = build_run_params(run)?;
let (stream_params, _stream_family) = build_stream_params(stream);
{
// Claim the model's compute lease for the whole stream lifetime: a
Expand Down Expand Up @@ -396,6 +402,7 @@ type RunParamsBundle = (
sys::transcribe_run_params,
Option<CString>,
Option<CString>,
Option<CString>,
Option<RunExtRaw>,
);

Expand All @@ -415,8 +422,10 @@ fn build_run_params(o: &RunOptions) -> Result<RunParamsBundle> {

let lang = o.language.as_deref().map(CString::new).transpose()?;
let target = o.target_language.as_deref().map(CString::new).transpose()?;
let context = o.context.as_deref().map(CString::new).transpose()?;
params.language = lang.as_ref().map_or(std::ptr::null(), |c| c.as_ptr());
params.target_language = target.as_ref().map_or(std::ptr::null(), |c| c.as_ptr());
params.context = context.as_ref().map_or(std::ptr::null(), |c| c.as_ptr());

let family = o
.family
Expand All @@ -425,7 +434,7 @@ fn build_run_params(o: &RunOptions) -> Result<RunParamsBundle> {
.transpose()?;
params.family = family.as_ref().map_or(std::ptr::null(), |f| f.ext_ptr());

Ok((params, lang, target, family))
Ok((params, lang, target, context, family))
}

/// PCM/utterance lengths cross the ABI as `int`; reject anything that overflows.
Expand Down
2 changes: 1 addition & 1 deletion bindings/swift/Sources/TranscribeCpp/ABIHash.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import CTranscribe
extension Transcribe {
/// sha256/16 of the normalized public FFI surface, pinned to the value in
/// include/transcribe.abihash at the time this binding was last reviewed.
public static let pinnedHeaderHash = "86b16dd97ad1cb58"
public static let pinnedHeaderHash = "3ba8dde028c487b6"

/// The public-ABI digest this binding was reviewed against (16 hex chars).
public static func headerHash() -> String { pinnedHeaderHash }
Expand Down
16 changes: 13 additions & 3 deletions bindings/swift/Sources/TranscribeCpp/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ public struct RunOptions: Sendable {
public var keepSpecialTags: Bool
/// Speculative-decode draft length: -1 = family default, 0 = disabled.
public var specKDrafts: Int32
/// Free-text recognition-biasing context (names, jargon, prior
/// transcript). Honored by models advertising the initial-prompt
/// feature (whisper, qwen3_asr, funasr_nano); the output remains a
/// transcript, and unsupported models warn and ignore it.
public var context: String?
/// Family-specific run extension (whisper run options); M3.
public var family: RunExtension?

Expand All @@ -136,6 +141,7 @@ public struct RunOptions: Sendable {
targetLanguage: String? = nil,
keepSpecialTags: Bool = false,
specKDrafts: Int32 = -1,
context: String? = nil,
family: RunExtension? = nil
) {
self.task = task
Expand All @@ -146,6 +152,7 @@ public struct RunOptions: Sendable {
self.targetLanguage = targetLanguage
self.keepSpecialTags = keepSpecialTags
self.specKDrafts = specKDrafts
self.context = context
self.family = family
}

Expand All @@ -165,9 +172,12 @@ public struct RunOptions: Sendable {
params.language = lang
return try withOptionalCString(targetLanguage) { tgt in
params.target_language = tgt
return try withRunExtension(family) { ext in
params.family = ext
return try withUnsafePointer(to: &params) { try body($0) }
return try withOptionalCString(context) { ctx in
params.context = ctx
return try withRunExtension(family) { ext in
params.family = ext
return try withUnsafePointer(to: &params) { try body($0) }
}
}
}
}
Expand Down
Loading
Loading