Skip to content

diarization#85

Open
cjpais wants to merge 9 commits into
mainfrom
diarization
Open

diarization#85
cjpais wants to merge 9 commits into
mainfrom
diarization

Conversation

@cjpais

@cjpais cjpais commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

add diarization support

  • granite 2b plus
  • moss transcribe

cjpais and others added 9 commits July 13, 2026 04:22
- transcribe_diarize_mode tri-state on run_params (DEFAULT/OFF/ON),
  validated like pnc/itn; non-DEFAULT against a non-supporting model
  WARNs and proceeds (TRANSCRIBE_FEATURE_DIARIZATION probe)
- transcribe_segment gains trailing speaker_id (1-based; 0 = none)
- new transcribe_speaker_segment result rows + init/n/get accessors,
  batch mirrors, TRANSCRIBE_ABI_SPEAKER_SEGMENT
- session plumbing: SegmentEntry.speaker_id, SpeakerSegmentEntry
  vector through capture/snapshot/restore/clear
- api_smoke + run_dispatch_unit coverage for the new contracts

NOTE: run_params layout changed (diarize inserted after itn) — 0.x ABI
break; abihash/bindings regen lands in a follow-up commit this branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New arch/moss/diarize.{h,cpp}: strict-grammar parser for the model's
[start][Sxx]text[end] output. Default (diarize DEFAULT/ON) now returns
per-turn segments with t0/t1 from the bracket timestamps, 1-based
speaker_id, speaker-segment rows, and dediarized full_text (the same
normalization the WER gates scored). diarize=OFF keeps the previous raw
single-segment passthrough byte-for-byte.

Unrecognized bracket spans degrade to verbatim text (no byte loss);
unknown turn boundaries are patched from neighbors / audio length.

capabilities: max_timestamp_kind NONE -> SEGMENT, FEATURE_DIARIZATION
on. run_batch fast path threads run params into finalize_utterance.

tests: moss_diarize_parser_unit (13 grammar cases incl. malformed
spans, bare tags, CJK, rounding, dediarize equivalence).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Correction to the exploration-phase assumption: -plus diarization is a
prompt-selected task (IBM's verbatim "Speaker attribution: ..."
instruction), not always-on. So for granite the family DEFAULT resolves
OFF (plain transcription, byte-identical to today; gates untouched) and
diarize=ON opts into the SAA task. Upstream defines timestamps and
speaker attribution as separate tasks; diarize=ON + timestamps=word is
rejected with INVALID_ARG, which removes the word-index remapping scope
entirely.

New arch/granite/diarize.{h,cpp}: [Speaker N] splitter (1-based per the
model card; optional ':' + space consumed; unrecognized spans pass
through verbatim). Turns become segments with speaker_id and speaker
rows with t0=t1=0 (the SAA task carries no timing).

model.cpp: FEATURE_DIARIZATION set from the GGUF
stt.capability.speaker_diarization KV (-plus only, mirrors the
word_timestamps lowering); run() and the run_batch capture loop now
share one finalize_granite_result().

tests: granite_diarize_parser_unit (model-card example, no-marker
passthrough, colon-less markers, Speaker 0 sentinel guard, byte-loss).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- flags mirror --pnc/--no-pnc; unset keeps family DEFAULT
- segments JSON gains "speaker_id" when attributed; segments now also
  emit for speaker-attributed turns without timing (granite SAA, kind
  NONE); new "speakers" array from the speaker-segment accessors in
  single-file and batch JSONL (p omitted when NaN)
- human output prefixes attributed segments with "S<N>: " and prints
  timing-less speaker turns without the timestamp column

Smoke-tested live: moss default 2-speaker (31 turns, S1->S2 boundary
correct), moss --no-diarize raw passthrough, granite-plus --diarize
2-speaker split, granite default unchanged, diarize+word-timestamps
INVALID_ARG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- generate.py: include/transcribe.abihash, python _generated.py,
  typescript _generated.ts
- cargo xtask bindgen: rust transcribe_sys.rs
- swift pinnedHeaderHash bumped after review (new: diarize_mode enum +
  run_params field, segment speaker_id, speaker-segment struct +
  accessors, ABI enum entry)

Intentional 0.x ABI break: run_params layout changed (diarize inserted
after itn). Both drift gates pass (swift_abihash_check.py,
generate.py --check).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n change

Backs the granite decoder out to the fixed 256-token generation budget
(pre-d24eeed state). The rework (chunked KV growth, decode-to-ceiling,
batch rerun path) ships separately once it has a granite_grow_kv test
and a repetition guard; saved as
~/sandboxes/transcribe/tmp/granite-dynamic-kv-growth.patch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant