diff --git a/.gitignore b/.gitignore index f7cf944a..3c60cc0c 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,10 @@ __pycache__/ # WER evaluation data + generated working reports. /samples/wer/ +# Diarization eval corpora (AMI audio + fetched RTTMs); regenerable via +# scripts/diar/ingest_ami.py + fetch_ami_forced_alignment.py. The committed +# oracle case lives at samples/sortformer-2spk-mix.wav (outside samples/diar/). +/samples/diar/ /reports/* # Reviewable porting evidence (intake, porting log) is intentionally committed. diff --git a/README.md b/README.md index e44ba798..7f13aac4 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ C/C++ speech-to-text inference library. Runs diverse STT model families via [GGU | Voxtral Realtime | `voxtral-mini-4b-realtime-2602` (streaming audio-LLM) | [docs/models/voxtral-realtime.md](docs/models/voxtral-realtime.md) | | MedASR | `medasr` (Conformer + CTC, English medical-dictation, gated) | [docs/models/medasr.md](docs/models/medasr.md) | | MOSS Transcribe-Diarize | `moss-transcribe-diarize` (audio-LLM; English + Chinese ASR with inline speaker diarization) | [docs/models/moss-transcribe-diarize.md](docs/models/moss-transcribe-diarize.md) | +| Sortformer | `diar_streaming_sortformer_4spk-v2.1` (streaming speaker diarizer, up to 4 speakers; no transcription) | [docs/models/diar_streaming_sortformer_4spk-v2.1.md](docs/models/diar_streaming_sortformer_4spk-v2.1.md) | Per-variant model cards live under [`docs/models/`](docs/models/). diff --git a/bindings/python/src/transcribe_cpp/__init__.py b/bindings/python/src/transcribe_cpp/__init__.py index 92d9126e..946cf10f 100644 --- a/bindings/python/src/transcribe_cpp/__init__.py +++ b/bindings/python/src/transcribe_cpp/__init__.py @@ -54,6 +54,7 @@ Task = Literal["transcribe", "translate"] Timestamps = Literal["none", "auto", "segment", "word", "token"] Diarize = Literal["default", "off", "on"] +SortformerPreset = Literal["default", "very_high_latency", "high_latency", "low_latency"] CommitPolicy = Literal["auto", "on_finalize", "stable_prefix"] Feature = Literal[ "initial_prompt", "temperature_fallback", "long_form", @@ -81,8 +82,10 @@ "MoonshineStreamingOptions", "ParakeetStreamOptions", "ParakeetBufferedStreamOptions", + "SortformerStreamOptions", "VoxtralRealtimeStreamOptions", "Backend", + "SortformerPreset", "KVType", "Task", "Timestamps", @@ -799,6 +802,40 @@ def _apply(self, ext) -> None: ext.min_decode_interval_ms = self.min_decode_interval_ms +class SortformerStreamOptions(FamilyExtension): + """Sortformer streaming operating-point options (run slot). + + Sortformer is a diarizer: a run produces speaker segments, no text. + ``preset`` selects the latency / accuracy trade-off from the model's + published menu; ``"default"`` keeps the GGUF-shipped checkpoint + configuration. ``"very_high_latency"`` (~30 s lookahead) is the + offline-file operating point; ``"low_latency"`` (~1 s) is the + real-time point and costs substantially more compute per audio + second.""" + + _slot = "run" + _kind = _generated.TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM + _struct = _generated.transcribe_sortformer_stream_ext + _init = "transcribe_sortformer_stream_ext_init" + + _presets = { + "default": _generated.TRANSCRIBE_SORTFORMER_PRESET_DEFAULT, + "very_high_latency": _generated.TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY, + "high_latency": _generated.TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY, + "low_latency": _generated.TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY, + } + + def __init__(self, *, preset: SortformerPreset | None = None): + if preset is not None and preset not in self._presets: + raise ValueError(f"unknown sortformer preset {preset!r}; " + f"expected one of {sorted(self._presets)}") + self.preset = preset + + def _apply(self, ext) -> None: + if self.preset is not None: + ext.preset = self._presets[self.preset] + + # --- high-level handles --------------------------------------------------- diff --git a/bindings/python/src/transcribe_cpp/_generated.py b/bindings/python/src/transcribe_cpp/_generated.py index 90b75343..9c133653 100644 --- a/bindings/python/src/transcribe_cpp/_generated.py +++ b/bindings/python/src/transcribe_cpp/_generated.py @@ -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 = "d67a9bd78b964445" +PUBLIC_HEADER_HASH = "fb2e64791dcbb70a" # === enum constants === TRANSCRIBE_OK = 0 @@ -101,6 +101,10 @@ TRANSCRIBE_STREAM_COMMIT_AUTO = 0 TRANSCRIBE_STREAM_COMMIT_ON_FINALIZE = 1 TRANSCRIBE_STREAM_COMMIT_STABLE_PREFIX = 2 +TRANSCRIBE_SORTFORMER_PRESET_DEFAULT = 0 +TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY = 1 +TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY = 2 +TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY = 3 TRANSCRIBE_WHISPER_PROMPT_FIRST_SEGMENT = 0 TRANSCRIBE_WHISPER_PROMPT_ALL_SEGMENTS = 1 @@ -108,6 +112,7 @@ TRANSCRIBE_EXT_KIND_MOONSHINE_STREAMING_STREAM = 1414746957 TRANSCRIBE_EXT_KIND_PARAKEET_BUFFERED_STREAM = 1396853584 TRANSCRIBE_EXT_KIND_PARAKEET_STREAM = 1414744912 +TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM = 1414743635 TRANSCRIBE_EXT_KIND_VOXTRAL_REALTIME_STREAM = 1414746710 TRANSCRIBE_EXT_KIND_WHISPER_RUN = 1314015319 @@ -148,6 +153,8 @@ class transcribe_parakeet_stream_ext(_c.Structure): pass class transcribe_parakeet_buffered_stream_ext(_c.Structure): pass +class transcribe_sortformer_stream_ext(_c.Structure): + pass class transcribe_voxtral_realtime_stream_ext(_c.Structure): pass class transcribe_whisper_run_ext(_c.Structure): @@ -173,6 +180,7 @@ class transcribe_whisper_chunk_trace(_c.Structure): transcribe_moonshine_streaming_stream_ext._fields_ = [("ext", transcribe_ext), ("min_decode_interval_ms", _c.c_int32)] transcribe_parakeet_stream_ext._fields_ = [("ext", transcribe_ext), ("att_context_right", _c.c_int32)] transcribe_parakeet_buffered_stream_ext._fields_ = [("ext", transcribe_ext), ("left_ms", _c.c_int32), ("chunk_ms", _c.c_int32), ("right_ms", _c.c_int32)] +transcribe_sortformer_stream_ext._fields_ = [("ext", transcribe_ext), ("preset", _c.c_int)] transcribe_voxtral_realtime_stream_ext._fields_ = [("ext", transcribe_ext), ("num_delay_tokens", _c.c_int32), ("min_decode_interval_ms", _c.c_int32)] transcribe_whisper_run_ext._fields_ = [("ext", transcribe_ext), ("initial_prompt", _c.c_char_p), ("prompt_tokens", _c.POINTER(_c.c_int32)), ("n_prompt_tokens", _c.c_size_t), ("prompt_condition", _c.c_int), ("condition_on_prev_tokens", _c.c_bool), ("max_prev_context_tokens", _c.c_int32), ("temperature", _c.c_float), ("temperature_inc", _c.c_float), ("compression_ratio_thold", _c.c_float), ("logprob_thold", _c.c_float), ("no_speech_thold", _c.c_float), ("seed", _c.c_uint32), ("max_initial_timestamp", _c.c_float)] transcribe_whisper_chunk_trace._fields_ = [("struct_size", _c.c_uint64), ("t0_ms", _c.c_int64), ("t1_ms", _c.c_int64), ("temperature_used", _c.c_float), ("compression_ratio", _c.c_float), ("avg_logprob", _c.c_float), ("no_speech_prob", _c.c_float), ("no_speech_triggered", _c.c_bool), ("n_fallbacks", _c.c_int32)] @@ -217,6 +225,7 @@ class transcribe_whisper_chunk_trace(_c.Structure): 'transcribe_moonshine_streaming_stream_ext': {'size': 24, 'align': 8, 'offsets': {'ext': 0, 'min_decode_interval_ms': 16}}, 'transcribe_parakeet_stream_ext': {'size': 24, 'align': 8, 'offsets': {'ext': 0, 'att_context_right': 16}}, 'transcribe_parakeet_buffered_stream_ext': {'size': 32, 'align': 8, 'offsets': {'ext': 0, 'left_ms': 16, 'chunk_ms': 20, 'right_ms': 24}}, + 'transcribe_sortformer_stream_ext': {'size': 24, 'align': 8, 'offsets': {'ext': 0, 'preset': 16}}, 'transcribe_voxtral_realtime_stream_ext': {'size': 24, 'align': 8, 'offsets': {'ext': 0, 'num_delay_tokens': 16, 'min_decode_interval_ms': 20}}, 'transcribe_whisper_run_ext': {'size': 80, 'align': 8, 'offsets': {'ext': 0, 'initial_prompt': 16, 'prompt_tokens': 24, 'n_prompt_tokens': 32, 'prompt_condition': 40, 'condition_on_prev_tokens': 44, 'max_prev_context_tokens': 48, 'temperature': 52, 'temperature_inc': 56, 'compression_ratio_thold': 60, 'logprob_thold': 64, 'no_speech_thold': 68, 'seed': 72, 'max_initial_timestamp': 76}}, 'transcribe_whisper_chunk_trace': {'size': 48, 'align': 8, 'offsets': {'struct_size': 0, 't0_ms': 8, 't1_ms': 16, 'temperature_used': 24, 'compression_ratio': 28, 'avg_logprob': 32, 'no_speech_prob': 36, 'no_speech_triggered': 40, 'n_fallbacks': 44}}, @@ -365,6 +374,8 @@ def configure(lib): lib.transcribe_session_params_init.argtypes = [_c.POINTER(transcribe_session_params)] lib.transcribe_set_abort_callback.restype = None lib.transcribe_set_abort_callback.argtypes = [_c.c_void_p, _c.CFUNCTYPE(_c.c_bool, _c.c_void_p), _c.c_void_p] + lib.transcribe_sortformer_stream_ext_init.restype = None + lib.transcribe_sortformer_stream_ext_init.argtypes = [_c.POINTER(transcribe_sortformer_stream_ext)] lib.transcribe_speaker_segment_init.restype = None lib.transcribe_speaker_segment_init.argtypes = [_c.POINTER(transcribe_speaker_segment)] lib.transcribe_status_string.restype = _c.c_char_p diff --git a/bindings/python/tests/test_family_ext.py b/bindings/python/tests/test_family_ext.py index 9bccecae..3b0a433e 100644 --- a/bindings/python/tests/test_family_ext.py +++ b/bindings/python/tests/test_family_ext.py @@ -22,6 +22,7 @@ t.MoonshineStreamingOptions, t.ParakeetStreamOptions, t.ParakeetBufferedStreamOptions, + t.SortformerStreamOptions, t.VoxtralRealtimeStreamOptions, ] @@ -73,6 +74,19 @@ def test_parakeet_buffered_partial_overrides(): assert built.right_ms == fresh.right_ms +def test_sortformer_preset_maps_to_enum_value(): + built = t.SortformerStreamOptions(preset="very_high_latency")._build() + assert built.preset == _generated.TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY + # None keeps the init default (DEFAULT = GGUF-shipped cfg). + default = t.SortformerStreamOptions()._build() + assert default.preset == _generated.TRANSCRIBE_SORTFORMER_PRESET_DEFAULT + + +def test_sortformer_unknown_preset_rejected(): + with pytest.raises(ValueError, match="preset"): + t.SortformerStreamOptions(preset="ultra_low_latency") # type: ignore[arg-type] + + # --- model-gated: resolve_family validation + a real extension run ---------- diff --git a/bindings/rust/sys/src/transcribe_sys.rs b/bindings/rust/sys/src/transcribe_sys.rs index a391f55a..bb3b5a39 100644 --- a/bindings/rust/sys/src/transcribe_sys.rs +++ b/bindings/rust/sys/src/transcribe_sys.rs @@ -1,17 +1,18 @@ // @generated by `cargo xtask bindgen` from include/transcribe/extensions.h // DO NOT EDIT BY HAND. Regenerate: `cargo xtask bindgen`. -// Pinned to include/transcribe.abihash = d67a9bd78b964445 +// Pinned to include/transcribe.abihash = fb2e64791dcbb70a /// 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 = "d67a9bd78b964445"; +pub const PUBLIC_HEADER_HASH: &str = "fb2e64791dcbb70a"; /* automatically generated by rust-bindgen 0.72.1 */ pub const TRANSCRIBE_EXT_KIND_MOONSHINE_STREAMING_STREAM: u32 = 1414746957; pub const TRANSCRIBE_EXT_KIND_PARAKEET_STREAM: u32 = 1414744912; pub const TRANSCRIBE_EXT_KIND_PARAKEET_BUFFERED_STREAM: u32 = 1396853584; +pub const TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM: u32 = 1414743635; pub const TRANSCRIBE_EXT_KIND_VOXTRAL_REALTIME_STREAM: u32 = 1414746710; pub const TRANSCRIBE_EXT_KIND_WHISPER_RUN: u32 = 1314015319; impl transcribe_status { @@ -1156,6 +1157,39 @@ unsafe extern "C" { ext: *mut transcribe_parakeet_buffered_stream_ext, ); } +impl transcribe_sortformer_preset { + pub const TRANSCRIBE_SORTFORMER_PRESET_DEFAULT: transcribe_sortformer_preset = + transcribe_sortformer_preset(0); + pub const TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY: transcribe_sortformer_preset = + transcribe_sortformer_preset(1); + pub const TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY: transcribe_sortformer_preset = + transcribe_sortformer_preset(2); + pub const TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY: transcribe_sortformer_preset = + transcribe_sortformer_preset(3); +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct transcribe_sortformer_preset(pub ::std::os::raw::c_uint); +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct transcribe_sortformer_stream_ext { + pub ext: transcribe_ext, + pub preset: transcribe_sortformer_preset, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of transcribe_sortformer_stream_ext"] + [::std::mem::size_of::() - 24usize]; + ["Alignment of transcribe_sortformer_stream_ext"] + [::std::mem::align_of::() - 8usize]; + ["Offset of field: transcribe_sortformer_stream_ext::ext"] + [::std::mem::offset_of!(transcribe_sortformer_stream_ext, ext) - 0usize]; + ["Offset of field: transcribe_sortformer_stream_ext::preset"] + [::std::mem::offset_of!(transcribe_sortformer_stream_ext, preset) - 16usize]; +}; +unsafe extern "C" { + pub fn transcribe_sortformer_stream_ext_init(ext: *mut transcribe_sortformer_stream_ext); +} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct transcribe_voxtral_realtime_stream_ext { diff --git a/bindings/rust/transcribe-cpp/src/family.rs b/bindings/rust/transcribe-cpp/src/family.rs index 13dce620..78b7b877 100644 --- a/bindings/rust/transcribe-cpp/src/family.rs +++ b/bindings/rust/transcribe-cpp/src/family.rs @@ -60,11 +60,55 @@ pub struct VoxtralRealtimeStreamOptions { pub min_decode_interval_ms: Option, } +/// Sortformer streaming operating point (latency / accuracy trade-off). +/// The menu is discrete (jointly-tuned bundles), not a latency dial; +/// `Default` keeps the GGUF-shipped checkpoint configuration. +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub enum SortformerPreset { + #[default] + Default, + /// ~30.4 s algorithmic lookahead; the offline-file operating point. + VeryHighLatency, + /// ~10.0 s lookahead. + HighLatency, + /// ~1.04 s lookahead; the real-time point (compute-heavy per audio + /// second — many small windows). + LowLatency, +} + +impl SortformerPreset { + fn to_sys(self) -> sys::transcribe_sortformer_preset { + match self { + SortformerPreset::Default => { + sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_DEFAULT + } + SortformerPreset::VeryHighLatency => { + sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY + } + SortformerPreset::HighLatency => { + sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY + } + SortformerPreset::LowLatency => { + sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY + } + } + } +} + +/// Sortformer diarizer run-extension knobs (run slot). Sortformer produces +/// speaker segments, no text; read results via the speaker-segment +/// accessors. `None` keeps the family default (the GGUF-shipped cfg). +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct SortformerStreamOptions { + pub preset: Option, +} + /// A family extension for the run slot (offline `run`/`run_batch`). #[derive(Debug, Clone, PartialEq)] #[non_exhaustive] pub enum RunExtension { Whisper(WhisperRunOptions), + Sortformer(SortformerStreamOptions), } /// A family extension for the stream slot. @@ -86,6 +130,7 @@ pub(crate) enum RunExtRaw { ext: Box, _prompt: Option, }, + Sortformer(Box), } impl RunExtRaw { @@ -95,6 +140,9 @@ impl RunExtRaw { RunExtRaw::Whisper { ext, .. } => { (&**ext) as *const sys::transcribe_whisper_run_ext as *const sys::transcribe_ext } + RunExtRaw::Sortformer(e) => { + (&**e) as *const sys::transcribe_sortformer_stream_ext as *const sys::transcribe_ext + } } } } @@ -128,6 +176,12 @@ impl RunExtension { _prompt: prompt, }) } + RunExtension::Sortformer(o) => { + let mut ext: sys::transcribe_sortformer_stream_ext = unsafe { std::mem::zeroed() }; + unsafe { sys::transcribe_sortformer_stream_ext_init(&mut ext) }; + set(&mut ext.preset, o.preset.map(SortformerPreset::to_sys)); + Ok(RunExtRaw::Sortformer(Box::new(ext))) + } } } } diff --git a/bindings/rust/transcribe-cpp/src/lib.rs b/bindings/rust/transcribe-cpp/src/lib.rs index 9ab98c07..d2dc48c7 100644 --- a/bindings/rust/transcribe-cpp/src/lib.rs +++ b/bindings/rust/transcribe-cpp/src/lib.rs @@ -65,7 +65,8 @@ pub use cancel::CancelToken; pub use error::{Error, Result}; pub use family::{ MoonshineStreamingOptions, ParakeetBufferedStreamOptions, ParakeetStreamOptions, RunExtension, - StreamExtension, VoxtralRealtimeStreamOptions, WhisperRunOptions, + SortformerPreset, SortformerStreamOptions, StreamExtension, VoxtralRealtimeStreamOptions, + WhisperRunOptions, }; pub use logging::{disable_logging, init_logging}; pub use model::{Capabilities, Model, ModelOptions, SessionLimits, SessionOptions}; diff --git a/bindings/swift/Sources/TranscribeCpp/ABIHash.swift b/bindings/swift/Sources/TranscribeCpp/ABIHash.swift index ca44e1ad..500fbf03 100644 --- a/bindings/swift/Sources/TranscribeCpp/ABIHash.swift +++ b/bindings/swift/Sources/TranscribeCpp/ABIHash.swift @@ -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 = "d67a9bd78b964445" + public static let pinnedHeaderHash = "fb2e64791dcbb70a" /// The public-ABI digest this binding was reviewed against (16 hex chars). public static func headerHash() -> String { pinnedHeaderHash } diff --git a/bindings/swift/Sources/TranscribeCpp/Family.swift b/bindings/swift/Sources/TranscribeCpp/Family.swift index f0d620da..59233a88 100644 --- a/bindings/swift/Sources/TranscribeCpp/Family.swift +++ b/bindings/swift/Sources/TranscribeCpp/Family.swift @@ -7,7 +7,7 @@ import CTranscribe // `transcribe_ext` pointer is handed to the run/begin call; the library copies // what it needs before returning. -// MARK: - Run-slot extensions (whisper) +// MARK: - Run-slot extensions (whisper, sortformer) public struct WhisperRunOptions: Sendable { public var initialPrompt: String? @@ -46,12 +46,42 @@ public struct WhisperRunOptions: Sendable { } } +/// Sortformer streaming operating point (latency / accuracy trade-off). +/// The menu is discrete (jointly-tuned bundles), not a latency dial; +/// `.default` keeps the GGUF-shipped checkpoint configuration. +/// `.veryHighLatency` (~30 s lookahead) is the offline-file operating +/// point; `.lowLatency` (~1 s) is the real-time point. +public enum SortformerPreset: Sendable { + case `default` + case veryHighLatency + case highLatency + case lowLatency + + var cValue: transcribe_sortformer_preset { + switch self { + case .default: return TRANSCRIBE_SORTFORMER_PRESET_DEFAULT + case .veryHighLatency: return TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY + case .highLatency: return TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY + case .lowLatency: return TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY + } + } +} + +/// Sortformer diarizer options (run slot). Sortformer produces speaker +/// segments, no text; read results via the speaker-segment accessors. +public struct SortformerStreamOptions: Sendable { + public var preset: SortformerPreset? + public init(preset: SortformerPreset? = nil) { self.preset = preset } +} + public enum RunExtension: Sendable { case whisper(WhisperRunOptions) + case sortformer(SortformerStreamOptions) var kind: UInt32 { switch self { case .whisper: return TRANSCRIBE_EXT_KIND_WHISPER_RUN + case .sortformer: return TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM } } } @@ -79,6 +109,11 @@ func withRunExtension( c.initial_prompt = prompt return try withUnsafePointer(to: &c.ext) { try body($0) } } + case .sortformer(let o): + var c = transcribe_sortformer_stream_ext() + transcribe_sortformer_stream_ext_init(&c) + if let v = o.preset { c.preset = v.cValue } + return try withUnsafePointer(to: &c.ext) { try body($0) } } } diff --git a/bindings/typescript/src/_generated.ts b/bindings/typescript/src/_generated.ts index 8089cb9f..6d316b12 100644 --- a/bindings/typescript/src/_generated.ts +++ b/bindings/typescript/src/_generated.ts @@ -11,7 +11,7 @@ // Stable digest of the ABI surface (structs, enums, macros, layout, // prototypes), computed by the Python oracle and pinned here so a header // ABI change turns this binding's drift check red for conscious review. -export const PUBLIC_HEADER_HASH = "d67a9bd78b964445"; +export const PUBLIC_HEADER_HASH = "fb2e64791dcbb70a"; // === enum constants === export const TRANSCRIBE_OK = 0; @@ -99,6 +99,10 @@ export const TRANSCRIBE_STREAM_FAILED = 3; export const TRANSCRIBE_STREAM_COMMIT_AUTO = 0; export const TRANSCRIBE_STREAM_COMMIT_ON_FINALIZE = 1; export const TRANSCRIBE_STREAM_COMMIT_STABLE_PREFIX = 2; +export const TRANSCRIBE_SORTFORMER_PRESET_DEFAULT = 0; +export const TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY = 1; +export const TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY = 2; +export const TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY = 3; export const TRANSCRIBE_WHISPER_PROMPT_FIRST_SEGMENT = 0; export const TRANSCRIBE_WHISPER_PROMPT_ALL_SEGMENTS = 1; @@ -106,6 +110,7 @@ export const TRANSCRIBE_WHISPER_PROMPT_ALL_SEGMENTS = 1; export const TRANSCRIBE_EXT_KIND_MOONSHINE_STREAMING_STREAM = 1414746957; export const TRANSCRIBE_EXT_KIND_PARAKEET_BUFFERED_STREAM = 1396853584; export const TRANSCRIBE_EXT_KIND_PARAKEET_STREAM = 1414744912; +export const TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM = 1414743635; export const TRANSCRIBE_EXT_KIND_VOXTRAL_REALTIME_STREAM = 1414746710; export const TRANSCRIBE_EXT_KIND_WHISPER_RUN = 1314015319; @@ -129,6 +134,7 @@ export const STRUCT_LAYOUT: Record = { 'transcribe_moonshine_streaming_stream_ext': { size: 24, align: 8, offsets: {'ext': 0, 'min_decode_interval_ms': 16} }, 'transcribe_parakeet_stream_ext': { size: 24, align: 8, offsets: {'ext': 0, 'att_context_right': 16} }, 'transcribe_parakeet_buffered_stream_ext': { size: 32, align: 8, offsets: {'ext': 0, 'left_ms': 16, 'chunk_ms': 20, 'right_ms': 24} }, + 'transcribe_sortformer_stream_ext': { size: 24, align: 8, offsets: {'ext': 0, 'preset': 16} }, 'transcribe_voxtral_realtime_stream_ext': { size: 24, align: 8, offsets: {'ext': 0, 'num_delay_tokens': 16, 'min_decode_interval_ms': 20} }, 'transcribe_whisper_run_ext': { size: 80, align: 8, offsets: {'ext': 0, 'initial_prompt': 16, 'prompt_tokens': 24, 'n_prompt_tokens': 32, 'prompt_condition': 40, 'condition_on_prev_tokens': 44, 'max_prev_context_tokens': 48, 'temperature': 52, 'temperature_inc': 56, 'compression_ratio_thold': 60, 'logprob_thold': 64, 'no_speech_thold': 68, 'seed': 72, 'max_initial_timestamp': 76} }, 'transcribe_whisper_chunk_trace': { size: 48, align: 8, offsets: {'struct_size': 0, 't0_ms': 8, 't1_ms': 16, 'temperature_used': 24, 'compression_ratio': 28, 'avg_logprob': 32, 'no_speech_prob': 36, 'no_speech_triggered': 40, 'n_fallbacks': 44} }, @@ -173,6 +179,7 @@ export function defineTypes(koffi: any): Record { T['transcribe_moonshine_streaming_stream_ext'] = koffi.struct({ ext: T['transcribe_ext'], min_decode_interval_ms: 'int32_t' }); T['transcribe_parakeet_stream_ext'] = koffi.struct({ ext: T['transcribe_ext'], att_context_right: 'int32_t' }); T['transcribe_parakeet_buffered_stream_ext'] = koffi.struct({ ext: T['transcribe_ext'], left_ms: 'int32_t', chunk_ms: 'int32_t', right_ms: 'int32_t' }); + T['transcribe_sortformer_stream_ext'] = koffi.struct({ ext: T['transcribe_ext'], preset: 'int' }); T['transcribe_voxtral_realtime_stream_ext'] = koffi.struct({ ext: T['transcribe_ext'], num_delay_tokens: 'int32_t', min_decode_interval_ms: 'int32_t' }); T['transcribe_whisper_run_ext'] = koffi.struct({ ext: T['transcribe_ext'], initial_prompt: 'char *', prompt_tokens: 'void *', n_prompt_tokens: 'size_t', prompt_condition: 'int', condition_on_prev_tokens: 'bool', max_prev_context_tokens: 'int32_t', temperature: 'float', temperature_inc: 'float', compression_ratio_thold: 'float', logprob_thold: 'float', no_speech_thold: 'float', seed: 'uint32_t', max_initial_timestamp: 'float' }); T['transcribe_whisper_chunk_trace'] = koffi.struct({ struct_size: 'uint64_t', t0_ms: 'int64_t', t1_ms: 'int64_t', temperature_used: 'float', compression_ratio: 'float', avg_logprob: 'float', no_speech_prob: 'float', no_speech_triggered: 'bool', n_fallbacks: 'int32_t' }); @@ -251,6 +258,7 @@ export const FUNCTION_SIGNATURES: Record = { 'transcribe_session_limits_init': { ret: 'void', args: ['struct transcribe_session_limits *'] }, 'transcribe_session_params_init': { ret: 'void', args: ['struct transcribe_session_params *'] }, 'transcribe_set_abort_callback': { ret: 'void', args: ['struct transcribe_session *', 'transcribe_abort_callback', 'void *'] }, + 'transcribe_sortformer_stream_ext_init': { ret: 'void', args: ['struct transcribe_sortformer_stream_ext *'] }, 'transcribe_speaker_segment_init': { ret: 'void', args: ['struct transcribe_speaker_segment *'] }, 'transcribe_status_string': { ret: 'const char *', args: ['int'] }, 'transcribe_stream_begin': { ret: 'transcribe_status', args: ['struct transcribe_session *', 'const struct transcribe_run_params *', 'const struct transcribe_stream_params *'] }, diff --git a/bindings/typescript/src/ffi.ts b/bindings/typescript/src/ffi.ts index cab0f932..e0d1ec11 100644 --- a/bindings/typescript/src/ffi.ts +++ b/bindings/typescript/src/ffi.ts @@ -166,6 +166,9 @@ export function bindLibrary(libraryPath: string): Bound { voxtralRealtimeStreamExtInit: lib.func("transcribe_voxtral_realtime_stream_ext_init", "void", [ outp(T.transcribe_voxtral_realtime_stream_ext), ]), + sortformerStreamExtInit: lib.func("transcribe_sortformer_stream_ext_init", "void", [ + outp(T.transcribe_sortformer_stream_ext), + ]), // batch (offline) runBatch: lib.func("transcribe_run_batch", "int", [ diff --git a/bindings/typescript/src/index.ts b/bindings/typescript/src/index.ts index 3f812e3e..970ba670 100644 --- a/bindings/typescript/src/index.ts +++ b/bindings/typescript/src/index.ts @@ -588,6 +588,20 @@ const FAMILY: Record = { min_decode_interval_ms: o.minDecodeIntervalMs, }), }, + sortformer: { + slot: "run", + kind: g.TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM, + type: "transcribe_sortformer_stream_ext", + init: "sortformerStreamExtInit", + map: (o) => ({ preset: SORTFORMER_PRESET[o.preset as string] }), + }, +}; + +const SORTFORMER_PRESET: Record = { + default: g.TRANSCRIBE_SORTFORMER_PRESET_DEFAULT, + very_high_latency: g.TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY, + high_latency: g.TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY, + low_latency: g.TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY, }; /** diff --git a/bindings/typescript/src/types.ts b/bindings/typescript/src/types.ts index 9dc03e61..9c087d72 100644 --- a/bindings/typescript/src/types.ts +++ b/bindings/typescript/src/types.ts @@ -238,10 +238,25 @@ export interface VoxtralRealtimeStreamOptions { numDelayTokens?: number; minDecodeIntervalMs?: number; } +/** Sortformer streaming operating point (latency / accuracy trade-off). + * "default" keeps the GGUF-shipped checkpoint configuration; + * "very_high_latency" (~30 s lookahead) is the offline-file operating + * point; "low_latency" (~1 s) is the real-time point. */ +export type SortformerPreset = + | "default" + | "very_high_latency" + | "high_latency" + | "low_latency"; +/** Sortformer diarizer options (run slot). A run produces speaker + * segments, no text. */ +export interface SortformerStreamOptions { + preset?: SortformerPreset; +} export type FamilyExtension = | ({ kind: "whisper" } & WhisperRunOptions) | ({ kind: "moonshine" } & MoonshineStreamingOptions) | ({ kind: "parakeet" } & ParakeetStreamOptions) | ({ kind: "parakeet_buffered" } & ParakeetBufferedStreamOptions) - | ({ kind: "voxtral" } & VoxtralRealtimeStreamOptions); + | ({ kind: "voxtral" } & VoxtralRealtimeStreamOptions) + | ({ kind: "sortformer" } & SortformerStreamOptions); diff --git a/docs/extension-kinds.md b/docs/extension-kinds.md index 2d5eee84..cb8dd94d 100644 --- a/docs/extension-kinds.md +++ b/docs/extension-kinds.md @@ -47,6 +47,7 @@ parameter; existing kinds keep their slot for life. | `0x5453534D` | `MSST` | `STREAM` | `TRANSCRIBE_EXT_KIND_MOONSHINE_STREAMING_STREAM` | moonshine_streaming | `include/transcribe/moonshine_streaming.h` | | `0x4E524857` | `WHRN` | `RUN` | `TRANSCRIBE_EXT_KIND_WHISPER_RUN` | whisper | `include/transcribe/whisper.h` | | `0x54535256` | `VRST` | `STREAM` | `TRANSCRIBE_EXT_KIND_VOXTRAL_REALTIME_STREAM` | voxtral_realtime | `include/transcribe/voxtral_realtime.h` | +| `0x54534653` | `SFST` | `RUN` | `TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM` | sortformer | `include/transcribe/sortformer.h` | Empty rows reserved for future allocations: diff --git a/docs/models/diar_streaming_sortformer_4spk-v2.1.md b/docs/models/diar_streaming_sortformer_4spk-v2.1.md new file mode 100644 index 00000000..9c2f44d1 --- /dev/null +++ b/docs/models/diar_streaming_sortformer_4spk-v2.1.md @@ -0,0 +1,217 @@ +# Streaming Sortformer Diarizer 4spk v2.1 + +NVIDIA's [`nvidia/diar_streaming_sortformer_4spk-v2.1`](https://huggingface.co/nvidia/diar_streaming_sortformer_4spk-v2.1) +ported to transcribe.cpp. A FastConformer encoder with an 18-layer +Transformer head that emits per-frame speaker-activity probabilities for +up to 4 speakers, running online with an Arrival-Order Speaker Cache +(AOSC) + FIFO. + +## What it's for + +Speaker diarization: who spoke when. This is **not a transcription +model** — a run produces no text. It takes a 16 kHz mono WAV and emits +speaker segments (`t0_ms`, `t1_ms`, `speaker_id`), with speakers numbered +in order of first appearance. Hard architectural cap of 4 concurrent +speakers. It is the diarization supervisor for the Parakeet multitalker +speaker-attributed ASR path (future work). + +See NVIDIA's [model card](https://huggingface.co/nvidia/diar_streaming_sortformer_4spk-v2.1) +for training data, intended use, and upstream evaluation methodology. + +Licensed under the NVIDIA Open Model License. Ported from upstream commit +[`fafaab5`](https://huggingface.co/nvidia/diar_streaming_sortformer_4spk-v2.1/commit/fafaab5faa1617a0ca52d38dd3dc4bd636800d3d), +pinned 2026-07-19. + +## Download + +| Quantization | Download | Size | DER (AMI IHM test) | +| --- | --- | ---: | ---: | +| F32 | [diar_streaming_sortformer_4spk-v2.1-F32.gguf](https://huggingface.co/handy-computer/diar_streaming_sortformer_4spk-v2.1-gguf/resolve/main/diar_streaming_sortformer_4spk-v2.1-F32.gguf) | 471 MB | 14.59% | +| F16 | [diar_streaming_sortformer_4spk-v2.1-F16.gguf](https://huggingface.co/handy-computer/diar_streaming_sortformer_4spk-v2.1-gguf/resolve/main/diar_streaming_sortformer_4spk-v2.1-F16.gguf) | 237 MB | 14.23% | +| Q8_0 | [diar_streaming_sortformer_4spk-v2.1-Q8_0.gguf](https://huggingface.co/handy-computer/diar_streaming_sortformer_4spk-v2.1-gguf/resolve/main/diar_streaming_sortformer_4spk-v2.1-Q8_0.gguf) | 139 MB | 14.73% | + +DER is measured on the full AMI IHM test set (16 meetings, ~9 h) against +forced-alignment RTTMs with dihard3-dev post-processing, collar 0.0, +overlap scored, at the `very_high_latency` operating point. Our measured +NeMo reference under the identical protocol is **14.83% DER / 19.89% +JER**; the C++ F32 port scores 14.59% / 19.51%. (Published DER numbers +for this model vary with the RTTM source and post-processing; manual +RTTMs score ~13 points worse than forced-alignment RTTMs on the same +system output. Compare like with like.) + +Only near-reference tiers ship for this family. K-quant tiers were +evaluated and withdrawn: the model's output depends on discrete +speaker-cache decisions, and k-tier weight error can deterministically +flip a near-tie and permute speaker labels mid-stream (observed at +Q5_K_M on one AMI meeting; details in +`docs/porting/families/sortformer.md`, "Quant policy (Stage 7)"). + +## Quick Start + +```bash +cmake -B build +cmake --build build + +# Speaker segments as JSON (one line per file): +echo audio.wav > files.txt +build/bin/transcribe-cli \ + -m models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-Q8_0.gguf \ + --batch files.txt --batch-jsonl +# {"file":"audio.wav","text":"","speakers":[{"t0_ms":320,"t1_ms":2400,"speaker_id":1},...]} +``` + +If your audio is not already 16 kHz mono WAV, convert it first: + +```bash +ffmpeg -i input.mp3 -ar 16000 -ac 1 output.wav +``` + +From the C API, read results via `transcribe_n_speaker_segments` / +`transcribe_get_speaker_segment` (the transcript accessors return empty +text). The streaming operating point (latency / accuracy trade-off) is +selected with the run extension in `include/transcribe/sortformer.h`: + +```c +transcribe_sortformer_stream_ext ext; +transcribe_sortformer_stream_ext_init(&ext); /* DEFAULT = model cfg */ +ext.preset = TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY; +run_params.family = &ext.ext; +``` + +`VERY_HIGH_LATENCY` (~30 s lookahead) is the offline-file operating +point used for the DER numbers above; `LOW_LATENCY` (~1 s lookahead) is +the real-time point and costs substantially more compute per audio +second (many small windows). + +## Performance + +Cells are wall-clock latency (mean over 3 iterations after 1 warmup), +with speedup over realtime in parentheses. Default (model-config) +operating point. + +### Apple M4 + +| Backend | Sample | F16 | Q8_0 | +| ------- | ------------ | ------------: | ------------: | +| Metal | jfk (11.0s) | 69 ms (159×) | 65 ms (171×) | +| Metal | dots (35.3s) | 318 ms (111×) | 320 ms (111×) | +| CPU | jfk (11.0s) | 137 ms (80×) | 110 ms (100×) | +| CPU | dots (35.3s) | 796 ms (44×) | 687 ms (51×) | + +macOS 25.5.0, transcribe.cpp `d42c3bb`. + +Benchmark reproduction: + +```bash +uv run scripts/bench/run.py \ + --models diar_streaming_sortformer_4spk-v2.1 \ + --quants f16,q8_0 \ + --samples jfk,dots \ + --backends metal,cpu,vulkan \ + --iters 3 --warmup 1 \ + --name diar_streaming_sortformer_4spk-v2.1-publication +``` + +## Numerical Validation + +transcribe.cpp is validated tensor-by-tensor against NeMo on +`samples/sortformer-2spk-mix.wav` (a committed deterministic 2-speaker +mix with a 1.5 s overlap). All 6 checkpointed tensors fall within family +tolerance, and the streaming AOSC cache-compression internals were +additionally verified bit-exact against NeMo at the index level on a +full 39-minute AMI meeting (87 compression calls). Last validated at +commit `d42c3bb`. + +| Field | Value | +| --- | --- | +| Reference | NeMo, `nvidia/diar_streaming_sortformer_4spk-v2.1` | +| Dump script | `scripts/dump_reference_sortformer_nemo.py` | +| Manifest | `tests/golden/sortformer/diar_streaming_sortformer_4spk-v2.1.manifest.json` | +| Command | `uv run scripts/validate.py compare --family sortformer` | + +Selected tensors: + +| Tensor | Max abs diff | Mean abs diff | Notes | +| --- | ---: | ---: | --- | +| `enc.mel.in` | `0.000e+00` | `0.000e+00` | Exact (shape differs by NeMo pad_to=16, values identical) | +| `enc.fastconformer.out`| `3.263e-03` | `1.396e-04` | F32 accumulation over 17 Conformer blocks | +| `enc.encoder_proj.out` | `9.829e-04` | `1.242e-04` | Drift attenuates through the projection | +| `enc.transformer.out` | `1.128e-03` | `1.323e-04` | 18-layer Transformer head | +| `diar.preds_offline` | `2.961e-04` | `5.007e-06` | Final sigmoid probabilities (offline) | +| `diar.probs` | `2.961e-04` | `5.007e-06` | Streaming path output (== offline on a single-chunk clip) | + +## Known Limitations + +- **Maximum 4 speakers** (architectural cap). More than 4 concurrent + speakers will be merged into the 4 arrival-order slots. +- **No transcript.** Pair with an ASR model if you need speaker-attributed + text; native multitalker interop is planned, not shipped. +- **Speaker labels are arrival-order, not identities.** Labels are stable + within a recording, but there is no cross-recording speaker matching. +- **Perturbation-sensitive label continuity.** The streaming speaker + cache makes discrete near-tie decisions; different backends (Metal vs + CPU float order) can occasionally resolve a near-tie differently on a + given recording, changing label assignment mid-stream. Aggregate DER is + unaffected in our measurements; the shipped F16/Q8_0 tiers showed no + label-swap events on the 16-meeting acceptance set. +- **`LOW_LATENCY` is compute-heavy on CPU** (~1.2x realtime on Apple M4; + the 0.5 s chunks rebuild the compute graph often). Use Metal or a + higher-latency preset for offline files. +- **No batch fast path** (`run_batch`); multi-file CLI batches run + serially. + +## Reproduction + +### Convert + +Loads NVIDIA's NeMo checkpoint via `SortformerEncLabelModel.from_pretrained`. + +```bash +uv run --project scripts/envs/sortformer \ + scripts/convert-sortformer.py nvidia/diar_streaming_sortformer_4spk-v2.1 \ + --out models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf +``` + +### Quantize + +```bash +build/bin/transcribe-quantize \ + models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf \ + models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F16.gguf \ + --quant F16 +# repeat with Q8_0 +``` + +### Validate + +```bash +uv run scripts/validate.py all --family sortformer +``` + +### DER acceptance + +The full protocol (AMI ingest, forced-alignment RTTMs, reference run, +scoring) is documented with commands in +`docs/porting/families/sortformer.md`. Short form: + +```bash +uv run --project scripts/envs/sortformer scripts/diar/run_cpp_sortformer.py \ + --manifest samples/diar/ami-ihm-test-fa.manifest.jsonl \ + --gguf models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf \ + --preset very_high_latency \ + --postprocessing-yaml scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml \ + --pred-dir reports/diar/pred/cpp-ami --out reports/diar/cpp-ami.jsonl +uv run scripts/diar/score_der.py \ + --manifest samples/diar/ami-ihm-test-fa.manifest.jsonl \ + --pred-dir reports/diar/pred/cpp-ami --out reports/diar/cpp-ami.score.json +``` + +### Run real-model tests + +```bash +cmake -B build -DTRANSCRIBE_BUILD_REAL_MODEL_TESTS=ON +cmake --build build + +TRANSCRIBE_SORTFORMER_GGUF=models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf \ + ctest --test-dir build --output-on-failure -R sortformer +``` diff --git a/docs/porting/families/_intake-schema.json b/docs/porting/families/_intake-schema.json index b0fe5da5..7d7d33ae 100644 --- a/docs/porting/families/_intake-schema.json +++ b/docs/porting/families/_intake-schema.json @@ -85,7 +85,7 @@ "type": "array", "items": { "type": "string", - "enum": ["encoder-transducer", "encoder-decoder", "audio-llm", "encoder-ctc"] + "enum": ["encoder-transducer", "encoder-decoder", "audio-llm", "encoder-ctc", "encoder-diarizer"] }, "description": "Heuristic matches against known patterns. Human selects one in architecture_pattern." }, @@ -288,7 +288,7 @@ }, "architecture_pattern": { "type": ["string", "null"], - "enum": ["encoder-transducer", "encoder-decoder", "audio-llm", "encoder-ctc", null] + "enum": ["encoder-transducer", "encoder-decoder", "audio-llm", "encoder-ctc", "encoder-diarizer", null] }, "known_risks": { "type": "array", diff --git a/docs/porting/families/sortformer.md b/docs/porting/families/sortformer.md new file mode 100644 index 00000000..118c2014 --- /dev/null +++ b/docs/porting/families/sortformer.md @@ -0,0 +1,256 @@ +# Sortformer + +Status: port complete (Stages 1-8; ship gate passed 2026-07-22) + +Intake signed off 2026-07-19: capability scope approved as drafted; +acceptance set = AMI (DER + JER vs NeMo reference, plus prob-tensor parity). +Stage 4 tensor parity 6/6; compression internals verified bit-exact vs a +neutral arbiter (residual #1). Stage 7 ref-dtype gate PASS: **C++ AMI DER +14.59% / JER 19.51%** (16 mtgs, very_high_latency, forced-alignment RTTMs + +dihard3 PP) vs measured reference 14.83% / 19.89% (gate: reference + 0.01). +Shipped matrix: **F32 + F16 + Q8_0** (k tiers withdrawn; see "Quant policy +(Stage 7)"). Private HF repo: +`handy-computer/diar_streaming_sortformer_4spk-v2.1-gguf`. + +Batch posture: **ACCEPTED GAP — no `run_batch()`** (user-approved Stage 4 +deferral; single-session `transcribe_run` is the shipped path; revisit with +multitalker interop). Streaming posture: **natively streaming — PASS**; the +chunk/lookahead contract is the preset menu in "Public API (run extension)" +(default = GGUF-shipped checkpoint cfg; very_high_latency ~30.4 s lookahead +... low_latency ~1.04 s), exposed via `transcribe_sortformer_stream_ext`. +Push-audio `transcribe_stream_*` entry point is future work (STREAM-slot +kind reserved by design). + +Streaming Sortformer is a **frame-level end-to-end neural speaker diarizer** +(architecture pattern `encoder-diarizer`, new to this repo). It is NOT a +transcription model: it consumes 16 kHz mono audio and emits a `T x 4` +matrix of per-frame per-speaker activity probabilities (one row per 80 ms +frame, up to 4 speakers, columns in speaker arrival order). It runs online +with a stateful Arrival-Order Speaker Cache (AOSC) + FIFO. + +Primary reason this family is being ported: it is the named hard +dependency of the Parakeet multitalker speaker-attributed ASR path +(`spk_supervision='diar'`). See +`reports/porting/parakeet/multitalker-parakeet-streaming-0.6b-v1/intake.json`. + +## Identity + +- Family key: `sortformer` +- Upstream architecture string: `nemo.collections.asr.models.sortformer_diar_models.SortformerEncLabelModel` +- Architecture pattern: `encoder-diarizer` (NEST/FastConformer encoder -> 18L Transformer encoder -> 2 FF -> 4 sigmoid/frame) +- Hugging Face repo: `nvidia/diar_streaming_sortformer_4spk-v2.1` +- Hugging Face revision: `fafaab5faa1617a0ca52d38dd3dc4bd636800d3d` +- License: NVIDIA Open Model License (v2.1). Sibling `diar_streaming_sortformer_4spk-v2` is CC-BY-4.0. +- Variants: + - `diar_streaming_sortformer_4spk-v2.1` — this port (best meeting DER; multitalker's named dependency). + - `streaming-4spk-v2` — architecturally identical, CC-BY-4.0. Deferred; add by dropping in weights once v2.1 is validated. + +### Diarization scope policy + +Sortformer is the repo's first diarization-only family. transcribe.cpp +remains a transcription library; diarization-only models are in scope only +when they (a) feed a transcription pipeline in-repo (here: the named +`spk_supervision='diar'` dependency of parakeet multitalker speaker- +attributed ASR), or (b) reuse an encoder family the repo already maintains +(here: the NEST FastConformer is parakeet's ConformerEncoder, reused +verbatim). A diarizer meeting neither clause (e.g. a pyannote +segmentation+clustering port: new architecture, new dependency surface, no +in-repo ASR consumer) is out of scope. Standalone diarization output is +exposed because it falls out of the multitalker dependency for free, via +the pre-existing transcript-independent `transcribe_speaker_segment` ABI — +no diarizer-specific output surface was added. + +## Public API (run extension) + +`include/transcribe/sortformer.h` — `TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM` +(`SFST`, RUN slot; registered in `docs/extension-kinds.md`). A run produces +no text; results are read via `transcribe_n_speaker_segments` / +`transcribe_get_speaker_segment` (`TRANSCRIBE_FEATURE_DIARIZATION`). + +```c +transcribe_sortformer_stream_ext ext; +transcribe_sortformer_stream_ext_init(&ext); /* preset = DEFAULT (GGUF cfg) */ +ext.preset = TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY; +run_params.family = &ext.ext; /* probe accepts_ext_kind first */ +``` + +Preset menu (frames are 80 ms; chunk/rc/fifo/update/spkcache geometry per +`k_presets` in `src/arch/sortformer/stream.cpp`, mirroring the upstream +published operating points): + +| Preset | Lookahead | Geometry (chunk/rc/fifo/update/cache) | DER (AMI ihm test, FA + dihard3 PP) | Throughput (M4 CPU) | +| --- | --- | --- | --- | --- | +| `VERY_HIGH_LATENCY` | ~30.4 s | 340/40/40/300/188 | 14.59% (full 16 mtgs; REF 14.83%) | ~25-31x realtime | +| `HIGH_LATENCY` | ~10.0 s | 124/1/124/124/188 | not separately gated | — | +| `LOW_LATENCY` | ~1.04 s | 6/7/188/144/188 | 14.80% (3-mtg subset; REF 14.81%) | ~0.85x realtime (many small windows) | +| `DEFAULT` | GGUF cfg | checkpoint values | — | — | + +The menu is discrete (jointly-tuned bundles), not a latency dial; only +these bundles are accuracy-validated. Precedence: GGUF cfg < ext preset < +`TRANSCRIBE_SORTFORMER_STREAM_PRESET` env < per-field env (env layers are +validation hooks; `small` is a diagnostic-only env preset, deliberately +not in the public enum). An out-of-range preset or wrong-kind ext is +rejected pre-clear (`run_validate`), preserving the previous result. +Unit test: `tests/sortformer_stream_ext_unit.cpp` +(`TRANSCRIBE_SORTFORMER_GGUF`-gated). + +## Quant policy (Stage 7) + +Shipped matrix: **F32 (reference) + F16 + Q8_0** only +(`FAMILY_PRESETS["sortformer"]` in `scripts/lib/quant_policy.py`). The +k-quant tiers are withdrawn: this family's output depends on discrete +AOSC speaker-cache compression decisions, and k-tier weight error can +deterministically flip a near-tie pick and permute speaker labels +mid-stream. Observed at Q5_K_M on AMI TS3003b under the default CPU +operating point (9.47% -> 32.13% DER; deterministic across thread +counts, escaped by Metal float order and by high_latency). The flip is +chaotic in quant error (coarser Q4_K_M passed the same sample), so a +clean 16-meeting result cannot certify a k tier; the tiers also save +little disk (139 -> 92 MB) and are slower than Q8_0 on CPU. Full +evidence: `reports/diar/diar_streaming_sortformer_4spk-v2.1.ami-ihm-test-fa.summary.md`. + +A future push-audio entry point (`transcribe_stream_begin/feed`, live +diarization) registers a separate STREAM-slot kind taking the same preset +enum; the multitalker interop path (raw T x 4 supervision into parakeet's +layer-0 speaker kernel) is internal C++ and does not round-trip through +this surface. + +## References + +- Canonical reference: NeMo `SortformerEncLabelModel.from_pretrained(...)` + `sortformer_modules.SortformerModules` (streaming speaker cache). Same NeMo toolkit already pinned for parakeet/canary. +- Instrumented reference: `scripts/envs/sortformer/` (to be created at Stage 2, mirroring `scripts/envs/parakeet`). +- Cross-check references: + - Sortformer paper: https://arxiv.org/abs/2409.06656 + - Streaming Sortformer (AOSC): https://arxiv.org/abs/2507.18446 + - NEST encoder: https://arxiv.org/abs/2408.13106 + - NeMo eval script: `examples/speaker_tasks/diarization/neural_diarizer/e2e_diarize_speech.py` + +## Commands + +Oracle audio (deterministic 2-speaker mix, committed): + +```bash +uv run scripts/gen_sortformer_oracle_audio.py +# -> samples/sortformer-2spk-mix.wav + tests/golden/sortformer/sortformer-2spk-mix.rttm +``` + +Reference dumps (NeMo, via scripts/envs/sortformer): + +```bash +BASE=build/validate/sortformer/diar_streaming_sortformer_4spk-v2.1/sortformer-2spk-mix +uv run --project scripts/envs/sortformer scripts/dump_reference_sortformer_nemo.py encoder \ + --model nvidia/diar_streaming_sortformer_4spk-v2.1 --audio samples/sortformer-2spk-mix.wav --out $BASE/encoder/ref +uv run --project scripts/envs/sortformer scripts/dump_reference_sortformer_nemo.py diarize \ + --model nvidia/diar_streaming_sortformer_4spk-v2.1 --audio samples/sortformer-2spk-mix.wav --out $BASE/diarize/ref +``` + +Conversion: + +```bash +scripts/convert-sortformer.py -> models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf (arch `sortformer`). +``` + +Validation: + +```bash +# Tensor parity (offline enc.* + diar.preds_offline + streaming diar.probs): +uv run scripts/validate.py all --family sortformer --backend cpu # 6/6 green (single-chunk diar.probs) +VALIDATE_SORTFORMER_PRESET=small uv run scripts/validate.py all --family sortformer # multi-chunk FIFO+compress diagnostic + +# Acceptance (DER + JER, official protocol: forced-alignment RTTMs + dihard3 PP). +uv run scripts/diar/ingest_ami.py --config ihm --split test # audio + manual RTTMs +uv run scripts/diar/fetch_ami_forced_alignment.py --config ihm --split test # forced-alignment RTTMs + FA manifest +# Reference baseline (one-time): +uv run --project scripts/envs/sortformer scripts/diar/run_reference_sortformer_nemo.py \ + --manifest samples/diar/ami-ihm-test.manifest.jsonl \ + --model nvidia/diar_streaming_sortformer_4spk-v2.1 --preset very_high_latency \ + --postprocessing-yaml scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-ami-ihm-test-PPdihard \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-REF.ami-ihm-test.PPdihard.jsonl +# C++ port (dumps diar.probs per meeting, applies the SAME dihard3 PP): +uv run --project scripts/envs/sortformer scripts/diar/run_cpp_sortformer.py \ + --manifest samples/diar/ami-ihm-test-fa.manifest.jsonl \ + --gguf models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf --preset very_high_latency \ + --postprocessing-yaml scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-cpp-ami-ihm-test \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-CPP.ami-ihm-test.jsonl --backend cpu +uv run scripts/diar/score_der.py \ + --manifest samples/diar/ami-ihm-test-fa.manifest.jsonl \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-cpp-ami-ihm-test \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-CPP.ami-ihm-test-fa.PPdihard.score.json +# -> REF DER 14.83% / JER 19.89% ; C++ DER 14.59% / JER 19.51% (within 0.24 pt). +``` + +Benchmarks (publication scope; on-doc artifacts +`reports/perf/apple-m4/diar-streaming-sortformer-4spk-v2-1-publication_*.json`): + +```bash +uv run scripts/bench/run.py \ + --models diar_streaming_sortformer_4spk-v2.1 \ + --quants f16,q8_0 \ + --samples jfk,dots \ + --backends metal,cpu,vulkan \ + --iters 3 --warmup 1 \ + --name diar_streaming_sortformer_4spk-v2.1-publication +# apple-m4: Metal ~170x (jfk) / ~110x (dots) rtf; CPU Q8_0 100x/51x, F16 80x/44x. +# Note: low_latency preset runs ~1.2x realtime on CPU (per-chunk graph +# rebuild dominates at 0.5 s chunks); the shipped default and +# very_high_latency are unaffected. +``` + +## Capability Validation + +> NOTE (non-standard family): the template's forced `MUST PASS` rows are +> transcription rows (explicit-language / auto transcribe). Sortformer +> emits no transcript, so those rows are `OUT OF SCOPE — not a +> transcription model`. The forced-row spirit is preserved by making the +> **diarization** capability the obligated one: streaming diarization, +> offline (single-chunk) diarization, and the raw activity-tensor output +> are the `MUST PASS` rows for this family. These substitutions require +> user sign-off at intake. + +| Capability | Mode | Command / test | Expected observable | Target | Status | +|------------|------|----------------|---------------------|--------|--------| +| Streaming diarization (<=4 spk) | online, AOSC/FIFO cache | port streaming diarize vs NeMo reference at a fixed preset (e.g. 1.04s latency) | prob-tensor parity vs reference; DER + JER within tolerance on AMI | MUST PASS | PASS — `diar.probs` parity (single-chunk 2.96e-4; multi-chunk `small` preset ~3.9e-4 uniform); AMI DER 14.59% / JER 19.51% vs ref 14.83% / 19.89% | +| Offline diarization | single large chunk | port diarize vs NeMo reference | prob-tensor parity vs reference | MUST PASS | PASS — `diar.preds_offline` 2.96e-4 (validate.py all 6/6) | +| Speaker-activity tensor | `include_tensor_outputs` | T x 4 sigmoid probs, port vs reference on the same audio | max-abs-diff within tolerance, columns arrival-order aligned | MUST PASS | PASS — `diar.probs` [150x4] within tolerance | +| Multitalker interop | feed diar supervision | Sortformer T x 4 drives parakeet multitalker layer-0 speaker kernel | multitalker emits speaker-attributed transcript | OUT OF SCOPE — owned by the multitalker port; unblocked once both land | N/A (deferred to multitalker port) | +| Transcription (text) | n/a | n/a | model produces no text output | OUT OF SCOPE — not a transcription model | N/A | +| Translation | n/a | n/a | n/a | OUT OF SCOPE — not a transcription model | N/A | +| Timestamps (transcription) | n/a | n/a | diarization segment times are intrinsic, not a transcript-timestamp capability | OUT OF SCOPE — not a transcription model | N/A | +| >4 speakers | n/a | n/a | hard cap at 4 speakers | OUT OF SCOPE — architectural 4-speaker cap | N/A | +| Batch (`run_batch`) | n/a | n/a | parallel multi-file fast path | ACCEPTED GAP — user-approved Stage 4 deferral; single-session runs only | N/A (deferred) | + +## Reference baselines (Stage 2 Oracle) + +- **Tensor parity oracle** (`build/validate/sortformer/diar_streaming_sortformer_4spk-v2.1/sortformer-2spk-mix/`): mel + fastconformer + encoder_proj + transformer + offline preds + streaming `diar.probs` [150×4]. Offline preds == streaming probs on this short clip (single chunk). Tolerances in `tests/tolerances/sortformer.json` (finalized Stage 4; no `_provisional` flags). +- **Measured reference DER/JER** on AMI ihm test (16 meetings, 9.06 h), preset `very_high_latency`, collar 0.0s / overlap included (NVIDIA AMI protocol). The reference pipeline REPRODUCES the published number (15.90 @ very_high_latency AMI-IHM). Full 2x2 decomposition of the two protocol levers: + + | predictions | vs manual RTTMs (diarizers-community/ami) | vs forced-alignment RTTMs (nttcslab-sp) | + |---|---|---| + | no post-processing | 29.44% | 15.96% | + | + dihard3 post-processing | 27.95% | **14.83%** | + + - **Official gate = forced-alignment RTTMs + dihard3 PP: DER 14.83%, JER 19.89%** (missed 5.89%, FA 5.60%, confusion 3.34%). File: `reports/diar/diar_streaming_sortformer_4spk-v2.1-REF.ami-ihm-test-fa.PPdihard.score.json`. Stage 4 / Stage 7 apply the SAME PP to the C++ probs and score vs the SAME forced-alignment RTTMs, gated against this number. + - The RTTM source is ~13 pts of the published-vs-manual gap; post-processing another ~1 pt. Confusion stays ~3% throughout, so the diarization core is correct; the manual-RTTM inflation was recall against dense annotations (within-utterance pauses), exactly as NVIDIA's forced-alignment `only_words` labels avoid. + - Ground truth: nttcslab-sp/diar-forced-alignment (ASRU 2025, card ref [7]), `only_words`, full-corpus-ASR partition — the labels NVIDIA used. PP: NeMo v2 `dihard3-dev` config (no AMI-specific or v2.1 PP is published; dihard3 is the meeting-domain proxy). + - Diagnostic/context files also kept: `...ami-ihm-test.score.json` (no-PP/manual 29.44%), `...ami-ihm-test-fa.noPP.score.json` (no-PP/FA 15.96%). + +## Conversion (Stage 3) + +`scripts/convert-sortformer.py` -> `models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf` (F32, 471 MB, arch string `sortformer`). 971 tensors emitted; 19 skipped (2 `preprocessor.*` recomputed in the C++ frontend, 17 BN `num_batches_tracked` counters). Gate B all-PASS. The GGUF tensor-name contract Stage 4's `src/arch/sortformer/weights.cpp` must implement: + +- `enc.pre_encode.*` — dw_striding subsample (same as Parakeet). +- `enc.blocks.{0..16}.*` — 17 Conformer/NEST blocks; identical suffix map to Parakeet's `ENCODER_BLOCK_TABLE` (macaron FF1/FF2, rel-pos self-attn with `pos_bias_u/v`, conv module with `conv.bn.{weight,bias,running_mean,running_var}`). `use_bias=true` (linear biases present); `conv_norm_type=batch_norm`. +- `diar.encoder_proj.{weight,bias}` — Linear 512 -> 192 between the two encoders. +- `tf.blocks.{0..17}.*` — 18 post-LN Transformer blocks: `norm_1` -> attn(`attn.{q,k,v,out}`) -> `norm_2` -> FFN(`ff.{in,out}`), ReLU, `pre_ln=false`. +- `diar.fc1.*`, `diar.spk_head.*` (4x384 -> 4 sigmoid), `diar.single_spk_head.*` (4x192). + +Tensor-name mapping decisions: Conformer names mirror `convert-parakeet.py` verbatim (shared NeMo ConformerEncoder). Transformer norms named `norm_1`/`norm_2` and BN kept as `.bn.` so `reference_dtype_for`/`policy.cpp` route them to F32; representatives registered in `scripts/lib/test_quant_policy_sync.py`. GGUF slug is the variant (`diar_streaming_sortformer_4spk-v2.1`), not the longer repo slug. + +## Notes + +- Frontend `normalize=NA` (no per-feature normalization); 128 mels, n_fft 512, win 400 / hop 160, hann, dither 1e-5. `preemphasis=0.97` CONFIRMED from the loaded preprocessor at Stage 2 (NeMo default applied, not disabled). +- Reaching the published DER later (optional, not a port gate) needs forced-alignment RTTMs + a tuned post-processing config; the `--collar` / `--skip-overlap` knobs in `scripts/diar/score_der.py` are for diagnostics only. +- Output post-processing (probs -> RTTM segments) is dataset-tuned upstream. Port gate is prob-tensor parity; DER/JER use a fixed/documented post-processing and are compared to the reference model, not to the published numbers. +- Streaming operating-point knobs: `chunk_len`, `chunk_right_context`, `fifo_len`, `spkcache_update_period`, `spkcache_len` (all in 80 ms frames). Published DER corresponds to specific presets (1.04s vs 30.4s input-buffer latency). diff --git a/include/transcribe.abihash b/include/transcribe.abihash index 549ecfa6..8513799e 100644 --- a/include/transcribe.abihash +++ b/include/transcribe.abihash @@ -1 +1 @@ -d67a9bd78b964445 +fb2e64791dcbb70a diff --git a/include/transcribe/extensions.h b/include/transcribe/extensions.h index 95790aa5..b93bf146 100644 --- a/include/transcribe/extensions.h +++ b/include/transcribe/extensions.h @@ -16,6 +16,7 @@ #include "transcribe.h" #include "transcribe/moonshine_streaming.h" #include "transcribe/parakeet.h" +#include "transcribe/sortformer.h" #include "transcribe/voxtral_realtime.h" #include "transcribe/whisper.h" diff --git a/include/transcribe/sortformer.h b/include/transcribe/sortformer.h new file mode 100644 index 00000000..751b11c8 --- /dev/null +++ b/include/transcribe/sortformer.h @@ -0,0 +1,81 @@ +/* + * include/transcribe/sortformer.h - Sortformer-family public extension. + * + * Includes transcribe.h; safe to include in C or C++ TUs. Holds the + * streaming-operating-point run extension, its kind constant, and its + * init function. + * + * Sortformer (diar_streaming_sortformer_4spk-v2.1) is a diarization-only model: a run + * produces no text; the product is the who-spoke-when rows read back via + * transcribe_n_speaker_segments / transcribe_get_speaker_segment + * (TRANSCRIBE_FEATURE_DIARIZATION). The compute core is streaming + * (AOSC speaker cache + FIFO) but the shipped entry point is the batch + * transcribe_run over a whole recording, so this extension lives on the + * RUN slot. A future push-audio entry point (transcribe_stream_begin/ + * feed) would register a separate STREAM-slot kind taking the same + * preset enum. + * + * Probe via transcribe_model_accepts_ext_kind(model, + * TRANSCRIBE_EXT_SLOT_RUN, TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM) + * before pointing transcribe_run_params::family at the struct. + * + * FourCC kinds are reserved in docs/extension-kinds.md. + */ + +#ifndef TRANSCRIBE_SORTFORMER_H +#define TRANSCRIBE_SORTFORMER_H + +#include "transcribe.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* 'SFST' little-endian = 0x54534653 */ +#define TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM 0x54534653u + +/* + * Streaming operating point (latency / accuracy trade-off). + * + * The model processes audio in fixed chunks and carries speaker identity + * across chunks in a bounded cache; the operating point sets the chunk + * geometry. Each named preset is a jointly-tuned bundle published by the + * upstream model (chunk length, lookahead, FIFO and speaker-cache + * geometry) - the menu is discrete, not a continuous latency dial, and + * only these bundles are accuracy-validated (AMI DER, see + * docs/porting/families/sortformer.md). + * + * DEFAULT The GGUF-shipped checkpoint configuration. + * VERY_HIGH_LATENCY ~30.4 s algorithmic lookahead (chunk 340 + rc 40 + * frames @ 80 ms). Highest accuracy; the published + * operating point for offline file processing. + * HIGH_LATENCY ~10.0 s lookahead (chunk 124 + rc 1). + * LOW_LATENCY ~1.04 s lookahead (chunk 6 + rc 7). The + * real-time operating point. Note: much higher + * compute per audio second than the larger chunks + * (many small windows); see the family doc for + * measured throughput. + * + * Values outside the enum range are rejected by transcribe_run with + * TRANSCRIBE_ERR_INVALID_ARG before the previous result is cleared. + */ +typedef enum { + TRANSCRIBE_SORTFORMER_PRESET_DEFAULT = 0, + TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY = 1, + TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY = 2, + TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY = 3, +} transcribe_sortformer_preset; + +struct transcribe_sortformer_stream_ext { + struct transcribe_ext ext; + transcribe_sortformer_preset preset; +}; + +/* Fills ext.size/kind and preset = DEFAULT (GGUF-shipped cfg). */ +TRANSCRIBE_API void transcribe_sortformer_stream_ext_init(struct transcribe_sortformer_stream_ext * ext); + +#ifdef __cplusplus +} +#endif + +#endif /* TRANSCRIBE_SORTFORMER_H */ diff --git a/reports/porting/sortformer/diar_streaming_sortformer_4spk-v2.1/intake.json b/reports/porting/sortformer/diar_streaming_sortformer_4spk-v2.1/intake.json new file mode 100644 index 00000000..d1fc1453 --- /dev/null +++ b/reports/porting/sortformer/diar_streaming_sortformer_4spk-v2.1/intake.json @@ -0,0 +1,235 @@ +{ + "schema_version": "transcribe-intake-v1", + "family": "sortformer", + "hf_repo": "nvidia/diar_streaming_sortformer_4spk-v2.1", + "hf_revision": "fafaab5faa1617a0ca52d38dd3dc4bd636800d3d", + "sources": { + "config": { + "kind": "hf_file", + "path": "config.json", + "status": "missing", + "detail": "NeMo .nemo archive only; no HF config.json. Architecture from model_config.yaml inside diar_streaming_sortformer_4spk-v2.1.nemo (nemo_version 2.6.0rc0)." + }, + "preprocessor": { + "kind": "hf_file", + "path": "preprocessor_config.json", + "status": "missing", + "detail": "Inside .nemo model_config.yaml: AudioToMelSpectrogramPreprocessor, 16kHz, features=128, n_fft=512, window_size=0.025, window_stride=0.01, window=hann, normalize=NA, dither=1e-5." + }, + "tokenizer_config": { + "kind": "hf_file", + "path": "tokenizer_config.json", + "status": "missing", + "detail": "No tokenizer. This is a diarizer: output is a T x 4 speaker-activity probability matrix, not text. No vocabulary of any kind." + }, + "tokenizer_json": { + "kind": "hf_file", + "path": "tokenizer.json", + "status": "missing", + "detail": "N/A for a diarizer." + }, + "generation_config": { + "kind": "hf_file", + "path": "generation_config.json", + "status": "missing", + "detail": "N/A; no autoregressive decoding." + }, + "safetensors_metadata": { + "kind": "hf_api", + "path": "HfApi.get_safetensors_metadata", + "status": "missing", + "detail": "PyTorch state_dict (model_weights.ckpt) inside the .nemo tar; not safetensors." + }, + "model_card": { + "kind": "hf_api", + "path": "https://huggingface.co/nvidia/diar_streaming_sortformer_4spk-v2.1", + "status": "found", + "detail": "Streaming Sortformer 4-spk v2.1, 117M params, DER published per dataset at 1.04s and 30.4s input-buffer latency." + }, + "nemo_model_config": { + "kind": "reference_code", + "path": "diar_streaming_sortformer_4spk-v2.1.nemo::model_config.yaml", + "status": "found", + "detail": "target: nemo.collections.asr.models.sortformer_diar_models.SortformerEncLabelModel. Extracted via HTTP range read of the tar head (config is the first member)." + }, + "reference_modeling_code": { + "kind": "reference_code", + "path": "nemo.collections.asr.models.SortformerEncLabelModel + nemo.collections.asr.modules.sortformer_modules.SortformerModules", + "status": "found", + "detail": "Same NeMo toolkit already pinned for parakeet/canary. diarize() and the streaming speaker-cache (AOSC/FIFO) logic live in sortformer_modules." + } + }, + "variants": [ + { + "name": "diar_streaming_sortformer_4spk-v2.1", + "memory_gb": 2, + "files": ["diar_streaming_sortformer_4spk-v2.1.nemo"] + } + ], + "config": { + "architecture_candidates": ["encoder-diarizer"], + "key_fields": { + "target": "nemo.collections.asr.models.sortformer_diar_models.SortformerEncLabelModel", + "model_type": "sortformer_enc_label", + "max_num_of_spks": 4, + "streaming_mode": true, + "frame_period_seconds": 0.08, + "output_shape": "T x 4 sigmoid speaker-activity probabilities (arrival-order columns)", + "encoder.type": "ConformerEncoder (NEST / FastConformer-Large)", + "encoder.n_layers": 17, + "encoder.d_model": 512, + "encoder.n_heads": 8, + "encoder.ff_expansion_factor": 4, + "encoder.conv_kernel_size": 9, + "encoder.conv_norm_type": "batch_norm", + "encoder.self_attention_model": "rel_pos", + "encoder.subsampling": "dw_striding", + "encoder.subsampling_factor": 8, + "encoder.subsampling_conv_channels": 256, + "encoder.xscaling": true, + "transformer_encoder.num_layers": 18, + "transformer_encoder.hidden_size": 192, + "transformer_encoder.inner_size": 768, + "transformer_encoder.num_attention_heads": 8, + "transformer_encoder.hidden_act": "relu", + "transformer_encoder.pre_ln": false, + "head": "2 feedforward layers -> 4 sigmoid outputs per frame", + "loss": "BCELoss (train-time; sort-based PIL/ATS objective, pil_weight=0.5 ats_weight=0.5)", + "sortformer_modules.spkcache_len": 188, + "sortformer_modules.fifo_len": 0, + "sortformer_modules.chunk_len": 188, + "sortformer_modules.spkcache_update_period": 188 + }, + "varying_across_variants": [] + }, + "dtype": { + "expected": "float32", + "source": "manual", + "evidence": "NeMo .nemo PyTorch state_dict; NeMo diarization models run and store at float32. No config torch_dtype and no safetensors header. Confirm the state_dict dtype at Stage 3 convert.", + "details": { + "config_declared": null, + "header_distribution": {} + }, + "expected_f32_tensors": [] + }, + "frontend": { + "sample_rate": 16000, + "n_mels": 128, + "hop_length": 160, + "fft_size": 512, + "window": "hann_periodic", + "normalization": "none", + "preemphasis": 0.97, + "dither": 1e-05, + "center": true, + "padding_mode": "reflect", + "mel_filterbank_norm": "slaney" + }, + "tokenizer": { + "type": "other", + "vocab_size": 0, + "special_tokens": {}, + "has_language_tokens": false, + "vocab_sha256": null + }, + "capabilities": { + "languages": ["en"], + "language_detection": false, + "translation": false, + "timestamps": [], + "streaming": true, + "speaker_diarization": true + }, + "upstream_benchmarks": [ + { + "dataset": "AMI Test IHM (forced-alignment RTTM)", + "language": "en", + "metric": "other", + "score": 16.67, + "score_unit": "percent DER", + "source": "model card", + "notes": "Metric is DER (lower is better), collar 0.0s with overlap. FREELY DOWNLOADABLE. CONFIRMED acceptance set. 30.4s-latency (very_high_latency) published DER is 15.90. Stage 2 REPRODUCED this: our measured NeMo reference on AMI ihm test = 15.96% (no PP) / 14.83% (dihard3 PP), both vs forced-alignment RTTMs (nttcslab-sp), preset very_high_latency. Scoring vs the denser diarizers-community manual RTTMs instead gives 29.44% (recall-inflated). Official gate = FA RTTMs + dihard3 PP = 14.83%." + }, + { + "dataset": "AMI Test SDM (forced-alignment RTTM)", + "language": "en", + "metric": "other", + "score": 20.57, + "score_unit": "percent DER", + "source": "model card", + "notes": "DER, collar 0.0s, 1.04s latency. Freely downloadable single-distant-mic condition. 30.4s-latency DER is 17.80." + }, + { + "dataset": "DIHARD III Eval full (1-9 spk)", + "language": "en", + "metric": "other", + "score": 20.21, + "score_unit": "percent DER", + "source": "model card", + "notes": "DER, collar 0.0s, 1.04s latency. Context only: DIHARD III is LDC-gated, not freely reproducible here. Uses dataset-tuned post-processing." + }, + { + "dataset": "CALLHOME-part2 full (2-6 spk)", + "language": "en", + "metric": "other", + "score": 11.19, + "score_unit": "percent DER", + "source": "model card", + "notes": "DER, collar 0.25s, 1.04s latency. Context only: NIST-SRE-2000 Disc8 is LDC-gated." + }, + { + "dataset": "CH109 (CALLHOME American English, 2 spk)", + "language": "en", + "metric": "other", + "score": 5.09, + "score_unit": "percent DER", + "source": "model card", + "notes": "DER, collar 0.25s, 1.04s latency. Context only: LDC-gated." + }, + { + "dataset": "AliMeeting Test near (forced-alignment RTTM)", + "language": "zh", + "metric": "other", + "score": 12.6, + "score_unit": "percent DER", + "source": "model card", + "notes": "DER, collar 0.0s, 1.04s latency. Mandarin meeting corpus; context only (model is English-primary)." + }, + { + "dataset": "NOTSOFAR1 Eval SC full (3-7 spk)", + "language": "en", + "metric": "other", + "score": 28.75, + "score_unit": "percent DER", + "source": "model card", + "notes": "DER, collar 0.0s, 1.04s latency. Meeting corpus; v2.1 improved markedly over v2 here (34.52 -> 28.75)." + } + ], + "reference_framework": "nemo", + "reference_rationale": "The model ships only as a NeMo .nemo checkpoint and loads exclusively via nemo.collections.asr.models.SortformerEncLabelModel (from_pretrained / restore_from). There is no HF transformers modeling class, no config.json, no trust_remote_code path. The forward pass, the AudioToMelSpectrogramPreprocessor frontend, and the streaming speaker-cache logic (AOSC/FIFO, arrival-order permutation) all live in NeMo (sortformer_diar_models.py + sortformer_modules.py). NeMo is therefore the sole source of truth, and it is the same toolkit already pinned for the parakeet and canary ports (scripts/envs/parakeet, scripts/envs/canary).", + "architecture_pattern": "encoder-diarizer", + "known_risks": [ + "NEW ARCHITECTURE FAMILY for the runtime. Sortformer is a frame-level end-to-end neural diarizer: NEST/FastConformer encoder -> 18-layer Transformer encoder -> 2 feedforward layers -> 4 sigmoid outputs per 80ms frame. Output is a T x 4 speaker-activity probability matrix, NOT text. transcribe.cpp has no such forward path today: the existing diarization support (moss, granite) is host-side text parsing of an audio-LLM's emergent [Sxx] speaker tags, a completely different mechanism. This port needs a genuinely new arch scaffold (encoder-diarizer): encoder + per-frame multi-label classification head, no decoder, no tokenizer, no generation loop.", + "STREAMING-ONLY STATEFUL INFERENCE is the core novelty and the largest lift. The model runs online with an Arrival-Order Speaker Cache (AOSC) plus a FIFO queue plus a speaker cache, all measured in 80ms frames and driven by chunk_len / chunk_right_context / fifo_len / spkcache_update_period / spkcache_len (sortformer_modules.SortformerModules). Offline is just streaming with one large chunk. Porting requires reproducing the speaker-cache update/eviction and arrival-order permutation exactly; these carry state across chunks and are where numerical parity is hardest.", + "MULTITALKER INTEROP is an explicit integration goal (not standalone-only). The parakeet multitalker port (reports/porting/parakeet/multitalker-parakeet-streaming-0.6b-v1) names nvidia/diar_streaming_sortformer_4spk-v2.1 as its HARD external dependency: multitalker's layer-0 speaker kernel consumes per-frame per-speaker speech-activity supervision (spk_supervision='diar'), which is exactly Sortformer's T x 4 output. Both sides run the same frame grid (10ms hop x8 subsampling = 80ms) and the same normalize=NA frontend. The diarization output/interface must be designed to feed the multitalker speaker-kernel (arrival-order speaker indices, 80ms cadence, streaming state alignment), not just to emit standalone RTTM.", + "MIXED-NORM TWO-ENCODER STACK. NEST/FastConformer encoder (ConformerEncoder, 17 layers, d=512, 8 heads, rel_pos with untied biases, xscaling, dw_striding x8, subsampling_conv_channels=256, conv kernel 9, conv_norm_type=batch_norm) feeds an 18-layer Transformer encoder (d=192, inner=768, 8 heads, ReLU, pre_ln=false i.e. post-LN, pre_ln_final_layer_norm=true). Conformer batch-norm convs vs Transformer LayerNorm, and the post-LN Transformer, must each be wired correctly; the d=512 -> d=192 handoff between the two stacks is a specific integration point.", + "FRONTEND normalize=NA (no per-feature normalization), unlike non-streaming parakeet (per_feature). 128 mels, n_fft=512, win_length=400 (25ms), hop=160 (10ms), hann, dither=1e-5. preemphasis is NOT set in model_config.yaml so the NeMo default (0.97) is assumed here, but the sibling streaming-parakeet models disable preemphasis; the true value MUST be confirmed against the Stage 2 Oracle dump. A silent frontend mismatch degrades DER without any shape error.", + "OUTPUT IS PROBABILITIES, NOT SEGMENTS. DER/JER require post-processing (thresholding plus optional onset/offset + median filtering) to turn the T x 4 probs into RTTM speaker segments. NVIDIA's published DER uses per-dataset tuned post-processing YAMLs. The porting parity gate must therefore be raw prob-tensor parity vs the NeMo reference (arrival-order columns are directly comparable, no Hungarian needed); DER and JER are computed with a fixed/documented post-processing and compared to the reference model on the SAME audio+manifest, not to the published numbers.", + "ACCEPTANCE DATA. LibriSpeech test-clean is single-speaker and degenerate for diarization, so it is NOT a valid acceptance set here. Most published eval corpora (CALLHOME, DIHARD III, CH109, NIST-SRE) are LDC-gated and not freely reproducible. AMI and VoxConverse are freely downloadable; AMI (NVIDIA publishes DER on it) is the proposed reproducible acceptance set. Confirm final acceptance set at sign-off.", + "OPERATING-POINT KNOBS. Hard cap of 4 speakers (>4 degrades sharply). The streaming knobs (chunk_len, chunk_right_context, fifo_len, spkcache_update_period, spkcache_len) trade latency for accuracy; the published numbers correspond to specific presets (e.g. 1.04s vs 30.4s input-buffer latency). These must be exposed/settable in the runtime to reproduce a published operating point and to match whichever preset the multitalker path expects." + ], + "intake_gaps": [ + { + "field": "frontend.preemphasis", + "reason": "RESOLVED at Stage 2 Oracle: the loaded AudioToMelSpectrogramPreprocessor reports preemph=0.97 and normalize='NA' (none). The 0.97 default is applied, not disabled. Frontend is locked." + }, + { + "field": "upstream_benchmarks.acceptance_dataset", + "reason": "RESOLVED at sign-off: acceptance set is AMI (freely downloadable, published DER), verified as prob-tensor parity + DER + JER vs the NeMo reference on the same manifest. Not LibriSpeech (single-speaker => degenerate for diarization)." + }, + { + "field": "capabilities.timestamps", + "reason": "Left empty: diarization output is intrinsically timed speaker segments, but the transcription-timestamp capability (none/segment/word/token) does not apply to a model that emits no transcript." + } + ] +} diff --git a/reports/porting/sortformer/forward-map.md b/reports/porting/sortformer/forward-map.md new file mode 100644 index 00000000..6da2a73c --- /dev/null +++ b/reports/porting/sortformer/forward-map.md @@ -0,0 +1,138 @@ +# Forward map - sortformer + +Reference: NeMo `SortformerEncLabelModel` (nemo.collections.asr.models.sortformer_diar_models) @ pin `6967f48fda2a` +Closest in-tree analog: src/arch/parakeet/ (shared NeMo ConformerEncoder for the FastConformer stage) + +Compact map from the reference forward pass to the C++ port. Sortformer is an +`encoder-diarizer`: no tokenizer, no decoder, no text. The product is a `T x 4` +per-frame speaker-activity probability matrix (80 ms frames, arrival-order +columns, max 4 speakers). Two forward paths: + +- **offline / full-context** (`forward` -> `forward_infer`): single-chunk, + non-stateful. The C++ encoder must match this first. Gate tensors below. +- **streaming** (`forward_streaming`): AOSC speaker-cache + FIFO over 188-frame + chunks. Needed for the streaming capability row and DER on long audio. See + "Streaming path" section; only diverges from offline once T > chunk_len. + +Dims (from GGUF KVs): conformer 17L d=512 h=8 dff=2048 k=9 sub=8 feat_in=128 +BN; transformer 18L **post-LN** d=192 h=8 (head_dim=24) dff=768 ReLU, **no +final norm** (pre_ln=false); encoder_proj 512->192; diar fc1 192->192, +single_spk_head 192->4 (spk_head 384->4 is streaming-only). + +## Frontend + +| Stage | Reference location | Output shape | Gate tensor | ggml / C++ pattern | In-tree analog | +|-------|--------------------|--------------|-------------|--------------------|----------------| +| Mel log-spectrogram | NeMo `AudioToMelSpectrogramPreprocessor` (preprocessor.*, recomputed in C++) | [128, T_mel] (T_mel=1216 for 12s) | `enc.mel.in` | reuse parakeet MelFrontend: preemph 0.97, dither 1e-5, n_fft 512, win 400, hop 160, hann-periodic, 128 mel, `normalize=none` | parakeet `MelFrontend` | + +Note: parakeet's NeMo preprocessor uses `normalize=per_feature`; Sortformer +uses `normalize=none`. Confirm the parakeet MelFrontend is parameterized on +normalize (KV `stt.frontend.normalize`) and does NOT hardcode per-feature. + +## Encoder + +| Stage | Reference location | Output shape | Gate tensor | ggml / C++ pattern | In-tree analog | +|-------|--------------------|--------------|-------------|--------------------|----------------| +| FastConformer (pre_encode dw_striding x8 + 17 Conformer blocks) | `ConformerEncoder.forward` (encoder.*) | [T=150, 512] (ref emits [B,512,T], transposed to [T,512]) | `enc.fastconformer.out` | **verbatim reuse** of parakeet ConformerEncoder graph (macaron FF, rel-pos MHA w/ pos_bias_u/v, conv+BN, use_bias=true). Same tensor suffix map. | parakeet `encoder.cpp` | +| encoder_proj | `sortformer_modules.encoder_proj` (Linear 512->192) applied after `emb_seq.transpose(1,2)` | [150, 192] | `enc.encoder_proj.out` | `ggml_mul_mat(W, x) + b` | any linear | +| Transformer encoder (18x post-LN block) | `transformer/transformer_encoders.py::TransformerEncoder.forward` + `TransformerEncoderBlock.forward_postln` | [150, 192] | `enc.transformer.out` | per block below; no final norm | new (cohere decoder self-attn is closest MHA) | + +### Transformer post-LN block (repeat x18) + +Reference `forward_postln(x, mask)`: +``` +a = MHA(q=x, k=x, v=x, mask) # first_sub_layer +a = a + x # residual +a = LN1(a) # layer_norm_1 (eps 1e-5) +f = dense_out(relu(dense_in(a))) # second_sub_layer (PositionWiseFF), 192->768->192 +o = f + a # residual +o = LN2(o) # layer_norm_2 (eps 1e-5) +``` +MHA (`transformer_modules.MultiHeadAttention`): q/k/v each `Linear(192,192)` +with bias (`attn.{q,k,v}`); `attn_scale = sqrt(sqrt(head_dim))`; q and k each +divided by attn_scale before `q@k^T` (=> scores/sqrt(head_dim)); `+ mask` +(0 attend / -10000 pad); softmax; `@v`; `out_projection` (`attn.out`, bias). +Gate tensors: verify block 0, 8, 17 output via TRANSCRIBE_DUMP_ALL_BLOCKS. + +## Decoder + +No decoder. The "head" is the diarization sigmoid stack. + +| Stage | Reference location | Output shape | Gate tensor | ggml / C++ pattern | In-tree analog | +|-------|--------------------|--------------|-------------|--------------------|----------------| +| Speaker sigmoids (offline) | `sortformer_modules.forward_speaker_sigmoids` | [150, 4] | `diar.preds_offline` | `relu(x)` -> `fc1`(192->192) -> `relu` -> `single_spk_head`(192->4) -> `sigmoid`; then `* mask` | new | + +`forward_speaker_sigmoids(x)`: +``` +h = relu(x) # dropout is identity at eval +h = fc1(h) # first_hidden_to_hidden, Linear(192,192) +h = relu(h) +s = single_spk_head(h) # single_hidden_to_spks, Linear(192,4) +preds = sigmoid(s) +preds = preds * encoder_mask # zero padded frames +``` + +## Generation / KV Path + +No autoregressive generation. N/A. + +## Streaming path (forward_streaming) — IMPLEMENTED (Stage 4 streaming checkpoint) + +Sync (`async_streaming=False`) stateful loop over chunks of `chunk_len` +diar-frames (chunk_len * subsampling_factor mel frames). Per chunk +(`forward_streaming_step`): + +1. `encoder.pre_encode(chunk mel window incl. lc/rc context)` -> chunk_embs + [T_diar, 512], **un-xscaled** (C++ Graph A: `conf::build_pre_encode`). +2. concat `[spkcache | fifo | chunk_embs]` (all 512-dim, host-owned state). +3. `frontend_encoder(bypass_pre_encode=True)`: xscale x sqrt(512) + rel pos_emb + over T_concat + 17 conformer blocks (full attention) + `encoder_proj` + 512->192 (C++ Graph B: `conf::build_conformer_block` x17 + linear). +4. `forward_infer`: 18L post-LN transformer + `forward_speaker_sigmoids` + (relu -> fc1 -> relu -> **single_spk_head** 192->4 -> sigmoid). NOTE: the + inference path uses `single_hidden_to_spks` (192->4), NOT the 2*hidden + `hidden_to_spks` (384->4) head, which is unused at inference. All frames are + valid in sync mode so `apply_mask_to_preds` / encoder_mask is a no-op. +5. `streaming_update` (host): slice fifo/chunk preds, append the middle chunk + to FIFO, pop `pop_out_len` frames FIFO->spkcache, update the silence + profile, and `_compress_spkcache` when spkcache > spkcache_len. + +C++ implementation: `src/arch/sortformer/model.cpp` (two-phase Graph A/B + +`run_streaming` driver) and `src/arch/sortformer/stream.cpp` (host +`streaming_update_sync` / `_compress_spkcache` / silence profile, exact ports of +`sortformer_modules.py`). The tensor-dump oracle runs on CPU, so `_compress_ +spkcache`'s topk/sort tie-breaks target ATen CPU semantics (value desc, +flat-index asc; `-inf` picks mapped to `max_index` before the ascending sort). + +Validation: single-chunk `diar.probs` == `diar.preds_offline` bit-close +(2.96e-4, oracle 150 dihard3 PP -> `score_der.py`). + +## Capabilities And Language Controls + +| Capability | Reference behavior | C++ API behavior | Family-doc Capability Validation row | +|------------|--------------------|------------------|--------------------------------------| +| Streaming diarization <=4spk | `m.diarize()` streaming AOSC/FIFO | TODO: streaming hooks emit T x 4 | Streaming diarization (MUST PASS) | +| Offline diarization | `forward` single chunk | `run()` offline forward -> T x 4 | Offline diarization (MUST PASS) | +| Speaker-activity tensor | preds [T,4] | dump / result surface T x 4 | Speaker-activity tensor (MUST PASS) | +| Transcription/translation/timestamps | none (not a transcriber) | not exposed | OUT OF SCOPE rows | + +## Deviations From Closest Analog + +- No decoder, no tokenizer, no text result. Output is a float matrix; the + transcript-oriented result/session API must carry it (see open decision: + diar result surface vs tensor-dump-only for Stage 4). +- Transformer is **post-LN** (parakeet/cohere self-attn are pre-LN); LN sits + AFTER each residual add, and there is no final norm. +- MHA scaling is split (q and k pre-divided by sqrt(sqrt(head_dim))) rather + than scaling scores once; numerically equivalent, keep as-is for parity. +- Frontend `normalize=none` (parakeet uses per_feature). +- Encoder output is transposed [B,512,T]->[B,T,512] before encoder_proj. + +## Variant Notes + +- `diar_streaming_sortformer_4spk-v2.1`: family baseline (this port). +- `streaming-4spk-v2`: architecturally identical, CC-BY-4.0; add weights once + v2.1 validated (sibling-variant shortcut, Step 1). diff --git a/samples/sortformer-2spk-mix.wav b/samples/sortformer-2spk-mix.wav new file mode 100644 index 00000000..18941047 Binary files /dev/null and b/samples/sortformer-2spk-mix.wav differ diff --git a/scripts/convert-sortformer.py b/scripts/convert-sortformer.py new file mode 100644 index 00000000..3fc2d3a7 --- /dev/null +++ b/scripts/convert-sortformer.py @@ -0,0 +1,316 @@ +#!/usr/bin/env python3 +""" +convert-sortformer.py - convert NVIDIA streaming Sortformer diarizer +(.nemo, NeMo SortformerEncLabelModel) into a reference-dtype GGUF. + +Sortformer is an `encoder-diarizer`: no tokenizer, no decoder, no text. +Pipeline and tensor sources (990 tensors in the .nemo state_dict): + + preprocessor.* -> skipped (C++ recomputes the mel frontend) + encoder.pre_encode.* -> enc.pre_encode.* (dw_striding subsample x8) + encoder.layers.{i}.* -> enc.blocks.{i}.* (17 Conformer/NEST blocks, d=512) + sortformer_modules.encoder_proj.* -> diar.encoder_proj.* (Linear 512 -> 192) + transformer_encoder.layers.{i}.* -> tf.blocks.{i}.* (18 post-LN Transformer blocks, d=192) + sortformer_modules.first_hidden_to_hidden.* -> diar.fc1.* + sortformer_modules.hidden_to_spks.* -> diar.spk_head.* (4 sigmoid outputs) + sortformer_modules.single_hidden_to_spks.* -> diar.single_spk_head.* (single-speaker path) + +The Conformer encoder is the same NeMo ConformerEncoder that Parakeet uses, +so the pre-encode + block tensor tables mirror scripts/convert-parakeet.py +(use_bias=true, conv_norm_type=batch_norm with running stats). + +Reference dtype is F32 (NeMo diarizer state_dict is fp32). + +Usage (via the Sortformer reference env, which has NeMo): + uv run --project scripts/envs/sortformer \ + scripts/convert-sortformer.py nvidia/diar_streaming_sortformer_4spk-v2.1 \ + --repo-id nvidia/diar_streaming_sortformer_4spk-v2.1 +""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +import numpy as np +from gguf import GGMLQuantizationType + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from lib.gguf_common import ( # noqa: E402 + add_general_identity, + canonicalize_normalize, + encode_for_gguf, + gguf_name, + gguf_writer, + reference_dtype_for, + slug_from_repo_id, +) + +REFERENCE_TYPE = GGMLQuantizationType.F32 +REFERENCE_DTYPE_LABEL = "F32" +REFERENCE_FILE_TYPE = 0 # LlamaFileType ALL_F32 + +# --- Conformer encoder tables (same NeMo ConformerEncoder as Parakeet) ------- + +PRE_ENCODE_TABLE = [ + ("encoder.pre_encode.conv.0.weight", "enc.pre_encode.conv.0.weight"), + ("encoder.pre_encode.conv.0.bias", "enc.pre_encode.conv.0.bias"), + ("encoder.pre_encode.conv.2.weight", "enc.pre_encode.conv.2.weight"), + ("encoder.pre_encode.conv.2.bias", "enc.pre_encode.conv.2.bias"), + ("encoder.pre_encode.conv.3.weight", "enc.pre_encode.conv.3.weight"), + ("encoder.pre_encode.conv.3.bias", "enc.pre_encode.conv.3.bias"), + ("encoder.pre_encode.conv.5.weight", "enc.pre_encode.conv.5.weight"), + ("encoder.pre_encode.conv.5.bias", "enc.pre_encode.conv.5.bias"), + ("encoder.pre_encode.conv.6.weight", "enc.pre_encode.conv.6.weight"), + ("encoder.pre_encode.conv.6.bias", "enc.pre_encode.conv.6.bias"), + ("encoder.pre_encode.out.weight", "enc.pre_encode.out.weight"), + ("encoder.pre_encode.out.bias", "enc.pre_encode.out.bias"), +] + +# Per-conformer-block suffix map (source suffix under encoder.layers.{i}. -> +# GGUF suffix under enc.blocks.{i}.). Norms keep the "norm_" prefix and BN +# params keep ".bn." so reference_dtype_for / policy.cpp route them to F32. +CONFORMER_BLOCK_TABLE = [ + ("norm_feed_forward1.weight", "norm_ff1.weight"), + ("norm_feed_forward1.bias", "norm_ff1.bias"), + ("feed_forward1.linear1.weight", "ff1.linear1.weight"), + ("feed_forward1.linear1.bias", "ff1.linear1.bias"), + ("feed_forward1.linear2.weight", "ff1.linear2.weight"), + ("feed_forward1.linear2.bias", "ff1.linear2.bias"), + ("norm_self_att.weight", "norm_attn.weight"), + ("norm_self_att.bias", "norm_attn.bias"), + ("self_attn.linear_q.weight", "attn.linear_q.weight"), + ("self_attn.linear_q.bias", "attn.linear_q.bias"), + ("self_attn.linear_k.weight", "attn.linear_k.weight"), + ("self_attn.linear_k.bias", "attn.linear_k.bias"), + ("self_attn.linear_v.weight", "attn.linear_v.weight"), + ("self_attn.linear_v.bias", "attn.linear_v.bias"), + ("self_attn.linear_out.weight", "attn.linear_out.weight"), + ("self_attn.linear_out.bias", "attn.linear_out.bias"), + ("self_attn.linear_pos.weight", "attn.linear_pos.weight"), + ("self_attn.pos_bias_u", "attn.pos_bias_u"), + ("self_attn.pos_bias_v", "attn.pos_bias_v"), + ("norm_conv.weight", "norm_conv.weight"), + ("norm_conv.bias", "norm_conv.bias"), + ("conv.pointwise_conv1.weight", "conv.pointwise1.weight"), + ("conv.pointwise_conv1.bias", "conv.pointwise1.bias"), + ("conv.depthwise_conv.weight", "conv.depthwise.weight"), + ("conv.depthwise_conv.bias", "conv.depthwise.bias"), + ("conv.batch_norm.weight", "conv.bn.weight"), + ("conv.batch_norm.bias", "conv.bn.bias"), + ("conv.batch_norm.running_mean", "conv.bn.running_mean"), + ("conv.batch_norm.running_var", "conv.bn.running_var"), + ("conv.pointwise_conv2.weight", "conv.pointwise2.weight"), + ("conv.pointwise_conv2.bias", "conv.pointwise2.bias"), + ("norm_feed_forward2.weight", "norm_ff2.weight"), + ("norm_feed_forward2.bias", "norm_ff2.bias"), + ("feed_forward2.linear1.weight", "ff2.linear1.weight"), + ("feed_forward2.linear1.bias", "ff2.linear1.bias"), + ("feed_forward2.linear2.weight", "ff2.linear2.weight"), + ("feed_forward2.linear2.bias", "ff2.linear2.bias"), + ("norm_out.weight", "norm_out.weight"), + ("norm_out.bias", "norm_out.bias"), +] + +# Post-LN Transformer encoder block (NeMo TransformerEncoder, pre_ln=false). +# Norms named norm_1/norm_2 so the "norm_" F32 rule catches them. +TRANSFORMER_BLOCK_TABLE = [ + ("layer_norm_1.weight", "norm_1.weight"), + ("layer_norm_1.bias", "norm_1.bias"), + ("first_sub_layer.query_net.weight", "attn.q.weight"), + ("first_sub_layer.query_net.bias", "attn.q.bias"), + ("first_sub_layer.key_net.weight", "attn.k.weight"), + ("first_sub_layer.key_net.bias", "attn.k.bias"), + ("first_sub_layer.value_net.weight", "attn.v.weight"), + ("first_sub_layer.value_net.bias", "attn.v.bias"), + ("first_sub_layer.out_projection.weight", "attn.out.weight"), + ("first_sub_layer.out_projection.bias", "attn.out.bias"), + ("layer_norm_2.weight", "norm_2.weight"), + ("layer_norm_2.bias", "norm_2.bias"), + ("second_sub_layer.dense_in.weight", "ff.in.weight"), + ("second_sub_layer.dense_in.bias", "ff.in.bias"), + ("second_sub_layer.dense_out.weight", "ff.out.weight"), + ("second_sub_layer.dense_out.bias", "ff.out.bias"), +] + +# Diarization projection + head (sortformer_modules). +HEAD_TABLE = [ + ("sortformer_modules.encoder_proj.weight", "diar.encoder_proj.weight"), + ("sortformer_modules.encoder_proj.bias", "diar.encoder_proj.bias"), + ("sortformer_modules.first_hidden_to_hidden.weight", "diar.fc1.weight"), + ("sortformer_modules.first_hidden_to_hidden.bias", "diar.fc1.bias"), + ("sortformer_modules.hidden_to_spks.weight", "diar.spk_head.weight"), + ("sortformer_modules.hidden_to_spks.bias", "diar.spk_head.bias"), + ("sortformer_modules.single_hidden_to_spks.weight", "diar.single_spk_head.weight"), + ("sortformer_modules.single_hidden_to_spks.bias", "diar.single_spk_head.bias"), +] + +# state_dict keys the loader recomputes / does not need. +EXPECTED_UNUSED_PREFIXES = ("preprocessor.",) +EXPECTED_UNUSED_SUFFIXES = (".num_batches_tracked",) + + +def _to_fp32(t) -> np.ndarray: + import torch + if not isinstance(t, torch.Tensor): + raise TypeError(f"expected torch.Tensor, got {type(t).__name__}") + if t.dtype != torch.float32: + raise ValueError(f"expected fp32 tensor, got {t.dtype} — cast at the source") + return np.ascontiguousarray(t.detach().cpu().numpy()) + + +def _add(writer, name: str, arr: np.ndarray) -> None: + ggml_type = reference_dtype_for(name, REFERENCE_TYPE) + data, out_type = encode_for_gguf(arr, ggml_type) + writer.add_tensor(name, data, raw_dtype=out_type) + + +def convert(model_spec: str, out_path: Path, repo_id: str | None = None) -> None: + from omegaconf import OmegaConf + from nemo.collections.asr.models import SortformerEncLabelModel + + print(f"Output dtype: {REFERENCE_DTYPE_LABEL} (source/reference dtype)") + if model_spec.endswith(".nemo") or Path(model_spec).exists(): + model = SortformerEncLabelModel.restore_from(restore_path=model_spec, map_location="cpu", strict=False) + else: + model = SortformerEncLabelModel.from_pretrained(model_spec, map_location="cpu") + model.eval() + cfg = OmegaConf.to_container(model.cfg, resolve=True) + sd = model.state_dict() + sd_keys = set(sd) + + enc = cfg["encoder"] + tfc = cfg["transformer_encoder"] + pre = cfg["preprocessor"] + n_conf = int(enc["n_layers"]) + n_tf = int(tfc["num_layers"]) + max_spk = int(cfg.get("max_num_of_spks", 4)) + print(f"conformer_layers={n_conf} transformer_layers={n_tf} max_speakers={max_spk}") + + writer = gguf_writer(str(out_path), "sortformer") + + add_general_identity( + writer, + name="Streaming Sortformer Diarizer 4spk v2.1", + basename="sortformer", + size_label="117M", + version="v2.1", + file_type=REFERENCE_FILE_TYPE, + languages=["en"], + author="NVIDIA", + organization="nvidia", + license="other", + license_name="nvidia-open-model-license", + license_link="https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-open-model-license/", + repo_url=f"https://huggingface.co/{repo_id}" if repo_id else None, + description="End-to-end streaming speaker diarizer (encoder-diarizer): NEST/FastConformer + Transformer, 4 sigmoid speaker-activity outputs per 80ms frame.", + ) + + writer.add_string("stt.variant", out_path.parent.name) + + # ----- frontend (C++ recomputes; these are the reference params) ----- + sr = int(pre["sample_rate"]) + writer.add_uint32("stt.frontend.sample_rate", sr) + writer.add_uint32("stt.frontend.num_mels", int(pre["features"])) + writer.add_uint32("stt.frontend.n_fft", int(pre["n_fft"])) + writer.add_uint32("stt.frontend.hop_length", int(round(float(pre["window_stride"]) * sr))) + writer.add_uint32("stt.frontend.win_length", int(round(float(pre["window_size"]) * sr))) + writer.add_string("stt.frontend.window", str(pre.get("window", "hann"))) + writer.add_string("stt.frontend.normalize", canonicalize_normalize(pre.get("normalize"))) + writer.add_float32("stt.frontend.pre_emphasis", float(pre.get("preemph") if pre.get("preemph") is not None else 0.97)) + writer.add_float32("stt.frontend.dither", float(pre.get("dither", 0.0))) + + # ----- capabilities ----- + writer.add_bool("stt.capability.streaming", True) + writer.add_bool("stt.capability.speaker_diarization", True) + writer.add_bool("stt.capability.lang_detect", False) + writer.add_bool("stt.capability.translate", False) + writer.add_bool("stt.capability.timestamps", False) + + # ----- architecture dims ----- + writer.add_uint32("stt.sortformer.max_speakers", max_spk) + writer.add_uint32("stt.sortformer.frame_hop", int(round(float(pre["window_stride"]) * sr)) * int(enc["subsampling_factor"])) + writer.add_uint32("stt.sortformer.encoder.n_layers", n_conf) + writer.add_uint32("stt.sortformer.encoder.d_model", int(enc["d_model"])) + writer.add_uint32("stt.sortformer.encoder.n_heads", int(enc["n_heads"])) + writer.add_uint32("stt.sortformer.encoder.d_ff", int(enc["d_model"]) * int(enc["ff_expansion_factor"])) + writer.add_uint32("stt.sortformer.encoder.conv_kernel", int(enc["conv_kernel_size"])) + writer.add_uint32("stt.sortformer.encoder.subsampling_factor", int(enc["subsampling_factor"])) + writer.add_uint32("stt.sortformer.encoder.subsampling_channels", int(enc["subsampling_conv_channels"])) + writer.add_uint32("stt.sortformer.encoder.feat_in", int(enc["feat_in"])) + writer.add_uint32("stt.sortformer.encoder.pos_emb_max_len", int(enc.get("pos_emb_max_len", 5000))) + writer.add_string("stt.sortformer.encoder.conv_norm_type", str(enc.get("conv_norm_type", "batch_norm"))) + writer.add_uint32("stt.sortformer.transformer.n_layers", n_tf) + writer.add_uint32("stt.sortformer.transformer.d_model", int(tfc["hidden_size"])) + writer.add_uint32("stt.sortformer.transformer.n_heads", int(tfc["num_attention_heads"])) + writer.add_uint32("stt.sortformer.transformer.d_ff", int(tfc["inner_size"])) + writer.add_string("stt.sortformer.transformer.activation", str(tfc.get("hidden_act", "relu"))) + writer.add_bool("stt.sortformer.transformer.pre_ln", bool(tfc.get("pre_ln", False))) + + # ----- shipped streaming defaults (runtime-tunable presets live in the runner) ----- + sm = cfg["sortformer_modules"] + writer.add_uint32("stt.sortformer.stream.chunk_len", int(sm["chunk_len"])) + writer.add_uint32("stt.sortformer.stream.spkcache_len", int(sm["spkcache_len"])) + writer.add_uint32("stt.sortformer.stream.fifo_len", int(sm["fifo_len"])) + writer.add_uint32("stt.sortformer.stream.spkcache_update_period", int(sm["spkcache_update_period"])) + + # ----- tensors ----- + used: set[str] = set() + + def emit(src: str, dst: str): + if src not in sd: + raise KeyError(f"missing expected tensor: {src}") + _add(writer, dst, _to_fp32(sd[src])) + used.add(src) + + for src, dst in PRE_ENCODE_TABLE: + emit(src, dst) + for i in range(n_conf): + for s_suf, d_suf in CONFORMER_BLOCK_TABLE: + emit(f"encoder.layers.{i}.{s_suf}", f"enc.blocks.{i}.{d_suf}") + for i in range(n_tf): + for s_suf, d_suf in TRANSFORMER_BLOCK_TABLE: + emit(f"transformer_encoder.layers.{i}.{s_suf}", f"tf.blocks.{i}.{d_suf}") + for src, dst in HEAD_TABLE: + emit(src, dst) + + # ----- unused-key audit ----- + unexpected = [] + for k in sd_keys - used: + if k.startswith(EXPECTED_UNUSED_PREFIXES) or k.endswith(EXPECTED_UNUSED_SUFFIXES): + continue + unexpected.append(k) + if unexpected: + raise ValueError(f"{len(unexpected)} unmapped state_dict tensors, e.g. {sorted(unexpected)[:8]}") + print(f"Emitted {len(used)} tensors ({len(sd_keys) - len(used)} skipped: preprocessor + BN counters)") + + writer.write_header_to_file() + writer.write_kv_data_to_file() + writer.write_tensors_to_file() + writer.close() + print(f"Wrote GGUF: {out_path} ({out_path.stat().st_size/1e6:.1f} MB)") + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("model", help="HF repo id or path to a .nemo checkpoint") + ap.add_argument("--repo-id", default=None, help="HF repo id (for slug + provenance)") + ap.add_argument("--out", default=None, help="Override output GGUF path") + args = ap.parse_args() + + repo_id = args.repo_id or (args.model if "/" in args.model and not Path(args.model).exists() else None) + if args.out: + out_path = Path(args.out) + else: + if not repo_id: + raise SystemExit("error: pass --repo-id (or a HF repo id) so the output slug can be derived") + slug = slug_from_repo_id(repo_id) + out_path = Path("models") / slug / gguf_name(slug, REFERENCE_DTYPE_LABEL) + out_path.parent.mkdir(parents=True, exist_ok=True) + convert(args.model, out_path, repo_id=repo_id) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/diar/compare_compress_spkcache.py b/scripts/diar/compare_compress_spkcache.py new file mode 100644 index 00000000..711939e2 --- /dev/null +++ b/scripts/diar/compare_compress_spkcache.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +""" +compare_compress_spkcache.py - Verify the Sortformer AOSC `_compress_spkcache` +step bit-for-bit between the NeMo reference and the transcribe.cpp C++ port +(residual-uncertainty #1). + +Both sides run the SAME clip at the SAME streaming preset, so the sequence of +compression calls lines up 1:1. For each call we compare: + + * frame_idx the sorted selected frame indices (C++ `frame_idx` vs NeMo + `_get_topk_indices` -> `topk_indices_sorted`, post-remainder, + disabled entries set to 0). An EXACT match confirms the topk + tie-break hypothesis (ATen CPU topk: value desc, flat-index + asc; -inf picks -> max_index before the ascending sort) on real + drifted scores. + * is_disabled the disabled mask (silence-pad / -inf placeholder frames). + * spkcache_preds the gathered [spkcache_len, n_spk] preds (numeric; small + F32 drift expected, reported as max_abs). + +NeMo dump: `compress.{k:03d}.{topk_indices,is_disabled,spkcache_preds}.npy` + (scripts/dump_reference_sortformer_nemo.py diarize --dump-compress). +C++ dump: `compress.{k:03d}.{frame_idx,is_disabled,spkcache_preds}.{f32,json}` + (TRANSCRIBE_SORTFORMER_COMPRESS_DUMP=1 + TRANSCRIBE_DUMP_DIR). + +Usage: + uv run scripts/diar/compare_compress_spkcache.py \ + --ref-dir build/validate/sortformer/.../compress-ref \ + --cpp-dir build/validate/sortformer/.../compress-cpp +""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + +import numpy as np + + +def _boost_topk(scores: np.ndarray, k: int, scale: float) -> np.ndarray: + """Increase the k highest scores per speaker column. Tie-break: value desc, + frame-index asc (ATen CPU topk). Mirrors _boost_topk_scores.""" + if k <= 0: + return scores + delta = scale * np.log(0.5) # negative -> subtracting boosts + n = scores.shape[0] + for s in range(scores.shape[1]): + col = scores[:, s] + order = np.lexsort((np.arange(n), -col)) # primary value desc, secondary idx asc + col[order[:min(k, n)]] -= delta + return scores + + +def select_indices(preds: np.ndarray, spkcache_len: int, sil_per_spk: int = 3, + pred_thr: float = 0.25, boost_latest: float = 0.05, + strong_rate: float = 0.75, weak_rate: float = 1.5, + min_pos_rate: float = 0.5, max_index: int = 99999): + """Independent numpy reimplementation of the Sortformer AOSC frame selection + (_get_log_pred_scores -> _disable_low_scores -> scores_boost_latest -> + _boost_topk_scores x2 -> silence pad -> _get_topk_indices). Returns + (frame_idx [spkcache_len], is_disabled [spkcache_len]). A third, neutral + arbiter for both the NeMo and C++ dumps.""" + N, n_spk = preds.shape + per_spk = spkcache_len // n_spk - sil_per_spk + import math + strong = math.floor(per_spk * strong_rate) + weak = math.floor(per_spk * weak_rate) + min_pos = math.floor(per_spk * min_pos_rate) + + lp = np.log(np.clip(preds, pred_thr, None)) + l1 = np.log(np.clip(1.0 - preds, pred_thr, None)) + scores = lp - l1 + l1.sum(1, keepdims=True) - math.log(0.5) + + is_speech = preds > 0.5 + scores = np.where(is_speech, scores, -np.inf) + is_pos = scores > 0 + n_pos = is_pos.sum(0, keepdims=True) + scores = np.where((~is_pos) & is_speech & (n_pos >= min_pos), -np.inf, scores) + + if boost_latest > 0: + scores[spkcache_len:, :] += boost_latest # -inf + x stays -inf + + scores = _boost_topk(scores, strong, 2.0) + scores = _boost_topk(scores, weak, 1.0) + + if sil_per_spk > 0: + scores = np.concatenate([scores, np.full((sil_per_spk, n_spk), np.inf)], axis=0) + n_frames = scores.shape[0] + n_frames_no_sil = n_frames - sil_per_spk + + flat = scores.T.reshape(-1) # flat index f = s * n_frames + i + order = np.lexsort((np.arange(flat.size), -flat)) # value desc, flat-idx asc + topk = order[:spkcache_len].copy() + topk = np.where(flat[topk] != -np.inf, topk, max_index) + topk_sorted = np.sort(topk) + is_disabled = topk_sorted == max_index + frame = np.remainder(topk_sorted, n_frames) + is_disabled = is_disabled | (frame >= n_frames_no_sil) + frame = np.where(is_disabled, 0, frame) + return frame.astype(np.int64), is_disabled.astype(bool) + + +def _load_cpp_f32(cpp_dir: Path, stem: str) -> np.ndarray: + """Load a C++ dump_host_f32 artifact (.f32 payload + .json shape).""" + meta = json.loads((cpp_dir / f"{stem}.json").read_text()) + shape = tuple(int(x) for x in meta["shape"]) # slow-to-fast + data = np.fromfile(cpp_dir / f"{stem}.f32", dtype=" int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--ref-dir", required=True, help="NeMo --dump-compress output dir") + ap.add_argument("--cpp-dir", required=True, help="C++ TRANSCRIBE_DUMP_DIR (compress.* artifacts)") + ap.add_argument("--preds-tol", type=float, default=1e-2, + help="Max allowed |Δ| on gathered spkcache_preds (F32 drift).") + ap.add_argument("--spkcache-len", type=int, default=188, + help="spkcache_len for the numpy adjudicator (188 for the shipped presets, " + "24 for `small`). Only used when input_preds dumps are present.") + args = ap.parse_args() + + ref_dir, cpp_dir = Path(args.ref_dir), Path(args.cpp_dir) + ref_calls = sorted(ref_dir.glob("compress.*.topk_indices.npy")) + cpp_calls = sorted(cpp_dir.glob("compress.*.frame_idx.json")) + n_ref, n_cpp = len(ref_calls), len(cpp_calls) + print(f"compression calls: ref={n_ref} cpp={n_cpp}") + if n_ref == 0: + raise SystemExit("error: no reference compression dumps found " + "(did the preset actually trigger AOSC compression?)") + if n_ref != n_cpp: + print(f"MISMATCH: call count differs (ref {n_ref} vs cpp {n_cpp}) -> streaming " + "trajectories diverged before/around compression", file=sys.stderr) + return 1 + + all_idx_ok = True + all_dis_ok = True + max_preds = 0.0 + # Adjudicator bookkeeping: does each side's own dumped selection match an + # independent numpy reimplementation run on that side's own input preds? + ref_self_ok = cpp_self_ok = True + ref_self_seen = cpp_self_seen = False + first_traj_div = None # first call where ref/cpp selections diverge + for k in range(n_ref): + ref_idx = np.load(ref_dir / f"compress.{k:03d}.topk_indices.npy").astype(np.int64) + ref_dis = np.load(ref_dir / f"compress.{k:03d}.is_disabled.npy").astype(bool) + cpp_idx = _load_cpp_f32(cpp_dir, f"compress.{k:03d}.frame_idx").astype(np.int64) + cpp_dis = _load_cpp_f32(cpp_dir, f"compress.{k:03d}.is_disabled").astype(bool) + + # Independent-arbiter check: run the numpy selection on each side's own + # input preds and confirm it reproduces that side's dumped selection. + ref_ipf = ref_dir / f"compress.{k:03d}.input_preds.npy" + cpp_ipf = cpp_dir / f"compress.{k:03d}.input_preds.json" + if ref_ipf.exists(): + ref_self_seen = True + nf, nd = select_indices(np.load(ref_ipf).astype(np.float32), args.spkcache_len) + if int(np.sum(nf != ref_idx)) or int(np.sum(nd != ref_dis)): + ref_self_ok = False + print(f" [{k:03d}] numpy-arbiter != NeMo dump " + f"(idx {int(np.sum(nf != ref_idx))}, dis {int(np.sum(nd != ref_dis))})", file=sys.stderr) + if cpp_ipf.exists(): + cpp_self_seen = True + nf, nd = select_indices(_load_cpp_f32(cpp_dir, f"compress.{k:03d}.input_preds"), args.spkcache_len) + if int(np.sum(nf != cpp_idx)) or int(np.sum(nd != cpp_dis)): + cpp_self_ok = False + print(f" [{k:03d}] numpy-arbiter != C++ dump " + f"(idx {int(np.sum(nf != cpp_idx))}, dis {int(np.sum(nd != cpp_dis))})", file=sys.stderr) + + if ref_idx.shape != cpp_idx.shape: + print(f" [{k:03d}] SHAPE MISMATCH idx ref{ref_idx.shape} cpp{cpp_idx.shape}", file=sys.stderr) + all_idx_ok = False + continue + idx_mism = int(np.sum(ref_idx != cpp_idx)) + dis_mism = int(np.sum(ref_dis != cpp_dis)) + all_idx_ok = all_idx_ok and idx_mism == 0 + all_dis_ok = all_dis_ok and dis_mism == 0 + if idx_mism and first_traj_div is None: + first_traj_div = k + + preds_line = "" + ref_pf = ref_dir / f"compress.{k:03d}.spkcache_preds.npy" + cpp_pf = cpp_dir / f"compress.{k:03d}.spkcache_preds.json" + if ref_pf.exists() and cpp_pf.exists(): + ref_p = np.load(ref_pf).astype(np.float32) + cpp_p = _load_cpp_f32(cpp_dir, f"compress.{k:03d}.spkcache_preds") + if ref_p.shape == cpp_p.shape: + m = float(np.max(np.abs(ref_p - cpp_p))) if ref_p.size else 0.0 + max_preds = max(max_preds, m) + preds_line = f" preds_max_abs {m:.2e}" + else: + preds_line = f" preds SHAPE MISMATCH ref{ref_p.shape} cpp{cpp_p.shape}" + + flag = "OK " if (idx_mism == 0 and dis_mism == 0) else "*** " + print(f" [{k:03d}] {flag}n={ref_idx.shape[0]:4d} idx_mismatch={idx_mism:4d} " + f"dis_mismatch={dis_mism:4d}{preds_line}") + + print() + print("== end-to-end trajectory (each side fed its OWN drifted preds) ==") + print(f"frame_idx : {'MATCH (bit-exact)' if all_idx_ok else 'MISMATCH'}" + + ("" if all_idx_ok else f" (first divergence at call {first_traj_div})")) + print(f"is_disabled : {'MATCH (bit-exact)' if all_dis_ok else 'MISMATCH'}") + print(f"spkcache_preds max_abs: {max_preds:.2e} (tol {args.preds_tol:.1e})") + + # The definitive residual-#1 check: is the compression FUNCTION correct? + # Independent numpy arbiter vs each side's own dump on that side's own input. + print() + print("== compression function (independent numpy arbiter, per-side own input) ==") + if ref_self_seen: + print(f"NeMo selection == numpy arbiter : {'MATCH' if ref_self_ok else 'MISMATCH'}") + if cpp_self_seen: + print(f"C++ selection == numpy arbiter : {'MATCH' if cpp_self_ok else 'MISMATCH'}") + if not (ref_self_seen and cpp_self_seen): + print("(input_preds dumps absent on one/both sides -> function-level arbiter skipped; " + "re-dump with the updated hooks to enable it)") + + # PASS criteria: if input_preds are present, the compression function is + # proven bit-exact against a neutral arbiter on both sides' real inputs + # (trajectory drift is expected and does NOT fail the check). If they are + # absent, fall back to end-to-end bit-exactness. + print() + if ref_self_seen and cpp_self_seen: + ok = ref_self_ok and cpp_self_ok + note = ("compression function bit-exact on both sides vs neutral arbiter" + if ok else "compression function disagrees with arbiter") + if ok and not all_idx_ok: + note += (f"; end-to-end trajectories diverge from call {first_traj_div} " + "purely via upstream F32 preds drift (near-tie topk flips)") + else: + ok = all_idx_ok and all_dis_ok and max_preds <= args.preds_tol + note = "compression internal state matches" if ok else "internal state mismatch" + print("VERDICT:", ("PASS - " + note) if ok else ("FAIL - " + note)) + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/diar/fetch_ami_forced_alignment.py b/scripts/diar/fetch_ami_forced_alignment.py new file mode 100644 index 00000000..5f257e18 --- /dev/null +++ b/scripts/diar/fetch_ami_forced_alignment.py @@ -0,0 +1,73 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.11" +# dependencies = [] +# /// +""" +fetch_ami_forced_alignment.py - fetch NVIDIA's forced-alignment AMI RTTMs and +build a forced-alignment acceptance manifest. + +NVIDIA's published AMI DER uses tight forced-alignment `only_words` RTTMs +(nttcslab-sp/diar-forced-alignment, ASRU 2025), NOT the denser manual +annotations shipped in diarizers-community/ami. Scoring against the manual +RTTMs inflates DER by ~13 pts (missed detection on within-utterance pauses); +scoring against these forced-alignment RTTMs reproduces the published number. + +Reads samples/diar/ami--.manifest.jsonl (from ingest_ami.py), +downloads the matching forced-alignment RTTM per meeting, and writes: + + samples/diar/ami---fa/.rttm + samples/diar/ami---fa.manifest.jsonl (same audio, FA rttm) + +Usage: + uv run scripts/diar/fetch_ami_forced_alignment.py --config ihm --split test +""" + +from __future__ import annotations + +import argparse +import json +import sys +import urllib.request +from pathlib import Path + +REPO = Path(__file__).resolve().parent.parent.parent +RAW = "https://raw.githubusercontent.com/nttcslab-sp/diar-forced-alignment/master/AMI/{split}/{meeting}.rttm" +# nttcslab uses the AMI train/dev/eval split; diarizers-community uses train/validation/test. +SPLIT_MAP = {"test": "test", "validation": "dev", "train": "train"} + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--config", default="ihm", choices=["ihm", "sdm"]) + ap.add_argument("--split", default="test") + args = ap.parse_args() + + ds_id = f"ami-{args.config}-{args.split}" + src_manifest = REPO / "samples" / "diar" / f"{ds_id}.manifest.jsonl" + if not src_manifest.exists(): + print(f"error: {src_manifest} not found; run ingest_ami.py first.", file=sys.stderr) + return 1 + fa_split = SPLIT_MAP[args.split] + fa_dir = REPO / "samples" / "diar" / f"{ds_id}-fa" + fa_dir.mkdir(parents=True, exist_ok=True) + + rows = [json.loads(l) for l in open(src_manifest) if l.strip()] + out = [] + for r in rows: + meeting = r["id"].replace(".Mix-Headset", "").replace(".Array1-01", "") + url = RAW.format(split=fa_split, meeting=meeting) + dst = fa_dir / f"{meeting}.rttm" + urllib.request.urlretrieve(url, dst) + n = sum(1 for l in dst.read_text().splitlines() if l.startswith("SPEAKER")) + out.append({**r, "rttm": str(dst.relative_to(REPO))}) + print(f" {meeting}: {n} forced-alignment turns", flush=True) + + fa_manifest = REPO / "samples" / "diar" / f"{ds_id}-fa.manifest.jsonl" + fa_manifest.write_text("\n".join(json.dumps(o) for o in out) + "\n") + print(f"wrote {fa_manifest.relative_to(REPO)} ({len(out)} meetings)") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/diar/ingest_ami.py b/scripts/diar/ingest_ami.py new file mode 100644 index 00000000..64f12328 --- /dev/null +++ b/scripts/diar/ingest_ami.py @@ -0,0 +1,127 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "datasets>=3.6", +# "numpy>=1.26", +# "soundfile>=0.12", +# ] +# /// +""" +ingest_ami.py - build an AMI diarization manifest from diarizers-community/ami. + +Diarization analog of scripts/wer/ingest.py. Sortformer has no transcript, +so the acceptance corpus needs multi-speaker audio + ground-truth speaker +RTTMs, not reference text. This pulls the AMI corpus from the HF dataset +diarizers-community/ami (ungated), which ships one full meeting per row with +`audio` + parallel `timestamps_start` / `timestamps_end` / `speakers` lists. + +Config `ihm` = mixed-headset audio (NVIDIA's "AMI Test IHM" condition); +`sdm` = single distant mic. + +Output (mirrors the wer/ layout): + samples/diar/ami--/.wav 16-bit PCM mono 16 kHz + samples/diar/ami--/.rttm ground-truth speaker turns + samples/diar/ami--.manifest.jsonl + {"id","audio","rttm","duration","num_speakers"} + +Usage: + uv run scripts/diar/ingest_ami.py --config ihm --split test +""" + +from __future__ import annotations + +import argparse +import io +import json +import sys +from pathlib import Path + +import numpy as np +import soundfile as sf + +SR = 16000 +REPO = Path(__file__).resolve().parent.parent.parent + + +def _uri(path: str) -> str: + # "EN2002b.Mix-Headset.wav" -> "EN2002b.Mix-Headset" + return Path(path).name.rsplit(".wav", 1)[0] + + +def _decode_16k_mono(raw: bytes) -> np.ndarray: + audio, sr = sf.read(io.BytesIO(raw), dtype="float32", always_2d=False) + if audio.ndim > 1: + audio = audio.mean(axis=1) + if sr != SR: + n_out = int(round(len(audio) * SR / sr)) + x_old = np.linspace(0.0, 1.0, num=len(audio), endpoint=False) + x_new = np.linspace(0.0, 1.0, num=n_out, endpoint=False) + audio = np.interp(x_new, x_old, audio).astype(np.float32) + return audio.astype(np.float32) + + +def _write_rttm(path: Path, uri: str, starts, ends, speakers) -> int: + lines = [] + for s, e, spk in zip(starts, ends, speakers): + dur = float(e) - float(s) + if dur <= 0: + continue + lines.append(f"SPEAKER {uri} 1 {float(s):.3f} {dur:.3f} {spk} ") + path.write_text("\n".join(lines) + "\n") + return len(lines) + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--config", default="ihm", choices=["ihm", "sdm"]) + ap.add_argument("--split", default="test") + ap.add_argument("--force", action="store_true") + args = ap.parse_args() + + from datasets import load_dataset, Audio + + ds_id = f"ami-{args.config}-{args.split}" + out_dir = REPO / "samples" / "diar" / ds_id + manifest = REPO / "samples" / "diar" / f"{ds_id}.manifest.jsonl" + out_dir.mkdir(parents=True, exist_ok=True) + if manifest.exists() and not args.force: + n = sum(1 for _ in open(manifest)) + print(f"OK already exists: {manifest} ({n} meetings). Use --force to rebuild.") + return 0 + + print(f"loading diarizers-community/ami [{args.config}/{args.split}] ...", flush=True) + ds = load_dataset("diarizers-community/ami", args.config, split=args.split) + ds = ds.cast_column("audio", Audio(decode=False)) + + entries = [] + total_dur = 0.0 + for i, ex in enumerate(ds): + uri = _uri(ex["audio"]["path"] or f"{ds_id}-{i:03d}") + audio = _decode_16k_mono(ex["audio"]["bytes"]) + wav = out_dir / f"{uri}.wav" + rttm = out_dir / f"{uri}.rttm" + sf.write(str(wav), audio, SR, subtype="PCM_16") + n_turns = _write_rttm(rttm, uri, ex["timestamps_start"], ex["timestamps_end"], ex["speakers"]) + dur = len(audio) / SR + total_dur += dur + n_spk = len(set(ex["speakers"])) + entries.append({ + "id": uri, + "audio": str(wav.relative_to(REPO)), + "rttm": str(rttm.relative_to(REPO)), + "duration": round(dur, 2), + "num_speakers": n_spk, + }) + print(f" [{i}] {uri}: {dur/60:.1f}min, {n_spk} spk, {n_turns} turns", flush=True) + + with open(manifest, "w") as f: + for e in entries: + f.write(json.dumps(e) + "\n") + print(f"\nmanifest: {manifest.relative_to(REPO)}") + print(f"{len(entries)} meetings, {total_dur/60:.1f} min total audio") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_callhome-part1.yaml b/scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_callhome-part1.yaml new file mode 100644 index 00000000..6083004f --- /dev/null +++ b/scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_callhome-part1.yaml @@ -0,0 +1,11 @@ +# Postprocessing parameters for timestamp outputs from speaker diarization models. +# This speaker diarization postprocessing scheme is inspired by the postprocessing procedure in the following paper: +# Medennikov, Ivan, et al. "Target-Speaker Voice Activity Detection: a Novel Approach for Multi-Speaker Diarization in a Dinner Party Scenario." (2020). +# These parameters were optimized on CallHome Dataset from the NIST SRE 2000 Disc8, especially from the part1 (callhome1) specified in: Kaldi, “Kaldi x-vector recipe v2,” https://github.com/kaldi-asr/kaldi/blob/master/egs/callhome_diarization/v2/run.sh +parameters: + onset: 0.641 # Onset threshold for detecting the beginning and end of a speech + offset: 0.561 # Offset threshold for detecting the end of a speech + pad_onset: 0.229 # Adding durations before each speech segment + pad_offset: 0.079 # Adding durations after each speech segment + min_duration_on: 0.511 # Threshold for small non-speech deletion + min_duration_off: 0.296 # Threshold for short speech segment deletion \ No newline at end of file diff --git a/scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml b/scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml new file mode 100644 index 00000000..a9e10471 --- /dev/null +++ b/scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml @@ -0,0 +1,11 @@ +# Postprocessing parameters for timestamp outputs from speaker diarization models. +# This speaker diarization postprocessing scheme is inspired by the postprocessing procedure in the following paper: +# Medennikov, Ivan, et al. "Target-Speaker Voice Activity Detection: a Novel Approach for Multi-Speaker Diarization in a Dinner Party Scenario." (2020). +# These parameters were optimized on the development split of DIHARD3 dataset (See https://arxiv.org/pdf/2012.01477). +parameters: + onset: 0.56 # Onset threshold for detecting the beginning and end of a speech + offset: 1.0 # Offset threshold for detecting the end of a speech + pad_onset: 0.063 # Adding durations before each speech segment + pad_offset: 0.002 # Adding durations after each speech segment + min_duration_on: 0.007 # Threshold for small non-speech deletion + min_duration_off: 0.151 # Threshold for short speech segment deletion \ No newline at end of file diff --git a/scripts/diar/run_cpp_sortformer.py b/scripts/diar/run_cpp_sortformer.py new file mode 100644 index 00000000..0ba36a75 --- /dev/null +++ b/scripts/diar/run_cpp_sortformer.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +""" +run_cpp_sortformer.py - C++ Sortformer diarization over an AMI-style manifest +(the C++ counterpart of run_reference_sortformer_nemo.py). + +For each meeting this runs the transcribe-cli C++ binary with the streaming +operating point selected (TRANSCRIBE_SORTFORMER_STREAM_PRESET) and the tensor +dump enabled (TRANSCRIBE_DUMP_DIR). The dumped raw `diar.probs` [T, n_spk] +sigmoid matrix is then post-processed with NeMo's *own* `ts_vad_post_processing` +(same dihard3 YAML the reference uses) so the timestamp post-processing is +bit-identical to the reference; only the probabilities differ. The resulting +per-speaker segments are written as one predicted RTTM per meeting. + +Score with scripts/diar/score_der.py against the forced-alignment RTTMs, e.g.: + + uv run --project scripts/envs/sortformer \ + scripts/diar/run_cpp_sortformer.py \ + --manifest samples/diar/ami-ihm-test-fa.manifest.jsonl \ + --gguf models/diar_streaming_sortformer_4spk-v2.1/diar_streaming_sortformer_4spk-v2.1-F32.gguf \ + --preset very_high_latency \ + --postprocessing-yaml scripts/diar/postprocessing/diar_streaming_sortformer_4spk-v2_dihard3-dev.yaml \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-cpp-ami-ihm-test \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-CPP.ami-ihm-test.jsonl + + uv run scripts/diar/score_der.py \ + --manifest samples/diar/ami-ihm-test-fa.manifest.jsonl \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-cpp-ami-ihm-test \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-CPP.ami-ihm-test.score.json +""" + +from __future__ import annotations + +import argparse +import json +import os +import subprocess +import sys +import tempfile +import time +from pathlib import Path + +import numpy as np + +# Diar frame = 80 ms = 8 * 10 ms (subsampling_factor). +UNIT_10MS_FRAME_COUNT = 8 + + +def _find_cli(repo: Path, override: str | None) -> Path: + if override: + p = Path(override) + if not p.exists(): + raise SystemExit(f"error: --cli not found: {p}") + return p + for cand in (repo / "build" / "bin" / "transcribe-cli", repo / "build" / "transcribe-cli"): + if cand.exists(): + return cand + raise SystemExit("error: transcribe-cli not found; build it first " + "(cmake --build build --target transcribe-cli)") + + +def _load_probs(dump_dir: Path) -> np.ndarray: + """Load the dumped diar.probs as [T, n_spk] float32.""" + meta = json.loads((dump_dir / "diar.probs.json").read_text()) + shape = tuple(int(x) for x in meta["shape"]) # slow-to-fast, e.g. [T, n_spk] + data = np.fromfile(dump_dir / "diar.probs.f32", dtype=" list[str]: + """Apply NeMo ts_vad_post_processing per speaker and emit RTTM lines.""" + import torch + from nemo.collections.asr.parts.utils.vad_utils import ts_vad_post_processing + + lines: list[str] = [] + n_spk = probs.shape[1] + for spk in range(n_spk): + ts_vad_vec = torch.from_numpy(np.ascontiguousarray(probs[:, spk])) + ts_mat = ts_vad_post_processing( + ts_vad_vec, + cfg_vad_params=cfg_vad, + unit_10ms_frame_count=UNIT_10MS_FRAME_COUNT, + bypass_postprocessing=False, + ) + for stt, end in ts_mat.tolist(): + stt = round(stt + offset, 2) + end = round(end + offset, 2) + dur = end - stt + if dur <= 0: + continue + lines.append(f"SPEAKER {uri} 1 {stt:.3f} {dur:.3f} speaker_{spk} ") + return lines + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--manifest", required=True) + ap.add_argument("--gguf", required=True) + ap.add_argument("--pred-dir", required=True) + ap.add_argument("--out", required=True) + ap.add_argument("--cli", default=None, help="Path to transcribe-cli (default: build/bin/transcribe-cli)") + ap.add_argument("--preset", default="very_high_latency", + help="Streaming operating point (TRANSCRIBE_SORTFORMER_STREAM_PRESET)") + ap.add_argument("--postprocessing-yaml", default=None, + help="dihard3 PP YAML (onset/offset/pad/min_duration); bypass PP if omitted.") + ap.add_argument("--backend", default="cpu") + ap.add_argument("--threads", type=int, default=0, help="0 -> CLI default") + ap.add_argument("--limit", type=int, default=0, help="Run only the first N meetings (smoke).") + args = ap.parse_args() + + from omegaconf import OmegaConf + + repo = Path(__file__).resolve().parent.parent.parent + cli = _find_cli(repo, args.cli) + entries = [json.loads(l) for l in open(args.manifest) if l.strip()] + if args.limit: + entries = entries[:args.limit] + pred_dir = Path(args.pred_dir) + pred_dir.mkdir(parents=True, exist_ok=True) + out_path = Path(args.out) + out_path.parent.mkdir(parents=True, exist_ok=True) + + if args.postprocessing_yaml: + pp = OmegaConf.load(args.postprocessing_yaml) + cfg_vad = pp.parameters if "parameters" in pp else pp + bypass = False + else: + cfg_vad = OmegaConf.create({"onset": 0.5, "offset": 0.5, "pad_onset": 0.0, "pad_offset": 0.0, + "min_duration_on": 0.0, "min_duration_off": 0.0}) + bypass = True + if bypass: + print("warning: no --postprocessing-yaml; using bypass thresholds (not the DER gate config)", flush=True) + + rows = [] + for i, e in enumerate(entries): + wav = str(repo / e["audio"]) if not Path(e["audio"]).is_absolute() else e["audio"] + uri = e["id"] + t0 = time.time() + with tempfile.TemporaryDirectory(prefix="sf-cpp-") as tmp: + env = os.environ.copy() + env["TRANSCRIBE_DUMP_DIR"] = tmp + env["TRANSCRIBE_SORTFORMER_STREAM_PRESET"] = args.preset + cmd = [str(cli), "--backend", args.backend, "-m", str(args.gguf)] + if args.threads > 0: + cmd += ["--threads", str(args.threads)] + cmd.append(wav) + res = subprocess.run(cmd, cwd=repo, env=env, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, text=True, errors="replace") + if res.returncode != 0: + sys.stderr.write(res.stdout or "") + raise SystemExit(f"error: transcribe-cli failed on {uri} (exit {res.returncode})") + probs = _load_probs(Path(tmp)) + lines = _probs_to_rttm(uri, probs, cfg_vad, offset=float(e.get("offset", 0.0))) + (pred_dir / f"{uri}.rttm").write_text("\n".join(lines) + "\n") + dt = time.time() - t0 + rtf = dt / max(e.get("duration", 1.0), 1e-6) + rows.append({"id": uri, "hyp_rttm": str(Path(args.pred_dir) / f"{uri}.rttm"), + "n_segments": len(lines), "n_frames": int(probs.shape[0]), + "duration": e.get("duration"), "compute_sec": round(dt, 2), "rtf": round(rtf, 4)}) + print(f" [{i}] {uri}: {len(lines)} segs, {probs.shape[0]} frames, {dt:.1f}s (rtf {rtf:.3f})", flush=True) + + with open(out_path, "w") as f: + for r in rows: + f.write(json.dumps(r) + "\n") + print(f"wrote {out_path} ({len(rows)} meetings)") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/diar/run_reference_sortformer_nemo.py b/scripts/diar/run_reference_sortformer_nemo.py new file mode 100644 index 00000000..1ec125ef --- /dev/null +++ b/scripts/diar/run_reference_sortformer_nemo.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +""" +run_reference_sortformer_nemo.py - measured Sortformer reference baseline +over a diarization manifest (diarization analog of +scripts/wer/run_reference__*.py). + +Runs NeMo streaming Sortformer over every meeting in an AMI-style manifest +and writes one predicted RTTM per meeting plus a summary JSONL. Score with +scripts/diar/score_der.py. This is the ONE-TIME reference run: Stage 4 and +Stage 7 compare the C++ port's DER/JER against this measured baseline, not +against the publisher's number. + +Streaming presets (frames are 80 ms) from the v2.1 model card: + very_high_latency 30.4s chunk_len=340 rc=40 fifo=40 update=300 spkcache=188 (fastest; card AMI-IHM DER 15.90) + low_latency 1.04s chunk_len=6 rc=7 fifo=188 update=144 spkcache=188 (card AMI-IHM DER 16.67) + +Run through the Sortformer reference env: + uv run --project scripts/envs/sortformer \ + scripts/diar/run_reference_sortformer_nemo.py \ + --manifest samples/diar/ami-ihm-test.manifest.jsonl \ + --model nvidia/diar_streaming_sortformer_4spk-v2.1 \ + --preset very_high_latency \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-ami-ihm-test \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-REF.ami-ihm-test.jsonl +""" + +from __future__ import annotations + +import argparse +import json +import sys +import time +from pathlib import Path + +PRESETS = { + "very_high_latency": dict(chunk_len=340, chunk_right_context=40, fifo_len=40, + spkcache_update_period=300, spkcache_len=188), + "high_latency": dict(chunk_len=124, chunk_right_context=1, fifo_len=124, + spkcache_update_period=124, spkcache_len=188), + "low_latency": dict(chunk_len=6, chunk_right_context=7, fifo_len=188, + spkcache_update_period=144, spkcache_len=188), +} + + +def _apply_preset(m, preset: str) -> dict: + cfg = PRESETS[preset] + sm = m.sortformer_modules + sm.chunk_len = cfg["chunk_len"] + sm.chunk_right_context = cfg["chunk_right_context"] + sm.fifo_len = cfg["fifo_len"] + sm.spkcache_update_period = cfg["spkcache_update_period"] + sm.spkcache_len = cfg["spkcache_len"] + if hasattr(sm, "_check_streaming_parameters"): + sm._check_streaming_parameters() + return cfg + + +def _seg_to_rttm(uri: str, segments) -> list[str]: + """NeMo diarize segments str() as 'start end speaker_k'.""" + lines = [] + for s in segments: + parts = str(s).strip().split() + if len(parts) < 3: + continue + start, end, spk = float(parts[0]), float(parts[1]), parts[2] + dur = end - start + if dur <= 0: + continue + lines.append(f"SPEAKER {uri} 1 {start:.3f} {dur:.3f} {spk} ") + return lines + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--manifest", required=True) + ap.add_argument("--model", required=True) + ap.add_argument("--preset", default="very_high_latency", choices=list(PRESETS)) + ap.add_argument("--pred-dir", required=True) + ap.add_argument("--out", required=True) + ap.add_argument("--device", default="cpu") + ap.add_argument("--postprocessing-yaml", default=None, + help="Optional NeMo diarization post-processing YAML (onset/offset/pad/min_duration).") + ap.add_argument("--limit", type=int, default=0, help="Run only the first N meetings (smoke).") + args = ap.parse_args() + + import torch + from nemo.collections.asr.models import SortformerEncLabelModel + + repo = Path(__file__).resolve().parent.parent.parent + entries = [json.loads(l) for l in open(args.manifest) if l.strip()] + if args.limit: + entries = entries[:args.limit] + pred_dir = Path(args.pred_dir) + pred_dir.mkdir(parents=True, exist_ok=True) + out_path = Path(args.out) + out_path.parent.mkdir(parents=True, exist_ok=True) + + m = SortformerEncLabelModel.from_pretrained(args.model, map_location=args.device) + m.eval() + cfg = _apply_preset(m, args.preset) + print(f"preset={args.preset} {cfg}", flush=True) + + rows = [] + for i, e in enumerate(entries): + wav = str(repo / e["audio"]) if not Path(e["audio"]).is_absolute() else e["audio"] + uri = e["id"] + t0 = time.time() + kw = {} + if args.postprocessing_yaml: + kw["postprocessing_yaml"] = args.postprocessing_yaml + segs = m.diarize(audio=[wav], batch_size=1, **kw) + dt = time.time() - t0 + seglist = segs[0] if segs else [] + lines = _seg_to_rttm(uri, seglist) + (pred_dir / f"{uri}.rttm").write_text("\n".join(lines) + "\n") + rtf = dt / max(e.get("duration", 1.0), 1e-6) + rows.append({"id": uri, "hyp_rttm": str(Path(args.pred_dir) / f"{uri}.rttm"), + "n_segments": len(lines), "duration": e.get("duration"), + "compute_sec": round(dt, 2), "rtf": round(rtf, 4)}) + print(f" [{i}] {uri}: {len(lines)} segs, {dt:.1f}s (rtf {rtf:.3f})", flush=True) + + with open(out_path, "w") as f: + for r in rows: + f.write(json.dumps(r) + "\n") + print(f"wrote {out_path} ({len(rows)} meetings)") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/diar/score_der.py b/scripts/diar/score_der.py new file mode 100644 index 00000000..43208438 --- /dev/null +++ b/scripts/diar/score_der.py @@ -0,0 +1,130 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "pyannote.metrics>=3.2", +# ] +# /// +""" +score_der.py - Diarization Error Rate + Jaccard Error Rate scorer. + +Diarization analog of scripts/wer/score.py. Compares predicted speaker +RTTMs (from scripts/diar/run_reference_sortformer_nemo.py, or later the C++ +port) against the ground-truth RTTMs named in an AMI-style manifest. + +DER and JER are computed with pyannote.metrics. Collar and overlap handling +mirror NVIDIA's AMI protocol: collar 0.0s, overlap INCLUDED (skip_overlap +False). The aggregate is pyannote's speech-time-weighted global figure, not +a mean of per-meeting rates. + +Writes .score.json: + {metric:"der", collar, skip_overlap, der, jer, der_pct, jer_pct, + n_meetings, total_speech_sec, missed_pct, false_alarm_pct, + confusion_pct, per_meeting:[{id, der, jer, ...}]} + +Usage: + uv run scripts/diar/score_der.py \ + --manifest samples/diar/ami-ihm-test.manifest.jsonl \ + --pred-dir reports/diar/pred/diar_streaming_sortformer_4spk-v2.1-ami-ihm-test \ + --out reports/diar/diar_streaming_sortformer_4spk-v2.1-REF.ami-ihm-test.score.json +""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + +from pyannote.core import Annotation, Segment +from pyannote.metrics.diarization import DiarizationErrorRate, JaccardErrorRate + + +def load_rttm(path: Path, uri: str) -> Annotation: + ann = Annotation(uri=uri) + if not path.exists(): + return ann + for line in path.read_text().splitlines(): + p = line.split() + if len(p) < 8 or p[0] != "SPEAKER": + continue + start, dur, spk = float(p[3]), float(p[4]), p[7] + if dur <= 0: + continue + ann[Segment(start, start + dur)] = spk + return ann + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--manifest", required=True) + ap.add_argument("--pred-dir", required=True) + ap.add_argument("--out", required=True) + ap.add_argument("--collar", type=float, default=0.0) + ap.add_argument("--skip-overlap", action="store_true", + help="Exclude overlapped regions from scoring (default: include, matching NVIDIA AMI).") + args = ap.parse_args() + + repo = Path(__file__).resolve().parent.parent.parent + pred_dir = Path(args.pred_dir) + entries = [json.loads(l) for l in open(args.manifest) if l.strip()] + + der = DiarizationErrorRate(collar=args.collar, skip_overlap=args.skip_overlap) + jer = JaccardErrorRate(collar=args.collar, skip_overlap=args.skip_overlap) + + per_meeting = [] + for e in entries: + uri = e["id"] + ref = load_rttm(repo / e["rttm"], uri) + hyp = load_rttm(pred_dir / f"{uri}.rttm", uri) + comp = der(ref, hyp, detailed=True) + d_i = comp["diarization error rate"] + j_i = jer(ref, hyp) + per_meeting.append({ + "id": uri, + "der": round(d_i, 5), + "jer": round(j_i, 5), + "missed": round(comp["missed detection"], 3), + "false_alarm": round(comp["false alarm"], 3), + "confusion": round(comp["confusion"], 3), + "total": round(comp["total"], 3), + "num_speakers": e.get("num_speakers"), + }) + print(f" {uri}: DER {d_i*100:.2f}% JER {j_i*100:.2f}%", flush=True) + + # Global (speech-time-weighted) aggregates. + agg_der = abs(der) + agg_jer = abs(jer) + comp = der[:] # accumulated components + total = sum(pm["total"] for pm in per_meeting) + missed = sum(pm["missed"] for pm in per_meeting) + fa = sum(pm["false_alarm"] for pm in per_meeting) + conf = sum(pm["confusion"] for pm in per_meeting) + + out = { + "metric": "der", + "collar": args.collar, + "skip_overlap": bool(args.skip_overlap), + "der": round(agg_der, 5), + "jer": round(agg_jer, 5), + "der_pct": round(agg_der * 100, 2), + "jer_pct": round(agg_jer * 100, 2), + "n_meetings": len(per_meeting), + "total_speech_sec": round(total, 2), + "missed_pct": round(missed / total * 100, 2) if total else None, + "false_alarm_pct": round(fa / total * 100, 2) if total else None, + "confusion_pct": round(conf / total * 100, 2) if total else None, + "per_meeting": per_meeting, + } + out_path = Path(args.out) + out_path.parent.mkdir(parents=True, exist_ok=True) + out_path.write_text(json.dumps(out, indent=2) + "\n") + print(f"\nAGGREGATE DER {out['der_pct']}% JER {out['jer_pct']}% " + f"(missed {out['missed_pct']}%, FA {out['false_alarm_pct']}%, conf {out['confusion_pct']}%) " + f"over {out['n_meetings']} meetings") + print(f"wrote {out_path}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/dump_reference_sortformer_nemo.py b/scripts/dump_reference_sortformer_nemo.py new file mode 100644 index 00000000..9233c5af --- /dev/null +++ b/scripts/dump_reference_sortformer_nemo.py @@ -0,0 +1,299 @@ +#!/usr/bin/env python3 +""" +dump_reference_sortformer_nemo.py - Sortformer streaming diarizer reference +tensors from NVIDIA NeMo (the canonical reference). + +Sortformer is a frame-level end-to-end neural diarizer (arch pattern +`encoder-diarizer`), NOT a transcription model. There is no tokenizer and +no text output: the reference "behavioral artifact" is the T x 4 speaker +activity probability matrix plus the derived speaker segments. + +Pipeline (offline / full-context forward): + preprocessor (mel, 128 x T_mel) + -> encoder ConformerEncoder / NEST-FastConformer, d=512, x8 subsample + -> encoder_proj Linear 512 -> 192 (sortformer_modules.encoder_proj) + -> transformer_encoder 18L Transformer, d=192 + -> hidden_to_spks -> sigmoid -> preds [T, 4] + +Two reference paths are dumped: + * `encoder` runs the offline m.forward() with hooks and dumps the mel and + the per-stage encoder activations plus the offline preds. This + is the non-stateful reference the C++ encoder must match first. + * `diarize` runs the streaming m.diarize() (the runtime target) and dumps + the T x 4 probability matrix + the speaker segments. + +For short clips (T frames < chunk_len, e.g. the 12s oracle mix = 150 frames +< 188) the streaming path is a single chunk, so offline preds ~= streaming +probs; longer audio exercises the AOSC/FIFO speaker cache and the two will +diverge. + +Tensor output uses the shared contract via scripts.lib.ref_dump +(write_tensor records rms / p99_abs for Stage 6 magnitude-aware tolerances). + + uv run --project scripts/envs/sortformer \ + scripts/dump_reference_sortformer_nemo.py encoder \ + --model nvidia/diar_streaming_sortformer_4spk-v2.1 \ + --audio samples/sortformer-2spk-mix.wav \ + --out build/validate/sortformer/diar_streaming_sortformer_4spk-v2.1/sortformer-2spk-mix/encoder/ref + + uv run --project scripts/envs/sortformer \ + scripts/dump_reference_sortformer_nemo.py diarize \ + --model nvidia/diar_streaming_sortformer_4spk-v2.1 \ + --audio samples/sortformer-2spk-mix.wav \ + --out build/validate/sortformer/diar_streaming_sortformer_4spk-v2.1/sortformer-2spk-mix/diarize/ref +""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path +from typing import Any + +import numpy as np +import soundfile as sf +import torch + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from lib import ref_dump # noqa: E402 + +write_tensor = ref_dump.write_tensor +write_transcript = ref_dump.write_transcript + + +def _load(model: str): + from nemo.collections.asr.models import SortformerEncLabelModel + + if model.endswith(".nemo") or Path(model).exists(): + m = SortformerEncLabelModel.restore_from(restore_path=model, map_location="cpu", strict=False) + else: + m = SortformerEncLabelModel.from_pretrained(model, map_location="cpu") + m.eval() + return m + + +def _read_audio(path: str) -> tuple[np.ndarray, int]: + audio, sr = sf.read(path, dtype="float32", always_2d=False) + if audio.ndim > 1: + audio = audio.mean(axis=1) + return audio.astype(np.float32), int(sr) + + +def _to_2d_time_major(a: np.ndarray) -> np.ndarray: + """Squeeze batch and return [T, D]. ConformerEncoder emits [B, D, T]; + the transformer path emits [B, T, D]. Detect by which axis is the + known speaker/model dim is impossible generically, so we squeeze batch + and, when the first (non-batch) axis looks like a channel dim (512/192) + and the second is longer, transpose to time-major.""" + a = np.asarray(a, dtype=np.float32) + if a.ndim == 3 and a.shape[0] == 1: + a = a[0] + if a.ndim == 2 and a.shape[0] in (192, 512) and a.shape[1] != a.shape[0]: + a = a.T # [D, T] -> [T, D] + return np.ascontiguousarray(a.astype(np.float32)) + + +def _src(model: str, hook: str) -> dict[str, Any]: + return {"framework": "nemo", "model": model, "hook": hook} + + +def cmd_encoder(args: argparse.Namespace) -> int: + m = _load(args.model) + audio, sr = _read_audio(args.audio) + out_dir = Path(args.out) + sig = torch.tensor(audio).unsqueeze(0) + length = torch.tensor([audio.shape[0]]) + + # Mel (frontend) — dump native NeMo layout [n_mels, T_mel]. + with torch.no_grad(): + mel, mel_len = m.preprocessor(input_signal=sig, length=length) + write_tensor("enc.mel.in", np.ascontiguousarray(mel[0].numpy().astype(np.float32)), + "frontend", _src(args.model, "preprocessor.out"), out_dir=out_dir) + + captured: dict[str, torch.Tensor] = {} + + def grab(name): + def hook(_mod, _inp, out): + t = out[0] if isinstance(out, (tuple, list)) else out + captured[name] = t.detach().to(torch.float32).cpu() + return hook + + handles = [ + m.encoder.register_forward_hook(grab("fastconformer")), + m.sortformer_modules.encoder_proj.register_forward_hook(grab("encoder_proj")), + m.transformer_encoder.register_forward_hook(grab("transformer")), + ] + try: + with torch.no_grad(): + preds = m.forward(audio_signal=sig, audio_signal_length=length) + finally: + for h in handles: + h.remove() + + if isinstance(preds, (tuple, list)): + preds = preds[0] + write_tensor("enc.fastconformer.out", _to_2d_time_major(captured["fastconformer"].numpy()), + "encoder", _src(args.model, "encoder.out"), out_dir=out_dir) + write_tensor("enc.encoder_proj.out", _to_2d_time_major(captured["encoder_proj"].numpy()), + "encoder", _src(args.model, "encoder_proj.out"), out_dir=out_dir) + write_tensor("enc.transformer.out", _to_2d_time_major(captured["transformer"].numpy()), + "encoder", _src(args.model, "transformer_encoder.out"), out_dir=out_dir) + write_tensor("diar.preds_offline", _to_2d_time_major(preds.detach().numpy()), + "encoder", _src(args.model, "forward.preds(offline,full-context)"), out_dir=out_dir) + print(f"wrote encoder-stage tensors to {out_dir}") + return 0 + + +# Streaming presets (frames are 80 ms). Mirror scripts/diar/run_reference_ +# sortformer_nemo.py PRESETS plus a `small` preset that forces multi-chunk + +# AOSC compression on the short oracle clip (diar.probs parity). Keep in sync +# with the C++ preset table in src/arch/sortformer/stream.cpp. +_PRESETS = { + "very_high_latency": dict(chunk_len=340, chunk_right_context=40, fifo_len=40, + spkcache_update_period=300, spkcache_len=188), + "high_latency": dict(chunk_len=124, chunk_right_context=1, fifo_len=124, + spkcache_update_period=124, spkcache_len=188), + "low_latency": dict(chunk_len=6, chunk_right_context=7, fifo_len=188, + spkcache_update_period=144, spkcache_len=188), + "small": dict(chunk_len=20, chunk_right_context=1, fifo_len=10, + spkcache_update_period=20, spkcache_len=24), +} + + +def _apply_preset(m, preset: str) -> None: + cfg = _PRESETS[preset] + sm = m.sortformer_modules + sm.chunk_len = cfg["chunk_len"] + sm.chunk_right_context = cfg["chunk_right_context"] + sm.fifo_len = cfg["fifo_len"] + sm.spkcache_update_period = cfg["spkcache_update_period"] + sm.spkcache_len = cfg["spkcache_len"] + if hasattr(sm, "_check_streaming_parameters"): + sm._check_streaming_parameters() + + +def _install_compress_hooks(m) -> list[dict]: + """Wrap sortformer_modules._compress_spkcache / _get_topk_indices to record, + per compression call, the selected (sorted) frame indices, the is_disabled + mask, and the gathered spkcache_preds. batch=1 in the CLI path, so squeeze + the batch dim. Returns the list the hooks append to (one dict per call).""" + sm = m.sortformer_modules + calls: list[dict] = [] + orig_topk = sm._get_topk_indices + orig_compress = sm._compress_spkcache + + def wrapped_topk(scores): + topk_indices, is_disabled = orig_topk(scores) + calls.append({ + "n_frames": int(scores.shape[1]), + "topk_indices": topk_indices[0].detach().cpu().numpy().astype(np.int64), + "is_disabled": is_disabled[0].detach().cpu().numpy().astype(bool), + }) + return topk_indices, is_disabled + + def wrapped_compress(*a, **kw): + # input preds ([1, n_frames, n_spk]) drive the whole selection; capture + # them (positionally emb_seq, preds, mean_sil_emb, ... or by kw). + in_preds = kw["preds"] if "preds" in kw else a[1] + in_preds = in_preds[0].detach().cpu().numpy().astype(np.float32) + spkcache, spkcache_preds, spk_perm = orig_compress(*a, **kw) + if calls: # the just-appended call from wrapped_topk + calls[-1]["input_preds"] = in_preds + calls[-1]["spkcache_preds"] = spkcache_preds[0].detach().cpu().numpy().astype(np.float32) + return spkcache, spkcache_preds, spk_perm + + sm._get_topk_indices = wrapped_topk + sm._compress_spkcache = wrapped_compress + return calls + + +def _write_compress_dump(calls: list[dict], dump_dir: Path) -> None: + dump_dir.mkdir(parents=True, exist_ok=True) + for k, c in enumerate(calls): + np.save(dump_dir / f"compress.{k:03d}.topk_indices.npy", c["topk_indices"]) + np.save(dump_dir / f"compress.{k:03d}.is_disabled.npy", c["is_disabled"]) + if "spkcache_preds" in c: + np.save(dump_dir / f"compress.{k:03d}.spkcache_preds.npy", c["spkcache_preds"]) + if "input_preds" in c: + np.save(dump_dir / f"compress.{k:03d}.input_preds.npy", c["input_preds"]) + summary = {"n_calls": len(calls), "n_frames_in": [c["n_frames"] for c in calls]} + (dump_dir / "compress.summary.json").write_text(_json_dumps(summary)) + print(f"wrote {len(calls)} _compress_spkcache dumps to {dump_dir}") + + +def _json_dumps(obj) -> str: + import json + return json.dumps(obj, indent=2) + + +def cmd_diarize(args: argparse.Namespace) -> int: + m = _load(args.model) + audio, sr = _read_audio(args.audio) + out_dir = Path(args.out) + + if getattr(args, "preset", None): + _apply_preset(m, args.preset) + print(f"diarize preset={args.preset} {_PRESETS[args.preset]}", flush=True) + + compress_calls = _install_compress_hooks(m) if getattr(args, "dump_compress", None) else None + + segs, probs = m.diarize(audio=[audio], batch_size=1, sample_rate=sr, + include_tensor_outputs=True) + + if compress_calls is not None: + _write_compress_dump(compress_calls, Path(args.dump_compress)) + p = np.asarray(probs[0], dtype=np.float32) + if p.ndim == 3 and p.shape[0] == 1: + p = p[0] + p = np.ascontiguousarray(p.astype(np.float32)) # [T, 4] + write_tensor("diar.probs", p, "diarize", + {**_src(args.model, "diarize.probs(streaming)"), + "streaming_cfg": { + "chunk_len": int(m.sortformer_modules.chunk_len), + "fifo_len": int(m.sortformer_modules.fifo_len), + "spkcache_len": int(m.sortformer_modules.spkcache_len), + "spkcache_update_period": int(m.sortformer_modules.spkcache_update_period), + "chunk_right_context": int(getattr(m.sortformer_modules, "chunk_right_context", 0)), + }}, + out_dir=out_dir) + + # Behavioral artifact: speaker segments, as RTTM-like text (no transcript + # exists for a diarizer). "start end speaker" per line, emission order. + seg_lines = [str(s).strip() for s in segs[0]] + write_transcript(out_dir, "\n".join(seg_lines), + source=_src(args.model, "diarize.segments(streaming)")) + print(f"wrote diarize probs [{p.shape[0]}x{p.shape[1]}] + {len(seg_lines)} segments to {out_dir}") + return 0 + + +def add_common_args(p: argparse.ArgumentParser) -> None: + p.add_argument("--model", required=True, help="HF repo id or path to a .nemo checkpoint") + p.add_argument("--audio", required=True, help="Path to a 16 kHz mono WAV") + p.add_argument("--out", required=True, help="Output ref/ directory") + # Accepted for the validate.py harness contract; a diarizer takes no + # language, and torch threading does not affect the dumped tensors. + p.add_argument("--torch-threads", type=int, default=None, help=argparse.SUPPRESS) + p.add_argument("--language", default=None, help=argparse.SUPPRESS) + + +def main() -> int: + p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + sub = p.add_subparsers(dest="cmd", required=True) + ep = sub.add_parser("encoder", help="Dump mel + encoder-stage activations (offline forward)") + add_common_args(ep) + ep.set_defaults(func=cmd_encoder) + dp = sub.add_parser("diarize", help="Dump streaming T x 4 probs + speaker segments") + add_common_args(dp) + dp.add_argument("--preset", default=None, choices=list(_PRESETS), + help="Streaming operating point (default: checkpoint cfg). Must match the C++ " + "TRANSCRIBE_SORTFORMER_STREAM_PRESET for parity.") + dp.add_argument("--dump-compress", default=None, + help="Directory to write per-_compress_spkcache selected frame indices + preds " + "(residual-uncertainty #1: compression internal-state parity vs C++).") + dp.set_defaults(func=cmd_diarize) + args = p.parse_args() + return args.func(args) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/envs/sortformer/pyproject.toml b/scripts/envs/sortformer/pyproject.toml new file mode 100644 index 00000000..0e402747 --- /dev/null +++ b/scripts/envs/sortformer/pyproject.toml @@ -0,0 +1,27 @@ +[project] +name = "transcribe-sortformer-env" +version = "0.1.0" +description = "Python env for Sortformer streaming diarizer reference dumps via NeMo (SortformerEncLabelModel)" +requires-python = ">=3.11,<3.13" +dependencies = [ + "torch>=2.2", + # Same NeMo pin as scripts/envs/parakeet: commit 6967f48fda2a already + # ships streaming Sortformer (sortformer_modules with spkcache/AOSC/FIFO + # and SortformerEncLabelModel.diarize(include_tensor_outputs=...)). + "nemo-toolkit[asr] @ git+https://github.com/NVIDIA-NeMo/NeMo.git@6967f48fda2a", + "huggingface-hub>=0.20", + "soundfile>=0.12", + "numpy>=1.26", + "sentencepiece>=0.2", + "gguf>=0.10.0", +] + +# NeMo main maps torch by platform: darwin->pypi (CPU), linux->cu129, +# windows->cpu. Restrict to the two we actually run on (laptop dumps +# on darwin, Modal sweeps on linux/cuda) so the resolver picks one +# torch source per split and the cpu/cu129 indexes do not collide. +[tool.uv] +environments = [ + "sys_platform == 'darwin'", + "sys_platform == 'linux'", +] diff --git a/scripts/envs/sortformer/uv.lock b/scripts/envs/sortformer/uv.lock new file mode 100644 index 00000000..80608bd5 --- /dev/null +++ b/scripts/envs/sortformer/uv.lock @@ -0,0 +1,3187 @@ +version = 1 +revision = 3 +requires-python = ">=3.11, <3.13" +resolution-markers = [ + "python_full_version >= '3.12' and sys_platform == 'darwin'", + "python_full_version < '3.12' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and sys_platform == 'linux'", + "python_full_version < '3.12' and sys_platform == 'linux'", +] +supported-markers = [ + "sys_platform == 'darwin'", + "sys_platform == 'linux'", +] + +[[package]] +name = "absl-py" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/4f/d79676ab82f2e42fc3611618139f13a9c4c31d0cff4b486982047679a802/absl_py-2.5.0.tar.gz", hash = "sha256:0c996f25c0490700fadabe6351630f6111534fa0ae252cc6d2014ea3b141135f", size = 118119, upload-time = "2026-07-03T10:57:48.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/0a/a10b45aab35b175aded078a462dc8d0c698f5b13946e7cb0869097b78bb6/absl_py-2.5.0-py3-none-any.whl", hash = "sha256:0f17b89f2a4eaaedc4f28c622998aa690564b3012a396a4ffad0821007fe03ba", size = 137410, upload-time = "2026-07-03T10:57:46.735Z" }, +] + +[[package]] +name = "accelerate" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "psutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "safetensors", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8d/75/94cd5d389649578aca399e5aa822637eec18319a1dadc400ffe2f9a7493f/accelerate-1.14.0.tar.gz", hash = "sha256:41b9c4377a54e0b460a959b0defa1b736e4ca0a2373252d9a539964c2afe3c8d", size = 412167, upload-time = "2026-06-11T13:45:52.326Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/db/253133d7e7cb40d3af384bb2f5c0b4a2b7fdcffbc95c688cc67a20a3c103/accelerate-1.14.0-py3-none-any.whl", hash = "sha256:e94390c2863b873be18f623f9df48a0d8fe5eff13ea7f1a00092b0a7904888c6", size = 389246, upload-time = "2026-06-11T13:45:50.477Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/f4/eec0465c2f67b2664688d0240b3212d5196fd89e741df67ddb81f8d35658/aiohappyeyeballs-2.7.1.tar.gz", hash = "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d", size = 24757, upload-time = "2026-07-01T17:11:55.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/43/1947f06babed6b3f1d7f38b0c767f52df66bfb2bc10b468c4a7de9eceff2/aiohappyeyeballs-2.7.1-py3-none-any.whl", hash = "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472", size = 15038, upload-time = "2026-07-01T17:11:54.055Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "aiosignal", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "attrs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "frozenlist", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "multidict", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "propcache", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "yarl", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/dd/bf526e6f0a1120dd6f2df2e97bacfe4d358f13d17a0ff5847301a1375a51/aiohttp-3.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa00140699487bd435fde4342d85c94cb256b7cd3a5b9c3396c67f19922afda2", size = 765225, upload-time = "2026-06-07T21:06:07.957Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e1/a2872aa55495a70f61310d411541c6ee23812d9a884e000c716e1bc3edbf/aiohttp-3.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c1af67559445498b502030c35c59db59966f47041ca9de5b4e707f86bd10b5f", size = 518743, upload-time = "2026-06-07T21:06:09.749Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e7/c60c7b209e509cc787de3cea0550a518538cfc08003e1c1e14c1c63fff71/aiohttp-3.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d44ec478e713ee7f29b439f7eb8dc2b9d4079e11ae114d2c2ac3d5daf30516c8", size = 514139, upload-time = "2026-06-07T21:06:11.26Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8d/614ace2f579702c9840ab1e1447fd8509e35b0b904f7196418fa2f57b25d/aiohttp-3.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3b1a184a9a8f548a6b73f1e26b96b052193e4b3175ed7342aaf1151a1f00a04", size = 1784088, upload-time = "2026-06-07T21:06:12.887Z" }, + { url = "https://files.pythonhosted.org/packages/49/e0/726e90f99542bf292f81a96a12cc4847deb86f3ccf62c6f4014a201f4d33/aiohttp-3.14.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5f2504bc0322437c9a1ff6d3333ca56c7477b727c995f036b976ae17b98372c8", size = 1737835, upload-time = "2026-06-07T21:06:14.564Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4b/d176d5c4db9d33dacf0543102ea59503bc1d528af4cfd0b719949ca49389/aiohttp-3.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73f05ea02013e02512c3bf42714f1208c57168c779cc6fe23516e4543089d0a6", size = 1842801, upload-time = "2026-06-07T21:06:16.228Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d6/5a99b563690ea0cbed912ae94a2ce33993a5709a651a3a4fe761e7dd973a/aiohttp-3.14.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:797457503c2d426bee06eef808d07b31ede30b65e054444e7de64cad0061b7af", size = 1929992, upload-time = "2026-06-07T21:06:17.947Z" }, + { url = "https://files.pythonhosted.org/packages/76/7f/a987b14a3859094b3cea3f4825219c3e5536242564af6e3f9c2f6c994eb2/aiohttp-3.14.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b821a1f7dedf7e37450654e620038ac3b2e81e8fa6ea269337e97101978ec730", size = 1786989, upload-time = "2026-06-07T21:06:19.677Z" }, + { url = "https://files.pythonhosted.org/packages/f1/1a/420e5c85a3e73349372ed22ce0b6af86bfa6ce16a4b20a64a2e94608c781/aiohttp-3.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4cd96b5ba05d67ed0cf00b5b405c8cd99586d8e3481e8ee0a831057591af7621", size = 1640129, upload-time = "2026-06-07T21:06:22.558Z" }, + { url = "https://files.pythonhosted.org/packages/a7/80/18a592ed3be0a402cc03670bd72ee1f8563ddbe1d8d5542dbf868f274136/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d459b98a932296c6f0e94f87511a0b1b90a8a02c30a50e60a297619cd5a58ee", size = 1756576, upload-time = "2026-06-07T21:06:24.8Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0b/8b3d5713373858ff71a617daf6e3b0e81ad63e79d09a3cf2f6b6b983939c/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:764457a7be60825fb770a644852ff717bcbb5042f189f2bd16df61a81b3f6573", size = 1754668, upload-time = "2026-06-07T21:06:26.528Z" }, + { url = "https://files.pythonhosted.org/packages/9f/49/fd564575cf225821d7ba5a117cb8bc27213d8a7e1811162afb43ae077039/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f7a16ef45b081454ef844502d87a848876c490c4cb5c650c230f6ec79ed2c1e7", size = 1817019, upload-time = "2026-06-07T21:06:28.297Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1b/e850c9ae6fc91356552ae668bb6c51e93fa29c8aef13398a10b56678557f/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2fbc3ed048b3475b9f0cbcb9978e9d2d3511acd91ead203af26ed9f0056004cf", size = 1631638, upload-time = "2026-06-07T21:06:30.242Z" }, + { url = "https://files.pythonhosted.org/packages/eb/94/3c337ba72451a89806ace6f75bddc92bafc5b8d53d90115a512858024b63/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bedb0cd073cc2dc035e30aeb99444389d3cd2113afe4ef9fcd23d439f5bade85", size = 1835660, upload-time = "2026-06-07T21:06:31.943Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9c/9c18cf367a0498212d9ba7daf990b504a5e8ae064cda4b504e2647c89c03/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b6feea921016eb3d4e04d65fc4e9ca402d1a3801f562aef94989f54694917af3", size = 1775698, upload-time = "2026-06-07T21:06:33.72Z" }, + { url = "https://files.pythonhosted.org/packages/1d/21/151624b51cd92553d95424daf4bf19f19ce9be9002d19253e7e7ce67197b/aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480", size = 757402, upload-time = "2026-06-07T21:06:40.311Z" }, + { url = "https://files.pythonhosted.org/packages/c2/82/280619e0bd7bf2454987e19282616e84762255dd9c8468f62382e8c191f1/aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d", size = 512310, upload-time = "2026-06-07T21:06:42.207Z" }, + { url = "https://files.pythonhosted.org/packages/55/b2/2aac325583aaa1353045f96dffa586d8a34e8322e14a7ba49cffeb103ab4/aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2", size = 512448, upload-time = "2026-06-07T21:06:43.813Z" }, + { url = "https://files.pythonhosted.org/packages/8a/72/a60607cb849faa8af8a356c9329ea2eb6f395d49e82cc82ccba1fd8deb8f/aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2", size = 1766854, upload-time = "2026-06-07T21:06:45.391Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d3/d9fe1c9ec7557ab4d0d82bebaa728c6418f0b93295ec2f4ab015f7710cc7/aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a", size = 1740884, upload-time = "2026-06-07T21:06:47.413Z" }, + { url = "https://files.pythonhosted.org/packages/c1/dc/f2cecfaf9337ba3e63f181500814ff502aa3d00d9c7ec93a9d23d10a27b2/aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264", size = 1810034, upload-time = "2026-06-07T21:06:50.165Z" }, + { url = "https://files.pythonhosted.org/packages/66/d7/2ff65c5e65c0d7476daf7e15c032e0805e36811185b9623e3238ad6c763e/aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842", size = 1904054, upload-time = "2026-06-07T21:06:52.035Z" }, + { url = "https://files.pythonhosted.org/packages/20/9c/d445818389df371f56d141d881153ba23183c4735a03f7356ffb43f7757d/aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c", size = 1790278, upload-time = "2026-06-07T21:06:54.049Z" }, + { url = "https://files.pythonhosted.org/packages/4d/aa/bf04cb4d865fc6101c2229a294ad744973b72e513fdc5a6b791e6983d72a/aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95", size = 1591795, upload-time = "2026-06-07T21:06:55.911Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b4/4dac0038960427ba832f6609dfb4ea5437d7fd80c72001b9e48f834f428b/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199", size = 1728397, upload-time = "2026-06-07T21:06:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/7cd4e8ad7aa3b75f17d56bb5498dd604a93d4e6eece822ba0568c413fff0/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817", size = 1766504, upload-time = "2026-06-07T21:07:00.009Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/fc01d9fcad0f73fed3f3d361f1f94f975947b50dff82919f6dc2bf4316cc/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a", size = 1777806, upload-time = "2026-06-07T21:07:02.064Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/47e2d090bddcc8fb4ccb4c314aadc32d7c5d9bb55f50f6ad1c92fc15d501/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4", size = 1580707, upload-time = "2026-06-07T21:07:03.942Z" }, + { url = "https://files.pythonhosted.org/packages/3d/36/f1a4ce904ae0b6930cfe9afc96d0896f7ec1a620c400405d63783bb95a9c/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087", size = 1798121, upload-time = "2026-06-07T21:07:05.987Z" }, + { url = "https://files.pythonhosted.org/packages/70/0a/e0075ce9ca0279ee1d4f0c0b85f54fea02ebc83c3007651a72bece658fec/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3", size = 1767580, upload-time = "2026-06-07T21:07:07.873Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "alembic" +version = "1.18.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mako", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/cc/ac0bed8e562e7407fe55c3ba85a4dce86e6dbd8730887bd1e406a6c5c18a/alembic-1.18.5.tar.gz", hash = "sha256:1554982221dd17e9a749b53902407578eb305e453f71999e8c7f0a48389fff8e", size = 2060480, upload-time = "2026-06-25T15:20:54.888Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/78/5fe6dc3a3a5b2f5a2a4faef8bfe336d5fa049a38884ab3172e0098160c01/alembic-1.18.5-py3-none-any.whl", hash = "sha256:06d8ba9d04558022f5395e9317de03d270f3dced49cee01f89fe7a13c26f14bc", size = 264664, upload-time = "2026-06-25T15:20:56.673Z" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "antlr4-python3-runtime" +version = "4.9.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/38/7859ff46355f76f8d19459005ca000b6e7012f2f1ca597746cbcd1fbfe5e/antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b", size = 117034, upload-time = "2021-11-06T17:52:23.524Z" } + +[[package]] +name = "anyio" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/25/1e/faf0f247f6f881b98fc4d6d07e14085cb89d13665084e6d6ac1dc2c03d0b/asttokens-3.0.2.tar.gz", hash = "sha256:3ecdbd8f2cc195f53ccada3a613538bb5f9ef6f6869129f13e03c30a677b8fe2", size = 63136, upload-time = "2026-07-12T03:31:49.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/2b/04b8a15f3a1c77bc79ddf5c73875327f34b4fa75982df2b76e45e402d364/asttokens-3.0.2-py3-none-any.whl", hash = "sha256:9da13157f5b28becde0bd374fc677dcd3c290614264eff096f167c469cd9f933", size = 28702, upload-time = "2026-07-12T03:31:47.542Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "audioread" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/4a/874ecf9b472f998130c2b5e145dcdb9f6131e84786111489103b66772143/audioread-3.1.0.tar.gz", hash = "sha256:1c4ab2f2972764c896a8ac61ac53e261c8d29f0c6ccd652f84e18f08a4cab190", size = 20082, upload-time = "2025-10-26T19:44:13.484Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/16/fbe8e1e185a45042f7cd3a282def5bb8d95bb69ab9e9ef6a5368aa17e426/audioread-3.1.0-py3-none-any.whl", hash = "sha256:b30d1df6c5d3de5dcef0fb0e256f6ea17bdcf5f979408df0297d8a408e2971b4", size = 23143, upload-time = "2025-10-26T19:44:12.016Z" }, +] + +[[package]] +name = "braceexpand" +version = "0.1.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/93/badd4f5ccf25209f3fef2573073da9fe4a45a3da99fca2f800f942130c0f/braceexpand-0.1.7.tar.gz", hash = "sha256:e6e539bd20eaea53547472ff94f4fb5c3d3bf9d0a89388c4b56663aba765f705", size = 7777, upload-time = "2021-05-07T13:49:07.323Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/93/e8c04e80e82391a6e51f218ca49720f64236bc824e92152a2633b74cf7ab/braceexpand-0.1.7-py2.py3-none-any.whl", hash = "sha256:91332d53de7828103dcae5773fb43bc34950b0c8160e35e0f44c4427a3b85014", size = 5923, upload-time = "2021-05-07T13:49:05.146Z" }, +] + +[[package]] +name = "certifi" +version = "2026.6.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, +] + +[[package]] +name = "cffi" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "(implementation_name != 'PyPy' and sys_platform == 'darwin') or (implementation_name != 'PyPy' and sys_platform == 'linux')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" }, + { url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" }, + { url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" }, + { url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" }, + { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" }, + { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" }, + { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" }, + { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/e3/85ec501f206fb049259288c1f3506e53876937fb00edb47009348e66756b/charset_normalizer-3.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5", size = 317075, upload-time = "2026-07-07T14:32:56.021Z" }, + { url = "https://files.pythonhosted.org/packages/c3/69/2a5385192e67175f7d8bd5ce4f57c24bc956439adeae5c13a99aa28a53d1/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2", size = 213837, upload-time = "2026-07-07T14:32:57.78Z" }, + { url = "https://files.pythonhosted.org/packages/b3/46/03ddc7da576d814fe0a36dd1f0fd3258e95404b4b2e3c026b7923d7e133f/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a", size = 235503, upload-time = "2026-07-07T14:32:59.205Z" }, + { url = "https://files.pythonhosted.org/packages/4e/6e/de0229a7ef40f6f9d28a837eebf4ec47bdca5dab4e900c84f22919af636a/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29", size = 229944, upload-time = "2026-07-07T14:33:00.803Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/49b9060e8418b14fb5cba9cf6bfb383111e2538a03a1fb18e66a95aeb3d5/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c", size = 221276, upload-time = "2026-07-07T14:33:02.199Z" }, + { url = "https://files.pythonhosted.org/packages/44/95/80282cce0fae9c3061203d723ee87da996aed79679e65d8935050ee7ca1f/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b", size = 205260, upload-time = "2026-07-07T14:33:03.698Z" }, + { url = "https://files.pythonhosted.org/packages/0c/74/2f62c8821b969ea3bd67cc2e6976834f48ca5d12664d2559ebcd9bcfbed7/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db", size = 217786, upload-time = "2026-07-07T14:33:05.12Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8d/feabb82cb49fcad14515b1d7d1ca4787b0da7fc723a212bf89bc9e0fac52/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993", size = 216798, upload-time = "2026-07-07T14:33:06.629Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ff/c946d63bc3786d5b84d960b0f7ab7e25b828486a946b5aa997625bcaf6a6/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da", size = 206429, upload-time = "2026-07-07T14:33:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/af/ba/5e5007c370702f85d2ef75791fac7943ed41e080364a673b20142e430e3e/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3", size = 223066, upload-time = "2026-07-07T14:33:09.783Z" }, + { url = "https://files.pythonhosted.org/packages/70/4a/ecbd131485c07fcdfad54e28946d513e3da22ef3b4bd854dcafae54ec739/charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", size = 319300, upload-time = "2026-07-07T14:33:15.666Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/5d9364e3342d69f3a045e1777bc47c85c383e6e9466d561b33fdb419d1f9/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", size = 215802, upload-time = "2026-07-07T14:33:17.031Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4c/5361f9aa7f2cb58d94f2ab831b3d493f69efb1d239654b4744e3c09527cb/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", size = 237171, upload-time = "2026-07-07T14:33:18.576Z" }, + { url = "https://files.pythonhosted.org/packages/50/78/ce342ca4ff30b2eb49fe6d9578df85974f90c67d294113e94efdd9664cbd/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", size = 233075, upload-time = "2026-07-07T14:33:20.084Z" }, + { url = "https://files.pythonhosted.org/packages/01/c4/4fa4c8b3097a11f3c5f09a35b72ed6855fb1d332469504962ab7bafcc702/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", size = 224256, upload-time = "2026-07-07T14:33:21.747Z" }, + { url = "https://files.pythonhosted.org/packages/87/3a/ad914516df7e358a81aae018caa5e0470ba827fa6d763b1d2e87d920a5f6/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", size = 208784, upload-time = "2026-07-07T14:33:23.313Z" }, + { url = "https://files.pythonhosted.org/packages/d7/74/3c12f9755717dfe5c5c87da63f35d765fa0c00382ec26bf23f7fae34f2ba/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", size = 219928, upload-time = "2026-07-07T14:33:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/895095b83e7907abd6d3d99aad3a38ad0d9686cc186cb0c94c24320fe63e/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", size = 218489, upload-time = "2026-07-07T14:33:26.42Z" }, + { url = "https://files.pythonhosted.org/packages/a1/34/ef5c05f412f42520d7709b7d3784d19640839eb7366ded1755511585429f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", size = 210267, upload-time = "2026-07-07T14:33:27.952Z" }, + { url = "https://files.pythonhosted.org/packages/83/dc/9b29fa4412b318bf3bfea985c35d67eb55e04b59a7c3f2237168b0e0be6f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", size = 226030, upload-time = "2026-07-07T14:33:29.397Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, +] + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, +] + +[[package]] +name = "cloudpickle" +version = "3.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "colorlog" +version = "6.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/bf/cb30a51af3aa8ce63735f77e23dcd4fc0720fe0339bcb04f77345659c277/colorlog-6.11.0.tar.gz", hash = "sha256:9d90fb53fa906c8970c18fbe46506bae1fb5f86b513b8f867db37e4ace9be7ae", size = 17734, upload-time = "2026-07-17T12:16:46.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/a1/6b71004ab0fea510230be9ce05a4059029ac847c009fcc80b1b73d6fa5ab/colorlog-6.11.0-py3-none-any.whl", hash = "sha256:f1e27d75aa2cb138f3f640c0e305b65b680ccbef6ecc034eba7e03494ffcd2a1", size = 12016, upload-time = "2026-07-17T12:16:45.3Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, + { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, + { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, + { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, + { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, + { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, + { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, + { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, + { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, + { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, + { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, + { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, + { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, + { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, + { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, +] + +[[package]] +name = "cuda-bindings" +version = "12.9.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cuda-pathfinder", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/f3/f9d1095f90d2a4df24cfcafe7487fd9444c6dacb94e3722be6fedd8ac26c/cuda_bindings-12.9.7-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16043ef5b15ab88fe9954c5c2061b1d8007591b27f2c916331056de0ebc6187e", size = 7114834, upload-time = "2026-05-27T18:44:07.746Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8a/1251e1794b69865aacd5629936006b18ea0816a495de4ecea9a825556eb3/cuda_bindings-12.9.7-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6496a88d84b1209d6651b0370c19c26319e157c22f6d018bf9a358cd8049041", size = 7647147, upload-time = "2026-05-27T18:44:09.4Z" }, + { url = "https://files.pythonhosted.org/packages/32/45/557d4ed1fa54f0c7db8aee083229f624990d69f7d00f55477eed5c7e169a/cuda_bindings-12.9.7-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0666d3c082ef8f4b2d670950589373550e9f3bf564d635dd883f24a0b40402ff", size = 7071026, upload-time = "2026-05-27T18:44:13.356Z" }, + { url = "https://files.pythonhosted.org/packages/91/97/e3c6e58ece26a053419ba0a18444b5443cfc64451bbf37f84e8143b8bdca/cuda_bindings-12.9.7-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c7ef48c5e13ae90f3b2ecfb72f8e99ac43c8f4c43e67e1325b8aae331453687", size = 7611059, upload-time = "2026-05-27T18:44:15.252Z" }, +] + +[[package]] +name = "cuda-pathfinder" +version = "1.5.6" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/53/8fc9b0cdc5b7f62746e6a01b85b6461e5ae27f871010a5fcf8fa6950766d/cuda_pathfinder-1.5.6-py3-none-any.whl", hash = "sha256:7e4c07c117b78ba1fb35dac4c444d21f3677b1b1ff56175c53a8e3025c5b43c0", size = 52972, upload-time = "2026-06-30T00:58:04.34Z" }, +] + +[[package]] +name = "cuda-toolkit" +version = "12.9.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/8f/a28e7da158e96ad61f7e1035e53851fafaddf22445300d664e68ec657fdc/cuda_toolkit-12.9.1-py2.py3-none-any.whl", hash = "sha256:0c8636dfacbecfe9867a949a211864f080a805bc54023ce4a361aa4e1fd8738b", size = 2303, upload-time = "2025-08-13T02:03:10.699Z" }, +] + +[package.optional-dependencies] +cublas = [ + { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, +] +cudart = [ + { name = "nvidia-cuda-runtime-cu12", marker = "sys_platform == 'linux'" }, +] +cufft = [ + { name = "nvidia-cufft-cu12", marker = "sys_platform == 'linux'" }, +] +cufile = [ + { name = "nvidia-cufile-cu12", marker = "sys_platform == 'linux'" }, +] +cupti = [ + { name = "nvidia-cuda-cupti-cu12", marker = "sys_platform == 'linux'" }, +] +curand = [ + { name = "nvidia-curand-cu12", marker = "sys_platform == 'linux'" }, +] +cusolver = [ + { name = "nvidia-cusolver-cu12", marker = "sys_platform == 'linux'" }, +] +cusparse = [ + { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux'" }, +] +nvjitlink = [ + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, +] +nvrtc = [ + { name = "nvidia-cuda-nvrtc-cu12", marker = "sys_platform == 'linux'" }, +] +nvtx = [ + { name = "nvidia-nvtx-cu12", marker = "sys_platform == 'linux'" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "cytoolz" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "toolz", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/d4/16916f3dc20a3f5455b63c35dcb260b3716f59ce27a93586804e70e431d5/cytoolz-1.1.0.tar.gz", hash = "sha256:13a7bf254c3c0d28b12e2290b82aed0f0977a4c2a2bf84854fcdc7796a29f3b0", size = 642510, upload-time = "2025-10-19T00:44:56.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/82/edf1d0c32b6222f2c22e5618d6db855d44eb59f9b6f22436ff963c5d0a5c/cytoolz-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dba8e5a8c6e3c789d27b0eb5e7ce5ed7d032a7a9aae17ca4ba5147b871f6e327", size = 1314345, upload-time = "2025-10-19T00:40:13.273Z" }, + { url = "https://files.pythonhosted.org/packages/2d/b5/0e3c1edaa26c2bd9db90cba0ac62c85bbca84224c7ae1c2e0072c4ea64c5/cytoolz-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:44b31c05addb0889167a720123b3b497b28dd86f8a0aeaf3ae4ffa11e2c85d55", size = 989259, upload-time = "2025-10-19T00:40:15.196Z" }, + { url = "https://files.pythonhosted.org/packages/09/aa/e2b2ee9fc684867e817640764ea5807f9d25aa1e7bdba02dd4b249aab0f7/cytoolz-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:653cb18c4fc5d8a8cfce2bce650aabcbe82957cd0536827367d10810566d5294", size = 986551, upload-time = "2025-10-19T00:40:16.831Z" }, + { url = "https://files.pythonhosted.org/packages/39/9f/4e8ee41acf6674f10a9c2c9117b2f219429a5a0f09bba6135f34ca4f08a6/cytoolz-1.1.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:853a5b4806915020c890e1ce70cc056bbc1dd8bc44f2d74d555cccfd7aefba7d", size = 2688378, upload-time = "2025-10-19T00:40:18.552Z" }, + { url = "https://files.pythonhosted.org/packages/78/94/ef006f3412bc22444d855a0fc9ecb81424237fb4e5c1a1f8f5fb79ac978f/cytoolz-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7b44e9de86bea013fe84fd8c399d6016bbb96c37c5290769e5c99460b9c53e5", size = 2798299, upload-time = "2025-10-19T00:40:20.191Z" }, + { url = "https://files.pythonhosted.org/packages/df/aa/365953926ee8b4f2e07df7200c0d73632155908c8867af14b2d19cc9f1f7/cytoolz-1.1.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:098d628a801dc142e9740126be5624eb7aef1d732bc7a5719f60a2095547b485", size = 2639311, upload-time = "2025-10-19T00:40:22.289Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ee/62beaaee7df208f22590ad07ef8875519af49c52ca39d99460b14a00f15a/cytoolz-1.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:779ee4096ed7a82cffab89372ffc339631c285079dbf33dbe7aff1f6174985df", size = 2979532, upload-time = "2025-10-19T00:40:24.006Z" }, + { url = "https://files.pythonhosted.org/packages/c5/04/2211251e450bed111ada1194dc42c461da9aea441de62a01e4085ea6de9f/cytoolz-1.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f2ce18dd99533d077e9712f9faa852f389f560351b1efd2f2bdb193a95eddde2", size = 3018632, upload-time = "2025-10-19T00:40:26.175Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a2/4a3400e4d07d3916172bf74fede08020d7b4df01595d8a97f1e9507af5ae/cytoolz-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac266a34437812cf841cecbfe19f355ab9c3dd1ef231afc60415d40ff12a76e4", size = 2788579, upload-time = "2025-10-19T00:40:27.878Z" }, + { url = "https://files.pythonhosted.org/packages/fe/82/bb88caa53a41f600e7763c517d50e2efbbe6427ea395716a92b83f44882a/cytoolz-1.1.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1920b9b9c13d60d0bb6cd14594b3bce0870022eccb430618c37156da5f2b7a55", size = 2593024, upload-time = "2025-10-19T00:40:29.601Z" }, + { url = "https://files.pythonhosted.org/packages/09/a8/8b25e59570da16c7a0f173b8c6ec0aa6f3abd47fd385c007485acb459896/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47caa376dafd2bdc29f8a250acf59c810ec9105cd6f7680b9a9d070aae8490ec", size = 2715304, upload-time = "2025-10-19T00:40:31.151Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/faec7696f235521b926ffdf92c102f5b029f072d28e1020364e55b084820/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5ab2c97d8aaa522b038cca9187b1153347af22309e7c998b14750c6fdec7b1cb", size = 2654461, upload-time = "2025-10-19T00:40:32.884Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/f790ed167c04b8d2a33bed30770a9b7066fc4f573321d797190e5f05685f/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4bce006121b120e8b359244ee140bb0b1093908efc8b739db8dbaa3f8fb42139", size = 2672077, upload-time = "2025-10-19T00:40:34.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b3/80b8183e7eee44f45bfa3cdd3ebdadf3dd43ffc686f96d442a6c4dded45d/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fc0f1e4e9bb384d26e73c6657bbc26abdae4ff66a95933c00f3d578be89181b", size = 2881589, upload-time = "2025-10-19T00:40:36.315Z" }, + { url = "https://files.pythonhosted.org/packages/8f/05/ac5ba5ddb88a3ba7ecea4bf192194a838af564d22ea7a4812cbb6bd106ce/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd3f894ff972da1994d06ac6157d74e40dda19eb31fe5e9b7863ca4278c3a167", size = 2589924, upload-time = "2025-10-19T00:40:38.317Z" }, + { url = "https://files.pythonhosted.org/packages/8e/cd/100483cae3849d24351c8333a815dc6adaf3f04912486e59386d86d9db9a/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0846f49cf8a4496bd42659040e68bd0484ce6af819709cae234938e039203ba0", size = 2868059, upload-time = "2025-10-19T00:40:40.025Z" }, + { url = "https://files.pythonhosted.org/packages/34/6e/3a7c56b325772d39397fc3aafb4dc054273982097178b6c3917c6dad48de/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:16a3af394ade1973226d64bb2f9eb3336adbdea03ed5b134c1bbec5a3b20028e", size = 2721692, upload-time = "2025-10-19T00:40:41.621Z" }, + { url = "https://files.pythonhosted.org/packages/c6/ec/01426224f7acf60183d3921b25e1a8e71713d3d39cb464d64ac7aace6ea6/cytoolz-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:99f8e134c9be11649342853ec8c90837af4089fc8ff1e8f9a024a57d1fa08514", size = 1327800, upload-time = "2025-10-19T00:40:48.674Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/e07e8fedd332ac9626ad58bea31416dda19bfd14310731fa38b16a97e15f/cytoolz-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0a6f44cf9319c30feb9a50aa513d777ef51efec16f31c404409e7deb8063df64", size = 997118, upload-time = "2025-10-19T00:40:50.919Z" }, + { url = "https://files.pythonhosted.org/packages/ab/72/c0f766d63ed2f9ea8dc8e1628d385d99b41fb834ce17ac3669e3f91e115d/cytoolz-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:945580dc158c557172fca899a35a99a16fbcebf6db0c77cb6621084bc82189f9", size = 991169, upload-time = "2025-10-19T00:40:52.887Z" }, + { url = "https://files.pythonhosted.org/packages/df/4b/1f757353d1bf33e56a7391ecc9bc49c1e529803b93a9d2f67fe5f92906fe/cytoolz-1.1.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:257905ec050d04f2f856854620d1e25556fd735064cebd81b460f54939b9f9d5", size = 2700680, upload-time = "2025-10-19T00:40:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/25/73/9b25bb7ed8d419b9d6ff2ae0b3d06694de79a3f98f5169a1293ff7ad3a3f/cytoolz-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82779049f352fb3ab5e8c993ab45edbb6e02efb1f17f0b50f4972c706cc51d76", size = 2824951, upload-time = "2025-10-19T00:40:56.137Z" }, + { url = "https://files.pythonhosted.org/packages/0c/93/9c787f7c909e75670fff467f2504725d06d8c3f51d6dfe22c55a08c8ccd4/cytoolz-1.1.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7d3e405e435320e08c5a1633afaf285a392e2d9cef35c925d91e2a31dfd7a688", size = 2679635, upload-time = "2025-10-19T00:40:57.799Z" }, + { url = "https://files.pythonhosted.org/packages/50/aa/9ee92c302cccf7a41a7311b325b51ebeff25d36c1f82bdc1bbe3f58dc947/cytoolz-1.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:923df8f5591e0d20543060c29909c149ab1963a7267037b39eee03a83dbc50a8", size = 2938352, upload-time = "2025-10-19T00:40:59.49Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a3/3b58c5c1692c3bacd65640d0d5c7267a7ebb76204f7507aec29de7063d2f/cytoolz-1.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:25db9e4862f22ea0ae2e56c8bec9fc9fd756b655ae13e8c7b5625d7ed1c582d4", size = 3022121, upload-time = "2025-10-19T00:41:01.209Z" }, + { url = "https://files.pythonhosted.org/packages/e1/93/c647bc3334355088c57351a536c2d4a83dd45f7de591fab383975e45bff9/cytoolz-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7a98deb11ccd8e5d9f9441ef2ff3352aab52226a2b7d04756caaa53cd612363", size = 2857656, upload-time = "2025-10-19T00:41:03.456Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c2/43fea146bf4141deea959e19dcddf268c5ed759dec5c2ed4a6941d711933/cytoolz-1.1.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dce4ee9fc99104bc77efdea80f32ca5a650cd653bcc8a1d984a931153d3d9b58", size = 2551284, upload-time = "2025-10-19T00:41:05.347Z" }, + { url = "https://files.pythonhosted.org/packages/6f/df/cdc7a81ce5cfcde7ef523143d545635fc37e80ccacce140ae58483a21da3/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80d6da158f7d20c15819701bbda1c041f0944ede2f564f5c739b1bc80a9ffb8b", size = 2721673, upload-time = "2025-10-19T00:41:07.528Z" }, + { url = "https://files.pythonhosted.org/packages/45/be/f8524bb9ad8812ad375e61238dcaa3177628234d1b908ad0b74e3657cafd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3b5c5a192abda123ad45ef716ec9082b4cf7d95e9ada8291c5c2cc5558be858b", size = 2722884, upload-time = "2025-10-19T00:41:09.698Z" }, + { url = "https://files.pythonhosted.org/packages/23/e6/6bb8e4f9c267ad42d1ff77b6d2e4984665505afae50a216290e1d7311431/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5b399ce7d967b1cb6280250818b786be652aa8ddffd3c0bb5c48c6220d945ab5", size = 2685486, upload-time = "2025-10-19T00:41:11.349Z" }, + { url = "https://files.pythonhosted.org/packages/d7/dd/88619f9c8d2b682562c0c886bbb7c35720cb83fda2ac9a41bdd14073d9bd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e7e29a1a03f00b4322196cfe8e2c38da9a6c8d573566052c586df83aacc5663c", size = 2839661, upload-time = "2025-10-19T00:41:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8d/4478ebf471ee78dd496d254dc0f4ad729cd8e6ba8257de4f0a98a2838ef2/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5291b117d71652a817ec164e7011f18e6a51f8a352cc9a70ed5b976c51102fda", size = 2547095, upload-time = "2025-10-19T00:41:16.054Z" }, + { url = "https://files.pythonhosted.org/packages/e6/68/f1dea33367b0b3f64e199c230a14a6b6f243c189020effafd31e970ca527/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8caef62f846a9011676c51bda9189ae394cdd6bb17f2946ecaedc23243268320", size = 2870901, upload-time = "2025-10-19T00:41:17.727Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/33591c09dfe799b8fb692cf2ad383e2c41ab6593cc960b00d1fc8a145655/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:de425c5a8e3be7bb3a195e19191d28d9eb3c2038046064a92edc4505033ec9cb", size = 2765422, upload-time = "2025-10-19T00:41:20.075Z" }, + { url = "https://files.pythonhosted.org/packages/84/32/0522207170294cf691112a93c70a8ef942f60fa9ff8e793b63b1f09cedc0/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f32e93a55681d782fc6af939f6df36509d65122423cbc930be39b141064adff8", size = 922014, upload-time = "2025-10-19T00:44:44.911Z" }, + { url = "https://files.pythonhosted.org/packages/4c/49/9be2d24adaa18fa307ff14e3e43f02b2ae4b69c4ce51cee6889eb2114990/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5d9bc596751cbda8073e65be02ca11706f00029768fbbbc81e11a8c290bb41aa", size = 918134, upload-time = "2025-10-19T00:44:47.122Z" }, + { url = "https://files.pythonhosted.org/packages/5c/b3/6a76c3b94c6c87c72ea822e7e67405be6b649c2e37778eeac7c0c0c69de8/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b16660d01c3931951fab49db422c627897c38c1a1f0393a97582004019a4887", size = 981970, upload-time = "2025-10-19T00:44:48.906Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8a/606e4c7ed14aa6a86aee6ca84a2cb804754dc6c4905b8f94e09e49f1ce60/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b7de5718e2113d4efccea3f06055758cdbc17388ecc3341ba4d1d812837d7c1a", size = 978877, upload-time = "2025-10-19T00:44:50.819Z" }, + { url = "https://files.pythonhosted.org/packages/97/ec/ad474dcb1f6c1ebfdda3c2ad2edbb1af122a0e79c9ff2cb901ffb5f59662/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a12a2a1a6bc44099491c05a12039efa08cc33a3d0f8c7b0566185e085e139283", size = 964279, upload-time = "2025-10-19T00:44:52.476Z" }, +] + +[[package]] +name = "datasets" +version = "5.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dill", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "fsspec", extra = ["http"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "httpx", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "multiprocess", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyarrow", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "xxhash", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/85/ce4f780c32f7e36d71257f1c27e8ba898ebe379cb54f211f5f2013f2c219/datasets-5.0.0.tar.gz", hash = "sha256:83dbbbdb07a33b82192b8c419deb18739b138ee2ce1a322d55ce6b100954ec1a", size = 631708, upload-time = "2026-06-05T13:18:26.124Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/66/73034ad30b59f13439b75e620989dacba4c047256e358ba7c2e9ec98ea22/datasets-5.0.0-py3-none-any.whl", hash = "sha256:7dd34927a0fd7046e98aad5cb9430e699c373238a15befa7b9bf22b991a7fee6", size = 555084, upload-time = "2026-06-05T13:18:24.435Z" }, +] + +[[package]] +name = "decorator" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/8b/32f9823da46cde7df2087faa08cd98d01b908f8dcab982cdba9c84e85355/decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", size = 58084, upload-time = "2026-05-18T06:03:28.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c", size = 10365, upload-time = "2026-05-18T06:03:26.517Z" }, +] + +[[package]] +name = "dill" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, +] + +[[package]] +name = "editdistance" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/18/9f4f975ca87a390832b1c22478f3702fcdf739f83211e24d054b7551270d/editdistance-0.8.1.tar.gz", hash = "sha256:d1cdf80a5d5014b0c9126a69a42ce55a457b457f6986ff69ca98e4fe4d2d8fed", size = 50006, upload-time = "2024-02-10T07:44:53.914Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/dc/d0c29fd52d8f9e795653ed2b838a2a48c739cdfff04ac5b79c6c0ecbdf79/editdistance-0.8.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:486105603a273d73d12a54f347dffa70ab281749d7c3879658b377bc49e4b98c", size = 106079, upload-time = "2024-02-10T07:43:34.34Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c6/75fa45d7b78fbea6fd894f4e48895a75bd3c83d4a9a6b57673881d74d3e0/editdistance-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fad081f5f86a175c1a09a4e9e45b95c9349e454c21e181e842e01c85f1f536fc", size = 80580, upload-time = "2024-02-10T07:43:35.947Z" }, + { url = "https://files.pythonhosted.org/packages/b7/a3/058d823b6285c3511dc94ed80620c3fb0c18b4aaa708f70ba71f3af28436/editdistance-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cb78e125f6759398885a775f5eed07c2bb72b2f86da43e674c6b6a3335b273b", size = 79087, upload-time = "2024-02-10T07:43:36.923Z" }, + { url = "https://files.pythonhosted.org/packages/a0/3a/0b13c7864c93b1e9b9952bd2a33c5ef3c4fd1bf70a5fad6924789e70e5eb/editdistance-0.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3778ca60aa89def9144b70e330bcec5330c7da1d69cb28c612e90b84510a1d3d", size = 409296, upload-time = "2024-02-10T07:43:38.52Z" }, + { url = "https://files.pythonhosted.org/packages/96/8a/db0fd79e8ddb9b5f86f274107c5d0a27ec4f2af88877df1f26c2c6d150cc/editdistance-0.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fba945eaa0436cf40bc53d7e299dc537c7c71353379a095b7459ff4af910da33", size = 412913, upload-time = "2024-02-10T07:43:39.852Z" }, + { url = "https://files.pythonhosted.org/packages/0d/d2/98be7112750ff17b436dd76f988f1e38570dcec0df8578ee19ef046f22fe/editdistance-0.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877f2a0d801f32bc1a1878901ffb947b974361e849c66e314a7f1d786a446b58", size = 407430, upload-time = "2024-02-10T07:43:41.048Z" }, + { url = "https://files.pythonhosted.org/packages/03/62/1815e3bf164910c47ba1948c8b5e937a40c7f9763b64e98fb6666b01dd06/editdistance-0.8.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e79d351ca40a6ead5f3763253fd7521572ee0d3e5d42538630e56d10f48db481", size = 909217, upload-time = "2024-02-10T07:43:42.916Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d3/a832cea7b507a9be54e4ac3d1340fb66dca5f9c16c70bf38d5039e8fdede/editdistance-0.8.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:70ed382b3052a51161bad0149d4665003bf3b949fce0b01bf1253a4cc1a88239", size = 969407, upload-time = "2024-02-10T07:43:44.912Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b4/db291d2a3845cbf8047b4b5aad3b3e038a8a2994d87027b40e1a1b0f4b74/editdistance-0.8.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a529bfb384c4000775d76739c4e64f73337f0f5a3784933b1321b577a62bed4e", size = 922112, upload-time = "2024-02-10T07:43:47.047Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4c/7f195588949b4e72436dc7fc902632381f96e586af829685b56daebb38b8/editdistance-0.8.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04af61b3fcdd287a07c15b6ae3b02af01c5e3e9c3aca76b8c1d13bd266b6f57", size = 106723, upload-time = "2024-02-10T07:43:50.268Z" }, + { url = "https://files.pythonhosted.org/packages/8d/82/31dc1640d830cd7d36865098329f34e4dad3b77f31cfb9404b347e700196/editdistance-0.8.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:18fc8b6eaae01bfd9cf999af726c1e8dcf667d120e81aa7dbd515bea7427f62f", size = 80998, upload-time = "2024-02-10T07:43:51.259Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2a/6b823e71cef694d6f070a1d82be2842706fa193541aab8856a8f42044cd0/editdistance-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6a87839450a5987028738d061ffa5ef6a68bac2ddc68c9147a8aae9806629c7f", size = 79248, upload-time = "2024-02-10T07:43:52.873Z" }, + { url = "https://files.pythonhosted.org/packages/e1/31/bfb8e590f922089dc3471ed7828a6da2fc9453eba38c332efa9ee8749fd7/editdistance-0.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24b5f9c9673c823d91b5973d0af8b39f883f414a55ade2b9d097138acd10f31e", size = 415262, upload-time = "2024-02-10T07:43:54.498Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c7/57423942b2f847cdbbb46494568d00cd8a45500904ea026f0aad6ca01bc7/editdistance-0.8.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c59248eabfad603f0fba47b0c263d5dc728fb01c2b6b50fb6ca187cec547fdb3", size = 418905, upload-time = "2024-02-10T07:43:55.779Z" }, + { url = "https://files.pythonhosted.org/packages/1b/05/dfa4cdcce063596cbf0d7a32c46cd0f4fa70980311b7da64d35f33ad02a0/editdistance-0.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e239d88ff52821cf64023fabd06a1d9a07654f364b64bf1284577fd3a79d0e", size = 412511, upload-time = "2024-02-10T07:43:57.567Z" }, + { url = "https://files.pythonhosted.org/packages/0e/14/39608ff724a9523f187c4e28926d78bc68f2798f74777ac6757981108345/editdistance-0.8.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2f7f71698f83e8c83839ac0d876a0f4ef996c86c5460aebd26d85568d4afd0db", size = 917293, upload-time = "2024-02-10T07:43:59.559Z" }, + { url = "https://files.pythonhosted.org/packages/df/92/4a1c61d72da40dedfd0ff950fdc71ae83f478330c58a8bccfd776518bd67/editdistance-0.8.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:04e229d6f4ce0c12abc9f4cd4023a5b5fa9620226e0207b119c3c2778b036250", size = 975580, upload-time = "2024-02-10T07:44:01.328Z" }, + { url = "https://files.pythonhosted.org/packages/47/3d/9877566e724c8a37f2228a84ec5cbf66dbfd0673515baf68a0fe07caff40/editdistance-0.8.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e16721636da6d6b68a2c09eaced35a94f4a4a704ec09f45756d4fd5e128ed18d", size = 929121, upload-time = "2024-02-10T07:44:02.764Z" }, +] + +[[package]] +name = "einops" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/77/850bef8d72ffb9219f0b1aac23fbc1bf7d038ee6ea666f331fa273031aa2/einops-0.8.2.tar.gz", hash = "sha256:609da665570e5e265e27283aab09e7f279ade90c4f01bcfca111f3d3e13f2827", size = 56261, upload-time = "2026-01-26T04:13:17.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/09/f8d8f8f31e4483c10a906437b4ce31bdf3d6d417b73fe33f1a8b59e34228/einops-0.8.2-py3-none-any.whl", hash = "sha256:54058201ac7087911181bfec4af6091bb59380360f069276601256a76af08193", size = 65638, upload-time = "2026-01-26T04:13:18.546Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fiddle" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "graphviz", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "libcst", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/36/7a4fac76351619b36bbc7937abf59f7b601326dc4efc253b3c16819f782a/fiddle-0.3.0.tar.gz", hash = "sha256:5d083d3299a479868345513385a6c5546141bd92086c15d3dcbf8008a90075d3", size = 277884, upload-time = "2024-04-09T17:23:58.974Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/98/a38e949a91ff9e15874487fd8329ff53c25f3413c0cfc809eb6ff7eb7fa1/fiddle-0.3.0-py3-none-any.whl", hash = "sha256:f4824541c103a94a2f33f6c93eeddf6007c3a7300440087a95907f3e74362e61", size = 419830, upload-time = "2024-04-09T17:23:56.7Z" }, +] + +[[package]] +name = "filelock" +version = "3.31.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/9f/994e80905542b748eb5b9f36d71458f0aea51a7be0fcb52ad959787dc1b7/filelock-3.31.0.tar.gz", hash = "sha256:c188cbc4307c18894c5424fa73f97ea7fa127ddf62192487546da3a214d0a381", size = 180931, upload-time = "2026-07-18T05:53:29.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/4a/e213905d3b8ad3d35d14fc056b36134a274e7f6a1050e94428b5be10a94c/filelock-3.31.0-py3-none-any.whl", hash = "sha256:739b73e580fe88bb78d830aeddbc492519ece3d97ac8368de13a2032c61010c1", size = 96080, upload-time = "2026-07-18T05:53:27.732Z" }, +] + +[[package]] +name = "fonttools" +version = "4.63.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/2b/a7f1545bdf5da69c4bda0cea2a5781f0ad2a6623e0277267672db43c5fe6/fonttools-4.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f", size = 2881793, upload-time = "2026-05-14T12:02:56.645Z" }, + { url = "https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9", size = 2428130, upload-time = "2026-05-14T12:02:58.891Z" }, + { url = "https://files.pythonhosted.org/packages/d8/38/6937fbd7f2dc3a6b48725851bc2c15ec949b9af14d9bbcb5fe83cdf9bdf9/fonttools-4.63.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b", size = 5111952, upload-time = "2026-05-14T12:03:01.263Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18", size = 5082308, upload-time = "2026-05-14T12:03:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/67/00/cdd9d4944ca6ae280d01e69cc37bde3bf663630b837a6fc6d2cd65d80e0e/fonttools-4.63.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0", size = 5087932, upload-time = "2026-05-14T12:03:05.147Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f1/0aa0dbea778c75adbef223c42019fd47d22262b905974d62d829545d485f/fonttools-4.63.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007", size = 5213271, upload-time = "2026-05-14T12:03:07.238Z" }, + { url = "https://files.pythonhosted.org/packages/08/ef/b3c6b9b5be2f82416d73fe2ed2e96e2793cd80e7510bd6a17ca79cdd88ec/fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02", size = 2881131, upload-time = "2026-05-14T12:03:13.386Z" }, + { url = "https://files.pythonhosted.org/packages/44/a0/c815bea63117fa63e4e1c01f8a1110d2112fa003f838e6467094ec2432ce/fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0", size = 2426704, upload-time = "2026-05-14T12:03:15.801Z" }, + { url = "https://files.pythonhosted.org/packages/44/04/0b91d8e916e92ad1fac9e4624760baf0fd5ff2ead614c2f68fb21373f03f/fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af", size = 5044298, upload-time = "2026-05-14T12:03:18.085Z" }, + { url = "https://files.pythonhosted.org/packages/77/c7/2342da9830e3e9d4870305ca5d2091d2a83284f2953079b7bdd3b5e029d8/fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8", size = 4999800, upload-time = "2026-05-14T12:03:20.161Z" }, + { url = "https://files.pythonhosted.org/packages/e6/6d/67fe16c48d7ce050979b33f47e0d28a318f02da030602e944c34f7a16ef3/fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b", size = 4982666, upload-time = "2026-05-14T12:03:22.87Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/3bbab338c07c71fa56269953845e92c951a61457bbbb0f1022551ea266d9/fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78", size = 5133598, upload-time = "2026-05-14T12:03:25.168Z" }, + { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "fsspec" +version = "2025.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/27/954057b0d1f53f086f681755207dda6de6c660ce133c829158e8e8fe7895/fsspec-2025.12.0.tar.gz", hash = "sha256:c505de011584597b1060ff778bb664c1bc022e87921b0e4f10cc9c44f9635973", size = 309748, upload-time = "2025-12-03T15:23:42.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/c7/b64cae5dba3a1b138d7123ec36bb5ccd39d39939f18454407e5468f4763f/fsspec-2025.12.0-py3-none-any.whl", hash = "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b", size = 201422, upload-time = "2025-12-03T15:23:41.434Z" }, +] + +[package.optional-dependencies] +http = [ + { name = "aiohttp", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] + +[[package]] +name = "gguf" +version = "0.19.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/ae/17f1308ae45cd7b08ebb521747d5b23f4efc4d172038a4e228dd5106c3ff/gguf-0.19.0.tar.gz", hash = "sha256:dbadcd6cc7ccd44256f2229fe7c2dff5e8aa5cf0612ab987fd2b1a57e428923f", size = 111220, upload-time = "2026-05-06T13:04:03.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/bb/d71d6da82763528c2c2ed6b59a9d6142c6595545a4c448e2085d155e88c2/gguf-0.19.0-py3-none-any.whl", hash = "sha256:70bcd10edfe697fb2dad6e40af2234b9d8ece9a41a99761405121ebda1c3c1cd", size = 118475, upload-time = "2026-05-06T13:04:02.588Z" }, +] + +[[package]] +name = "graphviz" +version = "0.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b3/3ac91e9be6b761a4b30d66ff165e54439dcd48b83f4e20d644867215f6ca/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", size = 200434, upload-time = "2025-06-15T09:35:05.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" }, +] + +[[package]] +name = "greenlet" +version = "3.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/f1/fbbfef6af0bad0548f09bc28948ea3c275b4edb19e17fc5ca9900a6a634d/greenlet-3.5.3.tar.gz", hash = "sha256:a61efc018fd3eb317eeca31aba90ee9e7f26f22884a79b6c6ec715bf71bb62f1", size = 200270, upload-time = "2026-06-26T19:28:24.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/58/5404031044f55afad7aad1aff8be3f22b1bed03e237cfeabbc7e5c8cfde0/greenlet-3.5.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:aca9b4ce85b152b5524ef7d88170efdff80dc0032aa8b75f9aaf7f3479ea95b4", size = 287424, upload-time = "2026-06-26T18:20:31.469Z" }, + { url = "https://files.pythonhosted.org/packages/b4/bf/1c65e9b94a54d547068fa5b5a8a06f221f3316b48908e08668d29c77cb50/greenlet-3.5.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f71be4920368fe1fabeeaa53d1e3548337e2b223d9565f8ad5e392a75ba23fc", size = 606523, upload-time = "2026-06-26T19:07:08.859Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c7/b66baacc95775ad511287acb0137b95574a9ce5491902372b7564799d790/greenlet-3.5.3-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d77e67f65f98449e3fb83f795b5d0a8437aead2f874ca89c96576caf4be3af6", size = 618315, upload-time = "2026-06-26T19:10:06.055Z" }, + { url = "https://files.pythonhosted.org/packages/78/2b/28ed29463522fdbe4c15b1f63922041626a7478316b34ab4adda3f0a4aba/greenlet-3.5.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8540f1e6205bd13ca0ce685581037219ca54a1b41a0a15d228c6c9b8ad5903d7", size = 617381, upload-time = "2026-06-26T18:32:16.077Z" }, + { url = "https://files.pythonhosted.org/packages/2a/7b/ad04e9d1337fc04965dc9fc616b6a72cb65a24b800a014c011ec812f5489/greenlet-3.5.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ef56fe650f50575bf843acde967b9c567687f3c22340941a899b7bc56e956a8", size = 1577771, upload-time = "2026-06-26T19:09:01.537Z" }, + { url = "https://files.pythonhosted.org/packages/d8/33/6c87ab7ba663f70ca21f3022aad1ffe56d3f3e0521e836c2415e13abcc3c/greenlet-3.5.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5121af01cf911e70056c00d4b46d5e9b5d1415550038573d744138bacb59e6b8", size = 1644048, upload-time = "2026-06-26T18:31:42.996Z" }, + { url = "https://files.pythonhosted.org/packages/5d/6e/4c37d51a2b7f82d2ff11bb6b5f7d766d9a011726624af255e843727627a3/greenlet-3.5.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:719757059f5a53fd0dde23f78cffeafcdd97b21c850ddb7ca684a3c1a1f122e2", size = 288685, upload-time = "2026-06-26T18:22:08.977Z" }, + { url = "https://files.pythonhosted.org/packages/7a/73/815dd90131c1b71ebdf53dbc7c276cafec2a1173b97559f97aba72724a87/greenlet-3.5.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:efa9f765dd09f9d0cdac651ffdf631ee59ec5dc6ee7a73e0c012ba9c52fbdf5b", size = 604761, upload-time = "2026-06-26T19:07:10.114Z" }, + { url = "https://files.pythonhosted.org/packages/9f/57/079cfe76bcef36b153b25607ee91c6fcb58f17f8b23c86bbbeabe0c88d72/greenlet-3.5.3-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7faba15ac005376e02a0384504e0243be3370ce010296a44a820feb342b505ab", size = 617044, upload-time = "2026-06-26T19:10:07.25Z" }, + { url = "https://files.pythonhosted.org/packages/37/87/b4d095775a3fb1bcafbb483fc206b27ebb785724c83051447737085dc54e/greenlet-3.5.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:87142215824be6ac05e2e8e2786eec307ccbc27c36723c3881959df654af6861", size = 614244, upload-time = "2026-06-26T18:32:17.594Z" }, + { url = "https://files.pythonhosted.org/packages/8a/70/7559b609683650fa2b95b8ab84b4ab0b26556a635d19675e12aa832d826d/greenlet-3.5.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215275b1b49320987352e6c1b054acca0064f965a2c66992bed9a6f7d913f149", size = 1574210, upload-time = "2026-06-26T19:09:03.077Z" }, + { url = "https://files.pythonhosted.org/packages/ae/73/be55392074c60fc37655ca40fa6022457bfbf6718e9e342a7b0b41f96dd2/greenlet-3.5.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6b1b0eed82364b0e32c4ea0f221452d33e6bb17ae094d9f72aed9851812747ea", size = 1638627, upload-time = "2026-06-26T18:31:44.748Z" }, +] + +[[package]] +name = "grpcio" +version = "1.82.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/90/bc/656b89387d6f4ed7e0686c7b64c2ae7e554a759aa58122c8e5fb99392c32/grpcio-1.82.1.tar.gz", hash = "sha256:707b24abd90fcb1e45bcc080577da1dbf9971d107490589b9539af8e1e77b4b5", size = 13187300, upload-time = "2026-07-08T12:36:16.588Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/5b/e5092af97fa671ca279b3e373251af4bf87d5fbda7dc85f6a616899562a7/grpcio-1.82.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:0ddb18a9a9e1f46692b3567ae4abb3f8d117ce6afea48650f8eca06d8ab5d06f", size = 6181472, upload-time = "2026-07-08T12:34:31.009Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/18053a3a2ca03d0c2a1b8cc7271e705007a16aa5dae84bac00935c5b1a7f/grpcio-1.82.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:cf855b1af246720f567b0ce5d0724d45dfa4188eecc3296a2a69257b11b9e94b", size = 11970995, upload-time = "2026-07-08T12:34:33.603Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7e/21b1acb052876ad00959ec4d1b05fe08607d650bcfa282073bb164c2703c/grpcio-1.82.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddb30cb13e25bc13cea70ffc69d6d90c49d36ea6c1d4549e6912f70177834cac", size = 6760127, upload-time = "2026-07-08T12:34:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/3e/12/25eef9c245c54f0061317d13a302357fe8ea03bac240b2b02ececcf54da4/grpcio-1.82.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1e822b2774f719c017cbe700b6e47173b6ae290fb84906f52a5a3c2c60b62e1e", size = 7484377, upload-time = "2026-07-08T12:34:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/a0/41/1a348767eb9d9bd7765dc4fa8a01723d3bb386d67f981ee5c6f9c02b8b1c/grpcio-1.82.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5dafb1ece8ed45dee7c738f166ec82e19673221ed5ab8967f72858a4685345b2", size = 6924269, upload-time = "2026-07-08T12:34:40.583Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b9/3aae7a03d34c86ea27988db859a6087c186f6c3f53f9b551e07afd989bfa/grpcio-1.82.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e06503106e7271e0a49fd5a1ac04747f1e47e87d900476db6fe45bc87ee411f4", size = 7531848, upload-time = "2026-07-08T12:34:43.277Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/3c4afa625d0dac9090707966916284c035fc5b2fb3e2c51e156accee6735/grpcio-1.82.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ff99bc8cafb6a952201c37b995f425e641c93ffa6e072258525feab57290141d", size = 8568217, upload-time = "2026-07-08T12:34:45.502Z" }, + { url = "https://files.pythonhosted.org/packages/20/9c/d8489c628e73e20a3d034e7f66912de7b1acb405f01d388f056a88e47924/grpcio-1.82.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:644ae1b94266ac785330f4590a69e52b6a7eb73029043a02209db81c81397d69", size = 7938771, upload-time = "2026-07-08T12:34:48.323Z" }, + { url = "https://files.pythonhosted.org/packages/dc/88/d1350bf3343a2ed87d801584e40609f6c6bd3087926eeca03de50348cf4a/grpcio-1.82.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:c09bd5fa0d5b1fbd773ec349fe61441c3e4ebf168c229aa7538a820bdfad6a58", size = 6144689, upload-time = "2026-07-08T12:34:55.567Z" }, + { url = "https://files.pythonhosted.org/packages/e6/33/71875cdecd27c24ac1385d4783a09853f01b84a825a36aec2a2bc7d0d080/grpcio-1.82.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:1eae24810720734598e3e6a1a528d5de0f265fe3fc86575e9ecce424b9ec7379", size = 11952034, upload-time = "2026-07-08T12:34:58.128Z" }, + { url = "https://files.pythonhosted.org/packages/82/b2/d9125df3d8a140dec12cc82c05b7deafedeababcff6496f28b2fd5634d10/grpcio-1.82.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a6bd5daf5bde7b24d7ad2cbaf8bf9eac620d96222016bb5e7ddde930dec0673f", size = 6710772, upload-time = "2026-07-08T12:35:01.33Z" }, + { url = "https://files.pythonhosted.org/packages/88/9b/69e2d1627398b964f34437dc476a5aff5a2cc8e7f247d26272b5674b5faf/grpcio-1.82.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1ecfde669cb687ac020d31ff76debe5dc7a62213335f02262eb6625628da1c03", size = 7450677, upload-time = "2026-07-08T12:35:03.926Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e7/8f855ca29c294956122a2a73023655b9b02602d5111dad2b9b00e7631c68/grpcio-1.82.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:011c8badee95734dee8bf05ce3464756a0ac3ebb8d443afd20c0e2b5e4640ad9", size = 6886855, upload-time = "2026-07-08T12:35:06.174Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f0/fa87e85f49925f44c479d07e58b051e69bcfef6b6d5fbc6749d140f6730a/grpcio-1.82.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b85f4564926fb23114d239392bdcae200db1e6179629edd7d7ab0ab89c96a197", size = 7501323, upload-time = "2026-07-08T12:35:08.49Z" }, + { url = "https://files.pythonhosted.org/packages/67/55/2e0b10ae1d3ef9dcc480b91dc2158f4931fc4675d3af0a2836e39b2a744f/grpcio-1.82.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2c0c8270833395644c3fe6b6a806397955a2bc0538000a19a78b90c05a6c16e0", size = 8536899, upload-time = "2026-07-08T12:35:10.975Z" }, + { url = "https://files.pythonhosted.org/packages/bd/95/a3d8b0431fa221efc51ee39d73595ede74ba82a43b7c4313192e580face2/grpcio-1.82.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2ba199205ff46c7778290fe1673c91ac8e7e45678dd5c86e9e56fa33ec8788f6", size = 7913892, upload-time = "2026-07-08T12:35:13.944Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "hf-xet" +version = "1.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/39/67be8d71f900d9a55761b6022821d6679fb56c64f1b6063d5af2c2606727/hf_xet-1.5.2.tar.gz", hash = "sha256:73044bd31bae33c984af832d19c752a0dffb67518fee9ddbd91d616e1101cf47", size = 903674, upload-time = "2026-07-16T17:29:56.833Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/ba/2b70603c7552db82baeb2623e2336898304a17328845151be4fe1f48d420/hf_xet-1.5.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f922b8f5fb84f1dd3d7ab7a1316354a1bca9b1c73ecfc19c76e51a2a49d29799", size = 4033760, upload-time = "2026-07-16T17:29:43.884Z" }, + { url = "https://files.pythonhosted.org/packages/60/ac/b097a86a1e4a6098f3a79382643ab09d5733d87ccc864877ad1e12b49b70/hf_xet-1.5.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:045f84440c55cdeb659cf1a1dd48c77bcd0d2e93632e2fea8f2c3bdee79f38ed", size = 3841438, upload-time = "2026-07-16T17:29:45.539Z" }, + { url = "https://files.pythonhosted.org/packages/d3/35/db860aa3a0780660324a506ad4b3d322ddc6ecbba4b9340aed0942cbf21c/hf_xet-1.5.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db78c39c83d6279daddc98e2238f373ab8980685556d42472b4ec51abcf03e8c", size = 4428006, upload-time = "2026-07-16T17:29:46.996Z" }, + { url = "https://files.pythonhosted.org/packages/af/6b/832dd980af4b0c3ae0660e309285f2ffcdff2faa38129390dbb47aa4a3f9/hf_xet-1.5.2-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7db73c810500c54c6760be8c39d4b2e476974de85424c50063efc22fdda13025", size = 4221099, upload-time = "2026-07-16T17:29:48.525Z" }, + { url = "https://files.pythonhosted.org/packages/9e/05/ae50f0d34e3254e6c3e208beb2519f6b8673016fc4b3643badaf6450d186/hf_xet-1.5.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6395cfe3c9cbead4f16b31808b0e67eac428b66c656f856e99636adaddea878f", size = 4420766, upload-time = "2026-07-16T17:29:50.092Z" }, + { url = "https://files.pythonhosted.org/packages/07/a9/c050bc2743a2bcd68928bfee157b08681667a164a24ec95fbfcfcd717e08/hf_xet-1.5.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cde8cd167126bb6109b2ceb19b844433a4988643e8f3e01dd9dd0e4a34535097", size = 4636716, upload-time = "2026-07-16T17:29:51.62Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "h11", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "certifi", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "httpcore", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "huggingface-hub" +version = "1.24.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "fsspec", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "hf-xet", marker = "(platform_machine == 'AMD64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'darwin') or (platform_machine == 'amd64' and sys_platform == 'darwin') or (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'darwin') or (platform_machine == 'AMD64' and sys_platform == 'linux') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'amd64' and sys_platform == 'linux') or (platform_machine == 'arm64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "httpx", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/9b/d3bb4e7d792835daf34dd7091bbc7d7b4e0437d9388f1ea7239cce49f478/huggingface_hub-1.24.0.tar.gz", hash = "sha256:18431ff4daae0749aa9ba102fc952e314c98e1d30ebdec5319d85ca0a83e1ae5", size = 921848, upload-time = "2026-07-17T09:54:01.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/c3/aeaaf3911d2529614be18d1c8b5496afc185560e76568063d517283318af/huggingface_hub-1.24.0-py3-none-any.whl", hash = "sha256:6ed4120a84a6beec900640aa7e346bd766a6b7341e41526fef5dc8bd81fb7d59", size = 771904, upload-time = "2026-07-17T09:53:59.106Z" }, +] + +[[package]] +name = "hydra-core" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "antlr4-python3-runtime", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "omegaconf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/8e/07e42bc434a847154083b315779b0a81d567154504624e181caf2c71cd98/hydra-core-1.3.2.tar.gz", hash = "sha256:8a878ed67216997c3e9d88a8e72e7b4767e81af37afb4ea3334b269a4390a824", size = 3263494, upload-time = "2023-02-23T18:33:43.03Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/50/e0edd38dcd63fb26a8547f13d28f7a008bc4a3fd4eb4ff030673f22ad41a/hydra_core-1.3.2-py3-none-any.whl", hash = "sha256:fa0238a9e31df3373b35b0bfb672c34cc92718d21f81311d8996a16de1141d8b", size = 154547, upload-time = "2023-02-23T18:33:40.801Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "indic-numtowords" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/46/683e92580d9c1752917d2f9ec2a44d2adc21cdfe4deeaa0fe87fc23dbea8/indic_numtowords-1.1.0.tar.gz", hash = "sha256:d1addc21444c332e05bfd8726af427960c096c2a16776d98bee4fbc36ade5d25", size = 44220, upload-time = "2025-08-18T12:24:13.075Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/16/b2b6491d95a15bda712163b4e27428f2cb1ac3a1b4fb59b140dbc76f6ce5/indic_numtowords-1.1.0-py3-none-any.whl", hash = "sha256:bf4b7b9e539323d9b00bc868caa2d9369170b8f3ac4d19619bf9c6cdc6f89572", size = 71635, upload-time = "2025-08-18T12:24:11.065Z" }, +] + +[[package]] +name = "inflect" +version = "7.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typeguard", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/c6/943357d44a21fd995723d07ccaddd78023eace03c1846049a2645d4324a3/inflect-7.5.0.tar.gz", hash = "sha256:faf19801c3742ed5a05a8ce388e0d8fe1a07f8d095c82201eb904f5d27ad571f", size = 73751, upload-time = "2024-12-28T17:11:18.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl", hash = "sha256:2aea70e5e70c35d8350b8097396ec155ffd68def678c7ff97f51aa69c1d92344", size = 35197, upload-time = "2024-12-28T17:11:15.931Z" }, +] + +[[package]] +name = "intervaltree" +version = "3.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sortedcontainers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/c3/b2afa612aa0373f3e6bb190e6de35f293b307d1537f109e3e25dbfcdf212/intervaltree-3.2.1.tar.gz", hash = "sha256:f3f7e8baeb7dd75b9f7a6d33cf3ec10025984a8e66e3016d537e52130c73cfe2", size = 1231531, upload-time = "2025-12-24T04:25:06.773Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/7f/8a80a1c7c2ed05822b5a2b312d2995f30c533641f8198366ba2e26a7bb03/intervaltree-3.2.1-py2.py3-none-any.whl", hash = "sha256:a8a8381bbd35d48ceebee932c77ffc988492d22fb1d27d0ba1d74a7694eb8f0b", size = 25929, upload-time = "2025-12-24T04:25:05.298Z" }, +] + +[[package]] +name = "ipython" +version = "9.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "decorator", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "ipython-pygments-lexers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "jedi", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "matplotlib-inline", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pexpect", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "prompt-toolkit", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "psutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "stack-data", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "traitlets", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/59/165d3b4d75cc34add3122c4417ecb229085140ac573103c223cd01dde96f/ipython-9.15.0.tar.gz", hash = "sha256:da2819ce2aa83135257df830660b1176d986c3d2876db24df01974fa955b2756", size = 4442580, upload-time = "2026-06-26T11:03:35.913Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/3a/948263ca3b9d65bb2b1b0c521b3a49fad5d59ada58724bd87d2bd5ff3f36/ipython-9.15.0-py3-none-any.whl", hash = "sha256:515ad9c3cdf0c932a5a9f6245419e8aba706b7bd03c3e1d3a1c83d9351d6aa6e", size = 630895, upload-time = "2026-06-26T11:03:33.809Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "jedi" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/b7/a3635f6a2d7cf5b5dd98064fc1d5fbbafcb25477bcea204a3a92145d158b/jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011", size = 3119416, upload-time = "2026-05-01T23:38:47.814Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/93/242e2eab5fe682ffcb8b0084bde703a41d51e17ee0f3a31ff0d9d813620a/jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67", size = 4884812, upload-time = "2026-05-01T23:38:43.919Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jiwer" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "rapidfuzz", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/3e/71b95cf0e2179fb5de8744a79fd36c8bd4e02e1803129a16d423884b6654/jiwer-3.1.0.tar.gz", hash = "sha256:dc492d09e570f1baba98c76aba09baf8e09c06e6808a4ba412dd4bde67fb79ac", size = 103187, upload-time = "2025-01-31T12:14:10.86Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/f4/35634d9eeff3b0bab51f5b9474ee569b1186bf29cf0d9d67b84acc80c53d/jiwer-3.1.0-py3-none-any.whl", hash = "sha256:5a14b5bba4692e1946ca3c6946435f7d90b1b526076ccb6c12be763e2146237d", size = 22303, upload-time = "2025-01-31T12:14:08.893Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + +[[package]] +name = "kaldi-python-io" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/45/e3e542ffa8970ebd782fcece35e2295de9c60e8c396c2c1a403410d1b24e/kaldi-python-io-1.2.2.tar.gz", hash = "sha256:4ebb4029c6c58296cc0abf96edff02832ba341d290ed37624a8d00105f0f7c00", size = 8814, upload-time = "2021-03-18T12:02:05.832Z" } + +[[package]] +name = "kaldialign" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/58/bd83457ab1f4296cb48da2057330fd669e14d0139353d87f9c138fc055af/kaldialign-0.12.0.tar.gz", hash = "sha256:f25743ef7dcf15716c5ac47e164dd7191cab791196a78c27cff6a99c253e1a14", size = 31415, upload-time = "2026-06-15T13:16:40.7Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/0a/8ab4e2d67477f99933d6223e895e9183c5dc03e998aece770b43ffd4996d/kaldialign-0.12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:188b7a5b267ee1435332c42a9862065b28ac72d74f883a58b2263d330dab1623", size = 165066, upload-time = "2026-06-15T13:16:32.139Z" }, + { url = "https://files.pythonhosted.org/packages/db/fe/3aced2daa28ab585e99b99c6503a5ad2423dfdfbb01591ea7b6c74ba5012/kaldialign-0.12.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb94f376bc851b32862b5e33f4ac948b8e0627e082ec6bf42611ca87564c19de", size = 99681, upload-time = "2026-06-15T13:17:01.06Z" }, + { url = "https://files.pythonhosted.org/packages/c6/df/8cab4ce97fe3f9654da1ca7e43a20b98de38491bb7aa4265e716aaa9450b/kaldialign-0.12.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0703057b1b8a5e46f58182d31729681ed0ce0a8fb4fcb5555f36cac39805d2b6", size = 110009, upload-time = "2026-06-15T13:16:57.525Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/f7c852333a77887ce9166415512d19da329c4896ec0a16127b250c20fd5e/kaldialign-0.12.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3a4f914f4971d20784710944a965de5ce0d1aa1ce26934767c0aee95194e0d98", size = 166411, upload-time = "2026-06-15T13:16:45.578Z" }, + { url = "https://files.pythonhosted.org/packages/35/c9/a01c036b6e0afef2139bcc3088d3ce9fbad111864457c89ac059b8fbaee4/kaldialign-0.12.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62694144a5e0ae086910bd979bc6b99b36c97a4276614bd28b5b06fed133abbf", size = 99987, upload-time = "2026-06-15T13:18:05.331Z" }, + { url = "https://files.pythonhosted.org/packages/d0/00/77885350408ef2ec6281cafd3dfbec099c25893d502bcc7ac819637309c5/kaldialign-0.12.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8189d32046b3a865b6f147662620feba736580b5424368164c6a7bc927d3e0a8", size = 110985, upload-time = "2026-06-15T13:16:46.189Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/dd/a495a9c104be1c476f0386e714252caf2b7eca883915422a64c50b88c6f5/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c", size = 122798, upload-time = "2026-03-09T13:12:58.963Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb", size = 66216, upload-time = "2026-03-09T13:13:00.155Z" }, + { url = "https://files.pythonhosted.org/packages/0a/aa/510dc933d87767584abfe03efa445889996c70c2990f6f87c3ebaa0a18c5/kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac", size = 63911, upload-time = "2026-03-09T13:13:01.671Z" }, + { url = "https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27", size = 1438209, upload-time = "2026-03-09T13:13:03.385Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d6/76621246f5165e5372f02f5e6f3f48ea336a8f9e96e43997d45b240ed8cd/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398", size = 1248888, upload-time = "2026-03-09T13:13:05.231Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c1/31559ec6fb39a5b48035ce29bb63ade628f321785f38c384dee3e2c08bc1/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db", size = 1266304, upload-time = "2026-03-09T13:13:06.743Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ef/1cb8276f2d29cc6a41e0a042f27946ca347d3a4a75acf85d0a16aa6dcc82/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc", size = 1319650, upload-time = "2026-03-09T13:13:08.607Z" }, + { url = "https://files.pythonhosted.org/packages/4c/e4/5ba3cecd7ce6236ae4a80f67e5d5531287337d0e1f076ca87a5abe4cd5d0/kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679", size = 970949, upload-time = "2026-03-09T13:13:10.299Z" }, + { url = "https://files.pythonhosted.org/packages/5a/69/dc61f7ae9a2f071f26004ced87f078235b5507ab6e5acd78f40365655034/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309", size = 2199125, upload-time = "2026-03-09T13:13:11.841Z" }, + { url = "https://files.pythonhosted.org/packages/e5/7b/abbe0f1b5afa85f8d084b73e90e5f801c0939eba16ac2e49af7c61a6c28d/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2", size = 2293783, upload-time = "2026-03-09T13:13:14.399Z" }, + { url = "https://files.pythonhosted.org/packages/8a/80/5908ae149d96d81580d604c7f8aefd0e98f4fd728cf172f477e9f2a81744/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c", size = 1960726, upload-time = "2026-03-09T13:13:16.047Z" }, + { url = "https://files.pythonhosted.org/packages/84/08/a78cb776f8c085b7143142ce479859cfec086bd09ee638a317040b6ef420/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08", size = 2464738, upload-time = "2026-03-09T13:13:17.897Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e1/65584da5356ed6cb12c63791a10b208860ac40a83de165cb6a6751a686e3/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4", size = 2270718, upload-time = "2026-03-09T13:13:19.421Z" }, + { url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9", size = 123158, upload-time = "2026-03-09T13:13:23.127Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588", size = 66388, upload-time = "2026-03-09T13:13:24.765Z" }, + { url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819", size = 64068, upload-time = "2026-03-09T13:13:25.878Z" }, + { url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f", size = 1477934, upload-time = "2026-03-09T13:13:27.166Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf", size = 1278537, upload-time = "2026-03-09T13:13:28.707Z" }, + { url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d", size = 1296685, upload-time = "2026-03-09T13:13:30.528Z" }, + { url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083", size = 1346024, upload-time = "2026-03-09T13:13:32.818Z" }, + { url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6", size = 987241, upload-time = "2026-03-09T13:13:34.435Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1", size = 2227742, upload-time = "2026-03-09T13:13:36.4Z" }, + { url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0", size = 2323966, upload-time = "2026-03-09T13:13:38.204Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15", size = 1977417, upload-time = "2026-03-09T13:13:39.966Z" }, + { url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314", size = 2491238, upload-time = "2026-03-09T13:13:41.698Z" }, + { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947, upload-time = "2026-03-09T13:13:43.343Z" }, + { url = "https://files.pythonhosted.org/packages/1c/fa/2910df836372d8761bb6eff7d8bdcb1613b5c2e03f260efe7abe34d388a7/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797", size = 130262, upload-time = "2026-03-09T13:15:35.629Z" }, + { url = "https://files.pythonhosted.org/packages/0f/41/c5f71f9f00aabcc71fee8b7475e3f64747282580c2fe748961ba29b18385/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203", size = 138036, upload-time = "2026-03-09T13:15:36.894Z" }, + { url = "https://files.pythonhosted.org/packages/fa/06/7399a607f434119c6e1fdc8ec89a8d51ccccadf3341dee4ead6bd14caaf5/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7", size = 194295, upload-time = "2026-03-09T13:15:38.22Z" }, + { url = "https://files.pythonhosted.org/packages/e9/eb/5fcbbbf9a0e2c3a35effb88831a483345326bbc3a030a3b5b69aee647f84/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232", size = 59532, upload-time = "2026-03-09T13:15:47.047Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9b/e17104555bb4db148fd52327feea1e96be4b88e8e008b029002c281a21ab/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a", size = 57420, upload-time = "2026-03-09T13:15:48.199Z" }, + { url = "https://files.pythonhosted.org/packages/48/44/2b5b95b7aa39fb2d8d9d956e0f3d5d45aef2ae1d942d4c3ffac2f9cfed1a/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737", size = 79892, upload-time = "2026-03-09T13:15:49.694Z" }, + { url = "https://files.pythonhosted.org/packages/52/7d/7157f9bba6b455cfb4632ed411e199fc8b8977642c2b12082e1bd9e6d173/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16", size = 77603, upload-time = "2026-03-09T13:15:50.945Z" }, +] + +[[package]] +name = "lazy-loader" +version = "0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/ac/21a1f8aa3777f5658576777ea76bfb124b702c520bbe90edf4ae9915eafa/lazy_loader-0.5.tar.gz", hash = "sha256:717f9179a0dbed357012ddad50a5ad3d5e4d9a0b8712680d4e687f5e6e6ed9b3", size = 15294, upload-time = "2026-03-06T15:45:09.054Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl", hash = "sha256:ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005", size = 8044, upload-time = "2026-03-06T15:45:07.668Z" }, +] + +[[package]] +name = "lhotse" +version = "1.33.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "audioread", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "cytoolz", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "intervaltree", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "soundfile", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tabulate", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/5a/b606c87b0a50322200aafb0f0682e719890bf0f045152b53e161090a6e8f/lhotse-1.33.0.tar.gz", hash = "sha256:3e91fca8531fc4c1798d0a6de1b3c7ea6bf2e181df70e5985927a131761c67f5", size = 686482, upload-time = "2026-04-20T13:11:08.579Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/e2/fbcb65dfed851f28ea15eca62cf449bc0b36378b005e6bec720714a9fb19/lhotse-1.33.0-py3-none-any.whl", hash = "sha256:8697bc74a8f3101594fca5661c7318c30899f3fdb132a44c7e99e794be6ac061", size = 903925, upload-time = "2026-04-20T13:11:07.027Z" }, +] + +[[package]] +name = "libcst" +version = "1.8.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/cd/337df968b38d94c5aabd3e1b10630f047a2b345f6e1d4456bd9fe7417537/libcst-1.8.6.tar.gz", hash = "sha256:f729c37c9317126da9475bdd06a7208eb52fcbd180a6341648b45a56b4ba708b", size = 891354, upload-time = "2025-11-03T22:33:30.621Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/15/95c2ecadc0fb4af8a7057ac2012a4c0ad5921b9ef1ace6c20006b56d3b5f/libcst-1.8.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3649a813660fbffd7bc24d3f810b1f75ac98bd40d9d6f56d1f0ee38579021073", size = 2211289, upload-time = "2025-11-03T22:32:04.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/c3/7e1107acd5ed15cf60cc07c7bb64498a33042dc4821874aea3ec4942f3cd/libcst-1.8.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0cbe17067055829607c5ba4afa46bfa4d0dd554c0b5a583546e690b7367a29b6", size = 2092927, upload-time = "2025-11-03T22:32:06.209Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ff/0d2be87f67e2841a4a37d35505e74b65991d30693295c46fc0380ace0454/libcst-1.8.6-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:59a7e388c57d21d63722018978a8ddba7b176e3a99bd34b9b84a576ed53f2978", size = 2237002, upload-time = "2025-11-03T22:32:07.559Z" }, + { url = "https://files.pythonhosted.org/packages/69/99/8c4a1b35c7894ccd7d33eae01ac8967122f43da41325223181ca7e4738fe/libcst-1.8.6-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:b6c1248cc62952a3a005792b10cdef2a4e130847be9c74f33a7d617486f7e532", size = 2301048, upload-time = "2025-11-03T22:32:08.869Z" }, + { url = "https://files.pythonhosted.org/packages/9b/8b/d1aa811eacf936cccfb386ae0585aa530ea1221ccf528d67144e041f5915/libcst-1.8.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6421a930b028c5ef4a943b32a5a78b7f1bf15138214525a2088f11acbb7d3d64", size = 2300675, upload-time = "2025-11-03T22:32:10.579Z" }, + { url = "https://files.pythonhosted.org/packages/c6/6b/7b65cd41f25a10c1fef2389ddc5c2b2cc23dc4d648083fa3e1aa7e0eeac2/libcst-1.8.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6d8b67874f2188399a71a71731e1ba2d1a2c3173b7565d1cc7ffb32e8fbaba5b", size = 2407934, upload-time = "2025-11-03T22:32:11.856Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3c/93365c17da3d42b055a8edb0e1e99f1c60c776471db6c9b7f1ddf6a44b28/libcst-1.8.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0c13d5bd3d8414a129e9dccaf0e5785108a4441e9b266e1e5e9d1f82d1b943c9", size = 2206166, upload-time = "2025-11-03T22:32:16.012Z" }, + { url = "https://files.pythonhosted.org/packages/1d/cb/7530940e6ac50c6dd6022349721074e19309eb6aa296e942ede2213c1a19/libcst-1.8.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f1472eeafd67cdb22544e59cf3bfc25d23dc94058a68cf41f6654ff4fcb92e09", size = 2083726, upload-time = "2025-11-03T22:32:17.312Z" }, + { url = "https://files.pythonhosted.org/packages/1b/cf/7e5eaa8c8f2c54913160671575351d129170db757bb5e4b7faffed022271/libcst-1.8.6-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:089c58e75cb142ec33738a1a4ea7760a28b40c078ab2fd26b270dac7d2633a4d", size = 2235755, upload-time = "2025-11-03T22:32:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/55/54/570ec2b0e9a3de0af9922e3bb1b69a5429beefbc753a7ea770a27ad308bd/libcst-1.8.6-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c9d7aeafb1b07d25a964b148c0dda9451efb47bbbf67756e16eeae65004b0eb5", size = 2301473, upload-time = "2025-11-03T22:32:20.499Z" }, + { url = "https://files.pythonhosted.org/packages/11/4c/163457d1717cd12181c421a4cca493454bcabd143fc7e53313bc6a4ad82a/libcst-1.8.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207481197afd328aa91d02670c15b48d0256e676ce1ad4bafb6dc2b593cc58f1", size = 2298899, upload-time = "2025-11-03T22:32:21.765Z" }, + { url = "https://files.pythonhosted.org/packages/35/1d/317ddef3669883619ef3d3395ea583305f353ef4ad87d7a5ac1c39be38e3/libcst-1.8.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:375965f34cc6f09f5f809244d3ff9bd4f6cb6699f571121cebce53622e7e0b86", size = 2408239, upload-time = "2025-11-03T22:32:23.275Z" }, +] + +[[package]] +name = "librosa" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "audioread", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "decorator", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "lazy-loader", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "msgpack", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numba", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pooch", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scikit-learn", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux')" }, + { name = "soundfile", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "soxr", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/36/360b5aafa0238e29758729e9486c6ed92a6f37fa403b7875e06c115cdf4a/librosa-0.11.0.tar.gz", hash = "sha256:f5ed951ca189b375bbe2e33b2abd7e040ceeee302b9bbaeeffdfddb8d0ace908", size = 327001, upload-time = "2025-03-11T15:09:54.884Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/ba/c63c5786dfee4c3417094c4b00966e61e4a63efecee22cb7b4c0387dda83/librosa-0.11.0-py3-none-any.whl", hash = "sha256:0b6415c4fd68bff4c29288abe67c6d80b587e0e1e2cfb0aad23e4559504a7fa1", size = 260749, upload-time = "2025-03-11T15:09:52.982Z" }, +] + +[[package]] +name = "lightning" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fsspec", extra = ["http"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "lightning-utilities", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pytorch-lightning", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, + { name = "torchmetrics", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/d0/78ea244ac044cd4df15aa8294a50ff3561fb177e7e5ba788aaa542046cae/lightning-2.4.0.tar.gz", hash = "sha256:9156604cc56e4b2b603f34fa7f0fe5107375c8e6d85e74544b319a15faa9ed0e", size = 620632, upload-time = "2024-08-07T09:46:44.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/2c/85eaf42c983b0cd81bcda5876da2c8e2a9fd347908666ea9855724369171/lightning-2.4.0-py3-none-any.whl", hash = "sha256:560163af9711cf59055c448232c473150a299089efce0d2be3cc3288082d8768", size = 810971, upload-time = "2024-08-07T09:46:39.874Z" }, +] + +[[package]] +name = "lightning-utilities" +version = "0.15.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/45/7fa8f56b17dc0f0a41ec70dd307ecd6787254483549843bef4c30ab5adce/lightning_utilities-0.15.3.tar.gz", hash = "sha256:792ae0204c79f6859721ac7f386c237a33b0ed06ba775009cb894e010a842033", size = 33553, upload-time = "2026-02-22T14:48:53.348Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/f4/ead6e0e37209b07c9baa3e984ccdb0348ca370b77cea3aaea8ddbb097e00/lightning_utilities-0.15.3-py3-none-any.whl", hash = "sha256:6c55f1bee70084a1cbeaa41ada96e4b3a0fea5909e844dd335bd80f5a73c5f91", size = 31906, upload-time = "2026-02-22T14:48:52.488Z" }, +] + +[[package]] +name = "llvmlite" +version = "0.48.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/a0/acc8ffcd5bdc63df0097e22c719bfcd61b604358343089313a8aebbb24ab/llvmlite-0.48.0.tar.gz", hash = "sha256:543b19f9ef8f3c7c60d1468191e4ee1b1537bf9f8a3d56f64c0ddd98de92edd2", size = 184016, upload-time = "2026-07-02T20:20:05.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/55/595981f14fbae9ba966feb12af552b1fe69889e44e64ac883a731ed335e0/llvmlite-0.48.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:56a7e24607d3f02d7b1bae8d29c7e1e423d53143d68b072999777f19678fe77b", size = 40480651, upload-time = "2026-07-01T18:41:18.438Z" }, + { url = "https://files.pythonhosted.org/packages/26/08/0109d1b9cb3f4603f3890e30bc66c65332b79185f12a045343b2ae431f67/llvmlite-0.48.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6fa532d6bb3fd3f0803567c736401c54aecfe1a396d3ad25d2440d220e09f0e7", size = 59890118, upload-time = "2026-07-01T18:41:28.184Z" }, + { url = "https://files.pythonhosted.org/packages/02/eb/c5281be180c789cdffbf45b671884c57d7e61345ef3b0f643a4965e108e8/llvmlite-0.48.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:979a66a3f28a02565383ff463527dce78e9b856298872a361283132488e83591", size = 58343458, upload-time = "2026-07-01T18:41:23.397Z" }, + { url = "https://files.pythonhosted.org/packages/92/a2/28696a9e61e245d1a79816d29d106692a90a2b6e7d78c98b326db70827af/llvmlite-0.48.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:d66c3beb4209087ddd4cf4ed2a0856b6887e6a913bdcf1aacfec9851cf2cba4e", size = 40480651, upload-time = "2026-07-01T18:41:35.694Z" }, + { url = "https://files.pythonhosted.org/packages/80/f2/72409351db66d0a317ec5087e076f31fb7b773a640db8a90ce6b5cac9edd/llvmlite-0.48.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:416fa4c2c66c2c6dc6d0a402648c19206e548efa0aa1eff01ad5cdad0af8217d", size = 59890118, upload-time = "2026-07-01T18:41:44.886Z" }, + { url = "https://files.pythonhosted.org/packages/3a/27/5ae2f3722606360480707adb47f001ad89df8251d06b14ee80336e660b66/llvmlite-0.48.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5e5a5131045b72345c71062ea1a91910dde913792b6c9b28ebb2c1c0a712e98", size = 58343459, upload-time = "2026-07-01T18:41:40.306Z" }, +] + +[[package]] +name = "lxml" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/3b/aab6728cae887456f409b4d75e8a01856e4f04bd510de38052a47768b680/lxml-6.1.1.tar.gz", hash = "sha256:ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40", size = 4197430, upload-time = "2026-05-18T19:19:06.424Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/b0/83f481780d1548750b8ce2ec824073deef2f452d9cd1a6faff8507e3d16d/lxml-6.1.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:53b7d2b7a10b1c35c0a5e21e9224accf60c1bbfba523990732e521b2b73adef2", size = 8526461, upload-time = "2026-05-18T19:17:25.862Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d5/30fa0f808002c7329397bfbb24e306789c0b29f04aa5842c07b174b4216f/lxml-6.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3f333630ab480244a1bff72043e511a91eb22e7595dead8653ee5612dd8f3d", size = 4595375, upload-time = "2026-05-18T19:17:34.555Z" }, + { url = "https://files.pythonhosted.org/packages/4f/d2/edb71cf0e561581a7c5eb2626244320eb04e9f8ce6d563184fd668b45073/lxml-6.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a4bbea04c97f6d78a48e3fbc1cb9116d2780b1b39e03a23f6eb9b603fd61f510", size = 4923654, upload-time = "2026-05-18T19:17:42.917Z" }, + { url = "https://files.pythonhosted.org/packages/4c/77/1bc7eeb0de4577d783fb625aa092cc9357883bba35845a3666bf1259f3dc/lxml-6.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db1d75f6617a49c1c01bc7023713e0ff59ab32c9579ae62a7674c0e34f3b0b0a", size = 5067921, upload-time = "2026-05-18T19:17:49.175Z" }, + { url = "https://files.pythonhosted.org/packages/1b/3c/c0690d74bd2bc17bc03b5b0d093569ead597dd0bfa088bf99eef8c24e19c/lxml-6.1.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a12689be69a28ddaa0ab99a5a1137da2afd5f8f16df7b5680b66f616d3eda1d", size = 5002456, upload-time = "2026-05-18T19:17:59.715Z" }, + { url = "https://files.pythonhosted.org/packages/66/8d/d1b3271af0c0f1e27e8472a849e4d2c65bc7766884b9ad2da9e76e145c88/lxml-6.1.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b73c339ae29b90fd2d06e58ebd555a751bde9cd6bbd36cc0281b9a2c94e9d8", size = 5202776, upload-time = "2026-05-18T19:18:08.924Z" }, + { url = "https://files.pythonhosted.org/packages/7a/45/689824ffb237fd10125ad273f32b28ff04dc6203c2822c85ff65a93df65e/lxml-6.1.1-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:752d3bbfe874715ccd0aec7f88d7fc623c0f1fd7aa7b3238a084e017bad2a009", size = 5329945, upload-time = "2026-05-18T19:18:13.673Z" }, + { url = "https://files.pythonhosted.org/packages/5d/c0/ef73af53767e958fd87d437c170f272e2f6e6c0f854939f133a895f1e711/lxml-6.1.1-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:6b1761fbf9ec984e2e9d9c589ef5f5fd684b7c19f92aadd567a26c5224958db6", size = 4659237, upload-time = "2026-05-18T19:18:18.657Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5e/e1158e40397585e91cb0472374a1f63d0926a1ddeaa92f13d1a1ffe306d5/lxml-6.1.1-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d680fbcb768404c601ecb43519ecd8461f6954cb11c06a78962f666832ccfca8", size = 5265904, upload-time = "2026-05-18T19:18:24.883Z" }, + { url = "https://files.pythonhosted.org/packages/a0/16/8687e5d1400ed1c0bc41dace232ebb7553952b618ea1f2e5fb6e2cfbbe23/lxml-6.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:162af1091cd785f2f27e62d3547ae9bc58ec5c86dd314d67021fd02463708d83", size = 5045225, upload-time = "2026-05-18T19:17:20.073Z" }, + { url = "https://files.pythonhosted.org/packages/ca/18/d877bd1ae2e5ffdfd4836565aba350db31feb2f2656d6ce70316ed66a05e/lxml-6.1.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e9308ff8241c532df3f3e570f9a5aeed6c853f888512ba4b75638d7c11c95ef6", size = 4712721, upload-time = "2026-05-18T19:17:40.512Z" }, + { url = "https://files.pythonhosted.org/packages/44/4d/1f44fd1d770b10dacbf6b5c6e520f4d6e0708744930f719dc04e67cab981/lxml-6.1.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5f6994074ebae6ffb04447268e37dc16edc304f9859cf91acb86e0af6c1b395c", size = 5252549, upload-time = "2026-05-18T19:17:51.236Z" }, + { url = "https://files.pythonhosted.org/packages/64/5d/1d66b84f850089254c230ef6ea6b267a5a54e2e179a5d960036a05d501d7/lxml-6.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80c2dfadb855da477cf73373ad29a333535dedb9b12bad02c9814c8e2b43bf08", size = 5226877, upload-time = "2026-05-18T19:18:00.875Z" }, + { url = "https://files.pythonhosted.org/packages/6a/6e/c4add832b6fc1e887125b96f880d7b9b70aae5248718e046b1704bcac4b9/lxml-6.1.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:104c09bda8d2a562824c0e319d0768ce26a779b7601e0931d33b09b53c392ef7", size = 8570821, upload-time = "2026-05-18T19:17:42.068Z" }, + { url = "https://files.pythonhosted.org/packages/22/00/ff3009c88e65de8011630acf8ab5a09cb2becd2aaf47fba2f3449f6224e9/lxml-6.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:25c6997a9a534e016695a0ba06b2f07945de682731ff01065b6d5a4474179da1", size = 4624252, upload-time = "2026-05-18T19:17:47.897Z" }, + { url = "https://files.pythonhosted.org/packages/42/95/bb63f0fd62e554fe078e1fb3c8fe9083c14ddc7ad7fa178d10e57e071ac7/lxml-6.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c921ba5c51e4e9f63b8b00267d06566e1f63407408a0496da2d1d0bfc819c7fc", size = 4930746, upload-time = "2026-05-18T19:18:29.637Z" }, + { url = "https://files.pythonhosted.org/packages/eb/99/0013e8d9b5960f4f041cf0b73e2f80c23eb5205b1f7bfb20203243651359/lxml-6.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:54a7f95e4de5fb94e2f9f4b9055c6ba33bf3d628fd77a1d647c5923caa2cdcdc", size = 5093723, upload-time = "2026-05-18T19:18:34.168Z" }, + { url = "https://files.pythonhosted.org/packages/29/91/317b332636bfc7bddcff828d41b3307f50043f4b237e40849c333d80fa1a/lxml-6.1.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f2ec43df44b1f76249ee0a615334f9b5b060e1c8bd90e706dad2d14d02f383", size = 5005557, upload-time = "2026-05-18T19:18:39.798Z" }, + { url = "https://files.pythonhosted.org/packages/42/2f/cc9bf06afe70f9c9093ae60855d9759da9db601ec4080f7473319666ffd7/lxml-6.1.1-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:70ef8a7e102a1508f8121aae5b0867abd663f72c14f0a9c937e6554cb4587b7b", size = 5631036, upload-time = "2026-05-18T19:18:44.858Z" }, + { url = "https://files.pythonhosted.org/packages/08/f6/af32e23e563971ffb0fb86be52bc5be5c2c118858ffc119bf6a9039b173d/lxml-6.1.1-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ebe6af670449830d6d9b752c256a983291c766a1365ba5d5460048f9e33a7818", size = 5240367, upload-time = "2026-05-18T19:18:49.217Z" }, + { url = "https://files.pythonhosted.org/packages/78/83/8555d40948b09ce86f1bd0c68a7ac31d07b1929f92cc1b074006c97ef2d2/lxml-6.1.1-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:27acc820660aaffa4f7c087f29120e12980f7779d56d8492d263170111284740", size = 5350171, upload-time = "2026-05-18T19:18:52.779Z" }, + { url = "https://files.pythonhosted.org/packages/63/75/5d92da93729b7bad783689e6496049fa40927b45bec7bf183c981de3ca70/lxml-6.1.1-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:1db753c9115ec7100d073b744d17e25e88a8f90f5c39b2f5dd878149af59671f", size = 4694874, upload-time = "2026-05-18T19:18:55.139Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b5/3aad415a9a25b822e783f15deeb4dffccf5113030f1afa2222dd929313d9/lxml-6.1.1-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4f469aebd783bb741c2ecb2a681008fd26bfe5c16a9a72ed5467f834e810df2", size = 5244492, upload-time = "2026-05-18T19:19:01.28Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a1/5fcf7eb9904b80086aa47dcf0027de07b1bb990afad2e6823144c368ae04/lxml-6.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:766b010012d59470072c1816b5b6c69f1d243e5db36ea5968e94accf430a4635", size = 5048232, upload-time = "2026-05-18T19:18:12.67Z" }, + { url = "https://files.pythonhosted.org/packages/77/74/1f601b63c7a69fcdf10fa9b148c81da8442204194f6c55509cc485c786b9/lxml-6.1.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b8d812c6011c08b8111a15e54dd990b8923692d80adf35488bee34026c35accf", size = 4777023, upload-time = "2026-05-18T19:18:15.928Z" }, + { url = "https://files.pythonhosted.org/packages/a2/b9/7a78f51aec95b1bf780d78e12705a9f6533284f8693dc5c0e6724fa53d3f/lxml-6.1.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:fe0306bd29505a9177aac19f1877174b0e7422c222a59f70b2cd41633448c3dc", size = 5645773, upload-time = "2026-05-18T19:18:23.223Z" }, + { url = "https://files.pythonhosted.org/packages/a5/6e/98a7b7ad54e4e74fa1f20fff776913980619d0ebe5558232d7da6580bdd8/lxml-6.1.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5ba186ad207446c65d3bb3d3e0412b032b1d9f595e59861e2354798c5703d955", size = 5233088, upload-time = "2026-05-18T19:18:31.433Z" }, + { url = "https://files.pythonhosted.org/packages/65/d1/bc0ed2427bf609f2ee10da303a6a226f9c8bce94f945dc29a32ce55de6e4/lxml-6.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aa366a1e55b8ebfe8ca8ddc3cfe75c8ebade181aeb0f661d0cb05986b647f72a", size = 5260995, upload-time = "2026-05-18T19:18:37.091Z" }, + { url = "https://files.pythonhosted.org/packages/b5/32/86a3f0f724a3a402d4627937a7fc27b160e45e7012b4adf47f6e1e844511/lxml-6.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:31033dc34636ea6b7d5cc11b1ddbda78a14de858ba9d3e1ed4b69a3085bc521e", size = 3930127, upload-time = "2026-05-18T19:19:02.27Z" }, + { url = "https://files.pythonhosted.org/packages/40/44/d832e82af08723761556d004b1d04d281c09f9a8cecd7d3148548c9941a3/lxml-6.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3893c14c4b6ac5b2d54ba8cf03e99fe5104e592de491f19bd6b82756c09f8004", size = 4210769, upload-time = "2026-05-18T19:20:41.427Z" }, + { url = "https://files.pythonhosted.org/packages/6d/39/0dc5949f759ed7d951e0bb8c2f2d9d7aca1908d22352fa84a8afd2ea54af/lxml-6.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c07da4cebf6889f03ebac8d238f62318e29f495de0aa18a51ea14e61ae907e2e", size = 4318163, upload-time = "2026-05-18T19:20:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/e6/fb/8ab3845fe046ba4cbf74536bcf6801a774b7caf4350de1c5d37f1f0a9e90/lxml-6.1.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6f0ce10945fab9c4c06ce14e22af9059d1a87493a9af4501a5b0b9187e21cf2", size = 4250945, upload-time = "2026-05-18T19:20:47.385Z" }, + { url = "https://files.pythonhosted.org/packages/68/1b/7553ab136894374ffae8851ec06f98f511cd8e66246e41b6be059d0a7289/lxml-6.1.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f8844cd288697c6425c9beba919302241e3278871dc6519515e72b04e987abcf", size = 4401664, upload-time = "2026-05-18T19:20:50.489Z" }, +] + +[[package]] +name = "mako" +version = "1.3.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/62/791b31e69ae182791ec67f04850f2f062716bbd205483d63a215f3e062d3/mako-1.3.12.tar.gz", hash = "sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a", size = 400219, upload-time = "2026-04-28T19:01:08.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/b1/a0ec7a5a9db730a08daef1fdfb8090435b82465abbf758a596f0ea88727e/mako-1.3.12-py3-none-any.whl", hash = "sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9", size = 78521, upload-time = "2026-04-28T19:01:10.393Z" }, +] + +[[package]] +name = "markdown" +version = "3.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, +] + +[[package]] +name = "marshmallow" +version = "4.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/25/7e/1dbd4096eb7c148cd2841841916f78820bb85a4d80a0c25c02d30815a7fb/marshmallow-4.3.0.tar.gz", hash = "sha256:fb43c53b3fe240b8f6af37223d6ef1636f927ad9bea8ab323afad95dff090880", size = 224485, upload-time = "2026-04-03T21:46:32.72Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/e0/ff24e25218bb59eb6290a530cea40651b14068b6e3659b20f9c175179632/marshmallow-4.3.0-py3-none-any.whl", hash = "sha256:46c4fe6984707e3cbd485dfebbf0a59874f58d695aad05c1668d15e8c6e13b46", size = 49148, upload-time = "2026-04-03T21:46:31.241Z" }, +] + +[[package]] +name = "matplotlib" +version = "3.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "cycler", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "fonttools", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "kiwisolver", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pillow", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyparsing", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/64/f9a391af28f518b11ad45a8a712353c94a0aefce09d3703200e5c54b610a/matplotlib-3.11.1.tar.gz", hash = "sha256:69647db5746941c793d6e445a4cd349323ffb87d9cc958c2ad84a659b4832d30", size = 32612045, upload-time = "2026-07-18T03:39:46.63Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/d0/791aa183dd88491555cf7d4be0b52b0bcf6c3c2a2c22c815a2e819bf53e2/matplotlib-3.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2", size = 9440302, upload-time = "2026-07-18T03:38:03.844Z" }, + { url = "https://files.pythonhosted.org/packages/35/74/82bbdf683a301f4478384c8aaba6903631a2ca18294b2d7655c9a542bffb/matplotlib-3.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2ace7273b9a5061a3b420918a16fae1f2dc5dfee1abcc13aba71b5d94b1820c", size = 9268549, upload-time = "2026-07-18T03:38:06.144Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f0/9b4298911303f74e6d83e64a81d996c0616405ec95046fac7f17e4258b9e/matplotlib-3.11.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee55e9041211bf84302ab55ec3965df18dd90ae19f8b58332a7feaf208bfe83", size = 10024922, upload-time = "2026-07-18T03:38:08.236Z" }, + { url = "https://files.pythonhosted.org/packages/84/6f/0bc3c3d05b021db44c14bc379a7c0df7d57302aa15380c16fd4e63fd6a9b/matplotlib-3.11.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f4bdeea33a8d15a071dbfe6d119451b1d719c733ac666d65357082901a9099", size = 10832170, upload-time = "2026-07-18T03:38:10.276Z" }, + { url = "https://files.pythonhosted.org/packages/db/4d/e375f39acdb2af5a9342730618608e39790ec842e6f1b392863028781459/matplotlib-3.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b4c78ceb2f11bcac7389d305cda17aeb1f4586a857854ab5780bd3dd8dbfc407", size = 10916701, upload-time = "2026-07-18T03:38:12.512Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6c/7ef7ebcb2bd9739b2b66b18b076e077f44bb46fdbe28ca0506edb3c62c79/matplotlib-3.11.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e15ef41507f3d525f46154ac9e3ae785dacde9f20e593a25de8986267892ef74", size = 9453849, upload-time = "2026-07-18T03:38:19.593Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f8/6d0c312c8d9738e7d9677f09fe5c986b3239e651a7b73a2deb38b65e4a71/matplotlib-3.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21a67b961a6d597bca54fae826cd20695ba4a6e4d05424a08da6e13e3176fd6b", size = 9283113, upload-time = "2026-07-18T03:38:21.95Z" }, + { url = "https://files.pythonhosted.org/packages/c9/cf/b4ad2cc81b6672ea29ea04e64e350a9f9b493b0908ccd884c67eeff8f7b2/matplotlib-3.11.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba8f811b8ddfac493734d6af0b2dff96919d0c28ca0d641858dab4262777c6ea", size = 10035615, upload-time = "2026-07-18T03:38:24.315Z" }, + { url = "https://files.pythonhosted.org/packages/88/90/4e10e033d9b66589d8ed98b84c95cdbb57033d57c1f41339d7393dbd2f2e/matplotlib-3.11.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c52f7ad20ef476806ed212380b1d54d20310c8b86bdc2c9a68b51f0024a44472", size = 10842559, upload-time = "2026-07-18T03:38:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/88/eb/799612d0f8cd3e816a10fec59329fca52cd2353264df80378dfc541ae855/matplotlib-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b14eb22961fe865efb0e4ff167e333e428908b00115a8d800ccb65ee108e481", size = 10927532, upload-time = "2026-07-18T03:38:28.532Z" }, + { url = "https://files.pythonhosted.org/packages/ee/38/ceb1d637c4db6d06141f3739e93af3321e7caaabe69b57ae48ffe3ee95b1/matplotlib-3.11.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:427258425f9a3fc4ed79a91f9e9b9aaf5a82cb6571e85dc14063cc6fbb993741", size = 9438045, upload-time = "2026-07-18T03:39:39.491Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/72ad8b58602d3a6ef1dfc4b65ecd01634ab65a2bdf494c9fe0e966dbf081/matplotlib-3.11.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:1ac697e591c11b6ad04679a73c2d2f9980fe9d9f0311fb414a2e329706343dfb", size = 9266127, upload-time = "2026-07-18T03:39:41.597Z" }, + { url = "https://files.pythonhosted.org/packages/8a/6d/69552382fcc8e93d1f2763ef2665980a900a48b7f3a4c57ed290726d1cbc/matplotlib-3.11.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e4b9ac2f1f607ecda2af90a5232beee2af7582fce1cc30c4b6a1b012dc21ee99", size = 10019439, upload-time = "2026-07-18T03:39:43.78Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/c0/9f7c9a46090390368a4d7bcb76bb87a4a36c421e4c0792cdb53486ffac7a/matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79", size = 8150, upload-time = "2026-05-08T17:33:33.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mediapy" +version = "1.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipython", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "matplotlib", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pillow", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/b2/451be65c13d2d69b7601eded7ddd3f150884486715a9b3a705ffb08d0177/mediapy-1.1.6.tar.gz", hash = "sha256:9f44b760400964d8bea5121a213f94dc9a225d026d6a819901283a695e585634", size = 25459, upload-time = "2023-02-24T13:08:42.429Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/a0/0d55c59ea8a5f1b13b3eb931e1c0eab9c2a07322cad79cb51a596d2d2a5c/mediapy-1.1.6-py3-none-any.whl", hash = "sha256:c74370808b445666f95272bfdf0eb5707a43b7e05e5527f2dd0830e6892f976f", size = 24955, upload-time = "2023-02-24T13:08:40.53Z" }, +] + +[[package]] +name = "ml-dtypes" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453", size = 692314, upload-time = "2025-11-17T22:32:31.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/5e/712092cfe7e5eb667b8ad9ca7c54442f21ed7ca8979745f1000e24cf8737/ml_dtypes-0.5.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6c7ecb74c4bd71db68a6bea1edf8da8c34f3d9fe218f038814fd1d310ac76c90", size = 679734, upload-time = "2025-11-17T22:31:39.223Z" }, + { url = "https://files.pythonhosted.org/packages/4f/cf/912146dfd4b5c0eea956836c01dcd2fce6c9c844b2691f5152aca196ce4f/ml_dtypes-0.5.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc11d7e8c44a65115d05e2ab9989d1e045125d7be8e05a071a48bc76eb6d6040", size = 5056165, upload-time = "2025-11-17T22:31:41.071Z" }, + { url = "https://files.pythonhosted.org/packages/a9/80/19189ea605017473660e43762dc853d2797984b3c7bf30ce656099add30c/ml_dtypes-0.5.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19b9a53598f21e453ea2fbda8aa783c20faff8e1eeb0d7ab899309a0053f1483", size = 5034975, upload-time = "2025-11-17T22:31:42.758Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b8/3c70881695e056f8a32f8b941126cf78775d9a4d7feba8abcb52cb7b04f2/ml_dtypes-0.5.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a174837a64f5b16cab6f368171a1a03a27936b31699d167684073ff1c4237dac", size = 676927, upload-time = "2025-11-17T22:31:48.182Z" }, + { url = "https://files.pythonhosted.org/packages/54/0f/428ef6881782e5ebb7eca459689448c0394fa0a80bea3aa9262cba5445ea/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7f7c643e8b1320fd958bf098aa7ecf70623a42ec5154e3be3be673f4c34d900", size = 5028464, upload-time = "2025-11-17T22:31:50.135Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cb/28ce52eb94390dda42599c98ea0204d74799e4d8047a0eb559b6fd648056/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ad459e99793fa6e13bd5b7e6792c8f9190b4e5a1b45c63aba14a4d0a7f1d5ff", size = 5009002, upload-time = "2025-11-17T22:31:52.001Z" }, +] + +[[package]] +name = "more-itertools" +version = "11.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/1d/f4da6f02cdffe04d6362210b807146a26044c88d839208aec273bb0d9184/more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d", size = 145772, upload-time = "2026-05-22T14:14:29.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192", size = 72226, upload-time = "2026-05-22T14:14:28.824Z" }, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, +] + +[[package]] +name = "msgpack" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f9/c0a1c127f9049db9155afc316952ea571720dd01833ff5e4d7e8e6352dbb/msgpack-1.2.1.tar.gz", hash = "sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647", size = 183960, upload-time = "2026-06-18T16:13:52.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/6b/e9b1cdc042c4458801d2545ed782a95f3d6ba8e270cce8745b8603c7f748/msgpack-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:29a3f6e9667868429d8240dfd063ea5ffdc1321c13d783aa23827a38de0dcb22", size = 82812, upload-time = "2026-06-18T16:12:45.022Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3a/dd518a1bf78ed1e9ad8afe57307c079a00eafe4b3068932a27ca1ea56b4f/msgpack-1.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aded5bdf32609dc7987a49bbbd15a8ef096193f96dd8bbeb791de729e650acf5", size = 82739, upload-time = "2026-06-18T16:12:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/70/e0/7ba9e1542bf0771a27b8b37c1316e3f95ae9d748fd765284655c476ad4ef/msgpack-1.2.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:146ee4e9ce80b365c6d4c47073da9da7bcec473e58194ceee5dd7620ace77e06", size = 414233, upload-time = "2026-06-18T16:12:47.029Z" }, + { url = "https://files.pythonhosted.org/packages/03/8d/671d81534ea0e2b0e8a121be100020da09eb78861fe3aa8f3ef7dcd3bed1/msgpack-1.2.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a28d076ca7c82b9c8728ad90b7147489449557038bed50e4241eb832395169b4", size = 423843, upload-time = "2026-06-18T16:12:48.19Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b6/e5c737515ed1f166664b87601b532f58cbb73d8aa6a90b99f7c2c5037e8e/msgpack-1.2.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7d31c0ac0c640f877804c67cb2bc9f4e23dc2db97e96c2e67fa27d38283b41f8", size = 390772, upload-time = "2026-06-18T16:12:49.624Z" }, + { url = "https://files.pythonhosted.org/packages/a8/46/62ed8c2e87d7021eab19921594d961ef3aa3794eec76c716dc30f3bfd433/msgpack-1.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ff92d7feeaf5bc26c51495b69e2f99ed97ab79346fb6555f44be7dd2ac6503b", size = 409559, upload-time = "2026-06-18T16:12:50.936Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/59aa3887b860bbf43532835e192b1c388a17590d6068ae4f8b2bc74c906e/msgpack-1.2.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:779197a6513bab3c3632265e3d0f7cb3227e62510841a6f34f1eaa37efbb345e", size = 387838, upload-time = "2026-06-18T16:12:52.161Z" }, + { url = "https://files.pythonhosted.org/packages/09/11/f8563e471093420cf6478cb3271a0175d8402b82d879783d4035d2d03360/msgpack-1.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:67f6dd22fa72a93752643f07889796d62739a13415ee630169a8ce764f86cf9f", size = 421732, upload-time = "2026-06-18T16:12:53.556Z" }, + { url = "https://files.pythonhosted.org/packages/bc/dd/9e8cbd8f5582ca4b590336f2b91ee5662f6a6ca562b565abaf696a0f81ff/msgpack-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35", size = 83531, upload-time = "2026-06-18T16:12:58.249Z" }, + { url = "https://files.pythonhosted.org/packages/50/2e/ebdb85a8da151397a2790363676b7ed7c125924fe618e4c6d8befb0cc62c/msgpack-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c", size = 82657, upload-time = "2026-06-18T16:12:59.396Z" }, + { url = "https://files.pythonhosted.org/packages/26/aa/753ad8b007b464e1d8aa0c8e650b9c5f4f725e658fc5ac8a7635c55b7f6e/msgpack-1.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0", size = 410634, upload-time = "2026-06-18T16:13:00.383Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/6adabd4f6d5e686f97dd02ce7fce3fe4cf672cbac36b8f67ff4040e8ad8b/msgpack-1.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a", size = 419989, upload-time = "2026-06-18T16:13:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cc/85039b7b0eb168aaad7383a23c97e291a11f08351cb45a606ce865e4e3f1/msgpack-1.2.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6", size = 377544, upload-time = "2026-06-18T16:13:03.637Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/35963899493b32030c85fc513b723ae66144ac70c11ebc52e889e16e3d99/msgpack-1.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a", size = 400842, upload-time = "2026-06-18T16:13:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/8e2ac970c8f99264cd9997d1c73df5466bc19da3301d7dc5500862a9b089/msgpack-1.2.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1", size = 374108, upload-time = "2026-06-18T16:13:06.232Z" }, + { url = "https://files.pythonhosted.org/packages/17/dd/fa8bd265110dfa51c20cb529f9e6d240a16fafe7e645004c6af2d01353ba/msgpack-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64", size = 414939, upload-time = "2026-06-18T16:13:07.478Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, + { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, + { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, + { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, + { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, + { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, + { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, + { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, +] + +[[package]] +name = "multiprocess" +version = "0.70.19" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dill", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/f2/e783ac7f2aeeed14e9e12801f22529cc7e6b7ab80928d6dcce4e9f00922d/multiprocess-0.70.19.tar.gz", hash = "sha256:952021e0e6c55a4a9fe4cd787895b86e239a40e76802a789d6305398d3975897", size = 2079989, upload-time = "2026-01-19T06:47:39.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/aa/714635c727dbfc251139226fa4eaf1b07f00dc12d9cd2eb25f931adaf873/multiprocess-0.70.19-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1bbf1b69af1cf64cd05f65337d9215b88079ec819cd0ea7bac4dab84e162efe7", size = 144743, upload-time = "2026-01-19T06:47:24.562Z" }, + { url = "https://files.pythonhosted.org/packages/0f/e1/155f6abf5e6b5d9cef29b6d0167c180846157a4aca9b9bee1a217f67c959/multiprocess-0.70.19-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5be9ec7f0c1c49a4f4a6fd20d5dda4aeabc2d39a50f4ad53720f1cd02b3a7c2e", size = 144738, upload-time = "2026-01-19T06:47:26.636Z" }, + { url = "https://files.pythonhosted.org/packages/af/cb/f421c2869d75750a4f32301cc20c4b63fab6376e9a75c8e5e655bdeb3d9b/multiprocess-0.70.19-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1c3dce098845a0db43b32a0b76a228ca059a668071cfeaa0f40c36c0b1585d45", size = 144741, upload-time = "2026-01-19T06:47:27.985Z" }, + { url = "https://files.pythonhosted.org/packages/e3/45/8004d1e6b9185c1a444d6b55ac5682acf9d98035e54386d967366035a03a/multiprocess-0.70.19-py310-none-any.whl", hash = "sha256:97404393419dcb2a8385910864eedf47a3cadf82c66345b44f036420eb0b5d87", size = 134948, upload-time = "2026-01-19T06:47:32.325Z" }, + { url = "https://files.pythonhosted.org/packages/86/c2/dec9722dc3474c164a0b6bcd9a7ed7da542c98af8cabce05374abab35edd/multiprocess-0.70.19-py311-none-any.whl", hash = "sha256:928851ae7973aea4ce0eaf330bbdafb2e01398a91518d5c8818802845564f45c", size = 144457, upload-time = "2026-01-19T06:47:33.711Z" }, + { url = "https://files.pythonhosted.org/packages/71/70/38998b950a97ea279e6bd657575d22d1a2047256caf707d9a10fbce4f065/multiprocess-0.70.19-py312-none-any.whl", hash = "sha256:3a56c0e85dd5025161bac5ce138dcac1e49174c7d8e74596537e729fd5c53c28", size = 150281, upload-time = "2026-01-19T06:47:35.037Z" }, + { url = "https://files.pythonhosted.org/packages/7e/82/69e539c4c2027f1e1697e09aaa2449243085a0edf81ae2c6341e84d769b6/multiprocess-0.70.19-py39-none-any.whl", hash = "sha256:0d4b4397ed669d371c81dcd1ef33fd384a44d6c3de1bd0ca7ac06d837720d3c5", size = 133477, upload-time = "2026-01-19T06:47:38.619Z" }, +] + +[[package]] +name = "narwhals" +version = "2.24.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/1d/58946e5aab18393e793bd4add6985b95d0e01c3a2d832f38f54468b10dcd/narwhals-2.24.0.tar.gz", hash = "sha256:b5c0f684ccd9d7475b564111e319a4964abcf2baf79d3cf6b1003d06ac9b828d", size = 661143, upload-time = "2026-07-13T10:49:19.086Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/85/a5bfaebfd305ac18b57b0854d74e37e586809061a91fda62f0bd50c8518e/narwhals-2.24.0-py3-none-any.whl", hash = "sha256:42fdedf44e5b2ca7505630d45b4ac3058f38d8485cba9fe1652ca23152df7489", size = 461030, upload-time = "2026-07-13T10:49:17.571Z" }, +] + +[[package]] +name = "nemo-toolkit" +version = "2.8.0rc0" +source = { git = "https://github.com/NVIDIA-NeMo/NeMo.git?rev=6967f48fda2a#6967f48fda2a776a68bbaed6a71d7fea78ccc3f6" } +dependencies = [ + { name = "cuda-bindings", marker = "sys_platform == 'linux'" }, + { name = "fsspec", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numba", marker = "sys_platform == 'darwin'" }, + { name = "numexpr", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "onnx", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "ruamel-yaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scikit-learn", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tensorboard", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "text-unidecode", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "wget", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "wrapt", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] + +[package.optional-dependencies] +asr = [ + { name = "braceexpand", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "cloudpickle", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "datasets", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "editdistance", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "einops", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "fiddle", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "hydra-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "inflect", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "jiwer", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "kaldi-python-io", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "kaldialign", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "lhotse", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "librosa", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "lightning", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "marshmallow", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "mediapy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "nv-one-logger-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "nv-one-logger-pytorch-lightning-integration", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "nv-one-logger-training-telemetry", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "omegaconf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "optuna", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "peft", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyannote-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyannote-metrics", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pydub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyloudnorm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "resampy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "ruamel-yaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sacrebleu", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sacremoses", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux')" }, + { name = "sentencepiece", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "soundfile", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sox", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torchmetrics", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "transformers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "wandb", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "webdataset", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "whisper-normalizer", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] + +[[package]] +name = "networkx" +version = "3.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" }, +] + +[[package]] +name = "numba" +version = "0.66.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "llvmlite", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/a0/570e3dc53e5602b49108f62a13e529f1eec8bfc7ef37d49c825924dcf546/numba-0.66.0.tar.gz", hash = "sha256:b900e63a0e26c05ea9a6d5a3a5a0a177cb64c5011887bf43edb8c3ed2c38d363", size = 2806181, upload-time = "2026-07-01T23:12:46.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/02/970796b4daa709604cde22e87a7cda9bde473c278ea4a75f59fe38cee47f/numba-0.66.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:bbd531c327557a9004507fa6bff06c53ab51a7a5776b75261bb9cef1efe2b2ea", size = 2727049, upload-time = "2026-07-01T23:12:11.296Z" }, + { url = "https://files.pythonhosted.org/packages/8c/99/33a6ed9c1a0b5e42efa98eb0edf617d61dca576c82625947377b1d4540c9/numba-0.66.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc6629becb21a867d85401ec89f426dd24c484a4193ade8a38309debfd1529ca", size = 3808870, upload-time = "2026-07-01T23:12:12.944Z" }, + { url = "https://files.pythonhosted.org/packages/04/20/8c51126025211659235b8de2866dfa226984ae0c8273461a3cf374716741/numba-0.66.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aac69f3ccb8af100f5913c1241edc9692bad1cdd2508721713f426eb06c9a659", size = 3514498, upload-time = "2026-07-01T23:12:15.307Z" }, + { url = "https://files.pythonhosted.org/packages/62/a3/70deb7f88461c1cd5d16aa990c2380604102661a427667b8950dcdccc27f/numba-0.66.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:53ca5900b7cab15109796030113a6b28576bae5ad7bb507ad6dd1360ddd81ba4", size = 2727264, upload-time = "2026-07-01T23:12:18.669Z" }, + { url = "https://files.pythonhosted.org/packages/2d/55/25c319845e9a4e08f16611ddbda56a192eb7b6ed13e1a2bff2da272ffb97/numba-0.66.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0999e3ee1b18c48e1fb51d11af35ef59852c7f4f50569c9550c25faef0616ad1", size = 3866252, upload-time = "2026-07-01T23:12:20.429Z" }, + { url = "https://files.pythonhosted.org/packages/71/ef/a82d6fd6bf1b0fe461651e924d3647eeec9ac17f8eee4896264bf7480930/numba-0.66.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:efe0d2d5099790df945e0cb6e1b3104bd965d7bbfac50d62f1d5d1d6ade0825d", size = 3566974, upload-time = "2026-07-01T23:12:22.116Z" }, +] + +[[package]] +name = "numexpr" +version = "2.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8d/ca/c1217ae2c15c3284a9e219c269624f80fa1582622eb0400c711a26f84a43/numexpr-2.13.1.tar.gz", hash = "sha256:ecb722249c2d6ed7fefe8504bb17e056481a5f31233c23a7ee02085c3d661fa1", size = 119296, upload-time = "2025-09-30T18:36:33.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/aa/734ccb5b2d62ddb8c903adf1be8bf668df7fd31f886f8a274203a8317a43/numexpr-2.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bdf62745e072c670151c0705bddfe3f33c341dacb7eb255ddb1e8d2a257bfef5", size = 162936, upload-time = "2025-09-30T18:35:22.227Z" }, + { url = "https://files.pythonhosted.org/packages/4b/bc/bc081354c99d896b5986bb6683bc7f36e221e1464d9b8a5d9c5ad7a29c13/numexpr-2.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:91cf0521d8fed3f804640c4a6d22b5d9813d7e64b32c38215de163c7f092f7cc", size = 151819, upload-time = "2025-09-30T18:35:23.612Z" }, + { url = "https://files.pythonhosted.org/packages/bf/6d/c3a1c3c113a5cf72b431a9f4433511eb35f2063836ed1020f21781ca77aa/numexpr-2.13.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:58e2f111756fff63e27e495473d950e4c98bbebca55aa1572798b59110d6c84b", size = 450816, upload-time = "2025-09-30T18:35:24.887Z" }, + { url = "https://files.pythonhosted.org/packages/77/45/634492e37e31c9db273b6f0d39a83759bfda58ea32690a892b6a5246cfc4/numexpr-2.13.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a5a37b74561ed8dbd5f9be182d94419fa53f452e2d7d3e8d6dbef35a20f19f7", size = 441502, upload-time = "2025-09-30T18:35:26.262Z" }, + { url = "https://files.pythonhosted.org/packages/6a/04/cfd65881165fd800e0ea17985b03793a7a16488c1a93257b2cfa658bb73a/numexpr-2.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:78cb76676e63f02dcf507e3c563888018a68b6a2e2cd444628e09df270dfd0b2", size = 1415631, upload-time = "2025-09-30T18:35:27.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/15/0d037d173c3cd0254fdf1cf148fa4aa79da10119a688cc2e1027de3e7cee/numexpr-2.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d29b3351de4c43b56d2ef7f138ab7a8988e797291bcbbd56d545e4e7902f254a", size = 1464365, upload-time = "2025-09-30T18:35:29.182Z" }, + { url = "https://files.pythonhosted.org/packages/b5/24/b87ad61f09132d92d92e93da8940055f1282ee30c913737ae977cebebab6/numexpr-2.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6aa48c2f2bfa142dfe260441486452be8f70b5551c17bc846fccf76123d4a226", size = 162534, upload-time = "2025-09-30T18:35:33.361Z" }, + { url = "https://files.pythonhosted.org/packages/91/b8/8ea90b2c64ef26b14866a38d13bb496195856b810c1a18a96cb89693b6af/numexpr-2.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:67a3dd8b51e94251f535a9a404f1ac939a3ebeb9398caad20ae9d0de37c6d3b3", size = 151938, upload-time = "2025-09-30T18:35:34.608Z" }, + { url = "https://files.pythonhosted.org/packages/ab/65/4679408c4c61badbd12671920479918e2893c8488de8d5c7f801b3a5f57d/numexpr-2.13.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ca152998d44ea30b45ad6b8a050ac4a9408b61a17508df87ad0d919335d79b44", size = 452166, upload-time = "2025-09-30T18:35:36.643Z" }, + { url = "https://files.pythonhosted.org/packages/31/1b/11a1202f8b67dce8e119a9f6481d839b152cc0084940a146b52f8f38685b/numexpr-2.13.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4280c8f7cc024846be8fdd6582572bb0b6bad98fb2a68a367ef5e6e2e130d5f", size = 443123, upload-time = "2025-09-30T18:35:38.14Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5e/271bf56efac177abe6e5d5349365e460a2a4205a514c99e0b2203d827264/numexpr-2.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b86e1daa4e27d6bf6304008ed4630a055babf863db2ec8f282b4058bbfe466bd", size = 1417039, upload-time = "2025-09-30T18:35:39.832Z" }, + { url = "https://files.pythonhosted.org/packages/72/33/6b3164fdc553eceec901793f9df467a7b4151e21772514fc2a392f12c42f/numexpr-2.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30d189fc52ee4a33b869a0592553cd2ed686c20cded21b2ddf347a4d143f1bea", size = 1465878, upload-time = "2025-09-30T18:35:41.437Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/49/ec46835a70be8fa6446c495126ac84fdb28cb2558e1620ffb87a10c8b64c/numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4", size = 16969194, upload-time = "2026-05-18T23:33:13.503Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0d/f5957185c0ee2f3e12f78715aa9e3b353fd83633316c8532b38faa37e3f6/numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d", size = 14964111, upload-time = "2026-05-18T23:33:17.795Z" }, + { url = "https://files.pythonhosted.org/packages/ad/40/40a40ee0ddf7ceb782c49af278894b686e586d65d8c1889c8b5da01a3d7d/numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8", size = 5469159, upload-time = "2026-05-18T23:33:20.654Z" }, + { url = "https://files.pythonhosted.org/packages/63/13/f9a8046535cb21deae82f8d03de9617e08882d274fad2539630761888228/numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538", size = 6798936, upload-time = "2026-05-18T23:33:22.987Z" }, + { url = "https://files.pythonhosted.org/packages/33/a8/6fa8c1a345a8c85dbb21932c447bee07c30a2c2a3f31e369c0a84b300147/numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47", size = 15966692, upload-time = "2026-05-18T23:33:26.62Z" }, + { url = "https://files.pythonhosted.org/packages/02/03/74fe2a4cb3817d94d86402f2506554130a2f01414e299b5a843e5a8a957f/numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93", size = 16918164, upload-time = "2026-05-18T23:33:29.955Z" }, + { url = "https://files.pythonhosted.org/packages/c5/80/3615be3313f7e7696609bc194b9f0101da809df79e859bdb84e0cd043f46/numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8", size = 17322877, upload-time = "2026-05-18T23:33:34.724Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ac/a691e0fe2675e370d0e08ff905adc49a1c8830e8cae03efe4477e92cd55d/numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6", size = 18651487, upload-time = "2026-05-18T23:33:38.217Z" }, + { url = "https://files.pythonhosted.org/packages/95/2a/3d7b5ac8aac24feaf9ad7ed58f45b0bbc06d37e4338ae84c9f2298b570f9/numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1", size = 16689119, upload-time = "2026-05-18T23:33:54.065Z" }, + { url = "https://files.pythonhosted.org/packages/ea/12/92c4c131527599e8288d6918e888d88726f84d805d784b771f32408aeaef/numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb", size = 14699246, upload-time = "2026-05-18T23:33:57.621Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/c0a6b7b2ca128a8fb228575147073b660656734b8ebe4d76c8fd748dcc79/numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41", size = 5204410, upload-time = "2026-05-18T23:34:00.302Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d4/9770d14ba719432bb90a421bfd443872ed0f70f7264b64bec12ea363d5fd/numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698", size = 6551240, upload-time = "2026-05-18T23:34:02.852Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c6/50a46a6205feba2343f1d6d17438107c5dc491ed1c736e6ea68689fd906b/numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f", size = 15671012, upload-time = "2026-05-18T23:34:05.485Z" }, + { url = "https://files.pythonhosted.org/packages/99/60/14115e6364fa676c5397c2ad3004e527e9aa487abf5d0706ec81bbd08529/numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853", size = 16645538, upload-time = "2026-05-18T23:34:09.265Z" }, + { url = "https://files.pythonhosted.org/packages/ae/c5/693cbe59e57db94d2231fa519ca3978dc9e19da5a8f088588f5c6e947ff2/numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a", size = 17020706, upload-time = "2026-05-18T23:34:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fc/85b7c4eff9b4966ade25c2273cf7e7012e92366c032058653934b37de044/numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2", size = 18368541, upload-time = "2026-05-18T23:34:17.024Z" }, + { url = "https://files.pythonhosted.org/packages/de/12/b422cc84439adc0d00de605bf4a308890ae5c26f2c71fbd73e5d08fbb0dd/numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662", size = 16847511, upload-time = "2026-05-18T23:36:50.673Z" }, + { url = "https://files.pythonhosted.org/packages/44/53/f481bef68011740f8849418d82db07230e825013f31f4eef5ba5b805316a/numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7", size = 14889064, upload-time = "2026-05-18T23:36:53.879Z" }, + { url = "https://files.pythonhosted.org/packages/7f/57/42ed575c10ced8af951d426bc4e1f8aff16fd851db33f067036215a7f860/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f", size = 5394157, upload-time = "2026-05-18T23:36:57.194Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/f66cc724fcc36c1e364c67f51ae9146090b8b584f27d58b97fdae3edd737/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c", size = 6708728, upload-time = "2026-05-18T23:36:59.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/9c/c531f2293b91265d8b48e9b329f54fdd7ffae73cb4134ea10cca4237e9cc/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0", size = 15798374, upload-time = "2026-05-18T23:37:02.674Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b0/413077f6b1153ed3cba361401c6783bbad6114804a000cc22eb71c13e190/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02", size = 16747286, upload-time = "2026-05-18T23:37:06.327Z" }, +] + +[[package]] +name = "nv-one-logger-core" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "overrides", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "strenum", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "toml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/37/963095797035f371e0db6ea761f5aaccb624fc786af217115b423baeb0e2/nv_one_logger_core-2.3.1.tar.gz", hash = "sha256:cbb2f87604c78b96a302f32d87199902129d76153a73a20f8455a250b3246c1d", size = 52640, upload-time = "2025-10-29T21:11:55.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/c4/ea91554c4fcbff66057f667690101d7a4b965605741350ac661b03fa6c46/nv_one_logger_core-2.3.1-py3-none-any.whl", hash = "sha256:0c8b77bcdac4daa1ea913bf8d4afd2a057bd5526e3654ac39f67caba157341a6", size = 63066, upload-time = "2025-10-29T21:11:52.753Z" }, +] + +[[package]] +name = "nv-one-logger-pytorch-lightning-integration" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lightning", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "nv-one-logger-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "nv-one-logger-training-telemetry", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "strenum", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0c/d0/3475b7ab17d367362f650fb0419e8669f41e63c1018f4a8ac2fbecfd2e85/nv_one_logger_pytorch_lightning_integration-2.3.1.tar.gz", hash = "sha256:b32d99b6a8f02a16538bcade939b0a7edd7249e936aacefe336b5519447340c3", size = 10979, upload-time = "2025-10-29T21:22:10.464Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/56/01a55efb365b6864646b4ac941a1d9de66f024e880764510ba5a7a63f62c/nv_one_logger_pytorch_lightning_integration-2.3.1-py3-none-any.whl", hash = "sha256:f92904055fb0082516480cc1e3dd0bb6cedb2b033985ebfd4814b9cbf7da2cb2", size = 9822, upload-time = "2025-10-29T21:22:09.37Z" }, +] + +[[package]] +name = "nv-one-logger-training-telemetry" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nv-one-logger-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "strenum", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c5/21/016fa067967734d52f1ccf5a2a37a1a65216f2d7053bc2b85872cce956ca/nv_one_logger_training_telemetry-2.3.1.tar.gz", hash = "sha256:8c67940ea71799afaf1f46df3ba2f52f93aea26321c6f1c1d54aae02efc2a4af", size = 44435, upload-time = "2025-10-29T21:21:42.035Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/15/97e6e4ddfe5fc35bcee74a45b7c33fb73abb83713c7dfa26420b971a86c3/nv_one_logger_training_telemetry-2.3.1-py3-none-any.whl", hash = "sha256:5319443829b59378a498c3c62ac98973e14f31be675c229ff2b14e2fe109aa0b", size = 44140, upload-time = "2025-10-29T21:21:40.72Z" }, +] + +[[package]] +name = "nvidia-cublas-cu12" +version = "12.9.1.4" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/6c/90d3f532f608a03a13c1d6c16c266ffa3828e8011b1549d3b61db2ad59f5/nvidia_cublas_cu12-12.9.1.4-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:7a950dae01add3b415a5a5cdc4ec818fb5858263e9cca59004bb99fdbbd3a5d6", size = 575006342, upload-time = "2025-06-05T20:04:16.902Z" }, + { url = "https://files.pythonhosted.org/packages/77/3c/aa88abe01f3be3d1f8f787d1d33dc83e76fec05945f9a28fbb41cfb99cd5/nvidia_cublas_cu12-12.9.1.4-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:453611eb21a7c1f2c2156ed9f3a45b691deda0440ec550860290dc901af5b4c2", size = 581242350, upload-time = "2025-06-05T20:04:51.979Z" }, +] + +[[package]] +name = "nvidia-cuda-cupti-cu12" +version = "12.9.79" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/78/351b5c8cdbd9a6b4fb0d6ee73fb176dcdc1b6b6ad47c2ffff5ae8ca4a1f7/nvidia_cuda_cupti_cu12-12.9.79-py3-none-manylinux_2_25_aarch64.whl", hash = "sha256:791853b030602c6a11d08b5578edfb957cadea06e9d3b26adbf8d036135a4afe", size = 10077166, upload-time = "2025-06-05T20:01:01.385Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2e/b84e32197e33f39907b455b83395a017e697c07a449a2b15fd07fc1c9981/nvidia_cuda_cupti_cu12-12.9.79-py3-none-manylinux_2_25_x86_64.whl", hash = "sha256:096bcf334f13e1984ba36685ad4c1d6347db214de03dbb6eebb237b41d9d934f", size = 10814997, upload-time = "2025-06-05T20:01:10.168Z" }, +] + +[[package]] +name = "nvidia-cuda-nvrtc-cu12" +version = "12.9.86" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/85/e4af82cc9202023862090bfca4ea827d533329e925c758f0cde964cb54b7/nvidia_cuda_nvrtc_cu12-12.9.86-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:210cf05005a447e29214e9ce50851e83fc5f4358df8b453155d5e1918094dcb4", size = 89568129, upload-time = "2025-06-05T20:02:41.973Z" }, + { url = "https://files.pythonhosted.org/packages/64/eb/c2295044b8f3b3b08860e2f6a912b702fc92568a167259df5dddb78f325e/nvidia_cuda_nvrtc_cu12-12.9.86-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:096d4de6bda726415dfaf3198d4f5c522b8e70139c97feef5cd2ca6d4cd9cead", size = 44528905, upload-time = "2025-06-05T20:02:29.754Z" }, +] + +[[package]] +name = "nvidia-cuda-runtime-cu12" +version = "12.9.79" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/e0/0279bd94539fda525e0c8538db29b72a5a8495b0c12173113471d28bce78/nvidia_cuda_runtime_cu12-12.9.79-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83469a846206f2a733db0c42e223589ab62fd2fabac4432d2f8802de4bded0a4", size = 3515012, upload-time = "2025-06-05T20:00:35.519Z" }, + { url = "https://files.pythonhosted.org/packages/bc/46/a92db19b8309581092a3add7e6fceb4c301a3fd233969856a8cbf042cd3c/nvidia_cuda_runtime_cu12-12.9.79-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:25bba2dfb01d48a9b59ca474a1ac43c6ebf7011f1b0b8cc44f54eb6ac48a96c3", size = 3493179, upload-time = "2025-06-05T20:00:53.735Z" }, +] + +[[package]] +name = "nvidia-cudnn-cu12" +version = "9.20.0.48" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/77/1c382fdc5de163b2ff14d6174d12dc318c0a42302f5e3a4fbc5114ab0501/nvidia_cudnn_cu12-9.20.0.48-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:d9da9c15344323afae571751393552652c52486eab0b886530997bef664e29de", size = 664659972, upload-time = "2026-03-09T19:27:37.986Z" }, + { url = "https://files.pythonhosted.org/packages/3b/52/94aecda69df65ba1079a8b7dbe84632af5614dc0ed2c733185f6431874e3/nvidia_cudnn_cu12-9.20.0.48-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:7d7479e1321c7a039b33827f0247791ee1be091759032c1f66a287c4a643396a", size = 657910570, upload-time = "2026-03-09T19:28:58.944Z" }, +] + +[[package]] +name = "nvidia-cufft-cu12" +version = "11.4.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/2b/76445b0af890da61b501fde30650a1a4bd910607261b209cccb5235d3daa/nvidia_cufft_cu12-11.4.1.4-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1a28c9b12260a1aa7a8fd12f5ebd82d027963d635ba82ff39a1acfa7c4c0fbcf", size = 200822453, upload-time = "2025-06-05T20:05:27.889Z" }, + { url = "https://files.pythonhosted.org/packages/95/f4/61e6996dd20481ee834f57a8e9dca28b1869366a135e0d42e2aa8493bdd4/nvidia_cufft_cu12-11.4.1.4-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c67884f2a7d276b4b80eb56a79322a95df592ae5e765cf1243693365ccab4e28", size = 200877592, upload-time = "2025-06-05T20:05:45.862Z" }, +] + +[[package]] +name = "nvidia-cufile-cu12" +version = "1.14.1.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/28/b960e06d705a440c030edd84e16888ee14c743390bdb2a6368e92ffe8ef8/nvidia_cufile_cu12-1.14.1.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9552e2231792e94b1ff17bc99e958cc0e6bbbaa4a9d91fa2dbeed97716628fe6", size = 1210714, upload-time = "2025-06-05T20:06:11.898Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d2/110af3a1f77999d5eebf6ffae5d2305ab839e53c76eec3696640cc25b35d/nvidia_cufile_cu12-1.14.1.1-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:8dea77590761e02cb6dd955a57cb6414c58aa3cb1b7adbf9919869a11509cf65", size = 1135994, upload-time = "2025-06-05T20:06:03.952Z" }, +] + +[[package]] +name = "nvidia-curand-cu12" +version = "10.3.10.19" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/1c/2a45afc614d99558d4a773fa740d8bb5471c8398eeed925fc0fcba020173/nvidia_curand_cu12-10.3.10.19-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:de663377feb1697e1d30ed587b07d5721fdd6d2015c738d7528a6002a6134d37", size = 68292066, upload-time = "2025-05-01T19:39:13.595Z" }, + { url = "https://files.pythonhosted.org/packages/31/44/193a0e171750ca9f8320626e8a1f2381e4077a65e69e2fb9708bd479e34a/nvidia_curand_cu12-10.3.10.19-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:49b274db4780d421bd2ccd362e1415c13887c53c214f0d4b761752b8f9f6aa1e", size = 68295626, upload-time = "2025-05-01T19:39:38.885Z" }, +] + +[[package]] +name = "nvidia-cusolver-cu12" +version = "11.7.5.82" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/99/686ff9bf3a82a531c62b1a5c614476e8dfa24a9d89067aeedf3592ee4538/nvidia_cusolver_cu12-11.7.5.82-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:62efa83e4ace59a4c734d052bb72158e888aa7b770e1a5f601682f16fe5b4fd2", size = 337869834, upload-time = "2025-06-05T20:06:53.125Z" }, + { url = "https://files.pythonhosted.org/packages/33/40/79b0c64d44d6c166c0964ec1d803d067f4a145cca23e23925fd351d0e642/nvidia_cusolver_cu12-11.7.5.82-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:15da72d1340d29b5b3cf3fd100e3cd53421dde36002eda6ed93811af63c40d88", size = 338117415, upload-time = "2025-06-05T20:07:16.809Z" }, +] + +[[package]] +name = "nvidia-cusparse-cu12" +version = "12.5.10.65" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/6f/8710fbd17cdd1d0fc3fea7d36d5b65ce1933611c31e1861da330206b253a/nvidia_cusparse_cu12-12.5.10.65-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:221c73e7482dd93eda44e65ce567c031c07e2f93f6fa0ecd3ba876a195023e83", size = 366359408, upload-time = "2025-06-05T20:07:42.501Z" }, + { url = "https://files.pythonhosted.org/packages/12/46/b0fd4b04f86577921feb97d8e2cf028afe04f614d17fb5013de9282c9216/nvidia_cusparse_cu12-12.5.10.65-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:73060ce019ac064a057267c585bf1fd5a353734151f87472ff02b2c5c9984e78", size = 366465088, upload-time = "2025-06-05T20:08:20.413Z" }, +] + +[[package]] +name = "nvidia-cusparselt-cu12" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/f8/a809966c96e824b92df09ee3b7032442f5e975d873d7dadfef818d527f48/nvidia_cusparselt_cu12-0.8.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:5c72f727722f74762380e5f8755557c788b26d8fdcc49df1641c1b08e16d256c", size = 235985605, upload-time = "2025-09-05T18:46:39.601Z" }, + { url = "https://files.pythonhosted.org/packages/bb/14/e46964290aa587cb9fb7df20efdc60528ddd00d291ccffec47617fb06ca3/nvidia_cusparselt_cu12-0.8.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:cd1b1dc9e1ad31ea3353c1f985e2bd6f9e7ae0e797d7e6ce879d7b2ace5e80e8", size = 239274390, upload-time = "2025-09-05T18:47:44.816Z" }, +] + +[[package]] +name = "nvidia-nccl-cu12" +version = "2.29.7" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/cc/f48875411d1f176bce58e6343fd5d4131fc1db5420719ff25944bdc006c6/nvidia_nccl_cu12-2.29.7-py3-none-manylinux_2_18_aarch64.whl", hash = "sha256:0cf032ee22b560447daf0456108a75e32bd74a4de6c6b64725637a359fa48cd8", size = 293563644, upload-time = "2026-03-03T05:34:46.166Z" }, + { url = "https://files.pythonhosted.org/packages/31/1e/9e366f36efc550f07d6737f199e3f6bffafdf28795d007f10a77dd274f5c/nvidia_nccl_cu12-2.29.7-py3-none-manylinux_2_18_x86_64.whl", hash = "sha256:ecd0a012051abc20c1aa87328841efa8cade3ced65803046e38c2f03c0891fea", size = 293633942, upload-time = "2026-03-03T05:37:05.625Z" }, +] + +[[package]] +name = "nvidia-nvjitlink-cu12" +version = "12.9.86" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/0c/c75bbfb967457a0b7670b8ad267bfc4fffdf341c074e0a80db06c24ccfd4/nvidia_nvjitlink_cu12-12.9.86-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:e3f1171dbdc83c5932a45f0f4c99180a70de9bd2718c1ab77d14104f6d7147f9", size = 39748338, upload-time = "2025-06-05T20:10:25.613Z" }, + { url = "https://files.pythonhosted.org/packages/97/bc/2dcba8e70cf3115b400fef54f213bcd6715a3195eba000f8330f11e40c45/nvidia_nvjitlink_cu12-12.9.86-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:994a05ef08ef4b0b299829cde613a424382aff7efb08a7172c1fa616cc3af2ca", size = 39514880, upload-time = "2025-06-05T20:10:04.89Z" }, +] + +[[package]] +name = "nvidia-nvshmem-cu12" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/6a/03aa43cc9bd3ad91553a88b5f6fb25ed6a3752ae86ce2180221962bc2aa5/nvidia_nvshmem_cu12-3.4.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b48363fc6964dede448029434c6abed6c5e37f823cb43c3bcde7ecfc0457e15", size = 138936938, upload-time = "2025-09-06T00:32:05.589Z" }, + { url = "https://files.pythonhosted.org/packages/b5/09/6ea3ea725f82e1e76684f0708bbedd871fc96da89945adeba65c3835a64c/nvidia_nvshmem_cu12-3.4.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:042f2500f24c021db8a06c5eec2539027d57460e1c1a762055a6554f72c369bd", size = 139103095, upload-time = "2025-09-06T00:32:31.266Z" }, +] + +[[package]] +name = "nvidia-nvtx-cu12" +version = "12.9.79" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/ed/bb230dce7741f2778ba2ae3e8778fdb8bc58eee9fd95f07bf7b2d18e8081/nvidia_nvtx_cu12-12.9.79-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fec150986817f2b4e7eed72ed059f2dcb9ba3856b9a96134e448eac946a6952f", size = 85504, upload-time = "2025-06-05T20:03:10.21Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e4/82155e4aaedb41621087ba219c95e99c5e417f37a7649b4fb6ec32dcb14d/nvidia_nvtx_cu12-12.9.79-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d1f258e752294acdb4f61c3d31fee87bd0f60e459f1e2f624376369b524cd15d", size = 86120, upload-time = "2025-06-05T20:02:51.838Z" }, +] + +[[package]] +name = "omegaconf" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "antlr4-python3-runtime", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/48/6388f1bb9da707110532cb70ec4d2822858ddfb44f1cdf1233c20a80ea4b/omegaconf-2.3.0.tar.gz", hash = "sha256:d5d4b6d29955cc50ad50c46dc269bcd92c6e00f5f90d23ab5fee7bfca4ba4cc7", size = 3298120, upload-time = "2022-12-08T20:59:22.753Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/94/1843518e420fa3ed6919835845df698c7e27e183cb997394e4a670973a65/omegaconf-2.3.0-py3-none-any.whl", hash = "sha256:7b4df175cdb08ba400f45cae3bdcae7ba8365db4d165fc65fd04b050ab63b46b", size = 79500, upload-time = "2022-12-08T20:59:19.686Z" }, +] + +[[package]] +name = "onnx" +version = "1.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ml-dtypes", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "protobuf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/19/8ea73a64b368b75fe339771a20a02bc61ea1f551484c9e3d9d0bfbd0450f/onnx-1.22.0.tar.gz", hash = "sha256:ef40c0aaf0b643857ea9306fc7eddce17eaf9fb0407e4801f1fc5758443a38e0", size = 12024721, upload-time = "2026-06-15T12:50:05.354Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/55/30825c02c92a0380ce84c3feeeec95d329fa77548ba58cb10ad4bbfd83c6/onnx-1.22.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:2d8f229a553fa440fe623ed7b36fca5e7762da3af871c3f8f8ce451df73e2914", size = 20167891, upload-time = "2026-06-15T12:49:14.212Z" }, + { url = "https://files.pythonhosted.org/packages/4b/24/cd4ab52ecaf41c3fbed674772ccbfe39041cb257b8471a47a37e48bff3f8/onnx-1.22.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1a89a7cb9ba13d78f009bdec448ec82a98972589734f157022a2bff7a5973a6", size = 18892720, upload-time = "2026-06-15T12:49:16.904Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a0/c9d9d56ceadb1c0a90a7cbec5a0510520ab6538938944fa84548e4b5b054/onnx-1.22.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d0a2bdb15eb2b3cb65c438f3423d9620d14fdce32f92380e6bb1b2e09568ef5", size = 19110720, upload-time = "2026-06-15T12:49:19.812Z" }, + { url = "https://files.pythonhosted.org/packages/ee/6a/481561f1093834376ed493e4ca42a73e5be0d50031f2969c86593bdc7c96/onnx-1.22.0-cp312-abi3-macosx_12_0_universal2.whl", hash = "sha256:596fbf0490947533c1c1045ba860851dc9fb77471023dac9a71ba5b42ceab103", size = 20167081, upload-time = "2026-06-15T12:49:32.078Z" }, + { url = "https://files.pythonhosted.org/packages/84/55/b34fc2aa30aa54b4a775402d24c4082242c720283a274fe976ac8eb94480/onnx-1.22.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae5a563f281cd9d2845622cecf6c092a57e4ee1b138f66fdbbdd4200567a5e16", size = 18889249, upload-time = "2026-06-15T12:49:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/09/a6/bd32357e6cc1ecb473afd78193d7231724f284435d2db25696ecfaaa1503/onnx-1.22.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:955e02e1f6d385b53d52f9cd7b9cdf5caf417c300bcfe3c64c6d542be763845b", size = 19106514, upload-time = "2026-06-15T12:49:37.424Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9d/3af461ac6c714b8b369cb71499659932f4f12cfb066250b62f7567c3d530/onnx-1.22.0-cp312-abi3-pyemscripten_2025_0_wasm32.whl", hash = "sha256:82e9f27fc1223cb06d68a56bed6f9d3caf3d0dad1b61bce45006d529b15bd94c", size = 16966387, upload-time = "2026-06-15T12:49:40.918Z" }, +] + +[[package]] +name = "optuna" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alembic", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "colorlog", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/aa/05f5e3f662cc96a4c478fc3446b8ed6359825a2b504ecb614a9ac84e4a4d/optuna-4.9.0.tar.gz", hash = "sha256:b322e5cbdf1655fb84c37646c4a7a1f391de1b47806bbe222e015825d0a82b87", size = 485834, upload-time = "2026-06-01T06:23:30.424Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/f3/e5fcd5d9b15771ed6dc10e3a7eeddc672e418f4f4c4653d216cc1d857e2d/optuna-4.9.0-py3-none-any.whl", hash = "sha256:f52f3be6148654850c92a5860d398fd88ec6b2c84ab68d9c3d07dcff02e7afee", size = 425553, upload-time = "2026-06-01T06:23:28.804Z" }, +] + +[[package]] +name = "overrides" +version = "7.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/36/86/b585f53236dec60aba864e050778b25045f857e17f6e5ea0ae95fe80edd2/overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a", size = 22812, upload-time = "2024-01-27T21:01:33.423Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/ab/fc8290c6a4c722e5514d80f62b2dc4c4df1a68a41d1364e625c35990fcf3/overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49", size = 17832, upload-time = "2024-01-27T21:01:31.393Z" }, +] + +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, +] + +[[package]] +name = "pandas" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/87/4341c6252d1c47b08768c3d25ac487362bf403f0313ddae4a2a26c9b1b4c/pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc", size = 4651414, upload-time = "2026-05-11T18:54:29.21Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/16/b5c76b838fd9bf6ce84d3a53346b8874ec05c5f0040d75ef2c320100cd2a/pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98", size = 10338495, upload-time = "2026-05-11T18:52:11.558Z" }, + { url = "https://files.pythonhosted.org/packages/5a/b0/a4ffc4ae74d2d822200dcc46898987d8eb6032d1e2b219cae39da6f5cbcc/pandas-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639", size = 9938250, upload-time = "2026-05-11T18:52:17.005Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b2/3323601a52caee42c019e370090ca4544b241437240ca04f786cce82b0cf/pandas-3.0.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2", size = 10770558, upload-time = "2026-05-11T18:52:19.865Z" }, + { url = "https://files.pythonhosted.org/packages/32/f1/bbecd2f867b97abebe0f9b53d750f862251b40337e061b36676ded3d920f/pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27", size = 11274611, upload-time = "2026-05-11T18:52:22.622Z" }, + { url = "https://files.pythonhosted.org/packages/7f/4f/eafabf2d5fae5adf143b4d18d3706c5efdc368a7c4eb1ee8a3eddabbd0f6/pandas-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824", size = 11784670, upload-time = "2026-05-11T18:52:25.4Z" }, + { url = "https://files.pythonhosted.org/packages/49/44/1eb20389301b57b19cc099a1c2f662501f72f08a65f912d05822613c1532/pandas-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938", size = 12353708, upload-time = "2026-05-11T18:52:28.139Z" }, + { url = "https://files.pythonhosted.org/packages/24/f1/392f8c5bfc16f66a0d2d41561c01627c228fe7ed2a0d056ef11315042570/pandas-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09", size = 10357846, upload-time = "2026-05-11T18:52:36.143Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4", size = 9899550, upload-time = "2026-05-11T18:52:38.976Z" }, + { url = "https://files.pythonhosted.org/packages/31/a8/fa2535168fffcedf67f4f6de28d2dd903a747ca7c8ea6989451aaeb3a92f/pandas-3.0.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c", size = 10412965, upload-time = "2026-05-11T18:52:41.915Z" }, + { url = "https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9", size = 10894600, upload-time = "2026-05-11T18:52:45.02Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a4/2eb28f2fccb4ced4a2c79ab2a5dee9ade1ebf44922ebad6fea158c9f95d4/pandas-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf", size = 11422824, upload-time = "2026-05-11T18:52:48.058Z" }, + { url = "https://files.pythonhosted.org/packages/f8/45/830bb57f533a4604b355e07edcb8ea18cf88b5f94e5fca92f27052d7c597/pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c", size = 11950889, upload-time = "2026-05-11T18:52:50.905Z" }, +] + +[[package]] +name = "parso" +version = "0.8.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/4b/90c937815137d43ce71ba043cd3566221e9df6b9c805f24b5d138c9d40a7/parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1", size = 401824, upload-time = "2026-05-01T23:13:02.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/5d/8268b644392ee874ee82a635cd0df1773de230bde356c38de28e298392cc/parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c", size = 107025, upload-time = "2026-05-01T23:12:58.867Z" }, +] + +[[package]] +name = "peft" +version = "0.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "accelerate", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "psutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "safetensors", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "transformers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/0c/f2938db546ac7fc961ab5917cd50fcf5d0d70b406de93e3faccaa504e152/peft-0.18.0.tar.gz", hash = "sha256:c81c80b2056ab40c23d58ef25f74daab417ac653970718589a11a8af28218588", size = 634141, upload-time = "2025-11-13T11:13:06.603Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/55/481bf25613d40ef53534f664deba7b138fe566356b6ca10304e2b3b2529c/peft-0.18.0-py3-none-any.whl", hash = "sha256:624f69ca6393b765ccc6734adda7ca57d80b238f0900a42c357d8b67a03d62ff", size = 556427, upload-time = "2025-11-13T11:13:03.664Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "pillow" +version = "12.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" }, + { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2d/ede717bc1144f63886c21fd349bb95860b0d1a21149ff16f2bb362b612b6/pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd", size = 6934408, upload-time = "2026-07-01T11:53:53.487Z" }, + { url = "https://files.pythonhosted.org/packages/a3/48/9c58b685e69d49c31af6c8eb9012055fab7e665785165c84796e2c73ce72/pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c", size = 6337160, upload-time = "2026-07-01T11:53:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fa/dc2a5c0ba6df93f67c31d34b808b7ce440b40cdbf96f0b81cde1d1e6fa93/pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5", size = 7045172, upload-time = "2026-07-01T11:53:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" }, + { url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" }, + { url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" }, + { url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" }, + { url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" }, + { url = "https://files.pythonhosted.org/packages/75/18/2e8b40223153ccbc60df07f9e8928dc0c76202aa4e55ae9f53962b6510d6/pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468", size = 5302510, upload-time = "2026-07-01T11:56:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/46/3e/51fabf59d5ab801ceab709453d3ab6b180083496579549de4c45ced6528a/pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94", size = 4736058, upload-time = "2026-07-01T11:56:28.041Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/22fe9384b7949e25fb1293bcfc84fb82590ff4ea6b37c95b24d26d793d86/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e", size = 5237776, upload-time = "2026-07-01T11:56:30.263Z" }, + { url = "https://files.pythonhosted.org/packages/08/14/f6ba68107680ffa74b39985f3f30884e41318fbc4250caa423c79b4788bb/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3", size = 5860358, upload-time = "2026-07-01T11:56:32.68Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/cd/4f25b2f95b23f5d2c9c1fe43e49841bff5800562149b2666afc09309aa8f/platformdirs-4.10.1.tar.gz", hash = "sha256:ceab4084426fe6319ce18e86deada8ab1b7487c7aee7040c55e277c9ae793695", size = 31678, upload-time = "2026-07-18T03:53:43.808Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/73/6fd0bb9ce84138c3857f12e9de63bc901852975a092d545f18087a204aa2/platformdirs-4.10.1-py3-none-any.whl", hash = "sha256:0e4eff26be2d75293977f7cddc153fd9b8eaa7fb0c7b64ffe4076cb443117443", size = 22906, upload-time = "2026-07-18T03:53:42.576Z" }, +] + +[[package]] +name = "pooch" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/43/85ef45e8b36c6a48546af7b266592dc32d7f67837a6514d111bced6d7d75/pooch-1.9.0.tar.gz", hash = "sha256:de46729579b9857ffd3e741987a2f6d5e0e03219892c167c6578c0091fb511ed", size = 61788, upload-time = "2026-01-30T19:15:09.649Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl", hash = "sha256:f265597baa9f760d25ceb29d0beb8186c243d6607b0f60b83ecf14078dbc703b", size = 67175, upload-time = "2026-01-30T19:15:08.36Z" }, +] + +[[package]] +name = "portalocker" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/77/65b857a69ed876e1951e88aaba60f5ce6120c33703f7cb61a3c894b8c1b6/portalocker-3.2.0.tar.gz", hash = "sha256:1f3002956a54a8c3730586c5c77bf18fae4149e07eaf1c29fc3faf4d5a3f89ac", size = 95644, upload-time = "2025-06-14T13:20:40.03Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/a6/38c8e2f318bf67d338f4d629e93b0b4b9af331f455f0390ea8ce4a099b26/portalocker-3.2.0-py3-none-any.whl", hash = "sha256:3cdc5f565312224bc570c49337bd21428bba0ef363bbcf58b9ef4a9f11779968", size = 22424, upload-time = "2025-06-14T13:20:38.083Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "propcache" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/44/c87281c333769159c50594f22610f77398a47ccbfbbf23074e744e86f87c/propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427", size = 50208, upload-time = "2026-05-08T21:02:12.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/f1/8a8cc1c2c7e7934ab77e0163414f736fadbc0f5e8dd9673b952355ac175b/propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78", size = 90744, upload-time = "2026-05-08T20:59:45.799Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f4/651b1225e976bd1a2ba5cfba0c29d096581c2636b437e3a9a7ab6276270a/propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959", size = 52033, upload-time = "2026-05-08T20:59:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/15/a8/8ede85d6aa1f79fc7dc2f8fd2c8d65920b8272c3892903c8a1affde48cfb/propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7", size = 52754, upload-time = "2026-05-08T20:59:49.202Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fe/b3551b41bbc2f5b5bb088fc6920567cd43101253e68fbaa261339eb96fe1/propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511", size = 57573, upload-time = "2026-05-08T20:59:50.778Z" }, + { url = "https://files.pythonhosted.org/packages/83/27/ab851ebd1b7172e3e161f5f8d39e315d54a91bea246f01f4d872d3376aef/propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660", size = 60645, upload-time = "2026-05-08T20:59:52.227Z" }, + { url = "https://files.pythonhosted.org/packages/95/7d/466b3d18022e9897cbda9c735c493c5bd747d7a4c6f5ea1480b4cec434b6/propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66", size = 61563, upload-time = "2026-05-08T20:59:53.866Z" }, + { url = "https://files.pythonhosted.org/packages/27/1b/16ab7f2cf2041da2f60d156ba64c2484eadf9168075b4ff43c3ef60045af/propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b", size = 58888, upload-time = "2026-05-08T20:59:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/0a/67/bb777ffd907633563bf35fd859c4ce97b0512c32f4633cf5d1eb7c33512b/propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67", size = 59253, upload-time = "2026-05-08T20:59:57.075Z" }, + { url = "https://files.pythonhosted.org/packages/b9/42/64f8d90b73fd9cdc1499b48057ff6d9cd2a98a25734c9bb62ecf07e87061/propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f", size = 57558, upload-time = "2026-05-08T20:59:58.602Z" }, + { url = "https://files.pythonhosted.org/packages/eb/02/dba5bc03c9041f2092ea55a449caf5dfe68352c6654511b29ba0654ddb69/propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c", size = 55007, upload-time = "2026-05-08T20:59:59.837Z" }, + { url = "https://files.pythonhosted.org/packages/14/c0/43f649c7aa2a77a3b100d84e9dea3a483120ecb608bfe36ce49eaff517fe/propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0", size = 60355, upload-time = "2026-05-08T21:00:01.144Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/435dafd27f1cb4a495381dae60e25883ccfe4020bb72818e8184c1678092/propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6", size = 59057, upload-time = "2026-05-08T21:00:02.401Z" }, + { url = "https://files.pythonhosted.org/packages/53/ae/6e292df9135d659944e96cb3389258e4a663e5b2b5f6c217ef0ddc8d2f73/propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27", size = 61938, upload-time = "2026-05-08T21:00:03.638Z" }, + { url = "https://files.pythonhosted.org/packages/0b/42/314ebc50d8159055411fd6b0bda322ff510e4b1f7d2e4927940ad0f6af20/propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f", size = 59731, upload-time = "2026-05-08T21:00:04.881Z" }, + { url = "https://files.pythonhosted.org/packages/4a/cb/e27bc2b2737a0bb49962b275efa051e8f1c35a936df7d5139b6b658b7dc9/propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba", size = 95887, upload-time = "2026-05-08T21:00:11.277Z" }, + { url = "https://files.pythonhosted.org/packages/e6/13/b8ae04c59392f8d11c6cd9fb4011d1dc7c86b81225c770280300e259ffe1/propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a", size = 54654, upload-time = "2026-05-08T21:00:12.604Z" }, + { url = "https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf", size = 55190, upload-time = "2026-05-08T21:00:13.935Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/085d0cd63062e84044e3f05797749c3f8e3938ff3aeb0eb2f69d43fafc91/propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144", size = 59995, upload-time = "2026-05-08T21:00:15.526Z" }, + { url = "https://files.pythonhosted.org/packages/9c/42/32cf8e3009e92b2645cf1e944f701e8ea4e924dffde1ee26db860bcbf7e4/propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9", size = 63422, upload-time = "2026-05-08T21:00:16.824Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/f112433f99fc979431b87a39ef169e3f8df070d99a72792c56d6937ac48b/propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42", size = 64342, upload-time = "2026-05-08T21:00:18.362Z" }, + { url = "https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476", size = 61639, upload-time = "2026-05-08T21:00:19.692Z" }, + { url = "https://files.pythonhosted.org/packages/cc/da/4d775080b1490c0ae604acda868bd71aabe3a89ed16f2aa4339eb8a283e7/propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba", size = 61588, upload-time = "2026-05-08T21:00:21.155Z" }, + { url = "https://files.pythonhosted.org/packages/04/ac/f076982cbe2195ee9cf32de5a1e46951d9fb399fc207f390562dd0fd8fb2/propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a", size = 60029, upload-time = "2026-05-08T21:00:22.713Z" }, + { url = "https://files.pythonhosted.org/packages/70/60/189be62e0dd898dce3b331e1b8c7a543cd3a405ac0c81fe8ee8a9d5d77e1/propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64", size = 56774, upload-time = "2026-05-08T21:00:24.001Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/93377b9c7939c1ffae98f878dee955efadfd638078bc86dbc21f9d52f651/propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913", size = 63532, upload-time = "2026-05-08T21:00:25.545Z" }, + { url = "https://files.pythonhosted.org/packages/14/f9/590ef6cfb9b8028d516d287812ece32bb0bc5f11fbb9c8bf6b2e6313fec8/propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1", size = 61592, upload-time = "2026-05-08T21:00:27.186Z" }, + { url = "https://files.pythonhosted.org/packages/b4/5e/70958b3034c297a630bba2f17ca7abc2d5f39a803ad7e370ab79d1ecd022/propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33", size = 64788, upload-time = "2026-05-08T21:00:28.8Z" }, + { url = "https://files.pythonhosted.org/packages/12/fd/77fe5936d8c3086ca9048f7f415f122ed82e53884a9ec193646b42deef06/propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a", size = 62514, upload-time = "2026-05-08T21:00:30.098Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" }, +] + +[[package]] +name = "protobuf" +version = "7.35.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/01/9ef0afd7999eb9badb3a768b4aedd78c86d4c65cfaf1958ab276199e76b4/protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a", size = 458717, upload-time = "2026-06-11T21:55:40.257Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/03/8aeeb7458d22546bf64b5250ca1daeb5ff757d900e8e4a7476c6f0db843e/protobuf-7.35.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6", size = 433226, upload-time = "2026-06-11T21:55:31.719Z" }, + { url = "https://files.pythonhosted.org/packages/37/4b/dfb89eb0e652a1ff073c39a59fb5e3a83cfe9b57a2c83fa6d78270101767/protobuf-7.35.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799", size = 328847, upload-time = "2026-06-11T21:55:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/0f/58/dc12f2cd484951524af6e3382c785869b9b3fb5e52ee95ae23add53ee8f9/protobuf-7.35.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4", size = 344030, upload-time = "2026-06-11T21:55:34.941Z" }, + { url = "https://files.pythonhosted.org/packages/e4/be/5b3cfe508bfab6761414ff944e3366eb13be4fd71efcd69450f89ba39f43/protobuf-7.35.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4", size = 327130, upload-time = "2026-06-11T21:55:35.921Z" }, + { url = "https://files.pythonhosted.org/packages/19/c7/5f7c636ec43e0c545e28d1f1db71990108306f7bdcb89f069ba97e428e7f/protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9", size = 171659, upload-time = "2026-06-11T21:55:39.155Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pyannote-core" +version = "6.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sortedcontainers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/be/4a35ea31c685aef801f7f35c193e7766ca1bb948ae497a625cbfaa8c31ba/pyannote_core-6.0.1.tar.gz", hash = "sha256:4b4ada3276f6df4e073fa79166636e3597d0dcb5a0fe26014a3477867cc033fb", size = 327540, upload-time = "2025-09-16T09:24:39.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/57/ecf62344b9b81debd0ca95ed987135e93d1b039507f8174f52d1d19d8c6b/pyannote_core-6.0.1-py3-none-any.whl", hash = "sha256:924550d6ecf6b05ad13bf3f66f59c29fc740cf1c62a6fca860ac2e66908203e5", size = 57505, upload-time = "2025-09-16T09:24:37.798Z" }, +] + +[[package]] +name = "pyannote-database" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyannote-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/45/6210274c187cc457e854be8b56c6819fa14376f27e7e2b6021b2aa02449a/pyannote_database-6.1.1.tar.gz", hash = "sha256:bbe76da738257a9e64061123d9694ad7e949c4f171d91a9269606d873528cd10", size = 112225, upload-time = "2025-12-07T06:33:10.296Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/bf/6a6f5abaa4d9f803f34c9883ef5e316624eac6be0eaa87720216be9bba12/pyannote_database-6.1.1-py3-none-any.whl", hash = "sha256:36460c70ce9f50ff25c9ea365bc83ad625bb6b2494deccf6bd3fc750686ae684", size = 53735, upload-time = "2025-12-07T06:33:11.578Z" }, +] + +[[package]] +name = "pyannote-metrics" +version = "4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyannote-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyannote-database", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scikit-learn", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/ba/7dbc2f790d5e321e46dc1e250ff00b69cdefc0c5695b811e96a4b932cddd/pyannote_metrics-4.1.tar.gz", hash = "sha256:afe24c54ee0799e8cfbe8ee85fa517793c3450bb7eae8fedd1a77ccec0343f7e", size = 883419, upload-time = "2026-05-06T16:33:10.163Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/d3/9cd1df66aa9be47a36df46f007e198bbdec3ddebc1bd8833c7a9e8a554a9/pyannote_metrics-4.1-py3-none-any.whl", hash = "sha256:34a54b7671f61709c1865d0484843e5b46ea3c4e4e5260ab065e5b3156c733d3", size = 52116, upload-time = "2026-05-06T16:33:08.586Z" }, +] + +[[package]] +name = "pyarrow" +version = "25.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/f3/95428098d1fa7d04432fb750eed06b41304c2f6a5d3319985e64db2d9d41/pyarrow-25.0.0.tar.gz", hash = "sha256:d2d697008b5ec06d75952ef260c2e9a8a0f6ccfce24266c04c9c8ade927cb3b4", size = 1199181, upload-time = "2026-07-10T08:29:50.116Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/98/ae2b5acf9876dbeffa6f320776242c52caab062df55c8ac5501ed2679e74/pyarrow-25.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:2e3b6544e26e393fe2cd530f523e36c1c8d3c345bbbb60cca3fd866be8322517", size = 35939080, upload-time = "2026-07-10T08:26:04.53Z" }, + { url = "https://files.pythonhosted.org/packages/80/09/3de2a968edbd496c86cb8b932cdbee2d4b08c4a28e9884a15e5c705a646b/pyarrow-25.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:b724d127783b4c19f088fcdfc844cbc318809246a30307bcabd5ed02045e890e", size = 37633420, upload-time = "2026-07-10T08:26:10.354Z" }, + { url = "https://files.pythonhosted.org/packages/19/86/8399243a4ce080426ec37db18d5e29148b7ec960a8a8c7f9059a7bf6ef0a/pyarrow-25.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:244f98a595f70fa4fd35faa7508c4ae67e14a173397a4b3b49d2b3c360fb0062", size = 46861050, upload-time = "2026-07-10T08:26:16.397Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/72d704b02bc5fc6d06954d76a0208c1e79cad3ab370f6d6a91ffe5078870/pyarrow-25.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:0222f0071d13313962a88d21bf28b80d355ac39d81bfa6ff3fe00eeaf748e4be", size = 50056458, upload-time = "2026-07-10T08:26:23.271Z" }, + { url = "https://files.pythonhosted.org/packages/06/5d/3c31a60b6403d63cad2e0f829096f5fc5763a129ead4207a5d4690b96448/pyarrow-25.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b58726f118c079f9d4ed7e904975d4f15fd69d0741ba511a4e2dcaa4ef16354f", size = 49957793, upload-time = "2026-07-10T08:26:30.232Z" }, + { url = "https://files.pythonhosted.org/packages/34/f7/8f8a019061f9863a831915329264372a87ed25eaf9109ce56eb0e84012c5/pyarrow-25.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:38a2c887cb3883e241b70201688db34133b6dfadd04f03c8f9213df53770c18e", size = 53100544, upload-time = "2026-07-10T08:26:36.414Z" }, + { url = "https://files.pythonhosted.org/packages/73/44/fdd3a4377807b7dcabe2d4b5aa99dbbc98e2e5df3f1ca4e7f0aec492d987/pyarrow-25.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:149730a3d1f0fb59d663a0b8aa210adfd9c17c27cd94a0d143e60daea8320d4e", size = 35850884, upload-time = "2026-07-10T08:26:47.357Z" }, + { url = "https://files.pythonhosted.org/packages/bf/71/9f053177a7709b8c90abb00a2375b916286f9f0d6cfb21a5cadd4ef811e8/pyarrow-25.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:0721332c30fdd453fdd1fc203b2ac1f4c9db5aea28fa38d41f2574c4b068b9ec", size = 37616197, upload-time = "2026-07-10T08:26:53.564Z" }, + { url = "https://files.pythonhosted.org/packages/95/1a/22bfb6597dcdc861fa83c39c06e1457cb56f698940eff42fbb25de30e8e5/pyarrow-25.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fa1482b3da10cac2d4db6e26b81da543e237616af2ef6d466018b31ca586496f", size = 46841966, upload-time = "2026-07-10T08:27:07.685Z" }, + { url = "https://files.pythonhosted.org/packages/55/0e/cd705c042bc4fe7022478db577fcab4abdcfabb9bc37ab7a75556b3fcb2b/pyarrow-25.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:5d1dbf24e151042f2fa3c129563f65d66674128868496fb008c4272b16bdf778", size = 50088993, upload-time = "2026-07-10T08:27:14.268Z" }, + { url = "https://files.pythonhosted.org/packages/98/ee/d822e1ee31fe31ec5d057210e0605c950b975dcd8d9a332976cc859a9df8/pyarrow-25.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:20887a762dd61dcc530f93a140840ab1f6aa7836b33270e42d627ab3cf11e537", size = 49941005, upload-time = "2026-07-10T08:27:21.274Z" }, + { url = "https://files.pythonhosted.org/packages/33/1b/207a90cc64619a095eb75a263ae069735f2810056d43c667befd573ec083/pyarrow-25.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:58d1ab556b0cea1c93fdb799b24ad58adb2f2a2788dbce782a94f64ae1a5cc9b", size = 53112355, upload-time = "2026-07-10T08:27:27.911Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pydantic-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-inspection", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, +] + +[[package]] +name = "pydub" +version = "0.25.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/9a/e6bca0eed82db26562c73b5076539a4a08d3cffd19c3cc5913a3e61145fd/pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f", size = 38326, upload-time = "2021-03-10T02:09:54.659Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327, upload-time = "2021-03-10T02:09:53.503Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyloudnorm" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/00/f915eaa75326f4209941179c2b93ac477f2040e4aeff5bb21d16eb8058f9/pyloudnorm-0.2.0.tar.gz", hash = "sha256:8bf597658ea4e1975c275adf490f6deb5369ea409f2901f939915efa4b681b16", size = 14037, upload-time = "2026-01-04T11:43:35.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/b6/65a49a05614b2548edbba3aab118f2ebe7441dfd778accdcdce9f6567f20/pyloudnorm-0.2.0-py3-none-any.whl", hash = "sha256:9bb69afb904f59d007a7f9ba3d75d16fb8aeef35c44d6df822a9f192d69cf13f", size = 10879, upload-time = "2026-01-04T11:43:34.534Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pytorch-lightning" +version = "2.6.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fsspec", extra = ["http"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "lightning-utilities", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, + { name = "torchmetrics", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/2c/8e73a3929b4c4bd600cafd38a97aaf7242a8cf518fb9f33d27c274ec898f/pytorch_lightning-2.6.5.tar.gz", hash = "sha256:1c32cefa76a1a9c4c5250338272d961d1e48b180e68396849efe128538ddb28e", size = 661673, upload-time = "2026-05-27T14:33:41.961Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/4d/5740c27110b83634d8491c3b5facf0111b3e554c3164f4fb953be9bddaf6/pytorch_lightning-2.6.5-py3-none-any.whl", hash = "sha256:62d9c8549b2278fedc3364f0a5607a56c6063d18635008f8cf3fae8d802b0d76", size = 852407, upload-time = "2026-05-27T14:33:39.856Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, +] + +[[package]] +name = "rapidfuzz" +version = "3.14.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/21/ef6157213316e85790041254259907eb722e00b03480256c0545d98acd33/rapidfuzz-3.14.5.tar.gz", hash = "sha256:ba10ac57884ce82112f7ed910b67e7fb6072d8ef2c06e30dc63c0f604a112e0e", size = 57901753, upload-time = "2026-04-07T11:16:31.931Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/f9/3c41a7be8855803f4f6c713b472226a98d31d41869d98f64f4ca790510d6/rapidfuzz-3.14.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e251126d48615e1f02b4a178f2cd0cd4f0332b8a019c01a2e10480f7552554b4", size = 1952372, upload-time = "2026-04-07T11:13:58.32Z" }, + { url = "https://files.pythonhosted.org/packages/9e/89/c2557e37531d03465193bff0ab9de70b468420a807d71a26a65100635459/rapidfuzz-3.14.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ab449c9abd0d4e1f8145dce0798a4c822a1a1933d613c764a641bea88b8bdab", size = 1159782, upload-time = "2026-04-07T11:14:00.127Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b2/ffeeb7eca1a897d51b998f4c0ef0281696c3b06abcca4f88f9def708ffe1/rapidfuzz-3.14.5-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb2829fedd672dd7107267189dabe2bbe07972801d636014417c6861eb89e358", size = 1383677, upload-time = "2026-04-07T11:14:01.696Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d0/4539e42a2d596e068f7738f279638a4a74edd1fbb6f8594e2458058979c6/rapidfuzz-3.14.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3d50e5861872935fece391351cbb5ba21d1bced277cf5e1143d207a0a35f1925", size = 3168906, upload-time = "2026-04-07T11:14:03.29Z" }, + { url = "https://files.pythonhosted.org/packages/5e/1c/3ec897eb9d8b05308aa8ef6ae4ed64b088ad521a3f9d8ff469e7e97bc2b0/rapidfuzz-3.14.5-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:7092a216728f80c960bd6b3807275d1ee318b168986bd5dc523349581d4890b8", size = 1478176, upload-time = "2026-04-07T11:14:04.94Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ba/970c03a12ce20a5399e22afe9f8932fd4cd1265b8a8461d0e63b00eb4eae/rapidfuzz-3.14.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9669753caef7fdc6529f6adcc5883ed98d65976445d9322e7dbdb6b697feee13", size = 2402441, upload-time = "2026-04-07T11:14:07.228Z" }, + { url = "https://files.pythonhosted.org/packages/81/93/61d351cae60c1d0e21ba5ff1a1015ad045539ed215da9d6e302204ed887a/rapidfuzz-3.14.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:823b1b9d9230809d8edcc18872770764bfe8ef4357995e16744047c8ccf0e489", size = 2511628, upload-time = "2026-04-07T11:14:09.234Z" }, + { url = "https://files.pythonhosted.org/packages/87/52/374d2d4f60fd98155142a869323aa221e30868cfa1f15171a0f64070c247/rapidfuzz-3.14.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f0b2af76b7e7060c09e1a0dfa9410eb19369cbe6164509bff2ef94094b54d2b6", size = 4275480, upload-time = "2026-04-07T11:14:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/d3/e3/574435c6aafb80254c191ef40d7aca2cb2bb97a095ec9395e9fa59ac307a/rapidfuzz-3.14.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0d3378f471ef440473a396ce2f8e97ee12f89a78b495540e0a5617bbfe895638", size = 1944601, upload-time = "2026-04-07T11:14:18.771Z" }, + { url = "https://files.pythonhosted.org/packages/d0/1f/fbad3102a255ecc112ce9a7e779bacab7fd14398217be8868dc9082ba363/rapidfuzz-3.14.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e910eebca9fd0eba245c0555e764597e8a0cccb673a92da2dc2397050725f48", size = 1164293, upload-time = "2026-04-07T11:14:20.534Z" }, + { url = "https://files.pythonhosted.org/packages/88/37/a3eb7ff6121ed3a5f199a8c38cc86c8e481816f879cb0e0b738b078c9a7e/rapidfuzz-3.14.5-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:01550fe5f60fd176aa66b7611289d46dc4aa4b1b904874c7b6d1d54e581c5ec1", size = 1371999, upload-time = "2026-04-07T11:14:22.63Z" }, + { url = "https://files.pythonhosted.org/packages/79/72/97a9728c711c7c1b06e107d3f0623880fb4ef90e147ed13c551a1730e7cc/rapidfuzz-3.14.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48bee0b91bebfaec41e1081e351000659ab7570cc4598d617aa04d5bf827f9e6", size = 3145715, upload-time = "2026-04-07T11:14:24.508Z" }, + { url = "https://files.pythonhosted.org/packages/ed/54/d5caabbea233ac90c286c87c260e49d7641467e87438a18d858e41c82e91/rapidfuzz-3.14.5-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:7e580cb04ad849ae9b786fa21383c6b994b6e6c1444ad1cb9f22392759d72741", size = 1456304, upload-time = "2026-04-07T11:14:26.515Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a7/2d1a81250ac8c01a0100c026018e76f0e7a097ff63e4c553e02a6938c6fb/rapidfuzz-3.14.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:09d6c9ba091854f07817055d795d604179c12a8f308ba4c7d56f3719dfea1646", size = 2389089, upload-time = "2026-04-07T11:14:28.635Z" }, + { url = "https://files.pythonhosted.org/packages/65/0d/c47c3872203ae88e6506997c0b576ad731f5261daa25d559be09c9756658/rapidfuzz-3.14.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1e989f86113be66574113b9c7bdf4793f3f863d248e47d911b355e05ca6b6b10", size = 2493404, upload-time = "2026-04-07T11:14:30.577Z" }, + { url = "https://files.pythonhosted.org/packages/8f/2f/71e0a5a3130792146c8a200a2dd1e52aa16f7c1074012e17f2601eea9a90/rapidfuzz-3.14.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ebd1a18e2e47bc0b292a07e6ed9c3642f8aaa672d12253885f599b50807a4f9", size = 4251709, upload-time = "2026-04-07T11:14:32.451Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ee/e71853bf82846c5c2174b924b71d8e8099fb05ff87c958a720380b434ba3/rapidfuzz-3.14.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:578e6051f6d5e6200c259b47a103cf06bb875ab5814d17333fc0b5c290b22f4c", size = 1888603, upload-time = "2026-04-07T11:16:18.223Z" }, + { url = "https://files.pythonhosted.org/packages/36/82/40f67b730f32be2ebad9f62add1571c754f52249254b2e88af094b907eee/rapidfuzz-3.14.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbf1b8bb2695415b347f3727da1addca2acb82c9b97ac86bebf8b1bead1eb12d", size = 1120599, upload-time = "2026-04-07T11:16:20.682Z" }, + { url = "https://files.pythonhosted.org/packages/ef/9f/a3635cc4ec8fc6e14b46e7db1f7f8763d8c4bef33dcc124eea2e6cb2c8f3/rapidfuzz-3.14.5-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f4a8f5cc84c7ad6bffa0e9947b33eb343ad66e6b53e94fe54378a5508c5ed53", size = 1348524, upload-time = "2026-04-07T11:16:23.451Z" }, + { url = "https://files.pythonhosted.org/packages/cc/1b/2b229520f0b48464cfcd7aa758f74551d12c9bc4ab544022a60210aab064/rapidfuzz-3.14.5-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c6d85283629646fa87acc22c66b30ea9d4de7f6fdf887daa2e30fa041829b5", size = 3099302, upload-time = "2026-04-07T11:16:25.858Z" }, +] + +[[package]] +name = "regex" +version = "2026.7.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/98/04b13f1ddfb63158025291c02e03eb42fbb7acb51d091d541050eb4e35e8/regex-2026.7.19.tar.gz", hash = "sha256:7e77b324909c1617cbb4c668677e2c6ae13f44d7c1de0d4f15f2e3c10f3315b5", size = 416440, upload-time = "2026-07-19T00:19:48.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/e5/cef4de2bac939280b68d32adc659478845238a8274f2f79c465063f590ad/regex-2026.7.19-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ac777001cdfc28b72477d93c8564bb7583081ea8fb45cdca3d568e0a4f87183c", size = 494012, upload-time = "2026-07-19T00:16:39.927Z" }, + { url = "https://files.pythonhosted.org/packages/ff/87/e86f51eb117457bb7803132ffe5cb6e2841e2b5bea4cc85d397f3c6e257d/regex-2026.7.19-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:59787bd5f8c70aa339084e961d2996b53fbdeab4d5393bba5c1fe1fc32e02bae", size = 295281, upload-time = "2026-07-19T00:16:41.433Z" }, + { url = "https://files.pythonhosted.org/packages/41/2e/2360c41d8080a3d9ec7e5c90fad6eab3b50192869d10e9a5609e48c8177b/regex-2026.7.19-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90c633e7e8d6bf4e992b8b36ce69e018f834b641dd6de8cea6d78c06ffa119c5", size = 290615, upload-time = "2026-07-19T00:16:43.058Z" }, + { url = "https://files.pythonhosted.org/packages/cf/69/b65ba4344efbc771b28fe5dde84cbbb6c8f9551165952fe78def5b9dde6a/regex-2026.7.19-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ccab0db8d5f4fbb0272642113c1adb2ffc698c16d3a0944580222331fa7a20", size = 791804, upload-time = "2026-07-19T00:16:44.662Z" }, + { url = "https://files.pythonhosted.org/packages/81/b6/a40dfa0dc6224b36f620c00296eacc830489cbf8c2837b6750dfe6170375/regex-2026.7.19-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e50d748a32da622f256e8d505867f5d3c43a837c6a9f0efb149655fadd1042a", size = 861723, upload-time = "2026-07-19T00:16:46.412Z" }, + { url = "https://files.pythonhosted.org/packages/e3/02/735991dee71abd83196a7962f7ed8bf5aa05720ff06e2d3ff896a85e2bbb/regex-2026.7.19-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bf1516fe58fc104f39b2d1dbe2d5e27d0cd45c4be2e42ba6ee0cc763701ec3c7", size = 905932, upload-time = "2026-07-19T00:16:47.956Z" }, + { url = "https://files.pythonhosted.org/packages/45/6c/e7098d8b846ccdbf431d8c081b61e496526a27a28094ed09e0dce21b3f54/regex-2026.7.19-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09f3e5287f94f17b709dc9a9e70865855feee835c861613be144218ce4ca82cc", size = 801407, upload-time = "2026-07-19T00:16:49.43Z" }, + { url = "https://files.pythonhosted.org/packages/8a/18/34b69274e2649bcc7d9b089c2b2983fb2632d8ecf667e359593be9072e79/regex-2026.7.19-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6383cd2ed53a646c659ba1fe65727db76437fdaa069e697a0b44a51d5843d864", size = 774448, upload-time = "2026-07-19T00:16:51.352Z" }, + { url = "https://files.pythonhosted.org/packages/bb/e6/0a72247d025585fd3800b98e040b84d562a88af6303347100484849f4f01/regex-2026.7.19-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:09d3007fc76249a83cdd33de160d50e6cb77f54e09d8fa9e7148e10607ce24af", size = 783297, upload-time = "2026-07-19T00:16:53.071Z" }, + { url = "https://files.pythonhosted.org/packages/b1/aa/c4f65ae7dd02a36b323a70c4cff326e1f3442361aaebc9311100a130d54f/regex-2026.7.19-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f8c6e7a1cfa3dc9d0ee2de0e65e834537fa29992cc3976ffec914afc35c5dd5", size = 854736, upload-time = "2026-07-19T00:16:54.607Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/668082bcc817b9e694189b84997aeba7385b7779faa6711788679c482e35/regex-2026.7.19-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:b2ea4a3e8357be8849e833beeae757ac3c7a6b3fc055c03c808a53c91ad30d82", size = 763298, upload-time = "2026-07-19T00:16:56.289Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fb/2d07ad555e7af88aa5f867fdafa47a8d945ee237c20af3ebceb46a820835/regex-2026.7.19-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:80115dd39481fd3a4b4080220799dbcacb921a844de4b827264ececacbe17c78", size = 844430, upload-time = "2026-07-19T00:16:57.933Z" }, + { url = "https://files.pythonhosted.org/packages/51/15/c82a471fe3dce56f03745635b43aa456c40dc0db089e07ef148b331507d1/regex-2026.7.19-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6ce43a0269d68cee79a7d1ade7def53c20f8f2a047b92d7b5d5bcc73ae88327", size = 789683, upload-time = "2026-07-19T00:16:59.583Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b9/d11d7e501ac8fd7d617684423ebb9561e0b998481c1e4cbc0cb212c5d74a/regex-2026.7.19-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2cc3460cedf7579948486eab03bc9ad7089df4d7281c0f47f4afe03e8d13f02d", size = 496778, upload-time = "2026-07-19T00:17:05.677Z" }, + { url = "https://files.pythonhosted.org/packages/3f/a9/a5ab6f312f24318019170dc485d5421fe4f89e43a98640da50d95a8a7041/regex-2026.7.19-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0e9554c8785eac5cffe6300f69a91f58ba72bc88a5f8d661235ad7c6aa5b8ccd", size = 297122, upload-time = "2026-07-19T00:17:07.59Z" }, + { url = "https://files.pythonhosted.org/packages/b3/63/4cab4d7f2d384a144d420b763d97674cb70619c878ea6fcd7640d0e62143/regex-2026.7.19-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d7da47a0f248977f08e2cb659ff3c17ddc13a4d39b3a7baa0a81bf5b415430f6", size = 292009, upload-time = "2026-07-19T00:17:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/22/85/102a81b218298957d4ea7d2f084fae537a71add9d6ff93c8e67284c5f45e/regex-2026.7.19-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93db40c8de0815baab96a06e08a984bac71f989d13bab789e382158c5d426797", size = 796708, upload-time = "2026-07-19T00:17:11.542Z" }, + { url = "https://files.pythonhosted.org/packages/78/b5/dc136af5629938a037cd2b304c12240e132ec92f38be8ff9cc89af2a1f2d/regex-2026.7.19-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:66bd62c59a5427746e8c44becae1d9b99d22fb13f30f492083dfb9ad7c45cc18", size = 865651, upload-time = "2026-07-19T00:17:13.312Z" }, + { url = "https://files.pythonhosted.org/packages/e0/75/67402ae3cd9c8c988a4c805d15ee3eef015e7ca4cb112cf3e640fc1f4153/regex-2026.7.19-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1649eb39fcc9ea80c4d2f110fde2b8ab2aef3877b98f02ab9b14e961f418c511", size = 911756, upload-time = "2026-07-19T00:17:15.015Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8e/096d00c7c480ef2ff4265349b14e2261d4ab787ba1f74e2e80d1c58079c3/regex-2026.7.19-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9dce8ec9695f531a1b8a6f314fd4b393adcccf2ea861db480cdf97a301d01a68", size = 801798, upload-time = "2026-07-19T00:17:17.208Z" }, + { url = "https://files.pythonhosted.org/packages/f0/41/e7ecac6edb5722417f85cc67eaf386322fbe8acf6918ec2fdc37c20dd9d0/regex-2026.7.19-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3080a7fd38ef049bd489e01c970c97dd84ff446a885b0f1f6b26d9b1ad13ce11", size = 776933, upload-time = "2026-07-19T00:17:19.347Z" }, + { url = "https://files.pythonhosted.org/packages/6f/69/03c9b3f058d66403e0ca2c938696e81d51cd4c6d47ec5265f02f96948d9a/regex-2026.7.19-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d793a7988e04fcb1e2e135567443d82173225d657419ec09414a9b5a145b986", size = 784338, upload-time = "2026-07-19T00:17:21.057Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f7/b38ab3d43f284afbb618fcd15d0e77eb786ae461ce1f6bc7494619ddc0f2/regex-2026.7.19-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e8b0abe7d870f53ca5143895fef7d1041a0c831a140d3dc2c760dd7ba25d4a8b", size = 860452, upload-time = "2026-07-19T00:17:23.119Z" }, + { url = "https://files.pythonhosted.org/packages/15/5c/ff60ef0571121714f3cf9920bc183071e384a10b556d042e0fdb06cc07a5/regex-2026.7.19-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:4e5413bd5f13d3a4e3539ca98f70f75e7fca92518dd7f117f030ebedd10b60cb", size = 765958, upload-time = "2026-07-19T00:17:24.81Z" }, + { url = "https://files.pythonhosted.org/packages/aa/0f/bd34021162c0ab47f9a315bd56cd5642e920c8e5668a75ef6c6a6fca590d/regex-2026.7.19-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:73b133a9e6fb512858e7f065e96f1180aa46646bc74a83aea62f1d314f3dd035", size = 851765, upload-time = "2026-07-19T00:17:26.993Z" }, + { url = "https://files.pythonhosted.org/packages/2a/20/a2ca43edade0595cccfdc98636739f536d9e26898e7dbddc2b9e98898953/regex-2026.7.19-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dbe6493fbd27321b1d1f2dd4f5c7e5bd4d8b1d7cab7f32fd67db3d0b2ed8248a", size = 789714, upload-time = "2026-07-19T00:17:28.699Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "charset-normalizer", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "urllib3", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "resampy" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numba", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/29/f1/34be702a69a5d272e844c98cee82351f880985cfbca0cc86378011078497/resampy-0.4.3.tar.gz", hash = "sha256:a0d1c28398f0e55994b739650afef4e3974115edbe96cd4bb81968425e916e47", size = 3080604, upload-time = "2024-03-05T20:36:08.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/b9/3b00ac340a1aab3389ebcc52c779914a44aadf7b0cb7a3bf053195735607/resampy-0.4.3-py3-none-any.whl", hash = "sha256:ad2ed64516b140a122d96704e32bc0f92b23f45419e8b8f478e5a05f83edcebd", size = 3076529, upload-time = "2024-03-05T20:36:02.439Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "ruamel-yaml" +version = "0.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/3b/ebda527b56beb90cb7652cb1c7e4f91f48649fbcd8d2eb2fb6e77cd3329b/ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993", size = 142709, upload-time = "2026-01-02T16:50:31.84Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/0c/51f6841f1d84f404f92463fc2b1ba0da357ca1e3db6b7fbda26956c3b82a/ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93", size = 118102, upload-time = "2026-01-02T16:50:29.201Z" }, +] + +[[package]] +name = "sacrebleu" +version = "2.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "lxml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "portalocker", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "regex", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tabulate", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/ed/d7acddcff74d690c56fe26a1f7828bdde548262828d0743414ea916c40c1/sacrebleu-2.6.0.tar.gz", hash = "sha256:91499b6cd46138d95154fff1e863c2f9be57e82f0c719d8dd718d0006cf6c566", size = 1893419, upload-time = "2026-01-12T17:17:20.799Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/f2/6c90ccf3ad1d09a7d662a405b274f3c93b92df59c8d6a025d26aaf34d302/sacrebleu-2.6.0-py3-none-any.whl", hash = "sha256:3edc1531575cfe4ad04ce53491a9307e234af1c3f805a1f491cbec844229a8a8", size = 100785, upload-time = "2026-01-12T17:17:18.868Z" }, +] + +[[package]] +name = "sacremoses" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "regex", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1d/51/fbdc4af4f6e85d26169e28be3763fe50ddfd0d4bf8b871422b0788dcc4d2/sacremoses-0.1.1.tar.gz", hash = "sha256:b6fd5d3a766b02154ed80b962ddca91e1fd25629c0978c7efba21ebccf663934", size = 883188, upload-time = "2023-10-30T15:56:20.187Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/f0/89ee2bc9da434bd78464f288fdb346bc2932f2ee80a90b2a4bbbac262c74/sacremoses-0.1.1-py3-none-any.whl", hash = "sha256:31e04c98b169bfd902144824d191825cd69220cdb4ae4bcf1ec58a7db5587b1a", size = 897476, upload-time = "2023-10-30T15:56:18.121Z" }, +] + +[[package]] +name = "safetensors" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/06/f955dbbb1859e3bd23c8ac6141af5106e7ad5fedec4a3a6e3d60f94b7001/safetensors-0.8.0.tar.gz", hash = "sha256:fabaf3e0f18a6618d9b36560682562157f77c2b71fcffc7b432be2baed9d753d", size = 325846, upload-time = "2026-06-09T07:52:25.563Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/a0/f718cda65b05407d228f97602cf60dca269c979867aa5beb25410de26cd3/safetensors-0.8.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c554f85858e05226d3c2828e32395e677434685d6d94594a41643361c5e837f0", size = 473568, upload-time = "2026-06-09T07:52:18.829Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b1/fa7c600e7dceae12e9606c7578cbc9ff1e1ed55844883ee5c92205e86226/safetensors-0.8.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:c80201d22cbf405b80647a60ada77bba06c8fba2da2743ba1e89cdcc39a81f25", size = 484562, upload-time = "2026-06-09T07:52:17.518Z" }, + { url = "https://files.pythonhosted.org/packages/09/7d/65a7de0af421317bb36a067241e4235fff194eed60b961ed6d3f59a3fc60/safetensors-0.8.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a46e5ff292c356d6991e60942ba7f79817682d3a2cef0702136448cb9c4d235", size = 502844, upload-time = "2026-06-09T07:52:07.624Z" }, + { url = "https://files.pythonhosted.org/packages/91/4f/3175c9d75634e0e0dda0082794193521035edd7c70a6f212bf33ca06ddf4/safetensors-0.8.0-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4124502b78f03534117c848f87a39b8f31e577b15eff423bf8bfb95f2a8c30d0", size = 511823, upload-time = "2026-06-09T07:52:09.565Z" }, + { url = "https://files.pythonhosted.org/packages/20/87/846c289e7aa2299eff406335717cf43ce8777194ece8aad75772e0411615/safetensors-0.8.0-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc0a787ba8a35be368ee3574edfa2b1ad389eebd0a72e482ae275490e3f6c98", size = 633461, upload-time = "2026-06-09T07:52:11.128Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/8d64d9df2c45d5ded401df889d0ad90882804ca172d79ec4f0df8f727fe0/safetensors-0.8.0-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040070828e36dc8e122178bbbd5830ff9e97920affb84cbe0f46442497bed358", size = 545148, upload-time = "2026-06-09T07:52:13.603Z" }, + { url = "https://files.pythonhosted.org/packages/28/50/f203ff3a3ddfe19308efc83c5a3a29ed02bf786732ec35e68bf9162f3365/safetensors-0.8.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd6f3f93c9a0a7cc2788ee63fb763353d4bd2e89b0751bc78fcf7dda00bea774", size = 516040, upload-time = "2026-06-09T07:52:16.29Z" }, + { url = "https://files.pythonhosted.org/packages/46/fb/cdaed17ceb2948784fd9c36b6fd3e951b608547cea81a48e8ee6f8cfdfcb/safetensors-0.8.0-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:fcdd41ec4628fee5799f807c73c353629130fbd942aa23d83c623dd6c9d52d78", size = 513832, upload-time = "2026-06-09T07:52:12.37Z" }, + { url = "https://files.pythonhosted.org/packages/0d/49/1e15de264dcc3b77943d2d0c56a95809956883b1c2d6d585c792523f180b/safetensors-0.8.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8e9f537aa183a38ace122d27303dcd986b26bd2a7591f9181d7f0c396f4677ca", size = 559930, upload-time = "2026-06-09T07:52:14.743Z" }, + { url = "https://files.pythonhosted.org/packages/2a/43/bf38443278eab4b1be1fce2931e2b012ad9cb7df52ada751d0aab8f7659a/safetensors-0.8.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:87eec7ffed2b809f05a398a8becb7d013f19f7837cd15d9748580d6cf30dbaf4", size = 678670, upload-time = "2026-06-09T07:52:20.032Z" }, + { url = "https://files.pythonhosted.org/packages/72/e3/68cd3fa5b48488e84add63e04cb12f3bc28ae4638c06d4508c6e88823d0e/safetensors-0.8.0-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:4a95ae2b05d7726d751da4ebf626a2ca782b706e101bd894c95bc2450b1cffcc", size = 786679, upload-time = "2026-06-09T07:52:21.322Z" }, + { url = "https://files.pythonhosted.org/packages/29/4b/1c19c509d56e01f4fbb3d0a2e597450f6cc04d1d56cf52defb0a62dfd715/safetensors-0.8.0-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:3ae091f16662658bdc019a4ff6cb4c085bb7d725eb5978b183ffd265863b6d2d", size = 765683, upload-time = "2026-06-09T07:52:22.594Z" }, + { url = "https://files.pythonhosted.org/packages/27/43/41c1621732edd934d868a00d1b891584c892a7b62a9aab82ea5a0a5623ee/safetensors-0.8.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8e080062fcde23be189565e1c3305d16751a218ecf9412c8601e64204eb6f846", size = 722361, upload-time = "2026-06-09T07:52:23.924Z" }, +] + +[[package]] +name = "scikit-learn" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "narwhals", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux')" }, + { name = "threadpoolctl", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fa/6f/37092bdb25f712817231799fc5674d8e704066a8a70c1d2d40517e18b4ab/scikit_learn-1.9.0.tar.gz", hash = "sha256:8833266989d3a5110178a9fae30783675460724d0e1efb13b14901d2c660c557", size = 7750767, upload-time = "2026-06-02T11:54:32.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/be/e844fd9586e66540a15b71924d17a6cbc1bb749e81ddd0a796bcdba4c055/scikit_learn-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9db6f4d34e68c8899e4cab27fdf8eafe6ed21f2ba52ceb25ea250cd237f8e47b", size = 8789686, upload-time = "2026-06-02T11:53:05.439Z" }, + { url = "https://files.pythonhosted.org/packages/42/e2/ff880f62677a17d035817d543cb0fc8727d01eccbee81c5f7fc733a9d856/scikit_learn-1.9.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f401448645a3e7bc115aa3c094097865155b34bff1cba8101857d9104e99074c", size = 8256782, upload-time = "2026-06-02T11:53:08.904Z" }, + { url = "https://files.pythonhosted.org/packages/25/64/eb40435e1a508ab1b4e284ce43ae80f6a162e5be5e38ed5a6fab467a9ea4/scikit_learn-1.9.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd3a8ef0c758555a3b23c03adaa858af32f7736785ded50ad5991f59c4ed03fa", size = 8992419, upload-time = "2026-06-02T11:53:11.551Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/4810a28e473185429e45a57eebcc91fc991b33d889cc0676063e671db03d/scikit_learn-1.9.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7e254636164090da847715a27f8e5478feb98c40a9e0ee90cbd277de9e5ceb8", size = 9281411, upload-time = "2026-06-02T11:53:15.063Z" }, + { url = "https://files.pythonhosted.org/packages/ac/20/75f915ff375d6249e6550ac740fdbbd66159a068fd3af1400ff62036b07a/scikit_learn-1.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2bd41b0d201bc81575531b96b713d3eb5e5f50fb0b82101ff0f92294fdc236ac", size = 8741122, upload-time = "2026-06-02T11:53:24.08Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d5/2b5148f2279196775e1db2aeb85d14b70ac80e7e32b3b28e7ebeafb0901d/scikit_learn-1.9.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5be45aa4a42a68a533913a6ed736cf309de2226411c79ef8d609a5456f1939b1", size = 8261512, upload-time = "2026-06-02T11:53:27.183Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ee/5adbc77656b71f9456a2f5a7a9fdb4bcf9207a6b962889f1c2f9323afa4e/scikit_learn-1.9.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e50ed4da51974e86e940690e9a3d82e729b62b5a49f7c9bac534d515d39d86f", size = 8837603, upload-time = "2026-06-02T11:53:30.328Z" }, + { url = "https://files.pythonhosted.org/packages/6c/c2/63fdda36c56437eeb44aaf9493c8bcd62ce230ab1598924fc626ffbfa943/scikit_learn-1.9.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:056c92bb67ad4c28463c2f2653d9701449201e7e7a9e94e321be0f71c4fef2b8", size = 9132097, upload-time = "2026-06-02T11:53:33.456Z" }, +] + +[[package]] +name = "scipy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.12' and sys_platform == 'darwin'", + "python_full_version < '3.12' and sys_platform == 'linux'", +] +dependencies = [ + { name = "numpy", marker = "(python_full_version < '3.12' and sys_platform == 'darwin') or (python_full_version < '3.12' and sys_platform == 'linux')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/75/b4ce781849931fef6fd529afa6b63711d5a733065722d0c3e2724af9e40a/scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec", size = 31613675, upload-time = "2026-02-23T00:16:00.13Z" }, + { url = "https://files.pythonhosted.org/packages/f7/58/bccc2861b305abdd1b8663d6130c0b3d7cc22e8d86663edbc8401bfd40d4/scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696", size = 28162057, upload-time = "2026-02-23T00:16:09.456Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ee/18146b7757ed4976276b9c9819108adbc73c5aad636e5353e20746b73069/scipy-1.17.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a3472cfbca0a54177d0faa68f697d8ba4c80bbdc19908c3465556d9f7efce9ee", size = 20334032, upload-time = "2026-02-23T00:16:17.358Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e6/cef1cf3557f0c54954198554a10016b6a03b2ec9e22a4e1df734936bd99c/scipy-1.17.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:766e0dc5a616d026a3a1cffa379af959671729083882f50307e18175797b3dfd", size = 22709533, upload-time = "2026-02-23T00:16:25.791Z" }, + { url = "https://files.pythonhosted.org/packages/4d/60/8804678875fc59362b0fb759ab3ecce1f09c10a735680318ac30da8cd76b/scipy-1.17.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:744b2bf3640d907b79f3fd7874efe432d1cf171ee721243e350f55234b4cec4c", size = 33062057, upload-time = "2026-02-23T00:16:36.931Z" }, + { url = "https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43af8d1f3bea642559019edfe64e9b11192a8978efbd1539d7bc2aaa23d92de4", size = 35349300, upload-time = "2026-02-23T00:16:49.108Z" }, + { url = "https://files.pythonhosted.org/packages/b4/3d/7ccbbdcbb54c8fdc20d3b6930137c782a163fa626f0aef920349873421ba/scipy-1.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd96a1898c0a47be4520327e01f874acfd61fb48a9420f8aa9f6483412ffa444", size = 35127333, upload-time = "2026-02-23T00:17:01.293Z" }, + { url = "https://files.pythonhosted.org/packages/e8/19/f926cb11c42b15ba08e3a71e376d816ac08614f769b4f47e06c3580c836a/scipy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4eb6c25dd62ee8d5edf68a8e1c171dd71c292fdae95d8aeb3dd7d7de4c364082", size = 37741314, upload-time = "2026-02-23T00:17:12.576Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/b992b488d6f299dbe3f11a20b24d3dda3d46f1a635ede1c46b5b17a7b163/scipy-1.17.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8", size = 31610954, upload-time = "2026-02-23T00:17:49.855Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/cf107b01494c19dc100f1d0b7ac3cc08666e96ba2d64db7626066cee895e/scipy-1.17.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76", size = 28172662, upload-time = "2026-02-23T00:18:01.64Z" }, + { url = "https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086", size = 20344366, upload-time = "2026-02-23T00:18:12.015Z" }, + { url = "https://files.pythonhosted.org/packages/35/f5/906eda513271c8deb5af284e5ef0206d17a96239af79f9fa0aebfe0e36b4/scipy-1.17.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b", size = 22704017, upload-time = "2026-02-23T00:18:21.502Z" }, + { url = "https://files.pythonhosted.org/packages/da/34/16f10e3042d2f1d6b66e0428308ab52224b6a23049cb2f5c1756f713815f/scipy-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21", size = 32927842, upload-time = "2026-02-23T00:18:35.367Z" }, + { url = "https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458", size = 35235890, upload-time = "2026-02-23T00:18:49.188Z" }, + { url = "https://files.pythonhosted.org/packages/c5/5c/9d7f4c88bea6e0d5a4f1bc0506a53a00e9fcb198de372bfe4d3652cef482/scipy-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb", size = 35003557, upload-time = "2026-02-23T00:18:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/65/94/7698add8f276dbab7a9de9fb6b0e02fc13ee61d51c7c3f85ac28b65e1239/scipy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea", size = 37625856, upload-time = "2026-02-23T00:19:00.307Z" }, +] + +[[package]] +name = "scipy" +version = "1.18.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and sys_platform == 'linux'", +] +dependencies = [ + { name = "numpy", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/25/c2700dfaf6442b4effaa91af24ebce5dc9d31bb4a69706313aae70d72cd0/scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378", size = 30774447, upload-time = "2026-06-19T15:01:43.456Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/19/ca10ead60b0acc80b2b833c2c4a4f2ff753d0f58b811f70d911c7e94a25c/scipy-1.18.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:7bd21faaf5a1a3b2eff922d02db5f191b99a6518db9078a8fb23169f6d22259a", size = 31056519, upload-time = "2026-06-19T14:59:45.203Z" }, + { url = "https://files.pythonhosted.org/packages/96/72/1e6442a00cd2924d361aa1b642ab6373ec35c6fabf311a760be9f76e0f13/scipy-1.18.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:265915e79107de9f946b855e50d7470d5893ec3f54b342e1aa6201cbdcd8bb6b", size = 28681889, upload-time = "2026-06-19T14:59:48.103Z" }, + { url = "https://files.pythonhosted.org/packages/9b/2d/11dd93d21e147a73ba22bd75c0b9208d3a2e0ec76d53170ce7d9029b1015/scipy-1.18.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9ab7b758be6940954a713ee466e2043e9f6e2ed965c1fce5c91039f4be3d90a9", size = 20423580, upload-time = "2026-06-19T14:59:50.665Z" }, + { url = "https://files.pythonhosted.org/packages/9c/01/93552f75e0d2a7dd115a45e59209c51e8d514daff02fc887d2623be06fe1/scipy-1.18.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:97b6cddaaee0a779ef6b5ca83c9604b27cc16b2b8fc22c142652df8793319fb8", size = 23054441, upload-time = "2026-06-19T14:59:53.564Z" }, + { url = "https://files.pythonhosted.org/packages/3c/23/21f5e703643d66f21faa6b4c73195bfcad70c55efcb4f1ab327cd7c4101a/scipy-1.18.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:52a96e21517c7292375c0e27dd796a811f03fcea5fd4d108fdfea8145dcf17ab", size = 33968720, upload-time = "2026-06-19T14:59:56.415Z" }, + { url = "https://files.pythonhosted.org/packages/dd/aa/1b939f6c67ed68635bb538e6752d3dacc02f66535182e939a89581a44e9c/scipy-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f55797419e16e7f30cf88ffb3113ce0467f00cfe3f70d5c281730b21769bfc2", size = 35287115, upload-time = "2026-06-19T14:59:59.411Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ff/eec46be7e9234208f801062b53e1983085eddebd693f6c9bfb03b459830d/scipy-1.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ad033410e2e0672ffdc1042110cef20e1c46f8fd0616cee1d44d8d58fad8fc11", size = 35577989, upload-time = "2026-06-19T15:00:02.235Z" }, + { url = "https://files.pythonhosted.org/packages/84/ca/210d4759c7210bb7d269437421959b39a33434e2776b60c5cb8a763bb30a/scipy-1.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a55985d54c769c872e64b7f4c8a81cc30ef700cc04296abbbf3705439c126de", size = 37421717, upload-time = "2026-06-19T15:00:05.102Z" }, +] + +[[package]] +name = "sentencepiece" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/33/ea3cb3839607eb175da835244a798f797f478c5ddf0e8ecdf57ea85a4c70/sentencepiece-0.2.2.tar.gz", hash = "sha256:3d2b5e824b5622038dc7b490897efe05ebbbb9e7350fc142f3ecc8789ef9bdf6", size = 8218435, upload-time = "2026-07-12T08:39:34.701Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/31/f23a2efaa0210b883574001b88fa64e499f798f0848a0b610fb9b384d162/sentencepiece-0.2.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:69e9dc8078e128286ed3b975e37c837ba96e215a50c3ef9f3f8b7ab9e5a832a0", size = 2184255, upload-time = "2026-07-12T08:38:14.855Z" }, + { url = "https://files.pythonhosted.org/packages/96/f2/1ee0ccb772d71e822f625d6cb5f0ea825835e877f28a9ef299a1291df19e/sentencepiece-0.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6dd76f3e5c8b2eb8a3a3efee787bbf5b9a66e52a048fe09cab85eca33fec6790", size = 1438545, upload-time = "2026-07-12T08:38:16.674Z" }, + { url = "https://files.pythonhosted.org/packages/2a/92/3a6ea4a2c6dd9e7062698a5a33534ca0e20844883338ae9c6b9c122c1a9f/sentencepiece-0.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:443ac618c7a2a1377cf5c82581fbb849591d14e656d5e5a3e4682d4e36a34e4e", size = 1346997, upload-time = "2026-07-12T08:38:18.499Z" }, + { url = "https://files.pythonhosted.org/packages/f3/3a/7839048997c7bc0c34c57526f539f835e20c7a57dc2a99f99579b11cdbef/sentencepiece-0.2.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0e2aae42960392d6dcb9a72d8e1e65a97294c965071b43c7b3429a42f350250e", size = 1324282, upload-time = "2026-07-12T08:38:20.342Z" }, + { url = "https://files.pythonhosted.org/packages/06/5f/9117bf854aef817ad0d0ee9310eed0308a7e529e7eaf2e80ad9cd281ef82/sentencepiece-0.2.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1416b92f2f010333786fe6306ed2631121d5ea492219b0841e967b6765e64107", size = 1394242, upload-time = "2026-07-12T08:38:22.976Z" }, + { url = "https://files.pythonhosted.org/packages/b8/13/7a562289c8d5b49ebdf3f9c1e8ab67cf14a8743b1d90c8f406bfdec36b72/sentencepiece-0.2.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1edb10e520e4bddf74d85b0f5ae74cc2d60c2b448885080bfb618bc2b3a49f6b", size = 2188384, upload-time = "2026-07-12T08:38:28.486Z" }, + { url = "https://files.pythonhosted.org/packages/85/d1/912f14fd5eae168aba726ffb6a9a2dc1c71fe7676c53da6f5c442b886d4a/sentencepiece-0.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7c06c751c19d923435a54bff4f7e66e728fad160e8da28254f133abc9725820", size = 1441553, upload-time = "2026-07-12T08:38:30.552Z" }, + { url = "https://files.pythonhosted.org/packages/bd/44/caa9cab5f261a019e2808bc5046152775dc57352ba9cbae7525e9e7a1ed4/sentencepiece-0.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38111ed1f79268f399c505028023d5eaaf0ab4e5eafceb709468b0d3323e7838", size = 1347176, upload-time = "2026-07-12T08:38:32.211Z" }, + { url = "https://files.pythonhosted.org/packages/19/90/cd798935668cff71d309d8ff10385844ecf216b1fe454f1993ed8bf2cb91/sentencepiece-0.2.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cbce24284f51f71d10a42b7b9c964dcb9048b28f1c8e5db40bcbcb6f428cba6a", size = 1325200, upload-time = "2026-07-12T08:38:33.689Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2d/37e3da037318a70066ded0d51bc2a7f35491ae6338dd993d5eb1503fc3b5/sentencepiece-0.2.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c8a168b040bc61681293f79a949b5d911c8e25086f4260285b8d97ab5f1195da", size = 1397736, upload-time = "2026-07-12T08:38:35.771Z" }, +] + +[[package]] +name = "sentry-sdk" +version = "2.66.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "urllib3", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/ff/670abe04c5072719b5060ed93851d0d69525d60f8f2c5810f8becd58f9c1/sentry_sdk-2.66.0.tar.gz", hash = "sha256:9727d35aa83c56cd53294676fe65b96296a334c9ce107fa2142bd70f47acb265", size = 935745, upload-time = "2026-07-16T12:42:04.663Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/bb/49b10783f29067da2eec179320617e94faf63196609de47aeab3c26c3325/sentry_sdk-2.66.0-py3-none-any.whl", hash = "sha256:096136c214c602be2b323524d30755dc5b30ec5a218a206207f33b12c05c6f11", size = 504769, upload-time = "2026-07-16T12:42:02.919Z" }, +] + +[[package]] +name = "setuptools" +version = "83.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/34/26/f5d29e25ffdb535afef2d35cdb55b325298f96debd670da4c325e08d70f4/setuptools-83.0.0.tar.gz", hash = "sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef", size = 1154254, upload-time = "2026-07-04T15:31:22.699Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/40/e1e72872c6354b306daef1703549e8e83b4d43cfea356311bf722a043752/setuptools-83.0.0-py3-none-any.whl", hash = "sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3", size = 1008090, upload-time = "2026-07-04T15:31:20.885Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, +] + +[[package]] +name = "soundfile" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d2/db/949331952a6fb1c5b12e9de80fd08747966c2039d1a61db4764fbd3981c2/soundfile-0.14.0.tar.gz", hash = "sha256:ba1c1a2d618bca5c406647c83b89f07cc8810fa506a50622a6993ba130c1de11", size = 47842, upload-time = "2026-06-06T08:58:47.869Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/d1/5e338af9ca6ed0786cd5bb03f6d60de1c325728c1189014f3b59aae7403c/soundfile-0.14.0-py2.py3-none-any.whl", hash = "sha256:8ba81ae3a89fd5ab3bef8a8eb481fbbe794e806309675a89b4df48b8d31908a8", size = 26799, upload-time = "2026-06-06T08:58:33.269Z" }, + { url = "https://files.pythonhosted.org/packages/7e/72/c6b21e58d3113596e7e8de0a08d6f1d95173492cfbca0a4db14148cbba2a/soundfile-0.14.0-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:19be05428da76ed61a4cad29b8e4bcf43a3e5c100089d2ec81dc961eed1b0dd4", size = 1144568, upload-time = "2026-06-06T08:58:35.231Z" }, + { url = "https://files.pythonhosted.org/packages/63/7a/dfdd6f8c748988427119f75eb860a3cedd858d1aea1fe28f39ad8559ef22/soundfile-0.14.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:d828d35a059626da52f1415b5faee610aeab393319cb3fc4a9aef47b619fc14c", size = 1103726, upload-time = "2026-06-06T08:58:37.948Z" }, + { url = "https://files.pythonhosted.org/packages/4a/f8/fc39fad6f879633461d27394cd1ddaf1f769ffa0597dca35872f51b16461/soundfile-0.14.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e85724a90bc99a6e8062c0b4ddf725f53b2a3b70afd4da875e9d2cfc4e92f377", size = 1238050, upload-time = "2026-06-06T08:58:39.932Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a2/70fd4432b924684c372df8b0a45708c36c057ef3596c9eb53e0a806b980b/soundfile-0.14.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:1e38bac1853412871318e82a1ba69a8be677619b56025bbfcccdb41b6cafe82d", size = 1315963, upload-time = "2026-06-06T08:58:41.716Z" }, +] + +[[package]] +name = "sox" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/a2/d8e0d8fd7abf509ead4a2cb0fb24e5758b5330166bf9223d5cb9f98a7e8d/sox-1.5.0.tar.gz", hash = "sha256:12c7be5bb1f548d891fe11e82c08cf5f1a1d74e225298f60082e5aeb2469ada0", size = 63905, upload-time = "2024-03-20T16:59:37.385Z" } + +[[package]] +name = "soxr" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/11/27cebce4a108f77afea7c80545115536b45e3f11ebfb914f638fdd9ba847/soxr-1.1.0.tar.gz", hash = "sha256:9f228ae21c78fa9359ca98d8a5e8e91f30639e438e574133dace62c5b5309e44", size = 173067, upload-time = "2026-05-03T00:15:18.214Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/49/3e6bc84f87439f222f40b616e9a29a170f41fb564710ea510df19dc26907/soxr-1.1.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:34cc92208c3c412c046813e69da639c04a792c6a41fbfd7d909d359cd3e97a2d", size = 205699, upload-time = "2026-05-03T00:14:46.67Z" }, + { url = "https://files.pythonhosted.org/packages/2f/94/216f46096a85b07d1e6ba7fd44491402e912a3d688cd4f36f0a600ca155f/soxr-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd30f7201eac896ebf5db7b09156e6f1a1b82601900d29d9c8449bdad8365b11", size = 167381, upload-time = "2026-05-03T00:14:48.012Z" }, + { url = "https://files.pythonhosted.org/packages/94/cb/06caa463b8181ec1981bd6376d4a873748b7008193188b8cfb60391eb131/soxr-1.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1577865e993f98ffb261257c3060fa76ec3db44ed3f181b16464268000424464", size = 210938, upload-time = "2026-05-03T00:14:49.768Z" }, + { url = "https://files.pythonhosted.org/packages/86/47/d5964551ca818b7f0c7ef7f3899056263b60ef098a801066350a9672ca8f/soxr-1.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3da87e3ffa3e41823d873b051c7ecb2acebd8d1b6b46b752f5facf10a0d84ab9", size = 245268, upload-time = "2026-05-03T00:14:51.422Z" }, + { url = "https://files.pythonhosted.org/packages/06/8a/f3da7973b5f1b05d2d7e94d5376b881dcbc05297900cae6c3d33d95b209b/soxr-1.1.0-cp312-abi3-macosx_10_14_x86_64.whl", hash = "sha256:e0e09fa633ce2e67df08b298afced4d184f6e753fc330f241022250f1d0d61da", size = 204124, upload-time = "2026-05-03T00:14:54.505Z" }, + { url = "https://files.pythonhosted.org/packages/03/dc/200013a74641f8774664bbcd2346c695c05c2e300ea792adcb40a293eed0/soxr-1.1.0-cp312-abi3-macosx_11_0_arm64.whl", hash = "sha256:d6a7ad82b8d5f3fcc04b1d2ca055562b96af571e1d4fa7c6c61d0fb509ac43b4", size = 165457, upload-time = "2026-05-03T00:14:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/88/2b/2e5eba817a762a2ec589ff165b8bc5955b25a0ad140045f7cd8e45410543/soxr-1.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf98c0d7b7d5ef5bf072fee8d3020e8b664f2d195933ea7bc5089267c2e22a06", size = 206529, upload-time = "2026-05-03T00:14:57.646Z" }, + { url = "https://files.pythonhosted.org/packages/5c/f1/0e55195893228609c9a08c3b13b7a83a46c3a992cd00d3304f0f320cfb07/soxr-1.1.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b033078e86f3c4a658e5697fac8995764fad9e799563616b630136b613167f1", size = 240413, upload-time = "2026-05-03T00:14:59.363Z" }, +] + +[[package]] +name = "sqlalchemy" +version = "2.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "(platform_machine == 'AMD64' and sys_platform == 'darwin') or (platform_machine == 'WIN32' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'darwin') or (platform_machine == 'amd64' and sys_platform == 'darwin') or (platform_machine == 'ppc64le' and sys_platform == 'darwin') or (platform_machine == 'win32' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'darwin') or (platform_machine == 'AMD64' and sys_platform == 'linux') or (platform_machine == 'WIN32' and sys_platform == 'linux') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'amd64' and sys_platform == 'linux') or (platform_machine == 'ppc64le' and sys_platform == 'linux') or (platform_machine == 'win32' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/69/a67c69e5f28fc9c99d6f7bd60bd50e91f2fed2423e3b30fb228fa00e51f3/sqlalchemy-2.0.51-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1aa10c0daee6705294d181daadaa793221e1a59ed55000a3fab1d42b088ce4ba", size = 2161838, upload-time = "2026-06-15T16:05:17.144Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a4/c8c22b8438bddc0a030157c6ec0f6ef97b3c38effa444bdab2a27af04090/sqlalchemy-2.0.51-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5b2ed6d828f1f09bd812861f4f59ca3bc3803f9df871f4555187f0faf018604", size = 3319402, upload-time = "2026-06-15T16:10:40.002Z" }, + { url = "https://files.pythonhosted.org/packages/90/54/44012d32fd77d991256d2ff793ba3807c51d40cb27a85b4796224f6744df/sqlalchemy-2.0.51-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:436728ce18a80f6951a1e11cc6112c2ede9faf20766f1a26195a7c441ca12dbd", size = 3319675, upload-time = "2026-06-15T16:12:25.658Z" }, + { url = "https://files.pythonhosted.org/packages/29/a5/de0592acaf5906cd7430874392d6f7e8b4a7c8437610953ee2d1501c0b44/sqlalchemy-2.0.51-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc261707bf5739aea8a541593f3cc1d463c2701fb05fbcbba0ce031b69a21260", size = 3270777, upload-time = "2026-06-15T16:10:42.125Z" }, + { url = "https://files.pythonhosted.org/packages/cb/14/a44c90739c780b362238e4ac3cb19dd0ca40d13e6ddc5daa112166ddab4f/sqlalchemy-2.0.51-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6d26094615306d116dd5e4a51b0304c99dd2356fc569eed6922a80a6bd3b265", size = 3293940, upload-time = "2026-06-15T16:12:27.156Z" }, + { url = "https://files.pythonhosted.org/packages/d5/70/e868bc5412acd101a8280f25c95f10eeae0771c4eb806b02491142810ee8/sqlalchemy-2.0.51-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d78702b26ba1c18b2d0fb2ea940ba7f17a9581b42e8361ff93920ebbee1235a", size = 2160291, upload-time = "2026-06-15T16:08:48.918Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1c/71ee0f8a6b9d7316a1ccd30430b4c62b6c2e36adc96017a4e3a72dce49d6/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581921d849d6e6f994d560389192955e80e2950e18fcdfe2ccea863e01158e6e", size = 3343835, upload-time = "2026-06-15T16:19:42.613Z" }, + { url = "https://files.pythonhosted.org/packages/2b/7c/7ab9f9aadc5944fdd06612484ed7918fe376ad871a5f50404dc1536e0194/sqlalchemy-2.0.51-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d21ce524ab86c23046e992a5b81cb54c21079c6df6e78b8fc77d77cac70a6b9", size = 3358470, upload-time = "2026-06-15T16:26:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7d/ff77169fee6186de145a7f2b87006c39638391130abbab2b1f63ac6ea583/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c5d98a2709840027f5a347c3af0a7c3d5f6c1ff93af2ca1c54494e23cba8f389", size = 3289874, upload-time = "2026-06-15T16:19:45.212Z" }, + { url = "https://files.pythonhosted.org/packages/6f/3b/6c505903710d781b55bc3141ee34a062bf9745a6b5bc7333305b9ed63b33/sqlalchemy-2.0.51-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1181256e0f16479691b5616d36375dc2620ad8332b25978763c3d206ad3f3f1d", size = 3321692, upload-time = "2026-06-15T16:26:39.747Z" }, + { url = "https://files.pythonhosted.org/packages/e2/22/dbf013a12ec759e54a34a119e9e217435b3f71b2dd5c61a7ade0a25dae87/sqlalchemy-2.0.51-py3-none-any.whl", hash = "sha256:bb024d8b621d0be75f4f44ecc7c950450026e76d66dc8f791bb5331d7fed59d5", size = 1944334, upload-time = "2026-06-15T16:09:22.418Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "executing", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pure-eval", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "strenum" +version = "0.4.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/ad/430fb60d90e1d112a62ff57bdd1f286ec73a2a0331272febfddd21f330e1/StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff", size = 23384, upload-time = "2023-06-29T22:02:58.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/69/297302c5f5f59c862faa31e6cb9a4cd74721cd1e052b38e464c5b402df8b/StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659", size = 8851, upload-time = "2023-06-29T22:02:56.947Z" }, +] + +[[package]] +name = "sympy" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, +] + +[[package]] +name = "tabulate" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/58/8c37dea7bbf769b20d58e7ace7e5edfe65b849442b00ffcdd56be88697c6/tabulate-0.10.0.tar.gz", hash = "sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d", size = 91754, upload-time = "2026-03-04T18:55:34.402Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl", hash = "sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3", size = 39814, upload-time = "2026-03-04T18:55:31.284Z" }, +] + +[[package]] +name = "tensorboard" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "grpcio", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "markdown", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pillow", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "protobuf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tensorboard-data-server", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/4b/cd2eec9642781a8f5b2fb9994e3933a7b259ab18e9d49aeede9b5acf6311/tensorboard-2.21.0-py3-none-any.whl", hash = "sha256:7279316dcb6bd5bc391d623dea841531299cde1887310e8133bc34a996d32255", size = 5516204, upload-time = "2026-06-29T20:48:04.472Z" }, +] + +[[package]] +name = "tensorboard-data-server" +version = "0.7.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl", hash = "sha256:7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb", size = 2356, upload-time = "2023-10-23T21:23:32.16Z" }, + { url = "https://files.pythonhosted.org/packages/b7/85/dabeaf902892922777492e1d253bb7e1264cadce3cea932f7ff599e53fea/tensorboard_data_server-0.7.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9fe5d24221b29625dbc7328b0436ca7fc1c23de4acf4d272f1180856e32f9f60", size = 4823598, upload-time = "2023-10-23T21:23:33.714Z" }, + { url = "https://files.pythonhosted.org/packages/73/c6/825dab04195756cf8ff2e12698f22513b3db2f64925bdd41671bfb33aaa5/tensorboard_data_server-0.7.2-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:ef687163c24185ae9754ed5650eb5bc4d84ff257aabdc33f0cc6f74d8ba54530", size = 6590363, upload-time = "2023-10-23T21:23:35.583Z" }, +] + +[[package]] +name = "text-unidecode" +version = "1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" }, +] + +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + +[[package]] +name = "tokenizers" +version = "0.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" }, + { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" }, + { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" }, + { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" }, + { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" }, + { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" }, + { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" }, + { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" }, + { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" }, +] + +[[package]] +name = "toml" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" }, +] + +[[package]] +name = "toolz" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z" }, +] + +[[package]] +name = "torch" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12' and sys_platform == 'darwin'", + "python_full_version < '3.12' and sys_platform == 'darwin'", +] +dependencies = [ + { name = "filelock", marker = "sys_platform == 'darwin'" }, + { name = "fsspec", marker = "sys_platform == 'darwin'" }, + { name = "jinja2", marker = "sys_platform == 'darwin'" }, + { name = "networkx", marker = "sys_platform == 'darwin'" }, + { name = "setuptools", marker = "sys_platform == 'darwin'" }, + { name = "sympy", marker = "sys_platform == 'darwin'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/fe/cba54dc58523434919b66f13a667e36e436deddd77ca519e96553617d4ec/torch-2.13.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:e76f9bcecc52b8ff711239a2f7547d5353df95878ab232f0773c1d95928b92f8", size = 111187938, upload-time = "2026-07-08T16:05:17.065Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3a/ed0f4d4d1dcde03bced7aac9a28e800abcdc0cbd06b6775044c9fbd877b7/torch-2.13.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2fe228aba290d14b9f31b049be550dbd469c3fd3013d7a19705b30454da97027", size = 111213045, upload-time = "2026-07-08T16:05:22.997Z" }, +] + +[[package]] +name = "torch" +version = "2.13.0+cu129" +source = { registry = "https://download.pytorch.org/whl/cu129" } +resolution-markers = [ + "python_full_version >= '3.12' and sys_platform == 'linux'", + "python_full_version < '3.12' and sys_platform == 'linux'", +] +dependencies = [ + { name = "cuda-bindings", marker = "sys_platform == 'linux'" }, + { name = "cuda-toolkit", extra = ["cublas", "cudart", "cufft", "cufile", "cupti", "curand", "cusolver", "cusparse", "nvjitlink", "nvrtc", "nvtx"], marker = "sys_platform == 'linux'" }, + { name = "filelock", marker = "sys_platform == 'linux'" }, + { name = "fsspec", marker = "sys_platform == 'linux'" }, + { name = "jinja2", marker = "sys_platform == 'linux'" }, + { name = "networkx", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cudnn-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cusparselt-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nccl-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvshmem-cu12", marker = "sys_platform == 'linux'" }, + { name = "setuptools", marker = "sys_platform == 'linux'" }, + { name = "sympy", marker = "sys_platform == 'linux'" }, + { name = "triton", marker = "sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'linux'" }, +] +wheels = [ + { url = "https://download-r2.pytorch.org/whl/cu129/torch-2.13.0%2Bcu129-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f47dd63ad198aee205ddb90393e574d19b4bb83185f75e71d63ed7634cb47bad", upload-time = "2026-07-08T20:03:09Z" }, + { url = "https://download-r2.pytorch.org/whl/cu129/torch-2.13.0%2Bcu129-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:545c1ecc90e0fb13a94a51ea9e82d03aaf416fa78fc8efe43be64cf93e7bc0fa", upload-time = "2026-07-08T20:04:05Z" }, + { url = "https://download-r2.pytorch.org/whl/cu129/torch-2.13.0%2Bcu129-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:4ee86fc2f4af36642751b95fecc7ba4ad18283f010c5a841208ecd850c22d48a", upload-time = "2026-07-08T20:05:05Z" }, + { url = "https://download-r2.pytorch.org/whl/cu129/torch-2.13.0%2Bcu129-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:df28741fcd89e3da7cce2d48cbe5299d6732d510ac20f5d422d0b85edf18c327", upload-time = "2026-07-08T20:06:04Z" }, +] + +[[package]] +name = "torchmetrics" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lightning-utilities", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/34/39b8b749333db56c0585d7a11fa62a283c087bb1dfc897d69fb8cedbefb1/torchmetrics-1.9.0.tar.gz", hash = "sha256:a488609948600df52d3db4fcdab02e62aab2a85ef34da67037dc3e65b8512faa", size = 581765, upload-time = "2026-03-09T17:41:22.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/a2/c7f6ebf546f8f644edf0f999aa98ece106986a77a7b922316bf6414ff825/torchmetrics-1.9.0-py3-none-any.whl", hash = "sha256:bfdcbff3dd1d96b3374bb2496eb39f23c4b28b8a845b6a18c313688e0d2d9ca1", size = 983384, upload-time = "2026-03-09T17:41:19.756Z" }, +] + +[[package]] +name = "tqdm" +version = "4.69.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/69/40407dfc835517f058b603dbf37a6df094d8582b015a51eddc988febbcb7/tqdm-4.69.0.tar.gz", hash = "sha256:700c5e85dcd5f009dd6222588a29180a193a748247a5d855b4d67db93d79a53b", size = 792569, upload-time = "2026-07-17T18:09:06.2Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/21/99a0cdaf54eb35e77623c41b5a2c9472ee4404bba687052791fe2aba6773/tqdm-4.69.0-py3-none-any.whl", hash = "sha256:9979978912be667a6ef21fd5d8abf54e324e63d82f7f43c360792ebc2bc4e622", size = 676680, upload-time = "2026-07-17T18:09:04.172Z" }, +] + +[[package]] +name = "traitlets" +version = "5.15.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/a9/a2584b8313b89f94869ddb3c4074617a691de1812a614d2d50e32ca5a7a6/traitlets-5.15.1.tar.gz", hash = "sha256:7b1c07854fe25acb39e009bae49f11b79ff6cbb2f27999104e9110e7a6b53722", size = 163344, upload-time = "2026-06-03T12:26:06.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/8d/1080ee4c231f361b6ce4470d556c8c435b67c7e0753aaa641497ee92f88b/traitlets-5.15.1-py3-none-any.whl", hash = "sha256:770a53705f84b81ac107e83a1b3328ff2dae16094d8fc3cfc004e4b22dfd8e92", size = 85858, upload-time = "2026-06-03T12:26:04.395Z" }, +] + +[[package]] +name = "transcribe-sortformer-env" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "gguf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "nemo-toolkit", extra = ["asr"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sentencepiece", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "soundfile", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" }, + { name = "torch", version = "2.13.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform == 'linux'" }, +] + +[package.metadata] +requires-dist = [ + { name = "gguf", specifier = ">=0.10.0" }, + { name = "huggingface-hub", specifier = ">=0.20" }, + { name = "nemo-toolkit", extras = ["asr"], git = "https://github.com/NVIDIA-NeMo/NeMo.git?rev=6967f48fda2a" }, + { name = "numpy", specifier = ">=1.26" }, + { name = "sentencepiece", specifier = ">=0.2" }, + { name = "soundfile", specifier = ">=0.12" }, + { name = "torch", specifier = ">=2.2" }, +] + +[[package]] +name = "transformers" +version = "5.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "regex", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "safetensors", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tokenizers", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typer", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/fb/2a2ba88f325e68a921d8b69ff63b477830b2e73ade9a3c8c8cab2f06d741/transformers-5.14.1.tar.gz", hash = "sha256:60d196c27781eacf8637e2b533f517582907ad6f9ae142046d6b69431a5b2173", size = 9295927, upload-time = "2026-07-16T09:41:57.773Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/67/8d85ca2323233ae3c0365a659c4e52ee1f587b440e4bc577e7d8e4416d0f/transformers-5.14.1-py3-none-any.whl", hash = "sha256:9db974c4079ede2d1a3ea7ca5a240df33f2cc26fc2b36ba64c5f2a4f43b6e725", size = 11625234, upload-time = "2026-07-16T09:41:54.143Z" }, +] + +[[package]] +name = "triton" +version = "3.7.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/f9/19d842d06a08559534fa1eaab6ca551b1bcf40f06620bddec1babaa2772d/triton-3.7.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4a0e1cd4c4a76370ed74a8432a53cea28716827d19e40ffc732233e35ceb3f6", size = 184664887, upload-time = "2026-06-17T20:03:42.913Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5e/fce69606f7f240297f163e25539906732b199530d486ce67ae319877e821/triton-3.7.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6744957e9fd610a29680ec2346057d0c86948ed3812468670719f391e94b44a5", size = 197701306, upload-time = "2026-06-17T19:53:13.673Z" }, + { url = "https://files.pythonhosted.org/packages/94/fa/f856e24deb462d5f18bd4b5a746957862ab9b6ee5834bda60605ec348366/triton-3.7.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9497f2e696ee368862a181a90b2dcc03ca978cc4f602abd67c7d81022a6988e1", size = 184692359, upload-time = "2026-06-17T20:03:48.288Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6f/fb96d15db6f36d6eae4cafb998c2e0353bf59d7c4ea1662d7497f269134a/triton-3.7.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e40869937a68206ec70d7f25bb7ec6433cb083f9135e1f36dbd318dc449a728", size = 197719725, upload-time = "2026-06-17T19:53:20.419Z" }, +] + +[[package]] +name = "typeguard" +version = "4.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/1c/dfba5c4633cafc4c701f237d2ba63b416805047fd6d96aab4cfc40969f98/typeguard-4.5.2.tar.gz", hash = "sha256:5a16dcac23502039299c97c8941651bc33d7ea8cc4b2f7d6bbb1b528f6eea423", size = 80240, upload-time = "2026-05-14T12:59:40.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/29/74eeb4d3f3ae61ca096b018ad486b3b3c74b17bec09ab4edab721cbefec3/typeguard-4.5.2-py3-none-any.whl", hash = "sha256:fcf9de18bd945cdb4c7b996e12b4c51ce83f92f191314a6d7cf1739586ec98cf", size = 36748, upload-time = "2026-05-14T12:59:39.473Z" }, +] + +[[package]] +name = "typer" +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "shellingham", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "wandb" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "protobuf", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "sentry-sdk", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/92/fb/8d3f96a8b143060d6fa145462d0785981373e04694e4152555ccb5d23939/wandb-0.28.1.tar.gz", hash = "sha256:870ccb1a01238b0ac07c6fd96a0810a1f79090aba04ea29f4ee012ac8327705d", size = 40578119, upload-time = "2026-07-16T18:47:05.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/21/8df50164d07623cfcefec19bbf9327d9be84b637a827cea1f0c06db005fd/wandb-0.28.1-py3-none-macosx_12_0_arm64.whl", hash = "sha256:da909a76e65c64c0d93acc485d2a19f66e336f1e3f725f1c98a070883e084943", size = 24277925, upload-time = "2026-07-16T18:46:42.383Z" }, + { url = "https://files.pythonhosted.org/packages/8f/18/6c3da7e6cb215ad363324db8dc4d83b93626f5e339822b05b1c38a6097fd/wandb-0.28.1-py3-none-macosx_12_0_x86_64.whl", hash = "sha256:3da3db219c54bfd1082c00e9061c8ea894ba43e42733b5af00bb10c09d7158fe", size = 25480852, upload-time = "2026-07-16T18:46:45.102Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1a/d15bcfb4417fa69edcaa33db8ea012db733da1057e193b047e3f69fdd671/wandb-0.28.1-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:ae9ae6fb29e2e2b1d097ed8b75c0c0240c778c2a8cad1d996dee870a1e401c2c", size = 24832138, upload-time = "2026-07-16T18:46:47.433Z" }, + { url = "https://files.pythonhosted.org/packages/b3/da/49924c7df2952dfd82c86c3779c339c0c3d6f6439387c03d97d0470c3658/wandb-0.28.1-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:8cfb898b6a6c884d9c9294b02764e88bce65049f027a124d6bee53fe722469b6", size = 26486533, upload-time = "2026-07-16T18:46:49.839Z" }, + { url = "https://files.pythonhosted.org/packages/11/c0/06b23518e29690784f1b3081e39c7679ca076cb0af094cb9b4bb309150f5/wandb-0.28.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:cf2b1533945395e4fdbe6182b272bb0ca8a02c10b3086a395e2d57686ae3ed0d", size = 25022635, upload-time = "2026-07-16T18:46:52.376Z" }, + { url = "https://files.pythonhosted.org/packages/23/30/6de2f7995a8a6eecbd03d24c79a139a734c0168f5520cf4c7ccb43c1dbbc/wandb-0.28.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7233061080507a4b4098bed1ccb381ce6f890c60397cd4153d060285bcb267bd", size = 27008895, upload-time = "2026-07-16T18:46:55.025Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" }, +] + +[[package]] +name = "webdataset" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "braceexpand", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "numpy", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/3a/68800d92e065cf4750ebecf973b13979c0c929b439e1293012938862038d/webdataset-1.0.2.tar.gz", hash = "sha256:7f0498be827cfa46cc5430a58768a24e2c6a410676a61be1838f53d61afdaab4", size = 80090, upload-time = "2025-06-19T23:26:21.945Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/00/aca6beb3658dab4ed3dbb41a78e6e7f31342e0b41d28088f205525751601/webdataset-1.0.2-py3-none-any.whl", hash = "sha256:3dbfced32b25c0d199c6b9787937b6f85742bc3c84f652c846893075c1c082d9", size = 74956, upload-time = "2025-06-19T23:26:20.354Z" }, +] + +[[package]] +name = "werkzeug" +version = "3.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/b2/381be8cfdee792dd117872481b6e378f85c957dd7c5bca38897b08f765fd/werkzeug-3.1.8.tar.gz", hash = "sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44", size = 875852, upload-time = "2026-04-02T18:49:14.268Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/8c/2e650f2afeb7ee576912636c23ddb621c91ac6a98e66dc8d29c3c69446e1/werkzeug-3.1.8-py3-none-any.whl", hash = "sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50", size = 226459, upload-time = "2026-04-02T18:49:12.72Z" }, +] + +[[package]] +name = "wget" +version = "3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/6a/62e288da7bcda82b935ff0c6cfe542970f04e29c756b0e147251b2fb251f/wget-3.2.zip", hash = "sha256:35e630eca2aa50ce998b9b1a127bb26b30dfee573702782aa982f875e3f16061", size = 10857, upload-time = "2015-10-22T15:26:37.51Z" } + +[[package]] +name = "whisper-normalizer" +version = "0.1.14" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "indic-numtowords", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "more-itertools", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "regex", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e8/22/7441906d01069452f054008d309c58bf833b5d0633e7c1acbb704d23b050/whisper_normalizer-0.1.14.tar.gz", hash = "sha256:e35c095bccfe566e64c8441f36e70af9af8b0b2e04d209102d50cea42d315f7b", size = 39078, upload-time = "2026-07-17T06:03:10.518Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/cd/5cfb3c2ff8222de9666feb7ef89a1c46e118a9a2a67bf8947bde2cebbd03/whisper_normalizer-0.1.14-py3-none-any.whl", hash = "sha256:93119c1425c6225df4ef33d071cde2f61706cab4f72bb5b4fe47c9f7cdce8747", size = 37387, upload-time = "2026-07-17T06:03:08.814Z" }, +] + +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/15/0c2d55168707465abfc41f33c0b23d792a5fa9b65c26983606940900a120/wrapt-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f1a2ff355ece6a111ca7a20dc86df6659c9205d3fcee674ca34f2a2854fd4e73", size = 80782, upload-time = "2026-06-20T23:47:44.367Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b5/5c0b093eb48f8a062ef6267d3cb36e9bb1b88440181f6545a383c60efdf8/wrapt-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55b9a899e6fff5444f229d30aa6e9ac92d2216d9d60f33c771b5d76a760d5f8e", size = 81678, upload-time = "2026-06-20T23:47:45.857Z" }, + { url = "https://files.pythonhosted.org/packages/34/f3/de70937472dd3e8a4e6811192f9c6075efdffd4a2cd9b4596bf160f89668/wrapt-2.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a2d78c363f97d8bd718ee40432c66395685e9e98528ccaa423c3355d1715a26d", size = 159671, upload-time = "2026-06-20T23:47:47.345Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ec/40aed2330e7f02ecf74386ffcfef9ccb7108c6a430f15b6a252b663b1bed/wrapt-2.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d619e1eed9bd4f6ed9f24cd61971aa086fa86505289628d464bcf8a2c2e3f328", size = 160785, upload-time = "2026-06-20T23:47:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/45/04/aa5309beed5344b00220ae6b3b24055852192656194c27947bee1736306a/wrapt-2.2.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:518b0c5e323511ec56a38894802ddd5e1222626484e68efe63f201854ad788e5", size = 153699, upload-time = "2026-06-20T23:47:50.177Z" }, + { url = "https://files.pythonhosted.org/packages/01/df/2def7e99d1fe87eea413f95f671924cdddcb08823b1ffd212748dfa6d062/wrapt-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4bccea5cdecffa9dd70e343741f0e41e0a16619313d04b72f78bb525162ebcd0", size = 159695, upload-time = "2026-06-20T23:47:51.602Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f6/a906d01a2ce12157bad2404957b3e2140da354b8a70b2fa48bbf282871c0/wrapt-2.2.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:209112cafd963710a05d199aae431d79a28bc76eb8e6d1bbbb8ad24340722cae", size = 152813, upload-time = "2026-06-20T23:47:53.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/49/bc0086292d239575b4c08f4cf8a4079fa58abbad58ec23abf84833a283ed/wrapt-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5a5290e4bf2f332fc29ce72ffb9a2fff678aaac047e2e9f5f7165cd7792e099", size = 158809, upload-time = "2026-06-20T23:47:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] + +[[package]] +name = "xxhash" +version = "3.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/63/71aa56b151a1b28770037a61bd4e461c2619cfc8866a4fcaf1548605e325/xxhash-3.8.1.tar.gz", hash = "sha256:b0de4bf3aa66363552d52c6a89003c479911f12098cd48a53d44a0f7a25f7c46", size = 86223, upload-time = "2026-07-06T10:49:58.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/5a/05eaa129555f85476a3e16ff869e95f81a78bbe4647eef9d0229f515a317/xxhash-3.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602efcad4a42c184e81d43a2b7e6e4f524d619878f2b6ee2ba469011f47c8147", size = 34699, upload-time = "2026-07-06T10:44:10.14Z" }, + { url = "https://files.pythonhosted.org/packages/80/59/0df1133958b2228929355e022aab1e958c7b2c43e27bf7f59bc9edfa8a54/xxhash-3.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:131324f719957b988861714de7d6ddf57b47abec3b0cc691302ffeaba0e05e10", size = 32373, upload-time = "2026-07-06T10:44:11.353Z" }, + { url = "https://files.pythonhosted.org/packages/3e/bf/1cfda5b5e6bf26617812b4a31662ef2220d2ad04e0a55b8ff9eb36e56a5c/xxhash-3.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:db77278a6eddadbf44ce5aae2fee5ebb4d061f026b1ce2130d058cd4d7a7b670", size = 220284, upload-time = "2026-07-06T10:44:12.683Z" }, + { url = "https://files.pythonhosted.org/packages/70/93/45dc0ad7913b69e5b08bd039236cf628380e4c9cc76a8a4c6625a328e058/xxhash-3.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c332dd48b8cb050da2bb2a3c96d72b1664168650a250ef9718e423df7989e05", size = 240980, upload-time = "2026-07-06T10:44:14.297Z" }, + { url = "https://files.pythonhosted.org/packages/e9/02/f28ba7d17f2c1410ee397982c817ab1bd5b2701070c2d2c373539aad000a/xxhash-3.8.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a5cd96f6dcdf4fa657b2d95668d71d58455248f98712ecffaa9c528edf40ccae", size = 264526, upload-time = "2026-07-06T10:44:16.017Z" }, + { url = "https://files.pythonhosted.org/packages/5c/d0/f10651cec2c7981b20d693deae6bdfc438427d92be2db4ccabb6181f0021/xxhash-3.8.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c959f88160b13b4e730b0d75b459b7929fc0d2225c284c9683ac95d6feeeac6a", size = 241369, upload-time = "2026-07-06T10:44:17.698Z" }, + { url = "https://files.pythonhosted.org/packages/ff/40/136e0cbaf5db51e191423b1c98643593189f02b6cd90837bf64b19113d70/xxhash-3.8.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:027dee4355f3fcc41481650d846cf6cfc895c85a1ab7acd063063821a0df5b4c", size = 473186, upload-time = "2026-07-06T10:44:19.354Z" }, + { url = "https://files.pythonhosted.org/packages/4b/3f/6aa808a96bdc43dba9a740dec56c744526ee3c0019e32c75e810fa90ae4d/xxhash-3.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad52a0e4bcc0ba956a953a169d1feec2734a64981d689e4fc8f490f7bf91af60", size = 220092, upload-time = "2026-07-06T10:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/47/28/a8675e78a9ced96dab853416162268e10e05b452e95db7888cf69f58ac5f/xxhash-3.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d3dfb1f0ff146da7952867a9414f0c7a29762f8825a84879592612fd6139342", size = 309846, upload-time = "2026-07-06T10:44:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/0f/7fe4d4ef4e69f0033e012396ee2a115886bca7b10b7e45ce398626436bfc/xxhash-3.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4482380b462ca9e59994d072a877ecadd1cf51102daeeab2db696f96ab763723", size = 237659, upload-time = "2026-07-06T10:44:24.135Z" }, + { url = "https://files.pythonhosted.org/packages/38/8f/83e9e31d4ed57fe963b99cb5b13a23e3e0f0dad1885aa0ebd2a7819dd423/xxhash-3.8.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:950ac754d16daea42038f38e7465eb84cda4d08d7343c1c915771b29470f065a", size = 268737, upload-time = "2026-07-06T10:44:25.875Z" }, + { url = "https://files.pythonhosted.org/packages/57/79/7e7de46dbe5d1f49afc96a0bc42e6b8df24eae3d6bad6007b99e42f48430/xxhash-3.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0418ec8b2331b9d4d575fc9284427e8e69449d7172e99e1a86fcdd1f51a0a937", size = 224955, upload-time = "2026-07-06T10:44:27.777Z" }, + { url = "https://files.pythonhosted.org/packages/ec/34/b8540839e958d5ef5c6101af6f16032109e7099698ae8edbc8dcefe4d8f4/xxhash-3.8.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:32a94ad2763e0263d9102037d349002c3d3c401e42770542c3eeb4801f311661", size = 239653, upload-time = "2026-07-06T10:44:29.422Z" }, + { url = "https://files.pythonhosted.org/packages/ce/87/a735d05f7f859354acadabe470ff40e2c46672275f96dcf096a761904def/xxhash-3.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:89b11a5cdd441aa463f6d34ca0241602bc09b001a76994b6059828494108c673", size = 300213, upload-time = "2026-07-06T10:44:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/98/31/3e1cb020237b68117fc212dc5f9753b87f865b4dfee7c1ce62d0836955b5/xxhash-3.8.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:09a204dd4bb0823daf938cdd0dc8057d5f1e14fe3cbde929424255f23f9de872", size = 442508, upload-time = "2026-07-06T10:44:33.023Z" }, + { url = "https://files.pythonhosted.org/packages/23/bf/f80090622141cc734b039ce1d15ce3ff6dced375e9680249bf5b9b8c6bf9/xxhash-3.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e710ad822c493fb80a4fbc1e3d0a807b1422cb90adbe64378f98291b7fa48fef", size = 216853, upload-time = "2026-07-06T10:44:34.983Z" }, + { url = "https://files.pythonhosted.org/packages/42/91/f65c34a7aa7b4e7cf4854f8e6ef3f7ee32ceac41d4f008da0780db0612f6/xxhash-3.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e6e49370822c1f4d8d90e678b06dbcb08b51a026a7c4b55479e7d467f2e813bc", size = 34680, upload-time = "2026-07-06T10:44:40.932Z" }, + { url = "https://files.pythonhosted.org/packages/57/04/b10a245a4c09a9cfa88f8e9ae755029413ad1ac17047f9a61906e5ae0799/xxhash-3.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:220d68130f83f7cc86d6edfdeab176adc73d7200bf3a8ec10c629e8cf605c215", size = 32397, upload-time = "2026-07-06T10:44:42.196Z" }, + { url = "https://files.pythonhosted.org/packages/3a/75/45ab795b5945b6388583bd75202106af505537935566c15a1577797a0e08/xxhash-3.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d365ee1892c1fa803536f8c6ce21d24b29c9718ec75eb856095c07830f8c478", size = 220549, upload-time = "2026-07-06T10:44:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/13/44/5ba2bd0a14ddf4193fc7d8ec29625f659f22c06d60b28f04bf46305d8330/xxhash-3.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:852bfe059720632e2f16a6a4745e41d20937b2bf2a42a401e2412046bb6971cc", size = 241186, upload-time = "2026-07-06T10:44:45.534Z" }, + { url = "https://files.pythonhosted.org/packages/23/32/c4147def4d1e4538b906f82731e0ba23424377fc50a7cddd03cd284c8f63/xxhash-3.8.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2f8c25a7061d952de589bd0ea0eaadee32378ff83dd6a677b267f9cd86f401f8", size = 264852, upload-time = "2026-07-06T10:44:47.199Z" }, + { url = "https://files.pythonhosted.org/packages/6c/bd/71ed14f4f0318bb7fd7b2ec51999413487fa8da8d41208e84d50d1ef0f98/xxhash-3.8.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:868a8dcaff1a84ba78038e1cef14fc88ccf84d9b4d12ea604696e0693296aa56", size = 242663, upload-time = "2026-07-06T10:44:48.846Z" }, + { url = "https://files.pythonhosted.org/packages/91/09/70af22c565a8473b3f2ae73f88e7721af281bc4a575236dbd1970c9f76f6/xxhash-3.8.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6536d8677d2fff7e64cd0b98b976df9de7aee0e69590044c2af5f51b76b7a170", size = 473510, upload-time = "2026-07-06T10:44:50.695Z" }, + { url = "https://files.pythonhosted.org/packages/18/96/34db781c8f0cf99c544ca1f2bc2e5bf55426e1eb4ca6de8ea5da56a9f352/xxhash-3.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82c0cedd280eab2e8291270e6c04894dbc096f8159a39dcf1807429f026ca3cc", size = 220469, upload-time = "2026-07-06T10:44:52.422Z" }, + { url = "https://files.pythonhosted.org/packages/93/5f/9a184f615fa5a4dce30c01534f62946ce5a11ce40f73785cbd356ccabaa9/xxhash-3.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daa86e4b68221d38e669bb236ba112d0335353829fb627c82e5909e4bbe8694c", size = 310290, upload-time = "2026-07-06T10:44:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/a9/dc/9b9a9789011ee153723a5eb9e7dd7fcbae2ba9b3fe7a729249ca7c252056/xxhash-3.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2bc7113e6f2b6b3922dd61796ca9f36af09da3773898e7003038dc992fc83b8d", size = 238173, upload-time = "2026-07-06T10:44:55.693Z" }, + { url = "https://files.pythonhosted.org/packages/ec/4d/71c6005ada9dcb608a4e1902e8475ecadb5f3fbfa04e1e244d276a2d0c43/xxhash-3.8.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5eed32dad81d6ba8e62dc7b9ffa0500199385d7810a8dd9d4eafaceb8c6e20bb", size = 269026, upload-time = "2026-07-06T10:44:57.424Z" }, + { url = "https://files.pythonhosted.org/packages/2f/87/d6c036ba25dfbd9c8633be5aa86fc9474bbb9e2c68212a841d090abe7344/xxhash-3.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:83697b0ea1f10e7f5d8b26a4906fa851393c61546c63839643a2b7fe2d868061", size = 224970, upload-time = "2026-07-06T10:44:59.085Z" }, + { url = "https://files.pythonhosted.org/packages/48/62/4c1f035a41c5752aa05e195b6c904c07b94fe9061a16de61e72a6e6b135f/xxhash-3.8.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:36fc69160465ae75c6ec4ac9f781bb2aa16ae7ff869e73c26fee85fbb11b9887", size = 240820, upload-time = "2026-07-06T10:45:00.746Z" }, + { url = "https://files.pythonhosted.org/packages/da/14/d39d565069b87e86d21a2af2a31d04db79249d25aa8d5b62959056a89857/xxhash-3.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:445e0f5a31f2f3546ae0895d4811e159518cdc9d824c11419898d40cfadb677e", size = 300619, upload-time = "2026-07-06T10:45:02.716Z" }, + { url = "https://files.pythonhosted.org/packages/13/22/75467acc887edc8cf71c97ab1708feb3df7a88bda589b9f399765c6387d2/xxhash-3.8.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:dfe0580fbfd5e4af87d0cc52d2044f155d55ebd8c8a93568758a2ea7d8e15975", size = 443267, upload-time = "2026-07-06T10:45:04.653Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b6/1da3baa5fa6ef705e3425fddd382be7dfc4dfba2686df90a20f16e9c7b1b/xxhash-3.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:095e1323fa108be1292c54c86da3ef3c7a7dc015b105a52133973bc07a6ad11a", size = 217338, upload-time = "2026-07-06T10:45:06.304Z" }, + { url = "https://files.pythonhosted.org/packages/99/e4/4d8040435aeac814fc69ba63621565fbeb19229a138e2568324a26b2a45c/xxhash-3.8.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:39c9d5b61508b0bb68f29e54546de0ed2a74943c6a18585535a7e37356f1dd12", size = 32687, upload-time = "2026-07-06T10:49:42.803Z" }, + { url = "https://files.pythonhosted.org/packages/da/6a/975f1f2318c760e5bcec109ed379713ae645d8d856c2a3b9ec5d26857087/xxhash-3.8.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:83b9130b80b216d56fdf9e87131946b353c9627930c061955a101ea82b09fed9", size = 29879, upload-time = "2026-07-06T10:49:45.172Z" }, + { url = "https://files.pythonhosted.org/packages/08/0b/40a2a55ff52cf635bfdc5eae67a772bec85b4f44c6c737f73f6f528d51d1/xxhash-3.8.1-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8304be0982130954b7fd3aad18e2c6f8ee40254bc3d2e635991c16d77c91e2bd", size = 43246, upload-time = "2026-07-06T10:49:47.905Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6d/56ed2b6b200f26fb474f3fd387d95d0601efcd5bb33430c90c68924bdd77/xxhash-3.8.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b512261801b1e5fde7b6ebf2fef7977339c620cbbca88a0040ad9ad134f4d02", size = 38202, upload-time = "2026-07-06T10:49:50.59Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a3/56864d895d1161a9f17502088e9c1fb7c06bde2c2efdde620d22bb7a9c43/xxhash-3.8.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49aa8692507835dcc1e8ad8021f20c74c2dc13d83b5112e87877faa2a0035b20", size = 34448, upload-time = "2026-07-06T10:49:53.242Z" }, +] + +[[package]] +name = "yarl" +version = "1.24.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "multidict", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "propcache", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/12/1e8f37460ea0f7eb59c221fdaf0ed75e7ac43e97f8093b9c6f411df50a78/yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8", size = 210798, upload-time = "2026-05-19T21:31:05.599Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/c5/1ce244152ff2839645e7cae92f90e7bafcb2c52bea7ff586ac714f14f5df/yarl-1.24.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:36348bebb147b83818b9d7e673ea4debc75970afc6ffdc7e3975ad05ce5a58c1", size = 128971, upload-time = "2026-05-19T21:28:20.543Z" }, + { url = "https://files.pythonhosted.org/packages/87/5a/00f36967203ed89cb3acd2c8ed526cc3fed9418eb70ce128160a911c8499/yarl-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a97e42c8a2233f2f279ecadd9e4a037bcb5d813b78435e8eedd4db5a9e9708c", size = 91507, upload-time = "2026-05-19T21:28:22.556Z" }, + { url = "https://files.pythonhosted.org/packages/31/d0/1fb0c1cd27288f39f6974da4318c32768d72c9890984541fdf1e2e32a51d/yarl-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d027d56f1035e339d1001ac33eceab5b2ec8e42e449787bb75e289fb9a5cd1d", size = 91343, upload-time = "2026-05-19T21:28:24.092Z" }, + { url = "https://files.pythonhosted.org/packages/03/ce/d4a646508bed2f8dec6435b40166fe9308dd191262033d3f307b2bbcaecd/yarl-1.24.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a6377060e7927187a42b7eb202090cbe2b34933a4eeaf90e3bd9e33432e5cae", size = 105704, upload-time = "2026-05-19T21:28:25.872Z" }, + { url = "https://files.pythonhosted.org/packages/4b/07/b3278e82d8bc41485bcf6d856cd0433262593de615b1d3dc43bd3f5bead4/yarl-1.24.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:17076578bce0049a5ce57d14ad1bded391b68a3b213e9b81b0097b090244999a", size = 97281, upload-time = "2026-05-19T21:28:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/17/5b/4cee6e7c92e487bebe7afc797da0aa54a248ab4e776a68fe369ec29665a5/yarl-1.24.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50713f1d4d6be6375bb178bb43d140ee1acb8abe589cd723320b7925a275be1e", size = 114020, upload-time = "2026-05-19T21:28:29.458Z" }, + { url = "https://files.pythonhosted.org/packages/5c/82/111076571545a7d4f9cca3fbd5c6f40615af58642be09f12328f48022468/yarl-1.24.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:34263e2fa8fb5bb63a0d97706cda38edbad62fddb58c7f12d6acbc092812aa50", size = 111450, upload-time = "2026-05-19T21:28:31.262Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ec/08f671f69a444d704aeecebf92af659b67b97a869942411d0a578b08c334/yarl-1.24.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49016d82f032b1bd1e10b01078a7d29ae71bf468eeae0ea22df8bab691e60003", size = 106384, upload-time = "2026-05-19T21:28:32.856Z" }, + { url = "https://files.pythonhosted.org/packages/e5/86/ce41e7a7a199340b2330d52b60f25c4074b6636dd0e60b1a80d31a9db042/yarl-1.24.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3f6d2c216318f8f32038ca3f72501ba08536f0fd18a36e858836b121b2deed9f", size = 106153, upload-time = "2026-05-19T21:28:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5d/31be8a729531ab3e55ac3e7e5c800be8c89ea98947f418b2f6ea259fb6ee/yarl-1.24.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08d3a33218e0c64393e7610284e770409a9c31c429b078bcb24096ed0a783b8f", size = 105322, upload-time = "2026-05-19T21:28:36.642Z" }, + { url = "https://files.pythonhosted.org/packages/47/9b/b57afb22b386ae87ac9940f09878b98d8c333f89113e6fc96fcf4ca9eb64/yarl-1.24.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5d699376c4ca3cba49bbfae3a05b5b70ded572937171ce1e0b8d87118e2ba294", size = 99057, upload-time = "2026-05-19T21:28:38.386Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4f/06348c27c8389256c313e8a57d796808fc0264c915dd5e7cfd3c0e314dc7/yarl-1.24.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a1cab588b4fa14bea2e55ebea27478adfb05372f47573738e1acc4a36c0b05d2", size = 113502, upload-time = "2026-05-19T21:28:40.091Z" }, + { url = "https://files.pythonhosted.org/packages/5f/1c/284f307b298e4a17b7943b07d9d7ecc4151537f8d137ba51f3bb6c31ca20/yarl-1.24.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ec87ccc31bd21db7ad009d8572c127c1000f268517618a4cc09adba3c2a7f21c", size = 105253, upload-time = "2026-05-19T21:28:41.987Z" }, + { url = "https://files.pythonhosted.org/packages/c8/bf/0de123bec8619e45c80cbded9085f61b5b4a9eddb8abe6d25d28ee1ec866/yarl-1.24.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d1dd47a22843b212baa8d74f37796815d43bd046b42a0f41e9da433386c3136b", size = 111345, upload-time = "2026-05-19T21:28:43.93Z" }, + { url = "https://files.pythonhosted.org/packages/90/af/0248eb065e51129d2a9b2436cd1b5c772c19a6b04e5b6a186955671e3319/yarl-1.24.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7b54b9c67c2b06bd7b9a77253d242124b9c95d2c02def5a1144001ee547dd9d5", size = 106558, upload-time = "2026-05-19T21:28:45.806Z" }, + { url = "https://files.pythonhosted.org/packages/f0/da/866bcb01076ba49d2b42b309867bed3826421f1c479655eb7a607b44f20b/yarl-1.24.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b975866c184564c827e0877380f0dae57dcca7e52782128381b72feff6dfceb8", size = 129957, upload-time = "2026-05-19T21:28:51.695Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1d/fcefb70922ea2268a8971d8e5874d9a8218644200fb8465f1dcad55e6851/yarl-1.24.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3b075301a2836a0e297b1b658cb6d6135df535d62efefdd60366bd589c2c82f2", size = 92164, upload-time = "2026-05-19T21:28:53.242Z" }, + { url = "https://files.pythonhosted.org/packages/29/b6/170e2b8d4e3bc30e6bfdcca53556537f5bf595e938632dfcb059311f3ff6/yarl-1.24.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ae44649b00947634ab0dab2a374a638f52923a6e67083f2c156cd5cbd1a881d", size = 91688, upload-time = "2026-05-19T21:28:54.865Z" }, + { url = "https://files.pythonhosted.org/packages/fe/a5/c9f655d5553ea0b99fdac9d6a99ad3f9b3e73b8e5758bb46f58c9831f74c/yarl-1.24.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507cc19f0b45454e2d6dcd62ff7d062b9f77a2812404e62dbdaec05b50faa035", size = 102902, upload-time = "2026-05-19T21:28:56.963Z" }, + { url = "https://files.pythonhosted.org/packages/5d/bc/6b9664d815d79af4ee553337f9d606c56bbf269186ada9172de45f1b5f60/yarl-1.24.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4c17bad5a530912d2111825d3f05e89bab2dd376aaa8cbc77e449e6db63e576", size = 97931, upload-time = "2026-05-19T21:28:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/98/ec/32ba48acae30fecd60928f5791188b80a9d6ee3840507ffda29fecd37b71/yarl-1.24.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5f0cbb112838a4a293985b6ed73948a547dadcc1ba6d2089938e7abdedceef8", size = 111030, upload-time = "2026-05-19T21:29:00.148Z" }, + { url = "https://files.pythonhosted.org/packages/82/5a/6f4cd081e5f4934d2ae3a8ef4abe3afacc010d26f0035ee91b35cd7d7c37/yarl-1.24.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ec8356b8a6afcf81fc7aeeef13b1ff7a49dec00f313394bbb9e83830d32ccd7", size = 110392, upload-time = "2026-05-19T21:29:02.155Z" }, + { url = "https://files.pythonhosted.org/packages/7a/da/323a01c349bd5fb01bb6652e314d9bb218cee630a736bdb810ad50e4013f/yarl-1.24.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e7ebcdef69dec6c6451e616f32b622a6d4a2e92b445c992f7c8e5274a6bbc4c", size = 105612, upload-time = "2026-05-19T21:29:04.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/80/264ab684f181e1a876389374519ff05d10248725535ae2ac4e8ac4e563d6/yarl-1.24.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:47a55d6cf6db2f401017a9e96e5288844e5051911fb4e0c8311a3980f5e59a7d", size = 104487, upload-time = "2026-05-19T21:29:06.491Z" }, + { url = "https://files.pythonhosted.org/packages/41/07/efabe5df87e96d7ad5959760b888344be48cd6884db127b407c6b5503adc/yarl-1.24.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3065657c80a2321225e804048597ad55658a7e76b32d6f5ee4074d04c50401db", size = 102333, upload-time = "2026-05-19T21:29:08.267Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/bcf7c42603e1009295f586d8890f2ba032c8b53310e815adf0a202c73d9f/yarl-1.24.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb84b80d88e19ede158619b80813968713d8d008b0e2497a576e6a0557d50712", size = 99025, upload-time = "2026-05-19T21:29:10.682Z" }, + { url = "https://files.pythonhosted.org/packages/4f/82/84482ab1a57a0f21a08afe6a7004c61d741f8f2ecc3b05c321577c612164/yarl-1.24.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:990de4f680b1c217e77ff0d6aa0029f9eb79889c11fb3e9a3942c7eba29c1996", size = 110507, upload-time = "2026-05-19T21:29:12.954Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8d/a546ba1dfe1b0f290e05fef145cd07614c0f15df1a707195e512d1e39d1d/yarl-1.24.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:abb8ec0323b80161e3802da3150ef660b41d0e9be2048b76a363d93eee992c2b", size = 103719, upload-time = "2026-05-19T21:29:14.893Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b6/267f2a09213138473adfce6b8a6e17791d7fee70bd4d9003218e4dec58b0/yarl-1.24.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e7977781f83638a4c73e0f88425563d70173e0dfd90ac006a45c65036293ee3c", size = 110438, upload-time = "2026-05-19T21:29:16.485Z" }, + { url = "https://files.pythonhosted.org/packages/48/2d/1c8d89c7c5f9cad9fb2902445d94e2ab1d7aa35de029afbb8ae95c42d00f/yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1", size = 105719, upload-time = "2026-05-19T21:29:18.367Z" }, + { url = "https://files.pythonhosted.org/packages/fd/4d/4b880086bd0d3e034d25647be1d830afc3e3f610e98c4ab3490af6b1b6d5/yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9", size = 53576, upload-time = "2026-05-19T21:31:03.909Z" }, +] diff --git a/scripts/gen_sortformer_oracle_audio.py b/scripts/gen_sortformer_oracle_audio.py new file mode 100644 index 00000000..2485675e --- /dev/null +++ b/scripts/gen_sortformer_oracle_audio.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +"""Deterministically synthesize a 2-speaker diarization oracle clip. + +Sortformer is a diarizer, so the oracle case must be multi-speaker; +samples/jfk.wav and the other committed clips are all single-speaker. +This builds a reproducible 2-speaker mixture from two distinct committed +mono clips, with a controlled overlap region, plus a ground-truth RTTM. + +Because we author the timeline, the RTTM is exact: it doubles as a +known-answer for a mini-DER sanity check without any external corpus. +Speaker identity does not depend on language (Sortformer keys on speaker +acoustics), so a cross-language pair maximizes speaker distinctness. + +Outputs (16 kHz mono, deterministic): + samples/sortformer-2spk-mix.wav + tests/golden/sortformer/sortformer-2spk-mix.rttm + +Run: + uv run scripts/gen_sortformer_oracle_audio.py +""" + +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + +import numpy as np +import soundfile as sf + +SR = 16000 +REPO = Path(__file__).resolve().parent.parent +SPK_A_SRC = REPO / "samples" / "jfk.wav" # English male, very distinctive +SPK_B_SRC = REPO / "samples" / "zh.wav" # different speaker/timbre +OUT_WAV = REPO / "samples" / "sortformer-2spk-mix.wav" +OUT_RTTM = REPO / "tests" / "golden" / "sortformer" / "sortformer-2spk-mix.rttm" +CLIP_ID = "sortformer-2spk-mix" + +# Authored timeline in seconds. Overlap is the [9.0, 10.5] region where +# both speakers are active. Total clip length 12.0 s. +SPK_A_WINDOWS = [(0.0, 3.0), (7.0, 10.5)] +SPK_B_WINDOWS = [(3.5, 6.5), (9.0, 12.0)] +TOTAL_SEC = 12.0 + + +def _load_mono_16k(path: Path) -> np.ndarray: + audio, sr = sf.read(str(path), dtype="float32", always_2d=False) + if audio.ndim > 1: + audio = audio.mean(axis=1) + if sr != SR: + # Deterministic linear resample; good enough for a diarization + # oracle clip (no ASR scoring on this audio). + n_out = int(round(len(audio) * SR / sr)) + x_old = np.linspace(0.0, 1.0, num=len(audio), endpoint=False) + x_new = np.linspace(0.0, 1.0, num=n_out, endpoint=False) + audio = np.interp(x_new, x_old, audio).astype(np.float32) + # Peak-normalize each source so both speakers sit at a similar level. + peak = float(np.max(np.abs(audio))) or 1.0 + return (audio / peak * 0.9).astype(np.float32) + + +def _tile_to(src: np.ndarray, n: int) -> np.ndarray: + if len(src) >= n: + return src[:n] + reps = int(np.ceil(n / max(1, len(src)))) + return np.tile(src, reps)[:n] + + +def _lay_windows(src: np.ndarray, windows: list[tuple[float, float]], total_n: int) -> np.ndarray: + track = np.zeros(total_n, dtype=np.float32) + for start, end in windows: + i0 = int(round(start * SR)) + i1 = int(round(end * SR)) + track[i0:i1] = _tile_to(src, i1 - i0) + return track + + +def main() -> int: + for p in (SPK_A_SRC, SPK_B_SRC): + if not p.exists(): + print(f"error: missing source clip {p}", file=sys.stderr) + return 1 + total_n = int(round(TOTAL_SEC * SR)) + a = _lay_windows(_load_mono_16k(SPK_A_SRC), SPK_A_WINDOWS, total_n) + b = _lay_windows(_load_mono_16k(SPK_B_SRC), SPK_B_WINDOWS, total_n) + mix = a + b + peak = float(np.max(np.abs(mix))) or 1.0 + mix = (mix / peak * 0.9).astype(np.float32) + + OUT_WAV.parent.mkdir(parents=True, exist_ok=True) + OUT_RTTM.parent.mkdir(parents=True, exist_ok=True) + sf.write(str(OUT_WAV), mix, SR, subtype="PCM_16") + + lines = [] + for spk, windows in (("spk_A", SPK_A_WINDOWS), ("spk_B", SPK_B_WINDOWS)): + for start, end in windows: + lines.append( + f"SPEAKER {CLIP_ID} 1 {start:.3f} {end - start:.3f} {spk} " + ) + OUT_RTTM.write_text("\n".join(lines) + "\n") + + dur = len(mix) / SR + print(f"wrote {OUT_WAV.relative_to(REPO)} ({dur:.2f}s, 16kHz mono)") + print(f"wrote {OUT_RTTM.relative_to(REPO)} ({len(lines)} turns, 2 speakers, overlap [9.0,10.5]s)") + # Emit a sha so the artifact is verifiably reproducible. + sha = subprocess.run(["shasum", "-a", "256", str(OUT_WAV)], capture_output=True, text=True) + print("sha256:", sha.stdout.split()[0] if sha.returncode == 0 else "n/a") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/hf_cards/diar_streaming_sortformer_4spk-v2.1.yaml b/scripts/hf_cards/diar_streaming_sortformer_4spk-v2.1.yaml new file mode 100644 index 00000000..61a9ab43 --- /dev/null +++ b/scripts/hf_cards/diar_streaming_sortformer_4spk-v2.1.yaml @@ -0,0 +1,86 @@ +# Spec for the HF README of handy-computer/diar_streaming_sortformer_4spk-v2.1-gguf. +# Consumed by scripts/hf_cards/generate.py. +# +# Diarizer family: metric is DER (not WER); pipeline_tag follows the +# upstream NVIDIA card's diarization tagging rather than ASR. + +hf_repo: nvidia/diar_streaming_sortformer_4spk-v2.1 +target_repo: handy-computer/diar_streaming_sortformer_4spk-v2.1-gguf +transcribe_docs_url: https://github.com/handy-computer/transcribe.cpp/blob/main/docs/models/diar_streaming_sortformer_4spk-v2.1.md + +upstream_commit: fafaab5 +pin_date: 2026-07-19 + +# Validation pin for the most recent upload. Updated on each release — +# older HF revisions carry whatever value was current at their upload time. +validation: + reference: NeMo + commit: d42c3bb + date: 2026-07-22 + +license: other +license_display: NVIDIA Open Model License +pipeline_tag: voice-activity-detection +languages: + - en +tags: + - gguf + - transcribe.cpp + - speaker-diarization + - diarization + - streaming + - sortformer + - fastconformer + +metric: DER + +summary: | + Streaming speaker diarization: who spoke when, for up to 4 speakers. + A FastConformer encoder with an 18-layer Transformer head emitting + per-frame speaker-activity probabilities, running online with an + Arrival-Order Speaker Cache (AOSC) + FIFO. NOT a transcription model: + a run produces speaker segments (start, end, speaker id in arrival + order), no text. Takes 16 kHz mono WAV. + +default_quant_index: 2 # Q8_0 + +# Capability flags for the transcribe_cpp metadata block. +capabilities: + streaming: true + translate: false + lang_detect: false + timestamps: none # segment times are diarization output, not transcript timestamps + +# Speedup-over-realtime (×RT) per rig/backend, hand-authored from the bench; +# published raw as rtf_ in the metadata block. +perf: + m4: + cpu: 51 + metal: 110 + +wer: + source: AMI IHM test + metadata_key: ami_ihm_test + notes: | + DER measured on the full AMI IHM test set (16 meetings, ~9 h) against + forced-alignment RTTMs with dihard3-dev post-processing, collar 0.0, + overlap scored, at the very_high_latency operating point. Measured NeMo + reference under the identical protocol: 14.83% DER / 19.89% JER; the + C++ F32 port scores 14.59% / 19.51%. Published DER numbers vary with + RTTM source and post-processing; compare like with like. Only + near-reference tiers ship for this family (k-quant tiers withdrawn; + see the transcribe.cpp family doc, "Quant policy (Stage 7)"). + +quants: + - name: F32 + filename: diar_streaming_sortformer_4spk-v2.1-F32.gguf + size: 471 MB + wer: 14.59% + - name: F16 + filename: diar_streaming_sortformer_4spk-v2.1-F16.gguf + size: 237 MB + wer: 14.23% + - name: Q8_0 + filename: diar_streaming_sortformer_4spk-v2.1-Q8_0.gguf + size: 139 MB + wer: 14.73% diff --git a/scripts/intake.py b/scripts/intake.py index 637b6bca..4cce1534 100755 --- a/scripts/intake.py +++ b/scripts/intake.py @@ -84,6 +84,11 @@ def _guess_architecture(config: dict) -> list[str]: candidates.append("encoder-decoder") if any(t in blob for t in ["audiolm", "audio_llm", "qwen2audio", "qwen3asr"]): candidates.append("audio-llm") + if any(t in blob for t in ["sortformer", "diariz", "eend", "enclabel"]): + # Frame-level end-to-end neural diarizers: encoder + per-frame + # multi-label sigmoid over a fixed max-speaker count (Sortformer, + # EEND/EEND-EDA, pyannote segmentation). Not a transcription head. + candidates.append("encoder-diarizer") return candidates or ["encoder-decoder"] # default guess; human confirms diff --git a/scripts/lib/quant_policy.py b/scripts/lib/quant_policy.py index 2e85c2e1..472a3eef 100644 --- a/scripts/lib/quant_policy.py +++ b/scripts/lib/quant_policy.py @@ -26,9 +26,10 @@ # `general.architecture` KV string written by the family's converter # (NOT the family directory name; e.g. cohere converts to "cohere_asr"). # Used when k-quant tiers would degenerate into Q8_0 because the model's -# row sizes do not divide the k-quant super-block size (256). Shipping -# four near-duplicate Q-tier GGUFs is wasted disk; restrict the matrix -# to the tiers that actually differ for that architecture. +# row sizes do not divide the k-quant super-block size (256), or when a +# family's output is too sensitive to weight perturbation to certify the +# k tiers. Shipping four near-duplicate Q-tier GGUFs is wasted disk; +# restrict the matrix to the tiers that actually earn their place. FAMILY_PRESETS: dict[str, tuple[str, ...]] = { # moonshine-tiny: hidden=288 / intermediate=1152 / vocab=32768 — none # divide 256, so Q6_K/Q5_K_M/Q4_K_M all fall back to Q8_0 storage. @@ -38,6 +39,15 @@ # land within ~5% of Q8_0 file size (measured Stage 5). Drop the K # tiers to avoid shipping near-duplicate GGUFs. "moonshine_streaming": ("F16", "Q8_0"), + # sortformer (streaming diarizer): output depends on discrete AOSC + # speaker-cache compression decisions; k-quant weight error can + # deterministically flip a near-tie pick and permute speaker labels + # mid-stream (Stage 7: Q5_K_M swapped labels on AMI TS3003b at the + # default CPU operating point, 9.5%->32.1% DER; flip risk is chaotic + # in quant error, so clean-on-sample Q6_K/Q4_K_M cannot be certified + # either). K tiers also save little (Q8_0 139MB -> Q4_K_M 92MB) and + # are slower than Q8_0 on CPU. Ship only the near-reference tiers. + "sortformer": ("F16", "Q8_0"), } diff --git a/scripts/lib/test_quant_policy_sync.py b/scripts/lib/test_quant_policy_sync.py index c0935ca9..4566aed4 100644 --- a/scripts/lib/test_quant_policy_sync.py +++ b/scripts/lib/test_quant_policy_sync.py @@ -75,6 +75,9 @@ "enc.layers.0.ln_pre.weight", # qwen3 encoder ln_pre "enc.blocks.0.self_attn.pos_bias_u", # conformer rel-pos bias u "enc.blocks.0.self_attn.pos_bias_v", # conformer rel-pos bias v + "tf.blocks.0.norm_1.weight", # sortformer transformer post-LN (norm_ prefix) + "tf.blocks.0.attn.q.bias", # sortformer transformer attn bias (.bias) + "diar.spk_head.bias", # sortformer diarization head bias (.bias) "dec.pos_enc", # cohere sinusoidal pos table "enc.pos_emb.weight", # whisper encoder pos_emb "dec.pos_emb.weight", # whisper decoder pos_emb @@ -100,6 +103,10 @@ "enc.blocks.3.attn.linear_out.weight", # attention output projection "dec.embed.token.weight", # cohere tied embedding (Embed) "dec.token_embd.weight", # llama-style embedding (Embed) + "tf.blocks.0.attn.q.weight", # sortformer transformer attn projection + "tf.blocks.0.ff.in.weight", # sortformer transformer FFN matrix + "diar.encoder_proj.weight", # sortformer 512->192 projection + "diar.spk_head.weight", # sortformer diarization head (4 sigmoid outputs) ] # KNOWN DRIFT — policy.cpp::classify_tensor places these in the Norm (F32) or diff --git a/scripts/validate.py b/scripts/validate.py index 14f21304..2b15d2de 100644 --- a/scripts/validate.py +++ b/scripts/validate.py @@ -403,8 +403,24 @@ def cmd_ref(args: argparse.Namespace) -> int: # decoder intermediates across subcommands (parakeet). Running # both is safe — if a tensor is dumped by both, the decode # pass overwrites the encoder pass (same values). - for stage in ["encoder", "decode"]: - cmd = base_args + [stage] + common_args + # + # Sortformer is an encoder-diarizer: the offline forward (encoder + # subcommand) emits the offline gate tensors; the streaming `diarize` + # subcommand emits diar.probs (AOSC/FIFO path). VALIDATE_SORTFORMER_PRESET + # selects a matching streaming operating point on both the reference + # (--preset) and the C++ side (TRANSCRIBE_SORTFORMER_STREAM_PRESET in + # cmd_cpp); unset -> the checkpoint-shipped cfg (single chunk on the + # short oracle, i.e. diar.probs == diar.preds_offline). + if args.family == "sortformer": + stages = ["encoder", "diarize"] + else: + stages = ["encoder", "decode"] + sf_preset = os.environ.get("VALIDATE_SORTFORMER_PRESET") + for stage in stages: + stage_args = list(common_args) + if args.family == "sortformer" and stage == "diarize" and sf_preset: + stage_args += ["--preset", sf_preset] + cmd = base_args + [stage] + stage_args run_cmd( cmd, repo, @@ -439,6 +455,18 @@ def cmd_cpp(args: argparse.Namespace) -> int: env = os.environ.copy() env["TRANSCRIBE_DUMP_DIR"] = str(out_dir) + # Sortformer: keep the C++ streaming operating point in lockstep with + # the reference `diarize --preset` (see cmd_ref) so the diar.probs + # tensors are comparable. Also enable the offline full-context forward + # so the enc.* / diar.preds_offline parity tensors are dumped (it is + # gated off by default because it is O(T^2) over the whole clip and + # would OOM on long DER audio). + if args.family == "sortformer": + env["TRANSCRIBE_SORTFORMER_OFFLINE_DUMP"] = "1" + sf_preset = os.environ.get("VALIDATE_SORTFORMER_PRESET") + if sf_preset: + env["TRANSCRIBE_SORTFORMER_STREAM_PRESET"] = sf_preset + # Whisper: by default, exercise the production C++ MelFrontend so # the per-tensor compare covers the full mel→encoder→decoder # pipeline. The env-var ref-mel injection is preserved as an @@ -599,8 +627,13 @@ def cmd_compare(args: argparse.Namespace) -> int: # Transcript comparison: if the reference produced a transcript.json, # verify the C++ transcript. Manifests can opt into normalized compare # for models whose generation differs only in punctuation/casing. + # + # Sortformer is a diarizer: it has no text transcript (the C++ CLI + # emits speaker segments, not `text`). Its behavioral artifact is the + # diar.probs tensor, gated above; the `diarize` stage's segment lines + # are informational only, so skip the text-transcript comparison. ref_transcript = ref_dir / "transcript.json" - if ref_transcript.exists(): + if ref_transcript.exists() and args.family != "sortformer": transcript_compare = case_transcript_compare(manifest, case) ref_data = json.loads(ref_transcript.read_text()) ref_text = str(ref_data.get("text", "")) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 46984c8d..87fcbfc1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,10 @@ add_library(transcribe arch/moss/weights.cpp arch/moss/encoder.cpp arch/moss/decoder.cpp + arch/sortformer/model.cpp + arch/sortformer/stream.cpp + arch/sortformer/capabilities.cpp + arch/sortformer/weights.cpp arch/voxtral/model.cpp arch/voxtral/capabilities.cpp arch/voxtral/weights.cpp diff --git a/src/arch/sortformer/capabilities.cpp b/src/arch/sortformer/capabilities.cpp new file mode 100644 index 00000000..7c929ef2 --- /dev/null +++ b/src/arch/sortformer/capabilities.cpp @@ -0,0 +1,35 @@ +// arch/sortformer/capabilities.cpp - Sortformer capability defaults. +// +// Applied before transcribe::read_capability_kv (KV present overrides, +// KV absent keeps the default). Sortformer is a pure frame-level diarizer: +// no transcript, no translation, no transcript-timestamp capability. Its +// output is speaker segments via the transcript-independent speaker_segment +// surface, so DIARIZATION is a family invariant. + +#include "sortformer.h" + +namespace transcribe::sortformer { + +void apply_family_invariants(transcribe_model & model) { + transcribe_capabilities & caps = model.caps; + + // Fixed 16 kHz mel bank (NeMo AudioToMelSpectrogramPreprocessor). + caps.native_sample_rate = 16000; + + // Not a transcription model. + caps.supports_translate = false; + + // Diarization segment times are intrinsic; there is no transcript, so + // there is no transcript-timestamp capability to advertise. + caps.max_timestamp_kind = TRANSCRIBE_TIMESTAMPS_NONE; + + // The model emits speaker-attributed output (T x 4 activity -> "who + // spoke when" segments). run() populates the transcript-independent + // speaker_segment surface directly from the probs. + transcribe::set_feature(&model, TRANSCRIBE_FEATURE_DIARIZATION, true); + + // Abort callback honored at the top of each run. + transcribe::set_feature(&model, TRANSCRIBE_FEATURE_CANCELLATION, true); +} + +} // namespace transcribe::sortformer diff --git a/src/arch/sortformer/model.cpp b/src/arch/sortformer/model.cpp new file mode 100644 index 00000000..e59c746b --- /dev/null +++ b/src/arch/sortformer/model.cpp @@ -0,0 +1,1019 @@ +// arch/sortformer/model.cpp - Sortformer (encoder-diarizer) load / run / +// Arch instance. The 17-layer NEST FastConformer encoder is the same NeMo +// ConformerEncoder Parakeet ports, so it reuses parakeet::build_encoder_graph +// verbatim (constructed from a ParakeetWeights populated with only the +// pre_encode + block slots). This file adds the Sortformer-specific graph: +// encoder_proj (512->192) -> 18x post-LN Transformer -> diar sigmoid head, +// producing a T x 4 speaker-activity matrix. + +#include "../parakeet/encoder.h" +#include "../parakeet/weights.h" +#include "conformer/conformer.h" +#include "ggml.h" +#include "gguf.h" +#include "sortformer.h" +#include "transcribe-arch.h" +#include "transcribe-backend.h" +#include "transcribe-batch-util.h" +#include "transcribe-debug.h" +#include "transcribe-flash-policy.h" +#include "transcribe-load-common.h" +#include "transcribe-loader.h" +#include "transcribe-log.h" +#include "transcribe-mel.h" +#include "transcribe-meta.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace transcribe::sortformer { + +extern const Arch arch; + +namespace pk = transcribe::parakeet; +namespace conf = transcribe::conformer; + +static constexpr float kBnEps = 1e-5f; +static constexpr char k_default_variant[] = "diar_streaming_sortformer_4spk-v2.1"; + +SortformerModel::~SortformerModel() { + if (bn_fused_ctx != nullptr) { + ggml_free(bn_fused_ctx); + } + if (bn_fused_buffer != nullptr) { + transcribe::safe_buffer_free(bn_fused_buffer); + } + if (ctx_meta != nullptr) { + ggml_free(ctx_meta); + } + if (backend_buffer != nullptr) { + transcribe::safe_buffer_free(backend_buffer); + } + for (auto it = plan.scheduler_list.rbegin(); it != plan.scheduler_list.rend(); ++it) { + transcribe::safe_backend_free(*it); + } + plan.scheduler_list.clear(); + plan.primary = nullptr; +} + +SortformerSession::~SortformerSession() { + if (sched != nullptr) { + transcribe::safe_sched_free(sched); + } + if (compute_ctx != nullptr) { + ggml_free(compute_ctx); + } +} + +namespace { + +// Map the Sortformer hparams onto the parakeet encoder hparams that +// build_encoder_graph reads. The FastConformer is NeMo's ConformerEncoder +// with xscaling=True, rel_pos self-attention, batch_norm conv, use_bias, +// full (offline) attention. +void fill_conformer_hp(const SortformerHParams & s, pk::ParakeetHParams & p) { + p.enc_n_layers = s.enc_n_layers; + p.enc_d_model = s.enc_d_model; + p.enc_n_heads = s.enc_n_heads; + p.enc_d_ff = s.enc_d_ff; + p.enc_conv_kernel = s.enc_conv_kernel; + p.enc_subsampling_factor = s.enc_subsampling_factor; + p.enc_subsampling_channels = s.enc_subsampling_channels; + p.enc_pos_emb_max_len = s.enc_pos_emb_max_len; + p.enc_use_bias = true; + p.enc_xscaling = true; // NEST FastConformer uses xscaling + p.enc_att_context_left = -1; + p.enc_att_context_right = -1; + p.enc_att_context_style = pk::ParakeetHParams::AttContextStyle::Regular; + p.enc_conv_context_left = -1; + p.enc_conv_context_right = -1; + p.enc_conv_norm_type = pk::ParakeetHParams::ConvNormType::BatchNorm; + + // Frontend fields build_encoder_graph's pre_encode geometry reads. + p.fe_num_mels = s.fe_num_mels; + p.fe_sample_rate = s.fe_sample_rate; + p.fe_n_fft = s.fe_n_fft; + p.fe_win_length = s.fe_win_length; + p.fe_hop_length = s.fe_hop_length; + p.fe_normalize = s.fe_normalize; + p.fe_dither = s.fe_dither; + p.fe_pre_emphasis = s.fe_pre_emphasis; +} + +// Populate ONLY the pre_encode + block slots of a ParakeetWeights from the +// GGUF (the conformer). Predictor / joint / head stay empty. Mirrors the +// encoder portion of build_parakeet_weights (identical tensor names). +transcribe_status load_conformer_weights(ggml_context * ctx, const pk::ParakeetHParams & hp, pk::ParakeetWeights & w) { + char name[128]; + auto get = [&](const char * nm) -> ggml_tensor * { + ggml_tensor * t = ggml_get_tensor(ctx, nm); + if (t == nullptr) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: missing conformer tensor %s", nm); + } + return t; + }; +#define G(dst, nm) \ + do { \ + (dst) = get(nm); \ + if ((dst) == nullptr) \ + return TRANSCRIBE_ERR_GGUF; \ + } while (0) +#define GL(dst, fmt, i) \ + do { \ + std::snprintf(name, sizeof(name), fmt, i); \ + G(dst, name); \ + } while (0) + + auto & pe = w.pre_encode; + G(pe.conv0_w, "enc.pre_encode.conv.0.weight"); + G(pe.conv0_b, "enc.pre_encode.conv.0.bias"); + G(pe.conv2_w, "enc.pre_encode.conv.2.weight"); + G(pe.conv2_b, "enc.pre_encode.conv.2.bias"); + G(pe.conv3_w, "enc.pre_encode.conv.3.weight"); + G(pe.conv3_b, "enc.pre_encode.conv.3.bias"); + G(pe.conv5_w, "enc.pre_encode.conv.5.weight"); + G(pe.conv5_b, "enc.pre_encode.conv.5.bias"); + G(pe.conv6_w, "enc.pre_encode.conv.6.weight"); + G(pe.conv6_b, "enc.pre_encode.conv.6.bias"); + G(pe.out_w, "enc.pre_encode.out.weight"); + G(pe.out_b, "enc.pre_encode.out.bias"); + + w.blocks.assign(static_cast(hp.enc_n_layers), pk::ParakeetBlock{}); + for (int i = 0; i < hp.enc_n_layers; ++i) { + auto & b = w.blocks[static_cast(i)]; + GL(b.norm_ff1_w, "enc.blocks.%d.norm_ff1.weight", i); + GL(b.norm_ff1_b, "enc.blocks.%d.norm_ff1.bias", i); + GL(b.ff1_lin1_w, "enc.blocks.%d.ff1.linear1.weight", i); + GL(b.ff1_lin2_w, "enc.blocks.%d.ff1.linear2.weight", i); + GL(b.norm_attn_w, "enc.blocks.%d.norm_attn.weight", i); + GL(b.norm_attn_b, "enc.blocks.%d.norm_attn.bias", i); + GL(b.attn_q_w, "enc.blocks.%d.attn.linear_q.weight", i); + GL(b.attn_k_w, "enc.blocks.%d.attn.linear_k.weight", i); + GL(b.attn_v_w, "enc.blocks.%d.attn.linear_v.weight", i); + GL(b.attn_out_w, "enc.blocks.%d.attn.linear_out.weight", i); + GL(b.attn_pos_w, "enc.blocks.%d.attn.linear_pos.weight", i); + GL(b.attn_pos_u, "enc.blocks.%d.attn.pos_bias_u", i); + GL(b.attn_pos_v, "enc.blocks.%d.attn.pos_bias_v", i); + GL(b.norm_conv_w, "enc.blocks.%d.norm_conv.weight", i); + GL(b.norm_conv_b, "enc.blocks.%d.norm_conv.bias", i); + GL(b.conv_pw1_w, "enc.blocks.%d.conv.pointwise1.weight", i); + GL(b.conv_dw_w, "enc.blocks.%d.conv.depthwise.weight", i); + GL(b.conv_pw2_w, "enc.blocks.%d.conv.pointwise2.weight", i); + GL(b.conv_bn_w, "enc.blocks.%d.conv.bn.weight", i); + GL(b.conv_bn_b, "enc.blocks.%d.conv.bn.bias", i); + GL(b.conv_bn_rm, "enc.blocks.%d.conv.bn.running_mean", i); + GL(b.conv_bn_rv, "enc.blocks.%d.conv.bn.running_var", i); + GL(b.norm_ff2_w, "enc.blocks.%d.norm_ff2.weight", i); + GL(b.norm_ff2_b, "enc.blocks.%d.norm_ff2.bias", i); + GL(b.ff2_lin1_w, "enc.blocks.%d.ff2.linear1.weight", i); + GL(b.ff2_lin2_w, "enc.blocks.%d.ff2.linear2.weight", i); + GL(b.norm_out_w, "enc.blocks.%d.norm_out.weight", i); + GL(b.norm_out_b, "enc.blocks.%d.norm_out.bias", i); + // use_bias=true: linear + conv biases (linear_pos stays bias-free). + GL(b.ff1_lin1_b, "enc.blocks.%d.ff1.linear1.bias", i); + GL(b.ff1_lin2_b, "enc.blocks.%d.ff1.linear2.bias", i); + GL(b.attn_q_b, "enc.blocks.%d.attn.linear_q.bias", i); + GL(b.attn_k_b, "enc.blocks.%d.attn.linear_k.bias", i); + GL(b.attn_v_b, "enc.blocks.%d.attn.linear_v.bias", i); + GL(b.attn_out_b, "enc.blocks.%d.attn.linear_out.bias", i); + GL(b.conv_pw1_b, "enc.blocks.%d.conv.pointwise1.bias", i); + GL(b.conv_dw_b, "enc.blocks.%d.conv.depthwise.bias", i); + GL(b.conv_pw2_b, "enc.blocks.%d.conv.pointwise2.bias", i); + GL(b.ff2_lin1_b, "enc.blocks.%d.ff2.linear1.bias", i); + GL(b.ff2_lin2_b, "enc.blocks.%d.ff2.linear2.bias", i); + } +#undef G +#undef GL + return TRANSCRIBE_OK; +} + +// Fuse the conformer BatchNorm into scale + bias tensors (parakeet's +// build_encoder_graph consumes conv_bn_fused_scale/bias, not the raw BN). +transcribe_status fuse_conformer_bn(SortformerModel & m) { + const size_t n_blocks = m.conformer.blocks.size(); + if (n_blocks == 0) { + return TRANSCRIBE_OK; + } + const int64_t d = m.conformer_hp.enc_d_model; + const size_t tensor_bytes = static_cast(d) * sizeof(float); + + const size_t ctx_size = n_blocks * 2 * ggml_tensor_overhead() + 256; + ggml_init_params params = { ctx_size, nullptr, /*no_alloc=*/true }; + m.bn_fused_ctx = ggml_init(params); + if (m.bn_fused_ctx == nullptr) { + return TRANSCRIBE_ERR_BACKEND; + } + for (size_t i = 0; i < n_blocks; ++i) { + auto & b = m.conformer.blocks[i]; + b.conv_bn_fused_scale = ggml_new_tensor_1d(m.bn_fused_ctx, GGML_TYPE_F32, d); + b.conv_bn_fused_bias = ggml_new_tensor_1d(m.bn_fused_ctx, GGML_TYPE_F32, d); + } + m.bn_fused_buffer = ggml_backend_alloc_ctx_tensors(m.bn_fused_ctx, m.plan.scheduler_list.back()); + if (m.bn_fused_buffer == nullptr) { + return TRANSCRIBE_ERR_BACKEND; + } + std::vector bn_w(d), bn_b(d), rm(d), rv(d), fused_s(d), fused_b(d); + for (size_t i = 0; i < n_blocks; ++i) { + auto & b = m.conformer.blocks[i]; + ggml_backend_tensor_get(b.conv_bn_w, bn_w.data(), 0, tensor_bytes); + ggml_backend_tensor_get(b.conv_bn_b, bn_b.data(), 0, tensor_bytes); + ggml_backend_tensor_get(b.conv_bn_rm, rm.data(), 0, tensor_bytes); + ggml_backend_tensor_get(b.conv_bn_rv, rv.data(), 0, tensor_bytes); + for (int64_t c = 0; c < d; ++c) { + const float s = bn_w[c] / std::sqrt(rv[c] + kBnEps); + fused_s[c] = s; + fused_b[c] = bn_b[c] - rm[c] * s; + } + ggml_backend_tensor_set(b.conv_bn_fused_scale, fused_s.data(), 0, tensor_bytes); + ggml_backend_tensor_set(b.conv_bn_fused_bias, fused_b.data(), 0, tensor_bytes); + } + return TRANSCRIBE_OK; +} + +// ---- diar-head graph helpers ---- + +ggml_tensor * layer_norm(ggml_context * ctx, ggml_tensor * x, ggml_tensor * w, ggml_tensor * b) { + x = ggml_norm(ctx, x, 1e-5f); + x = ggml_mul(ctx, x, w); + x = ggml_add(ctx, x, b); + return x; +} + +ggml_tensor * linear(ggml_context * ctx, ggml_tensor * W, ggml_tensor * x, ggml_tensor * b) { + ggml_tensor * y = ggml_mul_mat(ctx, W, x); + if (b != nullptr) { + y = ggml_add(ctx, y, b); + } + return y; +} + +// One post-LN Transformer encoder block (no positional encoding, full +// attention). x ne = [d, T]. +ggml_tensor * tf_block(ggml_context * ctx, const SortformerTfBlock & b, ggml_tensor * x, int d, int n_head, int T) { + const int head_dim = d / n_head; + const float attn_scale = std::sqrt(std::sqrt(static_cast(head_dim))); + const float inv_scale = 1.0f / attn_scale; + + ggml_tensor * residual = x; + + ggml_tensor * q = linear(ctx, b.attn_q_w, x, b.attn_q_b); + ggml_tensor * k = linear(ctx, b.attn_k_w, x, b.attn_k_b); + ggml_tensor * v = linear(ctx, b.attn_v_w, x, b.attn_v_b); + + q = ggml_cont(ctx, ggml_permute(ctx, ggml_reshape_3d(ctx, q, head_dim, n_head, T), 0, 2, 1, 3)); // [hd,T,H] + k = ggml_cont(ctx, ggml_permute(ctx, ggml_reshape_3d(ctx, k, head_dim, n_head, T), 0, 2, 1, 3)); // [hd,T,H] + v = ggml_cont(ctx, ggml_permute(ctx, ggml_reshape_3d(ctx, v, head_dim, n_head, T), 0, 2, 1, 3)); // [hd,T,H] + + // NeMo pre-divides q and k by sqrt(sqrt(head_dim)); scores = q.k^T / sqrt(head_dim). + q = ggml_scale(ctx, q, inv_scale); + k = ggml_scale(ctx, k, inv_scale); + + ggml_tensor * kq = ggml_mul_mat(ctx, k, q); // [T_k, T_q, H] + kq = ggml_soft_max(ctx, kq); // softmax over keys (ne0) + + ggml_tensor * v_t = ggml_cont(ctx, ggml_permute(ctx, v, 1, 0, 2, 3)); // [T, hd, H] + ggml_tensor * ctx_out = ggml_mul_mat(ctx, v_t, kq); // [hd, T_q, H] + ctx_out = ggml_cont(ctx, ggml_permute(ctx, ctx_out, 0, 2, 1, 3)); // [hd, H, T] + ctx_out = ggml_reshape_2d(ctx, ctx_out, d, T); // [d, T] + + ggml_tensor * attn_out = linear(ctx, b.attn_o_w, ctx_out, b.attn_o_b); + + // residual + LN1 (post-LN) + x = ggml_add(ctx, attn_out, residual); + x = layer_norm(ctx, x, b.norm1_w, b.norm1_b); + + // FFN: dense_in -> relu -> dense_out, residual + LN2 + ggml_tensor * res2 = x; + ggml_tensor * f = linear(ctx, b.ff_in_w, x, b.ff_in_b); + f = ggml_relu(ctx, f); + f = linear(ctx, b.ff_out_w, f, b.ff_out_b); + x = ggml_add(ctx, f, res2); + x = layer_norm(ctx, x, b.norm2_w, b.norm2_b); + return x; +} + +// ---- Streaming two-phase graph helpers ---- +// +// The FastConformer is reused via the family-agnostic conf:: primitives so +// the streaming path can split pre_encode (Graph A) from the block stack +// (Graph B) without touching parakeet. sf_*_view mirror the static +// to_view() helpers in parakeet/encoder.cpp; sf_conv_policy mirrors the +// policy build in build_encoder_graph (offline subsample, no causal). + +conf::ConvPolicy sf_conv_policy(const char * backend) { + conf::ConvPolicy policy{}; + policy.direct_pw = conf::detect_direct_pw(backend); + // Parakeet block/pre_encode depthwise defaults (encoder.cpp:50-66). + policy.direct_dw_in_block = conf::resolve_conv_direct("TRANSCRIBE_CONV_DIRECT_DW", "TRANSCRIBE_CONV_NO_DIRECT_DW", + /*backend_default=*/true); + const bool is_metal = + backend != nullptr && (std::strstr(backend, "Metal") != nullptr || std::strstr(backend, "metal") != nullptr); + policy.direct_dw_in_pre_encode = conf::resolve_conv_direct( + "TRANSCRIBE_CONV_DIRECT_DW", "TRANSCRIBE_CONV_NO_DIRECT_DW", /*backend_default=*/!is_metal); + policy.causal_pre_encode = false; // NEST offline subsample (Regular att) + return policy; +} + +conf::PreEncodeView sf_pre_view(const pk::ParakeetPreEncode & pe) { + conf::PreEncodeView v; + v.conv0_w = pe.conv0_w; + v.conv0_b = pe.conv0_b; + v.conv2_w = pe.conv2_w; + v.conv2_b = pe.conv2_b; + v.conv3_w = pe.conv3_w; + v.conv3_b = pe.conv3_b; + v.conv5_w = pe.conv5_w; + v.conv5_b = pe.conv5_b; + v.conv6_w = pe.conv6_w; + v.conv6_b = pe.conv6_b; + v.out_w = pe.out_w; + v.out_b = pe.out_b; + return v; +} + +conf::BlockView sf_block_view(const pk::ParakeetBlock & b) { + conf::BlockView v; + v.norm_ff1_w = b.norm_ff1_w; + v.norm_ff1_b = b.norm_ff1_b; + v.ff1_lin1_w = b.ff1_lin1_w; + v.ff1_lin1_b = b.ff1_lin1_b; + v.ff1_lin2_w = b.ff1_lin2_w; + v.ff1_lin2_b = b.ff1_lin2_b; + v.norm_attn_w = b.norm_attn_w; + v.norm_attn_b = b.norm_attn_b; + v.attn_q_w = b.attn_q_w; + v.attn_q_b = b.attn_q_b; + v.attn_k_w = b.attn_k_w; + v.attn_k_b = b.attn_k_b; + v.attn_v_w = b.attn_v_w; + v.attn_v_b = b.attn_v_b; + v.attn_out_w = b.attn_out_w; + v.attn_out_b = b.attn_out_b; + v.attn_pos_w = b.attn_pos_w; + v.attn_pos_u = b.attn_pos_u; + v.attn_pos_v = b.attn_pos_v; + v.norm_conv_w = b.norm_conv_w; + v.norm_conv_b = b.norm_conv_b; + v.conv_pw1_w = b.conv_pw1_w; + v.conv_pw1_b = b.conv_pw1_b; + v.conv_dw_w = b.conv_dw_w; + v.conv_dw_b = b.conv_dw_b; + v.conv_pw2_w = b.conv_pw2_w; + v.conv_pw2_b = b.conv_pw2_b; + v.conv_bn_fused_scale = b.conv_bn_fused_scale; + v.conv_bn_fused_bias = b.conv_bn_fused_bias; + v.conv_ln_w = b.conv_bn_w; + v.conv_ln_b = b.conv_bn_b; + v.norm_ff2_w = b.norm_ff2_w; + v.norm_ff2_b = b.norm_ff2_b; + v.ff2_lin1_w = b.ff2_lin1_w; + v.ff2_lin1_b = b.ff2_lin1_b; + v.ff2_lin2_w = b.ff2_lin2_w; + v.ff2_lin2_b = b.ff2_lin2_b; + v.norm_out_w = b.norm_out_w; + v.norm_out_b = b.norm_out_b; + return v; +} + +// Host sinusoidal rel-pos table [pos_len, d_model] (same as the offline +// builder in run(); factored for per-chunk reuse in the streaming path). +void fill_rel_pos_emb(std::vector & buf, std::vector & div_term, int pos_len, int d_model) { + const int zero_index = (pos_len - 1) / 2; + const float ln_10000 = std::log(10000.0f); + buf.assign(static_cast(pos_len) * d_model, 0.0f); + div_term.resize(static_cast(d_model / 2)); + for (int kk = 0; kk < d_model / 2; ++kk) { + div_term[static_cast(kk)] = + std::exp(static_cast(2 * kk) * (-ln_10000 / static_cast(d_model))); + } + for (int i = 0; i < pos_len; ++i) { + const float pos = static_cast(zero_index - i); + float * row = buf.data() + static_cast(i) * d_model; + for (int kk = 0; kk < d_model / 2; ++kk) { + const float div = div_term[static_cast(kk)]; + row[2 * kk] = std::sin(pos * div); + row[2 * kk + 1] = std::cos(pos * div); + } + } +} + +// Graph A: pre_encode over one mel window [n_mels, M] -> [enc_d_model, T_diar]. +struct PreEncodeBuild { + ggml_cgraph * graph = nullptr; + ggml_tensor * mel_in = nullptr; + ggml_tensor * out = nullptr; +}; + +PreEncodeBuild build_pre_encode_graph(ggml_context * ctx, SortformerModel & m, int M) { + PreEncodeBuild b{}; + const int n_mels = m.conformer_hp.fe_num_mels; + ggml_tensor * mel_in = ggml_new_tensor_4d(ctx, GGML_TYPE_F32, M, n_mels, 1, 1); + ggml_set_name(mel_in, "chunk.mel.in"); + ggml_set_input(mel_in); + const conf::ConvPolicy policy = sf_conv_policy(m.backend.c_str()); + ggml_tensor * out = conf::build_pre_encode(ctx, sf_pre_view(m.conformer.pre_encode), mel_in, policy, + /*name_prefix=*/"chunk.pre_encode", /*error_tag=*/"sortformer", nullptr); + if (out == nullptr) { + return b; + } + ggml_cgraph * graph = ggml_new_graph_custom(ctx, 8192, false); + ggml_build_forward_expand(graph, out); + b.graph = graph; + b.mel_in = mel_in; + b.out = out; + return b; +} + +// Graph B: [enc_d_model, T_concat] concat -> xscale -> 17 conformer blocks -> +// encoder_proj -> 18 post-LN transformer -> diar head -> preds [n_spk, T_concat]. +struct StreamInferBuild { + ggml_cgraph * graph = nullptr; + ggml_tensor * concat_in = nullptr; + ggml_tensor * pos_emb_in = nullptr; + ggml_tensor * preds = nullptr; +}; + +StreamInferBuild build_stream_infer_graph(ggml_context * ctx, SortformerModel & m, int T_concat) { + StreamInferBuild b{}; + const int ed = m.conformer_hp.enc_d_model; + ggml_tensor * concat_in = ggml_new_tensor_2d(ctx, GGML_TYPE_F32, ed, T_concat); + ggml_set_name(concat_in, "stream.concat.in"); + ggml_set_input(concat_in); + + // xscaling (NEST FastConformer, applied on the concat, not stored in cache). + ggml_tensor * x = ggml_scale(ctx, concat_in, std::sqrt(static_cast(ed))); + + const int pos_len = 2 * T_concat - 1; + ggml_tensor * pos_emb_in = ggml_new_tensor_2d(ctx, GGML_TYPE_F32, ed, pos_len); + ggml_set_name(pos_emb_in, "stream.pos_emb.in"); + ggml_set_input(pos_emb_in); + + conf::BlockParams bp{}; + bp.d_model = ed; + bp.n_head = m.conformer_hp.enc_n_heads; + bp.conv_kernel = m.conformer_hp.enc_conv_kernel; + bp.kv_type = GGML_TYPE_F32; + bool enc_use_flash = true, dec_use_flash = false; + transcribe::flash::apply_env_overrides(enc_use_flash, dec_use_flash); + bp.use_flash = enc_use_flash; + bp.policy = sf_conv_policy(m.backend.c_str()); + bp.att_context_left = -1; // full (offline) attention over the concat + bp.att_context_right = -1; + bp.att_context_style = conf::BlockParams::AttContextStyle::Regular; + bp.conv_context_left = -1; + bp.conv_context_right = -1; + bp.conv_norm_type = conf::BlockParams::ConvNormType::BatchNorm; + + for (int i = 0; i < m.conformer_hp.enc_n_layers; ++i) { + x = conf::build_conformer_block(ctx, x, pos_emb_in, sf_block_view(m.conformer.blocks[static_cast(i)]), + bp); + } + + // encoder_proj (enc_d_model -> tf_d_model) then 18x post-LN transformer. + ggml_tensor * t = linear(ctx, m.weights.enc_proj_w, x, m.weights.enc_proj_b); + const int d = m.hparams.tf_d_model; + for (int i = 0; i < m.hparams.tf_n_layers; ++i) { + t = tf_block(ctx, m.weights.tf_blocks[static_cast(i)], t, d, m.hparams.tf_n_heads, T_concat); + } + + // Diar head (forward_speaker_sigmoids). All frames valid in sync mode, so + // the encoder_mask multiply is a no-op. + ggml_tensor * h = ggml_relu(ctx, t); + h = linear(ctx, m.weights.fc1_w, h, m.weights.fc1_b); + h = ggml_relu(ctx, h); + ggml_tensor * s = linear(ctx, m.weights.single_spk_head_w, h, m.weights.single_spk_head_b); + ggml_tensor * preds = ggml_sigmoid(ctx, s); // [n_spk, T_concat] + + ggml_cgraph * graph = ggml_new_graph_custom(ctx, 8192, false); + ggml_build_forward_expand(graph, preds); + b.graph = graph; + b.concat_in = concat_in; + b.pos_emb_in = pos_emb_in; + b.preds = preds; + return b; +} + +} // namespace + +transcribe_status load(Loader & loader, const transcribe_model_load_params * params, transcribe_model ** out_model) { + const int64_t t_load_start = ggml_time_us(); + + auto m = std::make_unique(); + m->arch = &arch; + m->t_load_us = 0; + + m->variant = loader.variant().empty() ? k_default_variant : loader.variant(); + m->backend.clear(); + + apply_family_invariants(*m); + m->caps.n_languages = 0; + m->caps.languages = nullptr; + + if (const transcribe_status st = read_capability_kv(loader.gguf(), m->caps); st != TRANSCRIBE_OK) { + return st; + } + if (const transcribe_status st = read_languages_kv(loader.gguf(), *m); st != TRANSCRIBE_OK) { + return st; + } + if (const transcribe_status st = read_sortformer_hparams(loader.gguf(), m->hparams); st != TRANSCRIBE_OK) { + return st; + } + fill_conformer_hp(m->hparams, m->conformer_hp); + + // Mel front-end (NeMo AudioToMelSpectrogramPreprocessor; normalize=none). + { + transcribe::MelConfig cfg{}; + cfg.sample_rate = m->hparams.fe_sample_rate; + cfg.num_mels = m->hparams.fe_num_mels; + cfg.n_fft = m->hparams.fe_n_fft; + cfg.win_length = m->hparams.fe_win_length; + cfg.hop_length = m->hparams.fe_hop_length; + cfg.pre_emphasis = m->hparams.fe_pre_emphasis; + cfg.normalize = m->hparams.fe_normalize; + cfg.pad_mode = "constant"; + // NeMo AudioToMelSpectrogramPreprocessor uses ceil(n/hop) framing; + // the mel tensor is pad_to=16 padded but forward() trims it back to + // the real length before the encoder, so feeding the ceil length is + // the faithful path (see forward-map Frontend note). + cfg.nemo_seq_len_ceil = true; + m->mel.emplace(cfg); + } + + gguf_init_params init_params{}; + init_params.no_alloc = true; + init_params.ctx = &m->ctx_meta; + gguf_context * gguf_data = gguf_init_from_file(loader.path().c_str(), init_params); + if (gguf_data == nullptr) { + return TRANSCRIBE_ERR_GGUF; + } + + if (const transcribe_status st = load_conformer_weights(m->ctx_meta, m->conformer_hp, m->conformer); + st != TRANSCRIBE_OK) { + gguf_free(gguf_data); + return st; + } + if (const transcribe_status st = build_sortformer_weights(m->ctx_meta, m->hparams, m->weights); + st != TRANSCRIBE_OK) { + gguf_free(gguf_data); + return st; + } + + const transcribe_backend_request backend_req = (params != nullptr) ? params->backend : TRANSCRIBE_BACKEND_AUTO; + if (const transcribe_status st = transcribe::load_common::init_backends( + backend_req, (params != nullptr) ? params->gpu_device : 0, "sortformer", m->plan); + st != TRANSCRIBE_OK) { + gguf_free(gguf_data); + return st; + } + m->backend = ggml_backend_name(m->plan.primary); + m->primary_backend = m->plan.primary; + + ggml_backend_buffer_t weights_buffer = ggml_backend_alloc_ctx_tensors(m->ctx_meta, m->plan.primary); + if (weights_buffer == nullptr) { + gguf_free(gguf_data); + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: ggml_backend_alloc_ctx_tensors failed"); + return TRANSCRIBE_ERR_GGUF; + } + m->backend_buffer = weights_buffer; + ggml_backend_buffer_set_usage(weights_buffer, GGML_BACKEND_BUFFER_USAGE_WEIGHTS); + + if (const transcribe_status st = + transcribe::load_common::stream_tensor_data(loader.path(), gguf_data, m->ctx_meta, "sortformer"); + st != TRANSCRIBE_OK) { + gguf_free(gguf_data); + return st; + } + gguf_free(gguf_data); + + if (const transcribe_status st = fuse_conformer_bn(*m); st != TRANSCRIBE_OK) { + return st; + } + + m->t_load_us = ggml_time_us() - t_load_start; + *out_model = m.release(); + return TRANSCRIBE_OK; +} + +transcribe_status init_context(transcribe_model * model, + const transcribe_session_params * params, + transcribe_session ** out_ctx) { + if (model->arch != &arch) { + return TRANSCRIBE_ERR_INVALID_ARG; + } + auto pc = std::make_unique(); + pc->model = model; + pc->n_threads = params->n_threads; + pc->kv_type = params->kv_type; + *out_ctx = pc.release(); + return TRANSCRIBE_OK; +} + +// Threshold-based probs -> speaker segments (simple offline segmentation; +// the DER-grade dihard3 post-processing is a later, streaming-checkpoint +// concern). probs is row-major [T, n_spk]. Emits one contiguous run per +// speaker as a speaker_segment row. +static void probs_to_speaker_segments(transcribe_session * pc, + const std::vector & probs, + int T, + int n_spk, + double ms_per_frame, + float threshold) { + for (int s = 0; s < n_spk; ++s) { + int run_start = -1; + for (int t = 0; t <= T; ++t) { + const bool active = (t < T) && (probs[static_cast(t) * n_spk + s] > threshold); + if (active && run_start < 0) { + run_start = t; + } else if (!active && run_start >= 0) { + transcribe_session::SpeakerSegmentEntry row; + row.t0_ms = static_cast(std::llround(run_start * ms_per_frame)); + row.t1_ms = static_cast(std::llround(t * ms_per_frame)); + row.speaker_id = s + 1; // 1-based + row.p = std::numeric_limits::quiet_NaN(); + pc->speaker_segments.push_back(row); + run_start = -1; + } + } + } +} + +// Lazily create the persistent multi-backend scheduler shared by the offline +// and streaming graphs. +static transcribe_status ensure_sched(SortformerSession * pc, SortformerModel * pm) { + if (pc->sched == nullptr) { + pc->sched = ggml_backend_sched_new(pm->plan.scheduler_list.data(), nullptr, + static_cast(pm->plan.scheduler_list.size()), + /*graph_size=*/8192, /*parallel=*/false, /*op_offload=*/true); + if (pc->sched == nullptr) { + return TRANSCRIBE_ERR_GGUF; + } + } + return TRANSCRIBE_OK; +} + +// Offline full-context forward. Builds the whole encoder + transformer + diar +// head over the entire mel and dumps the Stage-4 parity tensors (enc.* + +// diar.preds_offline). Invoked only when tensor dumping is active (the +// streaming path is the product); keeps the offline tensor gate green. +static transcribe_status run_offline_forward(SortformerSession * pc, SortformerModel * pm, int mel_n_frames) { + if (pc->compute_ctx != nullptr) { + ggml_free(pc->compute_ctx); + pc->compute_ctx = nullptr; + } + { + ggml_init_params ip{}; + ip.mem_size = 16 * 1024 * 1024; + ip.mem_buffer = nullptr; + ip.no_alloc = true; + pc->compute_ctx = ggml_init(ip); + if (pc->compute_ctx == nullptr) { + return TRANSCRIBE_ERR_GGUF; + } + } + ggml_context * ctx = pc->compute_ctx; + + pk::EncoderBuild eb = + pk::build_encoder_graph(ctx, pm->conformer, pm->conformer_hp, mel_n_frames, GGML_TYPE_F32, pm->backend.c_str()); + if (eb.mel_in == nullptr || eb.out == nullptr || eb.graph == nullptr) { + return TRANSCRIBE_ERR_GGUF; + } + const int T = static_cast(eb.out->ne[1]); + const int d = pm->hparams.tf_d_model; + + ggml_tensor * proj = linear(ctx, pm->weights.enc_proj_w, eb.out, pm->weights.enc_proj_b); + ggml_tensor * x = proj; + for (int i = 0; i < pm->hparams.tf_n_layers; ++i) { + x = tf_block(ctx, pm->weights.tf_blocks[static_cast(i)], x, d, pm->hparams.tf_n_heads, T); + } + ggml_tensor * tf_out = x; + + ggml_tensor * h = ggml_relu(ctx, tf_out); + h = linear(ctx, pm->weights.fc1_w, h, pm->weights.fc1_b); + h = ggml_relu(ctx, h); + ggml_tensor * s = linear(ctx, pm->weights.single_spk_head_w, h, pm->weights.single_spk_head_b); + ggml_tensor * preds = ggml_sigmoid(ctx, s); + + ggml_build_forward_expand(eb.graph, preds); + transcribe::debug::mark_tensor_for_dump(proj); + transcribe::debug::mark_tensor_for_dump(tf_out); + transcribe::debug::mark_tensor_for_dump(preds); + + if (const transcribe_status st = ensure_sched(pc, pm); st != TRANSCRIBE_OK) { + return st; + } + ggml_backend_sched_reset(pc->sched); + if (!ggml_backend_sched_alloc_graph(pc->sched, eb.graph)) { + return TRANSCRIBE_ERR_GGUF; + } + + ggml_backend_tensor_set(eb.mel_in, pc->mel_buf.data(), 0, pc->mel_buf.size() * sizeof(float)); + transcribe::debug::dump_tensor("enc.mel.in", eb.mel_in, "frontend"); + + if (eb.pos_emb_in != nullptr) { + const int d_model = pm->conformer_hp.enc_d_model; + const int pos_len = static_cast(eb.pos_emb_in->ne[1]); + fill_rel_pos_emb(pc->pos_buf, pc->pos_div_term, pos_len, d_model); + ggml_backend_tensor_set(eb.pos_emb_in, pc->pos_buf.data(), 0, pc->pos_buf.size() * sizeof(float)); + } + + transcribe::configure_sched_n_threads(pc->sched, pc->n_threads); + if (ggml_backend_sched_graph_compute(pc->sched, eb.graph) != GGML_STATUS_SUCCESS) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer offline forward: graph_compute failed"); + return TRANSCRIBE_ERR_GGUF; + } + + transcribe::debug::dump_tensor("enc.fastconformer.out", eb.out, "encoder"); + transcribe::debug::dump_tensor("enc.encoder_proj.out", proj, "encoder"); + transcribe::debug::dump_tensor("enc.transformer.out", tf_out, "encoder"); + transcribe::debug::dump_tensor("diar.preds_offline", preds, "encoder"); + return TRANSCRIBE_OK; +} + +// Streaming AOSC/FIFO forward (the product path). Chunks the mel per NeMo's +// streaming_feat_loader, runs Graph A (pre_encode) then Graph B (blocks + +// proj + transformer + head) over the [spkcache|fifo|chunk] concat, and drives +// the host streaming_update_sync / _compress_spkcache state machine. Emits the +// accumulated T x n_spk probs as diar.probs and the speaker segments. +static transcribe_status run_streaming(SortformerSession * pc, + SortformerModel * pm, + int mel_n_mels, + int mel_n_frames, + double ms_per_frame, + transcribe_sortformer_preset preset) { + const SortformerStreamParams P = resolve_stream_params(pm->hparams, preset); + const int ed = pm->conformer_hp.enc_d_model; + const int n_spk = pm->hparams.max_speakers; + const int sub = pm->hparams.enc_subsampling_factor; + const int feat_len = mel_n_frames; + + if (sub <= 0 || P.chunk_len <= 0) { + return TRANSCRIBE_ERR_INVALID_ARG; + } + pc->stream.reset(ed); + if (const transcribe_status st = ensure_sched(pc, pm); st != TRANSCRIBE_OK) { + return st; + } + + const int64_t t_stream_start = ggml_time_us(); + int stt = 0, end = 0, chunk_idx = 0; + while (end < feat_len) { + if (pc->poll_abort()) { + return TRANSCRIBE_ERR_ABORTED; + } + const int left_offset = std::min(P.chunk_left_context * sub, stt); + end = std::min(stt + P.chunk_len * sub, feat_len); + const int right_offset = std::min(P.chunk_right_context * sub, feat_len - end); + const int win_lo = stt - left_offset; + const int win_hi = end + right_offset; + const int M = win_hi - win_lo; + // Diar-frame context: left_offset is a multiple of sub -> round is + // exact; right_offset may be short on the final chunk -> ceil. + const int lc = (left_offset + sub / 2) / sub; + const int rc = (right_offset + sub - 1) / sub; + + if (pc->compute_ctx != nullptr) { + ggml_free(pc->compute_ctx); + pc->compute_ctx = nullptr; + } + { + ggml_init_params ip{}; + ip.mem_size = 32 * 1024 * 1024; + ip.mem_buffer = nullptr; + ip.no_alloc = true; + pc->compute_ctx = ggml_init(ip); + if (pc->compute_ctx == nullptr) { + return TRANSCRIBE_ERR_GGUF; + } + } + ggml_context * ctx = pc->compute_ctx; + transcribe::debug::push_name_prefix("stream.chunk"); + + // ---- Graph A: pre_encode over the mel window ---- + PreEncodeBuild A = build_pre_encode_graph(ctx, *pm, M); + if (A.graph == nullptr) { + transcribe::debug::pop_name_prefix(); + return TRANSCRIBE_ERR_GGUF; + } + const int T_diar = static_cast(A.out->ne[1]); + + // Mel window [n_mels, M] from full mel [n_mels, feat_len], cols + // [win_lo, win_hi). ggml ne=[M, n_mels] -> offset mel*M + col. + pc->chunk_mel_buf.resize(static_cast(mel_n_mels) * M); + for (int mel = 0; mel < mel_n_mels; ++mel) { + const float * src = pc->mel_buf.data() + static_cast(mel) * feat_len + win_lo; + std::copy(src, src + M, pc->chunk_mel_buf.data() + static_cast(mel) * M); + } + + ggml_backend_sched_reset(pc->sched); + if (!ggml_backend_sched_alloc_graph(pc->sched, A.graph)) { + transcribe::debug::pop_name_prefix(); + return TRANSCRIBE_ERR_GGUF; + } + ggml_backend_tensor_set(A.mel_in, pc->chunk_mel_buf.data(), 0, pc->chunk_mel_buf.size() * sizeof(float)); + transcribe::configure_sched_n_threads(pc->sched, pc->n_threads); + if (ggml_backend_sched_graph_compute(pc->sched, A.graph) != GGML_STATUS_SUCCESS) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer streaming: pre_encode compute failed"); + transcribe::debug::pop_name_prefix(); + return TRANSCRIBE_ERR_GGUF; + } + pc->chunk_embs_host.resize(static_cast(T_diar) * ed); + ggml_backend_tensor_get(A.out, pc->chunk_embs_host.data(), 0, pc->chunk_embs_host.size() * sizeof(float)); + + // ---- host concat [spkcache | fifo | chunk_embs] ---- + const int S = pc->stream.spkcache_n; + const int F = pc->stream.fifo_n; + const int T_concat = S + F + T_diar; + pc->concat_host.resize(static_cast(T_concat) * ed); + std::copy(pc->stream.spkcache.begin(), pc->stream.spkcache.begin() + static_cast(S) * ed, + pc->concat_host.begin()); + std::copy(pc->stream.fifo.begin(), pc->stream.fifo.begin() + static_cast(F) * ed, + pc->concat_host.begin() + static_cast(S) * ed); + std::copy(pc->chunk_embs_host.begin(), pc->chunk_embs_host.end(), + pc->concat_host.begin() + static_cast(S + F) * ed); + + // ---- Graph B: xscale + 17 blocks + proj + 18 tf + head ---- + StreamInferBuild B = build_stream_infer_graph(ctx, *pm, T_concat); + if (B.graph == nullptr) { + transcribe::debug::pop_name_prefix(); + return TRANSCRIBE_ERR_GGUF; + } + fill_rel_pos_emb(pc->pos_buf, pc->pos_div_term, 2 * T_concat - 1, ed); + + ggml_backend_sched_reset(pc->sched); + if (!ggml_backend_sched_alloc_graph(pc->sched, B.graph)) { + transcribe::debug::pop_name_prefix(); + return TRANSCRIBE_ERR_GGUF; + } + ggml_backend_tensor_set(B.concat_in, pc->concat_host.data(), 0, pc->concat_host.size() * sizeof(float)); + ggml_backend_tensor_set(B.pos_emb_in, pc->pos_buf.data(), 0, pc->pos_buf.size() * sizeof(float)); + transcribe::configure_sched_n_threads(pc->sched, pc->n_threads); + if (ggml_backend_sched_graph_compute(pc->sched, B.graph) != GGML_STATUS_SUCCESS) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer streaming: infer compute failed"); + transcribe::debug::pop_name_prefix(); + return TRANSCRIBE_ERR_GGUF; + } + pc->stream_preds_host.resize(static_cast(T_concat) * n_spk); + ggml_backend_tensor_get(B.preds, pc->stream_preds_host.data(), 0, pc->stream_preds_host.size() * sizeof(float)); + + transcribe::debug::pop_name_prefix(); + + // ---- host streaming update (FIFO + AOSC compress) ---- + streaming_update_sync(pc->stream, P, n_spk, ed, pc->chunk_embs_host, T_diar, pc->stream_preds_host, T_concat, + lc, rc); + + stt = end; + ++chunk_idx; + } + pc->t_encode_us = ggml_time_us() - t_stream_start; + + // Trim padding tail: NeMo total_preds[:, :ceil(feat_len/sub)]. + const int n_frames = (feat_len + sub - 1) / sub; + const int used_n = std::min(pc->stream.total_n, n_frames); + + if (transcribe::debug::enabled()) { + const long long shape[2] = { used_n, n_spk }; + transcribe::debug::dump_host_f32("diar.probs", pc->stream.total_preds.data(), + static_cast(used_n) * n_spk, shape, 2, "diarize"); + } + + probs_to_speaker_segments(pc, pc->stream.total_preds, used_n, n_spk, ms_per_frame, /*threshold=*/0.5f); + (void) chunk_idx; + return TRANSCRIBE_OK; +} + +transcribe_status run(transcribe_session * session, + const float * pcm, + int n_samples, + const transcribe_run_params * params) { + auto * pc = static_cast(session); + auto * pm = static_cast(session->model); + + if (pc->poll_abort()) { + return TRANSCRIBE_ERR_ABORTED; + } + + // Streaming operating-point run ext (kind/size/range already validated + // by the dispatcher + run_validate pre-clear; re-check is belt-and-braces). + transcribe_sortformer_preset preset = TRANSCRIBE_SORTFORMER_PRESET_DEFAULT; + if (params != nullptr && params->family != nullptr) { + if (const transcribe_status st = transcribe_ext_check(params->family, TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM, + sizeof(struct transcribe_sortformer_stream_ext)); + st != TRANSCRIBE_OK) { + return st; + } + preset = reinterpret_cast(params->family)->preset; + } + pc->clear_result(); + transcribe::debug::init(); + + if (!pm->mel.has_value()) { + return TRANSCRIBE_ERR_INVALID_ARG; + } + int mel_n_mels = 0, mel_n_frames = 0; + if (const transcribe_status mst = + pm->mel->compute(pcm, static_cast(n_samples), pc->mel_buf, mel_n_mels, mel_n_frames); + mst != TRANSCRIBE_OK) { + return mst; + } + + const double ms_per_frame = + 1000.0 * static_cast(pm->hparams.frame_hop) / static_cast(pm->hparams.fe_sample_rate); + + // Offline forward: parity dumps only. Gated behind an explicit env + // (set by validate.py cmd_cpp) because it runs full-context O(T^2) + // attention over the WHOLE clip — fine for the short oracle, but it would + // OOM on the many-minute audio the DER runner feeds (which also enables + // dumping, to read diar.probs). The streaming path is always the product. + if (transcribe::debug::enabled() && std::getenv("TRANSCRIBE_SORTFORMER_OFFLINE_DUMP") != nullptr) { + if (const transcribe_status st = run_offline_forward(pc, pm, mel_n_frames); st != TRANSCRIBE_OK) { + return st; + } + } + + // Streaming AOSC/FIFO forward drives the product output + diar.probs. + if (const transcribe_status st = run_streaming(pc, pm, mel_n_mels, mel_n_frames, ms_per_frame, preset); + st != TRANSCRIBE_OK) { + return st; + } + + pc->result_kind = TRANSCRIBE_TIMESTAMPS_NONE; + pc->has_result = true; + return TRANSCRIBE_OK; +} + +// Kind+slot probe. Sortformer ships one RUN-slot extension (the streaming +// operating-point preset); there is no STREAM-slot surface (no push-audio +// entry point yet — a future one registers a separate kind). +static bool accepts_ext_kind(const transcribe_model * model, transcribe_ext_slot slot, uint32_t kind) { + if (model == nullptr) { + return false; + } + if (slot != TRANSCRIBE_EXT_SLOT_RUN) { + return false; + } + return kind == TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM; +} + +// Pre-clear validation for the _RUN slot (see Arch::run_validate): reject a +// malformed ext or an out-of-range preset before the previous result +// snapshot is destroyed. +static transcribe_status run_validate(const transcribe_session * /*ctx*/, const transcribe_run_params * params) { + if (params == nullptr || params->family == nullptr) { + return TRANSCRIBE_OK; // NULL ext -> family defaults + } + if (const transcribe_status st = transcribe_ext_check(params->family, TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM, + sizeof(struct transcribe_sortformer_stream_ext)); + st != TRANSCRIBE_OK) { + return st; + } + const auto * ext = reinterpret_cast(params->family); + switch (ext->preset) { + case TRANSCRIBE_SORTFORMER_PRESET_DEFAULT: + case TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY: + case TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY: + case TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY: + return TRANSCRIBE_OK; + } + return TRANSCRIBE_ERR_INVALID_ARG; +} + +extern const Arch arch = { + /* .name = */ "sortformer", + /* .load = */ load, + /* .init_context = */ init_context, + /* .run = */ run, + /* .run_batch = */ nullptr, + /* .stream_validate = */ nullptr, + /* .stream_begin = */ nullptr, + /* .stream_feed = */ nullptr, + /* .stream_finalize = */ nullptr, + /* .stream_reset = */ nullptr, + /* .accepts_ext_kind = */ accepts_ext_kind, + /* .run_validate = */ run_validate, +}; + +} // namespace transcribe::sortformer + +// --------------------------------------------------------------------------- +// Public sortformer extension init function (global scope, C linkage). +// Defined here so transcribe.cpp stays family-agnostic; stamps the +// transcribe_ext header (size + kind) and the preset default. +// --------------------------------------------------------------------------- + +extern "C" void transcribe_sortformer_stream_ext_init(struct transcribe_sortformer_stream_ext * p) { + if (p == nullptr) { + return; + } + std::memset(p, 0, sizeof(*p)); + p->ext.size = sizeof(*p); + p->ext.kind = TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM; + p->preset = TRANSCRIBE_SORTFORMER_PRESET_DEFAULT; +} diff --git a/src/arch/sortformer/sortformer.h b/src/arch/sortformer/sortformer.h new file mode 100644 index 00000000..9d044c34 --- /dev/null +++ b/src/arch/sortformer/sortformer.h @@ -0,0 +1,176 @@ +// arch/sortformer/sortformer.h - Sortformer-family internal model and +// context types. Sortformer is an `encoder-diarizer`: a NEST/FastConformer +// encoder (the same NeMo ConformerEncoder Parakeet ports, reused verbatim +// via parakeet::build_encoder_graph) followed by a Linear projection, an +// 18-layer post-LN Transformer encoder, and a 4-way sigmoid speaker head. +// No tokenizer, no decoder, no text: the product is a T x 4 per-frame +// speaker-activity probability matrix. +// +// The central dispatcher talks to the family only through the Arch trait +// and the base classes. + +#pragma once + +#include "../parakeet/encoder.h" // build_encoder_graph +#include "../parakeet/weights.h" // ParakeetHParams / ParakeetWeights (conformer) +#include "transcribe-backend.h" +#include "transcribe-mel.h" +#include "transcribe-model.h" +#include "transcribe-session.h" +#include "transcribe/sortformer.h" // public preset enum + run ext +#include "weights.h" + +#include +#include +#include +#include + +struct ggml_context; +struct ggml_tensor; +struct ggml_backend_buffer; +struct ggml_backend_sched; +typedef struct ggml_backend_buffer * ggml_backend_buffer_t; +typedef struct ggml_backend_sched * ggml_backend_sched_t; + +namespace transcribe::sortformer { + +// Family defaults, applied before transcribe::read_capability_kv (KV +// present overrides, KV absent keeps the default). Defined in +// capabilities.cpp. +void apply_family_invariants(transcribe_model & model); + +// Concrete model. Owns ctx_meta (every weight tensor's data buffer); +// the destructor frees it, invalidating every borrowed ggml_tensor* in +// `conformer` / `weights`. +struct SortformerModel final : public transcribe_model { + SortformerHParams hparams; + + // Conformer encoder reuse. `conformer_hp` carries only the encoder + + // frontend fields parakeet::build_encoder_graph reads; `conformer` + // holds only pre_encode + blocks (predictor/joint/etc. stay empty). + transcribe::parakeet::ParakeetHParams conformer_hp; + transcribe::parakeet::ParakeetWeights conformer; + + // Sortformer-specific weights (encoder_proj + transformer + diar head). + SortformerWeights weights; + + ggml_context * ctx_meta = nullptr; + transcribe::BackendPlan plan; + ggml_backend_buffer_t backend_buffer = nullptr; + + // Fused conformer BN params (computed at load from the raw BN tensors). + ggml_context * bn_fused_ctx = nullptr; + ggml_backend_buffer_t bn_fused_buffer = nullptr; + + // Mel front-end, constructed once at load() from hparams. + std::optional mel; + + SortformerModel() = default; + ~SortformerModel() override; + + // No tokenizer for a diarizer. + const transcribe::Tokenizer * tokenizer() const override { return nullptr; } +}; + +// Streaming operating point (resolved from GGUF stream defaults; a later +// change will expose the presets via a stream extension). All lengths are +// in 80 ms diar frames. +struct SortformerStreamParams { + int chunk_len = 188; + int chunk_left_context = 1; + int chunk_right_context = 1; + int fifo_len = 0; + int spkcache_len = 188; + int spkcache_update_period = 188; + int spkcache_sil_frames_per_spk = 3; + float sil_threshold = 0.2f; + float pred_score_threshold = 0.25f; + float scores_boost_latest = 0.05f; + float strong_boost_rate = 0.75f; + float weak_boost_rate = 1.5f; + float min_pos_scores_rate = 0.5f; + int max_index = 99999; +}; + +// Host-side streaming state (AOSC speaker cache + FIFO), mirroring NeMo's +// StreamingSortformerState. Embeddings are 512-dim pre_encode outputs stored +// row-major [n_frames, enc_d_model]; preds are [n_frames, n_spk]. +struct SortformerStreamState { + std::vector spkcache; // [spkcache_n * D] + std::vector spkcache_preds; // [spkcache_n * S] + int spkcache_n = 0; + bool spkcache_preds_init = false; // NeMo: spkcache_preds is None until first compress + std::vector fifo; // [fifo_n * D] + std::vector fifo_preds; // [fifo_n * S] + int fifo_n = 0; + std::vector mean_sil_emb; // [D] + int64_t n_sil_frames = 0; + std::vector total_preds; // [T_total * S], accumulated chunk preds + int total_n = 0; + int compress_count = 0; // # _compress_spkcache calls (parity-dump index) + + void reset(int emb_dim) { + spkcache.clear(); + spkcache_preds.clear(); + spkcache_n = 0; + spkcache_preds_init = false; + fifo.clear(); + fifo_preds.clear(); + fifo_n = 0; + mean_sil_emb.assign(static_cast(emb_dim), 0.0f); + n_sil_frames = 0; + total_preds.clear(); + total_n = 0; + compress_count = 0; + } +}; + +// Resolve the streaming operating point, lowest to highest precedence: +// GGUF-shipped stream cfg < public run-ext preset (transcribe_sortformer_ +// stream_ext; DEFAULT keeps the GGUF cfg) < TRANSCRIBE_SORTFORMER_STREAM_ +// PRESET env (very_high_latency / high_latency / low_latency / small; +// validation hook) < per-field env overrides. Defined in stream.cpp. +SortformerStreamParams resolve_stream_params(const SortformerHParams & hp, transcribe_sortformer_preset preset); + +// Exact host ports of the NeMo sync-streaming primitives (batch=1). All +// embeddings row-major [n_frames, emb_dim]; preds row-major [n_frames, n_spk]. +// Defined in stream.cpp. +void streaming_update_sync(SortformerStreamState & st, + const SortformerStreamParams & p, + int n_spk, + int emb_dim, + const std::vector & chunk_embs, + int T_diar, + const std::vector & preds, + int T_concat, + int lc, + int rc); + +// Compress st.spkcache (spkcache_n > spkcache_len frames) in place down to +// spkcache_len frames, matching sortformer_modules._compress_spkcache. +void compress_spkcache(SortformerStreamState & st, const SortformerStreamParams & p, int n_spk, int emb_dim); + +// Concrete context. Owns a per-call compute context and a persistent +// multi-backend scheduler. +struct SortformerSession final : public transcribe_session { + ggml_context * compute_ctx = nullptr; + ggml_backend_sched_t sched = nullptr; + + // Per-context scratch reused across runs. + std::vector mel_buf; + std::vector pos_buf; + std::vector pos_div_term; + std::vector probs_host; // [n_spk * T], read back from diar.preds + + // Streaming scratch (AOSC/FIFO path). + SortformerStreamState stream; + std::vector chunk_mel_buf; // [n_mels * M] mel window for Graph A + std::vector chunk_embs_host; // [T_diar * enc_d_model] pre_encode readback + std::vector concat_host; // [T_concat * enc_d_model] Graph B input + std::vector stream_preds_host; // [T_concat * n_spk] Graph B readback + + SortformerSession() = default; + ~SortformerSession() override; +}; + +} // namespace transcribe::sortformer diff --git a/src/arch/sortformer/stream.cpp b/src/arch/sortformer/stream.cpp new file mode 100644 index 00000000..643795b9 --- /dev/null +++ b/src/arch/sortformer/stream.cpp @@ -0,0 +1,475 @@ +// arch/sortformer/stream.cpp - Host-side sync streaming state machine for +// the Sortformer AOSC speaker-cache + FIFO path. Exact ports of NeMo's +// SortformerModules (sortformer_modules.py): streaming_update (sync branch), +// _get_silence_profile, and the exactness-critical _compress_spkcache stack +// (_get_log_pred_scores -> _disable_low_scores -> scores_boost_latest -> +// _boost_topk_scores x2 -> silence pad -> _get_topk_indices -> gather). +// +// Batch size is always 1 here (the CLI path), so every per-batch loop in the +// reference collapses and spk_perm is always None (inference, permute_spk= +// self.training=False). See reports/porting/sortformer/forward-map.md and the +// approved plan for the traced reference call graph. + +#include "sortformer.h" +#include "transcribe-debug.h" +#include "weights.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace transcribe::sortformer { + +namespace { + +constexpr float kNegInf = -std::numeric_limits::infinity(); +constexpr float kPosInf = std::numeric_limits::infinity(); + +// ---- env helpers ---- + +const char * env_get(const char * name) { + const char * v = std::getenv(name); + return (v != nullptr && v[0] != '\0') ? v : nullptr; +} + +bool env_int(const char * name, int & out) { + const char * v = env_get(name); + if (v == nullptr) { + return false; + } + char * end = nullptr; + const long parsed = std::strtol(v, &end, 10); + if (end == v) { + return false; + } + out = static_cast(parsed); + return true; +} + +// One card / validation preset. lc stays at the model default (1); only the +// chunking geometry changes. Mirrors scripts/diar/run_reference_sortformer_nemo.py +// PRESETS plus a "small" preset (forces multi-chunk + compression on the short +// oracle clip for diar.probs parity). +struct Preset { + const char * name; + int chunk_len; + int chunk_right_context; + int fifo_len; + int spkcache_update_period; + int spkcache_len; +}; + +const Preset k_presets[] = { + { "very_high_latency", 340, 40, 40, 300, 188 }, + { "high_latency", 124, 1, 124, 124, 188 }, + { "low_latency", 6, 7, 188, 144, 188 }, + { "small", 20, 1, 10, 20, 24 }, +}; + +} // namespace + +SortformerStreamParams resolve_stream_params(const SortformerHParams & hp, transcribe_sortformer_preset preset) { + SortformerStreamParams p; // score / boost params keep their (verified) defaults + // GGUF-shipped streaming cfg is the baseline. + p.chunk_len = hp.stream_chunk_len > 0 ? hp.stream_chunk_len : p.chunk_len; + p.spkcache_len = hp.stream_spkcache_len > 0 ? hp.stream_spkcache_len : p.spkcache_len; + p.fifo_len = hp.stream_fifo_len; // 0 is a valid shipped value + p.spkcache_update_period = + hp.stream_spkcache_update_period > 0 ? hp.stream_spkcache_update_period : p.spkcache_update_period; + + // Public run-ext preset (DEFAULT keeps the GGUF cfg). Range-checked by + // run_validate before the dispatcher clears the previous result. + const char * ext_name = nullptr; + switch (preset) { + case TRANSCRIBE_SORTFORMER_PRESET_DEFAULT: + break; + case TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY: + ext_name = "very_high_latency"; + break; + case TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY: + ext_name = "high_latency"; + break; + case TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY: + ext_name = "low_latency"; + break; + } + if (ext_name != nullptr) { + for (const Preset & pr : k_presets) { + if (std::string(ext_name) == pr.name) { + p.chunk_len = pr.chunk_len; + p.chunk_right_context = pr.chunk_right_context; + p.fifo_len = pr.fifo_len; + p.spkcache_update_period = pr.spkcache_update_period; + p.spkcache_len = pr.spkcache_len; + break; + } + } + } + + // Named preset env override (validation / DER operating point). + if (const char * name = env_get("TRANSCRIBE_SORTFORMER_STREAM_PRESET")) { + for (const Preset & pr : k_presets) { + if (std::string(name) == pr.name) { + p.chunk_len = pr.chunk_len; + p.chunk_right_context = pr.chunk_right_context; + p.fifo_len = pr.fifo_len; + p.spkcache_update_period = pr.spkcache_update_period; + p.spkcache_len = pr.spkcache_len; + break; + } + } + } + + // Per-field env overrides (highest precedence). + env_int("TRANSCRIBE_SORTFORMER_STREAM_CHUNK_LEN", p.chunk_len); + env_int("TRANSCRIBE_SORTFORMER_STREAM_FIFO_LEN", p.fifo_len); + env_int("TRANSCRIBE_SORTFORMER_STREAM_SPKCACHE_LEN", p.spkcache_len); + env_int("TRANSCRIBE_SORTFORMER_STREAM_UPDATE_PERIOD", p.spkcache_update_period); + env_int("TRANSCRIBE_SORTFORMER_STREAM_RC", p.chunk_right_context); + env_int("TRANSCRIBE_SORTFORMER_STREAM_LC", p.chunk_left_context); + return p; +} + +// ---- _get_silence_profile (sortformer_modules.py:636-667) ---- + +// File-local (only streaming_update_sync calls it). +static void get_silence_profile(SortformerStreamState & st, + float sil_threshold, + const float * pop_embs, + const float * pop_preds, + int n, + int n_spk, + int emb_dim) { + if (n <= 0) { + return; + } + // is_sil[i] = (sum_s preds[i,s]) < sil_threshold ; sil_count = sum is_sil + std::vector is_sil(static_cast(n)); + int64_t sil_count = 0; + for (int i = 0; i < n; ++i) { + float s = 0.0f; + for (int c = 0; c < n_spk; ++c) { + s += pop_preds[static_cast(i) * n_spk + c]; + } + is_sil[static_cast(i)] = (s < sil_threshold) ? 1 : 0; + sil_count += is_sil[static_cast(i)]; + } + if (sil_count == 0) { + return; // has_new_sil false -> unchanged + } + const int64_t old_n = st.n_sil_frames; + const int64_t new_n = old_n + sil_count; + const float denom = static_cast(std::max(new_n, 1)); + for (int d = 0; d < emb_dim; ++d) { + float sil_sum = 0.0f; + for (int i = 0; i < n; ++i) { + if (is_sil[static_cast(i)]) { + sil_sum += pop_embs[static_cast(i) * emb_dim + d]; + } + } + const float old_sum = st.mean_sil_emb[static_cast(d)] * static_cast(old_n); + st.mean_sil_emb[static_cast(d)] = (old_sum + sil_sum) / denom; + } + st.n_sil_frames = new_n; +} + +namespace { + +// _get_log_pred_scores (sortformer_modules.py:669-686). scores[i,s] = +// log(clamp(p,thr)) - log(clamp(1-p,thr)) + sum_s log(clamp(1-p,thr)) - log(0.5). +std::vector get_log_pred_scores(const float * preds, int n, int n_spk, float thr) { + std::vector scores(static_cast(n) * n_spk); + const float log_half = std::log(0.5f); + for (int i = 0; i < n; ++i) { + float l1sum = 0.0f; + for (int s = 0; s < n_spk; ++s) { + const float p = preds[static_cast(i) * n_spk + s]; + l1sum += std::log(std::max(1.0f - p, thr)); + } + for (int s = 0; s < n_spk; ++s) { + const float p = preds[static_cast(i) * n_spk + s]; + const float lp = std::log(std::max(p, thr)); + const float l1 = std::log(std::max(1.0f - p, thr)); + scores[static_cast(i) * n_spk + s] = lp - l1 + l1sum - log_half; + } + } + return scores; +} + +// _disable_low_scores (sortformer_modules.py:782-808). +void disable_low_scores(const float * preds, std::vector & scores, int n, int n_spk, int min_pos) { + // Non-speech (preds <= 0.5) -> -inf. + for (int i = 0; i < n; ++i) { + for (int s = 0; s < n_spk; ++s) { + const size_t idx = static_cast(i) * n_spk + s; + if (!(preds[idx] > 0.5f)) { + scores[idx] = kNegInf; + } + } + } + // Per speaker: if it has >= min_pos positive-scored frames, disable its + // non-positive (but speech) frames. + for (int s = 0; s < n_spk; ++s) { + int pos_count = 0; + for (int i = 0; i < n; ++i) { + if (scores[static_cast(i) * n_spk + s] > 0.0f) { + ++pos_count; + } + } + if (pos_count >= min_pos) { + for (int i = 0; i < n; ++i) { + const size_t idx = static_cast(i) * n_spk + s; + const bool is_speech = preds[idx] > 0.5f; + const bool is_pos = scores[idx] > 0.0f; + if (is_speech && !is_pos) { + scores[idx] = kNegInf; + } + } + } + } +} + +// _boost_topk_scores (sortformer_modules.py:611-634). For each speaker column, +// the k highest-scored frames get scores -= scale*log(0.5) (log(0.5)<0 => +// boosts). Tie-break matches ATen CPU topk: value desc, frame index asc. +void boost_topk_scores(std::vector & scores, int n, int n_spk, int k, float scale) { + if (k <= 0) { + return; + } + // Reference: scores[topk] -= scale * log(0.5). log(0.5) < 0, so the top-k + // scores are increased (boosted). + const float delta = scale * std::log(0.5f); // negative + std::vector order(static_cast(n)); + for (int s = 0; s < n_spk; ++s) { + std::iota(order.begin(), order.end(), 0); + const int kk = std::min(k, n); + std::partial_sort(order.begin(), order.begin() + kk, order.end(), [&](int a, int b) { + const float va = scores[static_cast(a) * n_spk + s]; + const float vb = scores[static_cast(b) * n_spk + s]; + if (va != vb) { + return va > vb; // descending value + } + return a < b; // tie -> lower index first + }); + for (int j = 0; j < kk; ++j) { + scores[static_cast(order[static_cast(j)]) * n_spk + s] -= delta; + } + } +} + +} // namespace + +// ---- _compress_spkcache (sortformer_modules.py:838-896) ---- + +void compress_spkcache(SortformerStreamState & st, const SortformerStreamParams & p, int n_spk, int emb_dim) { + const int N = st.spkcache_n; // n_frames (> spkcache_len) + const int L = p.spkcache_len; // target frames + const int sil = p.spkcache_sil_frames_per_spk; + + const int per_spk = L / n_spk - sil; + const int strong = static_cast(std::floor(per_spk * p.strong_boost_rate)); + const int weak = static_cast(std::floor(per_spk * p.weak_boost_rate)); + const int min_pos = static_cast(std::floor(per_spk * p.min_pos_scores_rate)); + + const float * preds = st.spkcache_preds.data(); // [N, n_spk] + + // 1. log-pred scores, disable low scores. + std::vector scores = get_log_pred_scores(preds, N, n_spk, p.pred_score_threshold); + disable_low_scores(preds, scores, N, n_spk, min_pos); + + // 2. boost latest frames (rows >= spkcache_len). += on -inf stays -inf. + if (p.scores_boost_latest > 0.0f) { + for (int i = L; i < N; ++i) { + for (int s = 0; s < n_spk; ++s) { + scores[static_cast(i) * n_spk + s] += p.scores_boost_latest; + } + } + } + + // 3. strong then weak top-k boosting. + boost_topk_scores(scores, N, n_spk, strong, /*scale=*/2.0f); + boost_topk_scores(scores, N, n_spk, weak, /*scale=*/1.0f); + + // 4. append `sil` rows of +inf per speaker; n_frames = N + sil. + const int n_frames = N + sil; + const int n_frames_no_sil = N; + std::vector scores_ext(static_cast(n_frames) * n_spk); + std::copy(scores.begin(), scores.end(), scores_ext.begin()); + for (int i = N; i < n_frames; ++i) { + for (int s = 0; s < n_spk; ++s) { + scores_ext[static_cast(i) * n_spk + s] = kPosInf; + } + } + + // 5. _get_topk_indices: flatten permute(0,2,1) -> flat[s*n_frames + i]; + // top-L largest (value desc, flat-idx asc), -inf picks -> max_index, sort + // ascending, derive frame idx + is_disabled. + const int64_t M = static_cast(n_spk) * n_frames; + std::vector flat(static_cast(M)); + std::iota(flat.begin(), flat.end(), int64_t{ 0 }); + auto flat_val = [&](int64_t f) -> float { + const int s = static_cast(f / n_frames); + const int i = static_cast(f % n_frames); + return scores_ext[static_cast(i) * n_spk + s]; + }; + const int kk = static_cast(std::min(L, M)); + std::partial_sort(flat.begin(), flat.begin() + kk, flat.end(), [&](int64_t a, int64_t b) { + const float va = flat_val(a); + const float vb = flat_val(b); + if (va != vb) { + return va > vb; + } + return a < b; + }); + std::vector picks(static_cast(L)); + for (int j = 0; j < L; ++j) { + if (j < kk) { + const int64_t f = flat[static_cast(j)]; + picks[static_cast(j)] = (flat_val(f) == kNegInf) ? p.max_index : f; + } else { + picks[static_cast(j)] = p.max_index; // fewer than L finite picks + } + } + std::sort(picks.begin(), picks.end()); + + std::vector frame_idx(static_cast(L)); + std::vector is_disabled(static_cast(L)); + for (int j = 0; j < L; ++j) { + const int64_t idx = picks[static_cast(j)]; + bool disabled = (idx == p.max_index); + int f = disabled ? 0 : static_cast(idx % n_frames); + if (!disabled && f >= n_frames_no_sil) { + disabled = true; // came from a +inf silence pad row + } + if (disabled) { + f = 0; + } + frame_idx[static_cast(j)] = f; + is_disabled[static_cast(j)] = disabled ? 1 : 0; + } + + // 6. gather embeddings + preds; disabled -> mean_sil_emb / 0. + std::vector new_emb(static_cast(L) * emb_dim); + std::vector new_preds(static_cast(L) * n_spk); + for (int j = 0; j < L; ++j) { + const int f = frame_idx[static_cast(j)]; + if (is_disabled[static_cast(j)]) { + std::copy(st.mean_sil_emb.begin(), st.mean_sil_emb.end(), + new_emb.begin() + static_cast(j) * emb_dim); + // preds row already zero-initialized. + } else { + std::copy(st.spkcache.begin() + static_cast(f) * emb_dim, + st.spkcache.begin() + static_cast(f + 1) * emb_dim, + new_emb.begin() + static_cast(j) * emb_dim); + std::copy(st.spkcache_preds.begin() + static_cast(f) * n_spk, + st.spkcache_preds.begin() + static_cast(f + 1) * n_spk, + new_preds.begin() + static_cast(j) * n_spk); + } + } + + // Parity dump (residual-uncertainty #1): emit the per-compression selected + // frame indices + is_disabled mask + gathered preds so a matching NeMo dump + // can be compared index-for-index. Gated behind an explicit env on top of + // the normal dump-enabled flag so DER/validate runs are unaffected. + if (transcribe::debug::enabled() && env_get("TRANSCRIBE_SORTFORMER_COMPRESS_DUMP") != nullptr) { + const int k = st.compress_count; + char name[64]; + std::vector fidx(static_cast(L)), fdis(static_cast(L)); + for (int j = 0; j < L; ++j) { + fidx[static_cast(j)] = static_cast(frame_idx[static_cast(j)]); + fdis[static_cast(j)] = is_disabled[static_cast(j)] ? 1.0f : 0.0f; + } + const long long li = L; + const long long shp_in[2] = { N, n_spk }; + std::snprintf(name, sizeof(name), "compress.%03d.input_preds", k); + transcribe::debug::dump_host_f32(name, st.spkcache_preds.data(), static_cast(N) * n_spk, shp_in, 2, + "compress"); + std::snprintf(name, sizeof(name), "compress.%03d.frame_idx", k); + transcribe::debug::dump_host_f32(name, fidx.data(), li, &li, 1, "compress"); + std::snprintf(name, sizeof(name), "compress.%03d.is_disabled", k); + transcribe::debug::dump_host_f32(name, fdis.data(), li, &li, 1, "compress"); + const long long shp[2] = { L, n_spk }; + std::snprintf(name, sizeof(name), "compress.%03d.spkcache_preds", k); + transcribe::debug::dump_host_f32(name, new_preds.data(), static_cast(L) * n_spk, shp, 2, "compress"); + } + ++st.compress_count; + + st.spkcache = std::move(new_emb); + st.spkcache_preds = std::move(new_preds); + st.spkcache_n = L; +} + +// ---- streaming_update (sync branch, sortformer_modules.py:526-609) ---- + +void streaming_update_sync(SortformerStreamState & st, + const SortformerStreamParams & p, + int n_spk, + int emb_dim, + const std::vector & chunk_embs, + int T_diar, + const std::vector & preds, + int /*T_concat*/, + int lc, + int rc) { + const int S = st.spkcache_n; // spkcache_len (local, pre-update) + const int F = st.fifo_n; // fifo_len (local, pre-update) + const int C = T_diar - lc - rc; // chunk_len (middle frames) + + // fifo_preds = preds[S : S+F] (rebuilt from the concat preds each call). + st.fifo_preds.assign(preds.begin() + static_cast(S) * n_spk, + preds.begin() + static_cast(S + F) * n_spk); + // chunk_preds = preds[S+F+lc : S+F+lc+C]. + std::vector chunk_preds(preds.begin() + static_cast(S + F + lc) * n_spk, + preds.begin() + static_cast(S + F + lc + C) * n_spk); + + // Append the middle chunk (embs + preds) to the FIFO. + st.fifo.insert(st.fifo.end(), chunk_embs.begin() + static_cast(lc) * emb_dim, + chunk_embs.begin() + static_cast(lc + C) * emb_dim); + st.fifo_preds.insert(st.fifo_preds.end(), chunk_preds.begin(), chunk_preds.end()); + st.fifo_n = F + C; + + if (F + C > p.fifo_len) { + int pop = p.spkcache_update_period; + pop = std::max(pop, C - p.fifo_len + F); + pop = std::min(pop, F + C); + + std::vector pop_embs(st.fifo.begin(), st.fifo.begin() + static_cast(pop) * emb_dim); + std::vector pop_preds(st.fifo_preds.begin(), st.fifo_preds.begin() + static_cast(pop) * n_spk); + + get_silence_profile(st, p.sil_threshold, pop_embs.data(), pop_preds.data(), pop, n_spk, emb_dim); + + // fifo = fifo[pop:]. + st.fifo.erase(st.fifo.begin(), st.fifo.begin() + static_cast(pop) * emb_dim); + st.fifo_preds.erase(st.fifo_preds.begin(), st.fifo_preds.begin() + static_cast(pop) * n_spk); + st.fifo_n = (F + C) - pop; + + // Append pop-out to speaker cache. + st.spkcache.insert(st.spkcache.end(), pop_embs.begin(), pop_embs.end()); + st.spkcache_n = S + pop; + if (st.spkcache_preds_init) { + st.spkcache_preds.insert(st.spkcache_preds.end(), pop_preds.begin(), pop_preds.end()); + } + + if (st.spkcache_n > p.spkcache_len) { + if (!st.spkcache_preds_init) { + // First compress: seed spkcache_preds = preds[:S] ++ pop_preds. + st.spkcache_preds.assign(preds.begin(), preds.begin() + static_cast(S) * n_spk); + st.spkcache_preds.insert(st.spkcache_preds.end(), pop_preds.begin(), pop_preds.end()); + st.spkcache_preds_init = true; + } + compress_spkcache(st, p, n_spk, emb_dim); + } + } + + // Accumulate the chunk's predictions. + st.total_preds.insert(st.total_preds.end(), chunk_preds.begin(), chunk_preds.end()); + st.total_n += C; +} + +} // namespace transcribe::sortformer diff --git a/src/arch/sortformer/weights.cpp b/src/arch/sortformer/weights.cpp new file mode 100644 index 00000000..bcd2de4e --- /dev/null +++ b/src/arch/sortformer/weights.cpp @@ -0,0 +1,196 @@ +// arch/sortformer/weights.cpp - Sortformer hparam KV reader + weight +// catalog for the Sortformer-specific tensors (encoder_proj + transformer +// + diar head). The conformer weights are loaded separately (parakeet +// reuse); see model.cpp::load. + +#include "weights.h" + +#include "ggml.h" +#include "gguf.h" +#include "transcribe-log.h" + +#include +#include + +namespace transcribe::sortformer { + +namespace { + +transcribe_status kv_u32(const gguf_context * g, const char * key, int32_t & out) { + const int64_t id = gguf_find_key(g, key); + if (id < 0) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: missing KV %s", key); + return TRANSCRIBE_ERR_GGUF; + } + out = static_cast(gguf_get_val_u32(g, id)); + return TRANSCRIBE_OK; +} + +transcribe_status kv_f32(const gguf_context * g, const char * key, float & out) { + const int64_t id = gguf_find_key(g, key); + if (id < 0) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: missing KV %s", key); + return TRANSCRIBE_ERR_GGUF; + } + out = gguf_get_val_f32(g, id); + return TRANSCRIBE_OK; +} + +transcribe_status kv_str(const gguf_context * g, const char * key, std::string & out) { + const int64_t id = gguf_find_key(g, key); + if (id < 0) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: missing KV %s", key); + return TRANSCRIBE_ERR_GGUF; + } + out = gguf_get_val_str(g, id); + return TRANSCRIBE_OK; +} + +} // namespace + +transcribe_status read_sortformer_hparams(const gguf_context * g, SortformerHParams & hp) { + if (g == nullptr) { + return TRANSCRIBE_ERR_INVALID_ARG; + } + +#define RD_U32(key, field) \ + if (const transcribe_status st = kv_u32(g, key, hp.field); st != TRANSCRIBE_OK) \ + return st +#define RD_F32(key, field) \ + if (const transcribe_status st = kv_f32(g, key, hp.field); st != TRANSCRIBE_OK) \ + return st +#define RD_STR(key, field) \ + if (const transcribe_status st = kv_str(g, key, hp.field); st != TRANSCRIBE_OK) \ + return st + + RD_U32("stt.sortformer.max_speakers", max_speakers); + RD_U32("stt.sortformer.frame_hop", frame_hop); + + RD_U32("stt.sortformer.encoder.n_layers", enc_n_layers); + RD_U32("stt.sortformer.encoder.d_model", enc_d_model); + RD_U32("stt.sortformer.encoder.n_heads", enc_n_heads); + RD_U32("stt.sortformer.encoder.d_ff", enc_d_ff); + RD_U32("stt.sortformer.encoder.conv_kernel", enc_conv_kernel); + RD_U32("stt.sortformer.encoder.subsampling_factor", enc_subsampling_factor); + RD_U32("stt.sortformer.encoder.subsampling_channels", enc_subsampling_channels); + RD_U32("stt.sortformer.encoder.feat_in", enc_feat_in); + RD_U32("stt.sortformer.encoder.pos_emb_max_len", enc_pos_emb_max_len); + RD_STR("stt.sortformer.encoder.conv_norm_type", enc_conv_norm_type); + + RD_U32("stt.sortformer.transformer.n_layers", tf_n_layers); + RD_U32("stt.sortformer.transformer.d_model", tf_d_model); + RD_U32("stt.sortformer.transformer.n_heads", tf_n_heads); + RD_U32("stt.sortformer.transformer.d_ff", tf_d_ff); + RD_STR("stt.sortformer.transformer.activation", tf_activation); + { + const int64_t id = gguf_find_key(g, "stt.sortformer.transformer.pre_ln"); + hp.tf_pre_ln = (id >= 0) && gguf_get_val_bool(g, id); + } + + RD_U32("stt.frontend.num_mels", fe_num_mels); + RD_U32("stt.frontend.sample_rate", fe_sample_rate); + RD_U32("stt.frontend.n_fft", fe_n_fft); + RD_U32("stt.frontend.win_length", fe_win_length); + RD_U32("stt.frontend.hop_length", fe_hop_length); + RD_STR("stt.frontend.window", fe_window); + RD_STR("stt.frontend.normalize", fe_normalize); + RD_F32("stt.frontend.dither", fe_dither); + RD_F32("stt.frontend.pre_emphasis", fe_pre_emphasis); + + RD_U32("stt.sortformer.stream.chunk_len", stream_chunk_len); + RD_U32("stt.sortformer.stream.spkcache_len", stream_spkcache_len); + RD_U32("stt.sortformer.stream.fifo_len", stream_fifo_len); + RD_U32("stt.sortformer.stream.spkcache_update_period", stream_spkcache_update_period); + +#undef RD_U32 +#undef RD_F32 +#undef RD_STR + + if (hp.tf_n_heads == 0 || hp.tf_d_model % hp.tf_n_heads != 0) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: tf_d_model %d not divisible by tf_n_heads %d", hp.tf_d_model, + hp.tf_n_heads); + return TRANSCRIBE_ERR_GGUF; + } + if (hp.tf_pre_ln) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: pre_ln=true transformer not supported (post-LN only)"); + return TRANSCRIBE_ERR_GGUF; + } + return TRANSCRIBE_OK; +} + +namespace { + +// Look up a tensor by name and validate its ne against the expected dims +// (fast-to-slow; pass -1 to skip a dim). Returns null + logs on failure. +ggml_tensor * get_checked(ggml_context * ctx, const char * name, int64_t ne0, int64_t ne1) { + ggml_tensor * t = ggml_get_tensor(ctx, name); + if (t == nullptr) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: missing tensor %s", name); + return nullptr; + } + if ((ne0 >= 0 && t->ne[0] != ne0) || (ne1 >= 0 && t->ne[1] != ne1)) { + log_msg(TRANSCRIBE_LOG_LEVEL_ERROR, "sortformer: tensor %s shape mismatch: have [%lld,%lld] want [%lld,%lld]", + name, (long long) t->ne[0], (long long) t->ne[1], (long long) ne0, (long long) ne1); + return nullptr; + } + return t; +} + +} // namespace + +transcribe_status build_sortformer_weights(ggml_context * ctx, const SortformerHParams & hp, SortformerWeights & w) { + const int64_t d = hp.tf_d_model; + const int64_t dff = hp.tf_d_ff; + const int64_t ed = hp.enc_d_model; + const int64_t spk = hp.max_speakers; + char name[128]; + +#define GET(dst, nm, e0, e1) \ + do { \ + (dst) = get_checked(ctx, (nm), (e0), (e1)); \ + if ((dst) == nullptr) \ + return TRANSCRIBE_ERR_GGUF; \ + } while (0) + + GET(w.enc_proj_w, "diar.encoder_proj.weight", ed, d); + GET(w.enc_proj_b, "diar.encoder_proj.bias", d, -1); + + w.tf_blocks.resize(static_cast(hp.tf_n_layers)); + for (int i = 0; i < hp.tf_n_layers; ++i) { + SortformerTfBlock & b = w.tf_blocks[static_cast(i)]; +#define GETB(dst, suffix, e0, e1) \ + do { \ + std::snprintf(name, sizeof(name), "tf.blocks.%d.%s", i, suffix); \ + GET(dst, name, e0, e1); \ + } while (0) + GETB(b.norm1_w, "norm_1.weight", d, -1); + GETB(b.norm1_b, "norm_1.bias", d, -1); + GETB(b.attn_q_w, "attn.q.weight", d, d); + GETB(b.attn_q_b, "attn.q.bias", d, -1); + GETB(b.attn_k_w, "attn.k.weight", d, d); + GETB(b.attn_k_b, "attn.k.bias", d, -1); + GETB(b.attn_v_w, "attn.v.weight", d, d); + GETB(b.attn_v_b, "attn.v.bias", d, -1); + GETB(b.attn_o_w, "attn.out.weight", d, d); + GETB(b.attn_o_b, "attn.out.bias", d, -1); + GETB(b.norm2_w, "norm_2.weight", d, -1); + GETB(b.norm2_b, "norm_2.bias", d, -1); + GETB(b.ff_in_w, "ff.in.weight", d, dff); + GETB(b.ff_in_b, "ff.in.bias", dff, -1); + GETB(b.ff_out_w, "ff.out.weight", dff, d); + GETB(b.ff_out_b, "ff.out.bias", d, -1); +#undef GETB + } + + GET(w.fc1_w, "diar.fc1.weight", d, d); + GET(w.fc1_b, "diar.fc1.bias", d, -1); + GET(w.single_spk_head_w, "diar.single_spk_head.weight", d, spk); + GET(w.single_spk_head_b, "diar.single_spk_head.bias", spk, -1); + GET(w.spk_head_w, "diar.spk_head.weight", 2 * d, spk); + GET(w.spk_head_b, "diar.spk_head.bias", spk, -1); + +#undef GET + return TRANSCRIBE_OK; +} + +} // namespace transcribe::sortformer diff --git a/src/arch/sortformer/weights.h b/src/arch/sortformer/weights.h new file mode 100644 index 00000000..9b655e96 --- /dev/null +++ b/src/arch/sortformer/weights.h @@ -0,0 +1,119 @@ +// arch/sortformer/weights.h - Sortformer hparams + the Sortformer-specific +// weight slots (encoder_proj + the 18-layer post-LN Transformer encoder + +// the diarization sigmoid head). The 17-layer NEST/FastConformer encoder is +// NOT here: it reuses parakeet::ParakeetWeights (pre_encode + blocks), +// loaded separately in the sortformer loader. +// +// Tensor layout conventions (matched by scripts/convert-sortformer.py): +// - Linear weights: PyTorch [out, in] -> ggml ne [in, out]. +// - LayerNorm: separate weight + bias, shape [d_model]. + +#pragma once + +#include "transcribe.h" + +#include +#include +#include + +struct gguf_context; +struct ggml_context; +struct ggml_tensor; + +namespace transcribe::sortformer { + +struct SortformerHParams { + // Diarization. + int32_t max_speakers = 4; // hard architectural cap + int32_t frame_hop = 0; // samples per diar frame (hop * subsampling) + + // Conformer encoder (mirrors the parakeet fields; see convert KVs). + int32_t enc_n_layers = 0; + int32_t enc_d_model = 0; + int32_t enc_n_heads = 0; + int32_t enc_d_ff = 0; + int32_t enc_conv_kernel = 0; + int32_t enc_subsampling_factor = 0; + int32_t enc_subsampling_channels = 0; + int32_t enc_feat_in = 0; + int32_t enc_pos_emb_max_len = 0; + std::string enc_conv_norm_type; // "batch_norm" + + // Transformer encoder (post-LN, no positional encoding, no final norm). + int32_t tf_n_layers = 0; + int32_t tf_d_model = 0; + int32_t tf_n_heads = 0; + int32_t tf_d_ff = 0; + std::string tf_activation; // "relu" + bool tf_pre_ln = false; + + // Frontend (mel feature extractor). + int32_t fe_num_mels = 0; + int32_t fe_sample_rate = 0; + int32_t fe_n_fft = 0; + int32_t fe_win_length = 0; + int32_t fe_hop_length = 0; + std::string fe_window; // "hann" + std::string fe_normalize; // "none" + float fe_dither = 0.0f; + float fe_pre_emphasis = 0.0f; + + // Shipped streaming defaults (deferred streaming path; read for KV + // completeness and later use). + int32_t stream_chunk_len = 0; + int32_t stream_spkcache_len = 0; + int32_t stream_fifo_len = 0; + int32_t stream_spkcache_update_period = 0; + + int32_t tf_head_dim() const { return tf_n_heads > 0 ? tf_d_model / tf_n_heads : 0; } +}; + +// One post-LN Transformer encoder block. All linears carry bias. +struct SortformerTfBlock { + ggml_tensor * norm1_w = nullptr; // [d] + ggml_tensor * norm1_b = nullptr; // [d] + ggml_tensor * attn_q_w = nullptr; // [d, d] + ggml_tensor * attn_q_b = nullptr; // [d] + ggml_tensor * attn_k_w = nullptr; + ggml_tensor * attn_k_b = nullptr; + ggml_tensor * attn_v_w = nullptr; + ggml_tensor * attn_v_b = nullptr; + ggml_tensor * attn_o_w = nullptr; + ggml_tensor * attn_o_b = nullptr; + ggml_tensor * norm2_w = nullptr; // [d] + ggml_tensor * norm2_b = nullptr; // [d] + ggml_tensor * ff_in_w = nullptr; // [d, d_ff] + ggml_tensor * ff_in_b = nullptr; // [d_ff] + ggml_tensor * ff_out_w = nullptr; // [d_ff, d] + ggml_tensor * ff_out_b = nullptr; // [d] +}; + +struct SortformerWeights { + // encoder_proj: Linear 512 -> 192. + ggml_tensor * enc_proj_w = nullptr; // [enc_d_model, tf_d_model] + ggml_tensor * enc_proj_b = nullptr; // [tf_d_model] + + std::vector tf_blocks; // tf_n_layers entries + + // Diar head (forward_speaker_sigmoids offline path). + ggml_tensor * fc1_w = nullptr; // [tf_d_model, tf_d_model] + ggml_tensor * fc1_b = nullptr; // [tf_d_model] + ggml_tensor * single_spk_head_w = nullptr; // [tf_d_model, max_speakers] + ggml_tensor * single_spk_head_b = nullptr; // [max_speakers] + // Streaming 2*hidden head (spkcache concat path); loaded but unused offline. + ggml_tensor * spk_head_w = nullptr; // [2*tf_d_model, max_speakers] + ggml_tensor * spk_head_b = nullptr; // [max_speakers] +}; + +// Read every required stt.sortformer.* / stt.frontend.* KV into hp. +transcribe_status read_sortformer_hparams(const gguf_context * gguf, SortformerHParams & hp); + +// Look up the Sortformer-specific tensors (encoder_proj + transformer + +// head) by name in ctx_meta, validate shapes against hp, store borrowed +// pointers. Returns TRANSCRIBE_ERR_GGUF (naming the tensor) on any +// missing / mis-shaped tensor. +transcribe_status build_sortformer_weights(ggml_context * ctx_meta, + const SortformerHParams & hp, + SortformerWeights & weights); + +} // namespace transcribe::sortformer diff --git a/src/transcribe-arch.cpp b/src/transcribe-arch.cpp index c75f478a..981dbeb1 100644 --- a/src/transcribe-arch.cpp +++ b/src/transcribe-arch.cpp @@ -79,16 +79,20 @@ namespace medasr { extern const Arch arch; } +namespace sortformer { +extern const Arch arch; +} + const Arch * find_arch(const char * name) { if (name == nullptr) { return nullptr; } static const Arch * const k_archs[] = { - ¶keet::arch, &cohere::arch, &canary::arch, &qwen3_asr::arch, &voxtral::arch, - &voxtral_realtime::arch, &canary_qwen::arch, &whisper::arch, &moonshine::arch, &moonshine_streaming::arch, - &sensevoice::arch, &funasr_nano::arch, &gigaam::arch, &granite::arch, &granite_nar::arch, - &medasr::arch, &moss::arch, + ¶keet::arch, &cohere::arch, &canary::arch, &qwen3_asr::arch, &voxtral::arch, + &voxtral_realtime::arch, &canary_qwen::arch, &whisper::arch, &moonshine::arch, &moonshine_streaming::arch, + &sensevoice::arch, &funasr_nano::arch, &gigaam::arch, &granite::arch, &granite_nar::arch, + &medasr::arch, &moss::arch, &sortformer::arch, }; constexpr size_t k_n = sizeof(k_archs) / sizeof(k_archs[0]); diff --git a/src/transcribe-mel.cpp b/src/transcribe-mel.cpp index eb60d63e..1a3b8d66 100644 --- a/src/transcribe-mel.cpp +++ b/src/transcribe-mel.cpp @@ -329,6 +329,13 @@ int MelFrontend::n_frames_for(size_t n_samples) const { static_cast(cfg_.hop_length)) + 1; } + // Newer NeMo (e.g. Sortformer) computes ceil(n / hop); the legacy + // families use floor(n / hop) + 1. They differ only when n is an exact + // multiple of hop, where ceil drops the trailing center frame. + if (cfg_.nemo_seq_len_ceil) { + return static_cast((n_samples + static_cast(cfg_.hop_length) - 1) / + static_cast(cfg_.hop_length)); + } // Matches NeMo features_lens = (waveforms_lens / hop_length) + 1. // The +1 accounts for the centered first frame. return static_cast(n_samples / static_cast(cfg_.hop_length)) + 1; @@ -351,11 +358,7 @@ transcribe_status MelFrontend::compute(const float * pcm, const int pad = n_fft / 2; const bool no_pad = (cfg_.pad_mode == "none"); - const int n_frames = - no_pad ? (static_cast(n_samples) < win ? - 0 : - static_cast((n_samples - static_cast(win)) / static_cast(hop)) + 1) : - static_cast(n_samples / static_cast(hop)) + 1; + const int n_frames = n_frames_for(n_samples); // Per-feature normalize divides by (n_frames - 1) and the // reflect pad needs at least pad+1 input samples to reflect diff --git a/src/transcribe-mel.h b/src/transcribe-mel.h index 9d2a19c7..697e79f7 100644 --- a/src/transcribe-mel.h +++ b/src/transcribe-mel.h @@ -98,6 +98,14 @@ struct MelConfig { // Optional checkpoint-provided window [win_length]. When non-empty, // used instead of computing a periodic Hann window. std::vector window; + + // NeMo seq-len semantics for the centered (reflect/constant) paths. + // Newer NeMo AudioToMelSpectrogramPreprocessor computes the feature + // length as ceil(n_samples / hop) rather than floor(n_samples / hop) + 1. + // The two agree except when n_samples is an exact multiple of hop, where + // ceil drops the extra trailing center frame. Sortformer's preprocessor + // uses the ceil form; leave false for the legacy +1 families. + bool nemo_seq_len_ceil = false; }; // Pure C++ log-mel extractor. Construct once, call compute() any diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bec7501c..e4b12330 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1085,6 +1085,26 @@ if(TRANSCRIBE_BUILD_REAL_MODEL_TESTS) COMMAND transcribe_qwen3_asr_e2e_smoke) set_tests_properties(transcribe_qwen3_asr_e2e_smoke PROPERTIES SKIP_RETURN_CODE 77) + + # Sortformer streaming operating-point run ext (SFST, RUN slot). + # Kind/slot probe, init stamping, pre-clear rejection with snapshot + # preservation, and ext-vs-env preset parity on the committed 2-spk + # oracle mix. Gated by TRANSCRIBE_SORTFORMER_GGUF (RC 77 skip). + add_executable(transcribe_sortformer_stream_ext_unit + sortformer_stream_ext_unit.cpp) + + target_link_libraries(transcribe_sortformer_stream_ext_unit + PRIVATE transcribe transcribe-common-example) + + target_compile_definitions(transcribe_sortformer_stream_ext_unit PRIVATE + "TRANSCRIBE_TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/samples\"") + + transcribe_apply_warnings(transcribe_sortformer_stream_ext_unit) + + add_test(NAME transcribe_sortformer_stream_ext_unit + COMMAND transcribe_sortformer_stream_ext_unit) + set_tests_properties(transcribe_sortformer_stream_ext_unit PROPERTIES + SKIP_RETURN_CODE 77) endif() # ----------------------------------------------------------------------------- diff --git a/tests/golden/sortformer/diar_streaming_sortformer_4spk-v2.1.manifest.json b/tests/golden/sortformer/diar_streaming_sortformer_4spk-v2.1.manifest.json new file mode 100644 index 00000000..067726d5 --- /dev/null +++ b/tests/golden/sortformer/diar_streaming_sortformer_4spk-v2.1.manifest.json @@ -0,0 +1,55 @@ +{ + "schema": "transcribe-golden-manifest-v1", + "family": "sortformer", + "variant": "diar_streaming_sortformer_4spk-v2.1", + "source_model": { + "hf_repo": "nvidia/diar_streaming_sortformer_4spk-v2.1", + "hf_revision": "fafaab5faa1617a0ca52d38dd3dc4bd636800d3d" + }, + "reference": { + "kind": "nemo", + "source": "https://github.com/NVIDIA-NeMo/NeMo", + "revision": "6967f48fda2a", + "entrypoint": "scripts/dump_reference_sortformer_nemo.py" + }, + "expected_dtype": "float32", + "dtype_source": "manual", + "frontend": { + "sample_rate": 16000, + "n_mels": 128, + "hop_length": 160, + "fft_size": 512, + "win_length": 400, + "window": "hann_periodic", + "normalization": "none", + "preemphasis": 0.97, + "dither": 1e-5 + }, + "tokenizer_summary": { + "type": "other", + "vocab_size": 0, + "special_tokens": {} + }, + "capabilities": { + "languages": ["en"], + "language_detection": false, + "translation": false, + "timestamps": [], + "streaming": true, + "speaker_diarization": true + }, + "diarization": { + "max_speakers": 4, + "frame_period_seconds": 0.08, + "output": "T x 4 sigmoid speaker-activity probabilities (arrival-order columns)", + "streaming_cfg_shipped": { + "chunk_len": 188, + "fifo_len": 0, + "spkcache_len": 188, + "spkcache_update_period": 188, + "chunk_right_context": 1 + } + }, + "tolerance_file": "tests/tolerances/sortformer.json", + "cases": ["sortformer-2spk-mix"] +} diff --git a/tests/golden/sortformer/sortformer-2spk-mix.rttm b/tests/golden/sortformer/sortformer-2spk-mix.rttm new file mode 100644 index 00000000..1b4ff9c5 --- /dev/null +++ b/tests/golden/sortformer/sortformer-2spk-mix.rttm @@ -0,0 +1,4 @@ +SPEAKER sortformer-2spk-mix 1 0.000 3.000 spk_A +SPEAKER sortformer-2spk-mix 1 7.000 3.500 spk_A +SPEAKER sortformer-2spk-mix 1 3.500 3.000 spk_B +SPEAKER sortformer-2spk-mix 1 9.000 3.000 spk_B diff --git a/tests/sortformer_stream_ext_unit.cpp b/tests/sortformer_stream_ext_unit.cpp new file mode 100644 index 00000000..31bd1001 --- /dev/null +++ b/tests/sortformer_stream_ext_unit.cpp @@ -0,0 +1,188 @@ +// sortformer_stream_ext_unit.cpp - Sortformer streaming operating-point run +// extension (TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM, RUN slot). +// +// Covers, against a real GGUF (env-gated, RC 77 skip): +// +// 1. transcribe_model_accepts_ext_kind: SFST accepted on _RUN only; +// foreign kinds rejected. +// 2. transcribe_sortformer_stream_ext_init stamps size/kind/preset. +// 3. Pre-clear rejection: a wrong-kind ext and an out-of-range preset +// both fail with INVALID_ARG and PRESERVE the previous result +// (run_validate fires before clear_result). +// 4. Ext preset == env preset parity: running the committed 2-speaker +// oracle mix with ext=VERY_HIGH_LATENCY produces exactly the same +// speaker-segment rows as TRANSCRIBE_SORTFORMER_STREAM_PRESET= +// very_high_latency (the DER-validated env path), and a different +// geometry (LOW_LATENCY) is accepted and produces rows. +// +// Gated by TRANSCRIBE_SORTFORMER_GGUF (same pattern as the other +// real-model tests) because the preset resolution runs inside run() and +// needs real weights to produce comparable segments. + +#include "transcribe.h" +#include "transcribe/sortformer.h" +#include "wav.h" + +#include + +#include +#include +#include +#include + +namespace { + +int g_failures = 0; + +#define CHECK(cond) \ + do { \ + if (!(cond)) { \ + std::fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \ + ++g_failures; \ + } \ + } while (0) + +bool file_exists(const std::string & path) { + struct stat st{}; + return ::stat(path.c_str(), &st) == 0; +} + +std::vector read_segments(const transcribe_session * session) { + std::vector rows; + const int n = transcribe_n_speaker_segments(session); + for (int i = 0; i < n; ++i) { + transcribe_speaker_segment row; + transcribe_speaker_segment_init(&row); + if (transcribe_get_speaker_segment(session, i, &row) == TRANSCRIBE_OK) { + rows.push_back(row); + } + } + return rows; +} + +bool same_segments(const std::vector & a, + const std::vector & b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (a[i].t0_ms != b[i].t0_ms || a[i].t1_ms != b[i].t1_ms || a[i].speaker_id != b[i].speaker_id) { + return false; + } + } + return true; +} + +} // namespace + +int main() { + const char * env = std::getenv("TRANSCRIBE_SORTFORMER_GGUF"); + if (env == nullptr || env[0] == '\0') { + std::fprintf(stderr, + "sortformer_stream_ext_unit: TRANSCRIBE_SORTFORMER_GGUF not set; skipping.\n" + "Re-run with TRANSCRIBE_SORTFORMER_GGUF=models/diar_streaming_sortformer_4spk-v2.1/" + "diar_streaming_sortformer_4spk-v2.1-F32.gguf\n"); + return 77; + } + const std::string gguf = env; + if (!file_exists(gguf)) { + std::fprintf(stderr, "sortformer_stream_ext_unit: file not found: %s\n", gguf.c_str()); + return 77; + } + const std::string wav_path = std::string(TRANSCRIBE_TEST_SAMPLES_DIR) + "/sortformer-2spk-mix.wav"; + std::vector pcm; + std::string wav_err; + if (!transcribe_cli::load_wav_mono_16k(wav_path, pcm, wav_err)) { + std::fprintf(stderr, "sortformer_stream_ext_unit: wav load: %s\n", wav_err.c_str()); + return 77; + } + + // The parity leg compares the ext path against the env path, so the + // environment must start clean of the validation overrides. + ::unsetenv("TRANSCRIBE_SORTFORMER_STREAM_PRESET"); + + transcribe_model_load_params mp; + transcribe_model_load_params_init(&mp); + mp.backend = TRANSCRIBE_BACKEND_CPU; // deterministic float order for the parity leg + struct transcribe_model * model = nullptr; + if (transcribe_model_load_file(gguf.c_str(), &mp, &model) != TRANSCRIBE_OK || model == nullptr) { + std::fprintf(stderr, "FAIL: model load\n"); + return EXIT_FAILURE; + } + + // 1. Kind+slot probe. + CHECK(transcribe_model_accepts_ext_kind(model, TRANSCRIBE_EXT_SLOT_RUN, TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM)); + CHECK(!transcribe_model_accepts_ext_kind(model, TRANSCRIBE_EXT_SLOT_STREAM, TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM)); + CHECK(!transcribe_model_accepts_ext_kind(model, TRANSCRIBE_EXT_SLOT_RUN, 0x4E524857u /* WHRN */)); + + // 2. Init function stamps the header + default. + transcribe_sortformer_stream_ext ext; + transcribe_sortformer_stream_ext_init(&ext); + CHECK(ext.ext.size == sizeof(ext)); + CHECK(ext.ext.kind == TRANSCRIBE_EXT_KIND_SORTFORMER_STREAM); + CHECK(ext.preset == TRANSCRIBE_SORTFORMER_PRESET_DEFAULT); + + struct transcribe_session * session = nullptr; + if (transcribe_session_init(model, nullptr, &session) != TRANSCRIBE_OK || session == nullptr) { + std::fprintf(stderr, "FAIL: session create\n"); + transcribe_model_free(model); + return EXIT_FAILURE; + } + + transcribe_run_params rp; + transcribe_run_params_init(&rp); + + // Baseline run (env preset path, the DER-validated harness route). + ::setenv("TRANSCRIBE_SORTFORMER_STREAM_PRESET", "very_high_latency", 1); + CHECK(transcribe_run(session, pcm.data(), static_cast(pcm.size()), &rp) == TRANSCRIBE_OK); + const std::vector env_rows = read_segments(session); + ::unsetenv("TRANSCRIBE_SORTFORMER_STREAM_PRESET"); + CHECK(!env_rows.empty()); // the oracle mix has two speakers + + // 3. Pre-clear rejection preserves the previous result. + { + transcribe_sortformer_stream_ext bad; + transcribe_sortformer_stream_ext_init(&bad); + bad.ext.kind = 0x4E524857u; // WHRN: wrong family kind + rp.family = &bad.ext; + CHECK(transcribe_run(session, pcm.data(), static_cast(pcm.size()), &rp) == TRANSCRIBE_ERR_INVALID_ARG); + CHECK(same_segments(read_segments(session), env_rows)); // snapshot intact + + transcribe_sortformer_stream_ext oor; + transcribe_sortformer_stream_ext_init(&oor); + oor.preset = static_cast(99); + rp.family = &oor.ext; + CHECK(transcribe_run(session, pcm.data(), static_cast(pcm.size()), &rp) == TRANSCRIBE_ERR_INVALID_ARG); + CHECK(same_segments(read_segments(session), env_rows)); + } + + // 4a. Ext preset == env preset parity (same operating point, same rows). + { + transcribe_sortformer_stream_ext vh; + transcribe_sortformer_stream_ext_init(&vh); + vh.preset = TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY; + rp.family = &vh.ext; + CHECK(transcribe_run(session, pcm.data(), static_cast(pcm.size()), &rp) == TRANSCRIBE_OK); + CHECK(same_segments(read_segments(session), env_rows)); + } + + // 4b. A different geometry is accepted and produces speaker rows. + { + transcribe_sortformer_stream_ext lo; + transcribe_sortformer_stream_ext_init(&lo); + lo.preset = TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY; + rp.family = &lo.ext; + CHECK(transcribe_run(session, pcm.data(), static_cast(pcm.size()), &rp) == TRANSCRIBE_OK); + CHECK(!read_segments(session).empty()); + } + + transcribe_session_free(session); + transcribe_model_free(model); + + if (g_failures != 0) { + std::fprintf(stderr, "sortformer_stream_ext_unit: %d failure(s)\n", g_failures); + return EXIT_FAILURE; + } + std::printf("sortformer_stream_ext_unit: OK\n"); + return 0; +} diff --git a/tests/tolerances/sortformer.json b/tests/tolerances/sortformer.json new file mode 100644 index 00000000..54dc1de1 --- /dev/null +++ b/tests/tolerances/sortformer.json @@ -0,0 +1,35 @@ +{ + "_comment": [ + "CORRECTNESS REGIME (Stage 4, offline path): reference-dtype F32 GGUF; KV f32; C++ MelFrontend real mel (NeMo ceil(n/hop) framing); --backend cpu --threads 1. Every number below is measured in that regime via validate.py all / compare_tensors.py.", + "Sortformer is a diarizer: diar.preds_offline is [T,4] sigmoid activity in [0,1] (arrival-order columns); enc.* are pre-sigmoid encoder activations. The model's actual output (diar.preds_offline) matches NeMo to max_abs 2.96e-4 / mean_abs 5.0e-6 (near bit-exact).", + "Dominant drift source: F32 accumulation over the 17-layer NEST FastConformer (reused verbatim from parakeet::build_encoder_graph) with normalize=none mel magnitudes (~16). Drift is uniform across frames (peaks mid-sequence, boundaries no worse) and DECREASES down the stack (fastconformer 3.3e-3 -> encoder_proj 9.8e-4 -> transformer 1.1e-3 -> preds 3.0e-4), confirming intrinsic accumulation, not a masking/framing bug. Mel values verified to 1.6e-4 (~1e-5 relative) vs NeMo.", + "Finalized = max(1.5 x observed, provisional). Widened vs Stage-2 provisional: fastconformer, encoder_proj, transformer, preds (F32 conformer accumulation; ~0.1% relative, well under the 1% investigate threshold).", + "enc.mel.in is shape_optional: NeMo pads the mel tensor to a multiple of 16 (pad_to=16, zero pad) which its own forward() trims off before the encoder; the C++ feeds the real ceil(n/hop) length. The real frames match to 1.6e-4; full padded-tensor parity is a Step-7 (frontend) item.", + "diar.probs (streaming AOSC/FIFO path) is now dumped by the C++ streaming forward (run_streaming) and gated. With the checkpoint-shipped cfg the short oracle clip is a single chunk, so diar.probs == diar.preds_offline math (empty spkcache/fifo -> concat is just the chunk); its tolerance tracks diar.preds_offline. Multi-chunk / compression parity is exercised via VALIDATE_SORTFORMER_PRESET=small (and the AMI DER acceptance)." + ], + "diar.preds_offline": { + "max_abs": 4.5e-04, + "mean_abs": 7.6e-06 + }, + "enc.encoder_proj.out": { + "max_abs": 1.5e-03, + "mean_abs": 1.9e-04 + }, + "enc.fastconformer.out": { + "max_abs": 4.9e-03, + "mean_abs": 2.1e-04 + }, + "enc.transformer.out": { + "max_abs": 1.7e-03, + "mean_abs": 2.0e-04 + }, + "enc.mel.in": { + "max_abs": 2.5e-04, + "mean_abs": 2.7e-06, + "shape_optional": true + }, + "diar.probs": { + "max_abs": 4.5e-04, + "mean_abs": 7.6e-06 + } +}