mostlyright.weather.earnings.streaming_transcriber
mostlyright.weather.earnings.streaming_transcriber
Section titled “mostlyright.weather.earnings.streaming_transcriber”Streaming STT engine (Phase 27, 27-10 Task 2).
StreamingTranscriber turns the 27-09 live PCM frame stream
(Iterator[tuple[pcm_bytes, spoken_at]] from
mostlyright.weather.earnings.capture.base.CaptureAdapter.live()) into
incremental transcript Segments + provisional final-only
:class:FactDeltas that the 27-11 SSE endpoint fans out over the
:class:~mostlyright.weather.earnings.segment_bus.SegmentBus.
Pipeline (per D-27.14 / D-27.16, RESEARCH-LIVE-STREAMING §2):
- VAD-guided chunking.
_vad_chunks()groups the incoming frames into ~3-5 s windows with ~0.5 s overlap. A speech run ends on a VAD speech-end (a silence gap). The plan mandates NO torch / NO silero here — we use a LIGHTWEIGHT energy gate (RMS over the s16le samples) behind a pluggablevadinterface, so a real Silero-ONNX VAD can be dropped in later WITHOUT touching this engine (and without tripping the 27-03 package-legitimacy gate for a new pip dep). - Transcribe. Each in-flight window is transcribed with the per-call
initial_prompt(seeded from the market strike terms via the 27-03seed_initial_prompt()). faster-whisper is the D-27.5 engine — it is injected as a callabletranscriberso unit tests stub it and NO realWhisperModel/ no real audio is needed. The default production transcriber lazy-imports faster-whisper (behind the[earnings]extra). - partial → final. An in-flight window emits a revisable PARTIAL
Segment(is_final=False). On the speech-end boundary the segment is re-emitted FINAL (is_final=True) with the stabilised text. - final-only counting.
classify_mentions()runs over FINAL segments ONLY →FactDeltas aggregated per(term, compound_type)(resolution_status="provisional",is_final=True,kalshi_counted=validate_kalshi_counted_occurrence(...)). A term in a PARTIAL is NEVER counted (else a retracted word settles a market — T-27-35). classify_mentions (NOT count_mentions) is the production counter (D-30, review F1): it additionally surfaces CLOSED-compound candidates (firefighterforfire) that count_mentions never matches — without them a Polymarket closed-straddle silently resolvedresolved_no.
Authority (D-27.16, codex P2). is_final denotes STT-segment finality
ONLY; a counted fact delta is is_final=True yet STILL
resolution_status="provisional". Settlement/backtest authority is gated on
resolution_status / source, NEVER on is_final. Live deltas are
early-signal rows — the post-call ledger (27-04) stays authoritative.
Legal (D-27.9). Audio is a TRANSIENT ingest artifact — the emitted
Segment / FactDelta carry TEXT + facts ONLY, never PCM bytes.
The bus (27-10 Task 3) enforces the same gate structurally.
DEFERRED (operator / live). This engine is fully implemented + tested
against SYNTHETIC PCM and a STUB transcriber. Validation against a REAL live
earnings webcast (a webcast in progress) and a real faster-whisper model on
real audio requires an operator with a live call and the [earnings] extra
installed — that end-to-end run is DEFERRED and cannot be exercised in unit
tests. The energy VAD is a floor; swapping in a real Silero-ONNX VAD (which
would add a pip dep and must clear the 27-03 package-legitimacy checkpoint) is
also deferred.
Module Attributes
Section titled “Module Attributes”TranscribeFn | (window_pcm, *, initial_prompt) -> text. |
|---|---|
TurnProvider | A turn provider maps a (partial) segment to the role-parser Turn whose speaker_role / role_source drive the fail-closed Kalshi rule. |
Classes
Section titled “Classes”FactDelta(term_canonical, …[, …]) | A provisional live fact delta counted off a FINAL segment (never a partial). |
|---|---|
Segment(text, is_final, spoken_at, …[, …]) | One streaming transcript segment — TEXT ONLY (never audio, D-27.9). |
StreamingTranscriber(*[, transcriber, …]) | VAD-chunked streaming STT → partial/final segments + final-only fact deltas. |
class mostlyright.weather.earnings.streaming_transcriber.FactDelta(term_canonical, matched_surface_form, mention_count, speaker_role, role_source, speaker_name, kalshi_counted, is_final, spoken_at, stream_seq, compound_type=‘standalone’, resolution_status=‘provisional’, source=‘earnings_call’)
Section titled “class mostlyright.weather.earnings.streaming_transcriber.FactDelta(term_canonical, matched_surface_form, mention_count, speaker_role, role_source, speaker_name, kalshi_counted, is_final, spoken_at, stream_seq, compound_type=‘standalone’, resolution_status=‘provisional’, source=‘earnings_call’)”Bases: object
A provisional live fact delta counted off a FINAL segment (never a partial).
Shaped for schema.earnings_fact.v1: resolution_status="provisional"
(live early-signal — NOT a settlement source), is_final=True (STT
finality — orthogonal to authority), kalshi_counted derived via the
unchanged fail-closed validate_kalshi_counted_occurrence() (D-27.11,
mode-agnostic). TEXT/facts only — no audio (D-27.9).
compound_type (D-30, review F1) is the per-delta compound axis — one
delta per (term, compound_type), never an aggregate mixing types, so the
venue filters in fact_builder apply row-wise (closed candidates surface
for Polymarket human review; Kalshi-No on closed). ADDITIVE with default
"standalone": an existing SSE consumer or a persisted pre-fix delta is
unaffected (standalone counts for both venues exactly as before the axis).
- Parameters:
compound_type : str
Section titled “compound_type : str”is_final : bool
Section titled “is_final : bool”kalshi_counted : bool
Section titled “kalshi_counted : bool”matched_surface_form : str
Section titled “matched_surface_form : str”mention_count : int
Section titled “mention_count : int”resolution_status : str
Section titled “resolution_status : str”role_source : str
Section titled “role_source : str”source : str
Section titled “source : str”speaker_name : str | None
Section titled “speaker_name : str | None”speaker_role : str
Section titled “speaker_role : str”spoken_at : float
Section titled “spoken_at : float”stream_seq : int
Section titled “stream_seq : int”term_canonical : str
Section titled “term_canonical : str”to_stt_count(, turn_index=None)
Section titled “to_stt_count(, turn_index=None)”Map this delta to a build_fact_rows stt_counts occurrence record.
The propagation seam (review F1): compound_type survives from the
live classifier through the occurrence record into the fact row, so the
venue filters + the fail-loud closed-candidate resolution operate on the
SAME axis end-to-end. turn_index (when known) links the occurrence
to the role-parser turns list so build_fact_rows re-derives the
speaker scope from the authoritative turn.
TEMPORAL MAPPING (review R2-F3): this delta’s spoken_at is an
ENGINE-RELATIVE float (seconds into the stream, e.g. 12.5), NOT a
wallclock. It maps into offset_seconds — the schema’s
engine-relative int audit field, which build_fact_rows already
accepts. It is NEVER emitted as the occurrence’s spoken_at: that
schema column is timestamp_utc and pyarrow silently coerces a float
to microseconds-after-epoch, persisting 1970-01-01 00:00:00.000012+00:00 as the temporal audit marker. spoken_at is
left ABSENT (the column is nullable); a caller holding a genuine
tz-aware wallclock sets it on the occurrence record explicitly —
build_fact_rows fail-louds on any non-tz-aware-datetime value.
class mostlyright.weather.earnings.streaming_transcriber.Segment(text, is_final, spoken_at, stream_seq, knowledge_time, fact_deltas=)
Section titled “class mostlyright.weather.earnings.streaming_transcriber.Segment(text, is_final, spoken_at, stream_seq, knowledge_time, fact_deltas=)”Bases: object
One streaming transcript segment — TEXT ONLY (never audio, D-27.9).
is_final is STT-segment finality ONLY (partial vs final text, D-27.14);
it NEVER gates settlement authority. spoken_at is the aired/event-time
wallclock of the window’s start; knowledge_time is the STT-finalization/
publish wallclock (>= spoken_at, D-27.16). fact_deltas is populated
on FINAL segments ONLY.
- Parameters:
fact_deltas : list[FactDelta]
Section titled “fact_deltas : list[FactDelta]”is_final : bool
Section titled “is_final : bool”knowledge_time : float
Section titled “knowledge_time : float”spoken_at : float
Section titled “spoken_at : float”stream_seq : int
Section titled “stream_seq : int”class mostlyright.weather.earnings.streaming_transcriber.StreamingTranscriber(, transcriber=None, initial_prompt_terms=None, market_terms=None, turn_provider=None, model_size=‘small’)
Section titled “class mostlyright.weather.earnings.streaming_transcriber.StreamingTranscriber(, transcriber=None, initial_prompt_terms=None, market_terms=None, turn_provider=None, model_size=‘small’)”Bases: object
VAD-chunked streaming STT → partial/final segments + final-only fact deltas.
- Parameters:
- transcriber (
Callable[...,str] |None) – A callable(window_pcm, *, initial_prompt) -> text. Injected so unit tests stub faster-whisper. WhenNone, a lazy faster-whisper transcriber is built (DEFERRED / operator-only path). - initial_prompt_terms (
Sequence[str] |None) – The market strike terms the per-callinitial_promptis seeded from (reuses 27-03seed_initial_prompt()). - market_terms (
Sequence[Mapping[str,object]] |None) – Per-term market specs (term_canonicalat minimum) the final-only counter runs over. When empty, no fact deltas are produced. - turn_provider (
Callable[[Segment],Turn|None] |None) – Maps a segment to the role-parserTurn(speaker_role / role_source) driving the fail-closed Kalshi rule. Defaults to anunknown/diarization_advisoryturn (Kalshi-excluded — fail-closed). - model_size (str)
- transcriber (
fact_deltas : list[FactDelta]
Section titled “fact_deltas : list[FactDelta]”All fact deltas emitted this run (final-only) — inspectable by callers.
run(frame_iter)
Section titled “run(frame_iter)”Consume (pcm_frame, spoken_at) frames → yield partial/final Segments.
For each VAD speech run: yields ONE revisable partial per accumulated
window (is_final=False), then ONE final (is_final=True) on the
speech-end boundary. The FINAL carries the STABILISED text of the ENTIRE
run (every window’s transcription, overlap de-duplicated), NOT just the
post-flush tail — so a term spoken early in a continuous run is counted
exactly once. Fact deltas are computed on the FINAL segment only and
appended to fact_deltas (and to the final segment’s
fact_deltas list).
mostlyright.weather.earnings.streaming_transcriber.TranscribeFn
Section titled “mostlyright.weather.earnings.streaming_transcriber.TranscribeFn”(window_pcm, *, initial_prompt) -> text. Injected
so unit tests stub it; the production default lazy-imports faster-whisper.
- Type: A transcriber callable
mostlyright.weather.earnings.streaming_transcriber.TurnProvider
Section titled “mostlyright.weather.earnings.streaming_transcriber.TurnProvider”A turn provider maps a (partial) segment to the role-parser Turn
whose speaker_role / role_source drive the fail-closed Kalshi rule.
27-04’s live role attribution supplies this; tests inject a fixed turn.
alias of Callable[[Segment], Turn | None]