Alignment¶
Spectrogram-guided alignment of transcript tokens to speech (audio extra).
@domain alignment @see [[knowledge/architecture/alignment]]
Spectrogram-guided alignment of transcript tokens to speech (SGPA).
A CTC model aligns the transcript’s characters to frames; each token boundary then moves to the quietest, steadiest point of the waveform near it (RMS energy and spectral flux), so a segment cut does not split a sound.
@domain alignment @see [[knowledge/architecture/alignment]] @tested-by [[tests/alignment/test_sgpa.py]]
- mllm_shap.alignment.sgpa.DEFAULT_MODEL: str = 'facebook/wav2vec2-base-960h'¶
English character-level CTC model used when no model is given.
- mllm_shap.alignment.sgpa.MIN_DURATION_S: float = 0.05¶
Shortest segment the aligner emits, in seconds.
- class mllm_shap.alignment.sgpa.CtcModel(*args, **kwargs)[source]¶
Bases:
ProtocolCharacter-level CTC acoustic model.
- class mllm_shap.alignment.sgpa.Wav2Vec2Ctc(model_id: str = 'facebook/wav2vec2-base-960h', revision: str | None = None, device: str = 'cpu')[source]¶
Bases:
objectA Hugging Face
Wav2Vec2ForCTCcheckpoint (transformersextra).
- class mllm_shap.alignment.sgpa.SpectrogramGuidedAligner(model: CtcModel | None = None, energy_weight: float = 0.8, flux_weight: float = 0.2, separator: str = '|')[source]¶
Bases:
objectAlign transcript tokens to speech and refine their boundaries.
- align(transcript: str | Sequence[str], audio: AudioPart, attach_audio: bool = False) list[AudioSegment][source]¶
Return one segment per token of
transcriptthe model can spell.A string is split on whitespace. Tokens without a character in the model’s vocabulary (punctuation, for example) have no segment.
- Raises:
ValueError – If no token has a character the model knows, or the audio is too short for the transcript.
The sgpa_segments partition: one player per spoken word of an audio message.
@domain alignment @see [[knowledge/architecture/alignment]] @tested-by [[tests/alignment/test_sgpa_players.py]]
- class mllm_shap.alignment.partitions.SgpaOptions(*, model_id: str = 'facebook/wav2vec2-base-960h', revision: str | None = None, device: str = 'cpu', energy_weight: Annotated[float, ~annotated_types.Ge(ge=0)] = 0.8, flux_weight: Annotated[float, ~annotated_types.Ge(ge=0)] = 0.2, text_roles: list[~typing.Literal['user', 'assistant', 'system']]=<factory>, transcript: Literal['send', 'align_only']='send')[source]¶
Bases:
PluginOptionsOptions of the
sgpa_segmentspartition.- text_roles: list[Literal['user', 'assistant', 'system']]¶
Roles whose text-only messages also give one player per word, so typed and spoken words are explained in one run; none by default.
- transcript: Literal['send', 'align_only']¶
sendgives the model each audio message’s transcript with its audio;align_onlyuses the transcript to build the players and sends audio only, so values reflect what the model hears, not what it reads.
- model_config = {'extra': 'forbid', 'frozen': True, 'strict': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class mllm_shap.alignment.partitions.SgpaSegmentPartitioner(context: PluginContext | None = None, aligner: SpectrogramGuidedAligner | None = None)[source]¶
Bases:
objectMake each spellable word of every audio message’s transcript a player.
A message qualifies when it has an
AudioPartand text: the text is the transcript the audio is aligned to. Each player’s span covers the word in the text and, throughsamples, its stretch of audio, so absence policies mask both. Text-only messages give word players when their role is intext_rolesand no players otherwise.- options_model¶
Options accepted from
explanation.plugin_options.alias of
SgpaOptions
- partition(snapshot: ConversationSnapshot) PlayerSet[source]¶
Align every audio message and return its words as players.
- Raises:
ValueError – If no message has audio, or an audio message has no transcript text.
Transcript tokens aligned to audio time ranges.
@domain alignment @see [[knowledge/architecture/alignment]] @tested-by [[tests/alignment/test_segments.py]]
- class mllm_shap.alignment.segments.AudioSegment(token: str, token_index: int, start_time: float, end_time: float, ctc_start_time: float, ctc_end_time: float, confidence: float, boundary_refined: bool, sample_rate: int, start_sample: int, end_sample: int, audio: bytes = b'')[source]¶
Bases:
objectOne transcript token and the stretch of audio that speaks it.
CTC forced alignment (Viterbi over the blank-extended target sequence).
@domain alignment @see [[knowledge/architecture/alignment]] @tested-by [[tests/alignment/test_ctc.py]]
- class mllm_shap.alignment.ctc.TargetSpan(start: int, end: int, confidence: float)[source]¶
Bases:
objectFrames
[start, end)that one target label occupies.
- mllm_shap.alignment.ctc.forced_align(log_probs: NDArray[floating], targets: Sequence[int], blank: int = 0) NDArray[int64][source]¶
Return, per frame, the index into
targetsit aligns to, orBLANK_STATE.The most probable monotonic path over
targetswith optional blanks between labels and a mandatory blank between two equal neighbours (standard CTC).- Raises:
ValueError – If
log_probshas too few frames fortargets.
- mllm_shap.alignment.ctc.target_spans(path: NDArray[int64], log_probs: NDArray[floating], targets: Sequence[int]) list[TargetSpan][source]¶
Return the frame span and mean probability of every target in
path.
Encoded audio bytes to mono float waveforms and back.
@domain alignment @see [[knowledge/architecture/alignment]] @tested-by [[tests/alignment/test_io.py]]
- mllm_shap.alignment.io.require(module: str) ModuleType[source]¶
Import an optional dependency of the
audioortransformersextra.- Raises:
ImportError – Naming the extra to install.
- mllm_shap.alignment.io.decode_audio(data: bytes, sample_rate: int | None = None) tuple[NDArray[float32], int][source]¶
Decode
datato a mono float32 waveform, resampled tosample_rate.Channels are averaged. Without
sample_ratethe file’s own rate is kept.- Raises:
ValueError – If
datais not a formatsoundfilecan read.