From 2d4043ddf2f85777959e5930907e1cec146545ab Mon Sep 17 00:00:00 2001 From: Jacob Lasky Date: Sat, 25 Jul 2026 14:45:45 -0400 Subject: [PATCH] fix(diarize): expose diarize_model so the v2 diarizer is reachable at all The params panel could not produce the v2 diarizer by any path. `diarize` is a deprecated boolean that ALWAYS routes to v1. `diarize_model` is the current parameter and both enables diarization and picks the version, so it must be sent WITHOUT `diarize`. The panel instead offered the legacy `diarize_version` select gated behind `x-if="params.diarize"`, so the only way to see the version control was to enable the thing that forces v1. Confirmed on the wire against production: diarize=true 200, speaker labels (v1) diarize_version=latest (alone) 400 Failed to parse query string diarize=true + diarize_version=latest 200 diarize_model=v2 (alone) 200 diarize_model=latest (alone) 200 diarize=true + diarize_model=v2 400 diarize_model cannot be used together with diarize or diarize_version. (INVALID_QUERY_PARAMETER) diarize_model=v2 on streaming handshake rejected Note Deepgram does not pick a winner between them, it rejects the pair outright, so this is a mutual exclusion rather than a precedence rule. Changes: - UI models `diarize_model` (v1 / v2 / latest) instead of `diarize_version`, and the select is no longer gated behind the checkbox. - The two controls clear each other, since sending both is a hard 400. - Hints state that v2 is batch only and that the checkbox means v1. - `clean_params` drops `diarize` and `diarize_version` when `diarize_model` is present. The UI already prevents the pair; this covers the `extra` escape hatch and any saved preset from before the rename, so an old config degrades to the modern parameter instead of a hard 400. - The deprecated boolean still works alone, because replicating a legacy customer config is a job this tool has. `diarize_model` is one of the params deepgram-sdk 7 added, so it rides as a real connect() kwarg rather than through the passthrough; a test pins that. Semantics confirmed via DeepHive against the Deepgram docs, then verified on the wire rather than taken on faith. 116 passed, 1 skipped. UI probe: select reachable with diarize unchecked, exclusion holds both ways, preview emits diarize_model=latest with no diarize, no console errors. --- config/defaults.json | 2 +- static/app.js | 4 +-- stt/options.py | 16 ++++++++++++ templates/index.html | 59 ++++++++++++++++++++++++++++++++++--------- tests/test_options.py | 49 ++++++++++++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/config/defaults.json b/config/defaults.json index 8a411ba..adbf006 100644 --- a/config/defaults.json +++ b/config/defaults.json @@ -15,7 +15,7 @@ "dictation": false, "profanity_filter": false, "diarize": false, - "diarize_version": "", + "diarize_model": "", "detect_entities": false, "multichannel": false, "utterances": false, diff --git a/static/app.js b/static/app.js index 6044708..6246112 100644 --- a/static/app.js +++ b/static/app.js @@ -305,7 +305,7 @@ function appData() { dictation: false, profanity_filter: false, diarize: false, - diarize_version: '', + diarize_model: '', detect_entities: false, multichannel: false, utterances: false, @@ -1089,7 +1089,7 @@ function appData() { dictation: false, profanity_filter: false, diarize: false, - diarize_version: '', + diarize_model: '', detect_entities: false, multichannel: false, utterances: false, diff --git a/stt/options.py b/stt/options.py index 005a1c7..491edc4 100644 --- a/stt/options.py +++ b/stt/options.py @@ -173,6 +173,22 @@ def clean_params(params: dict, mode: Mode) -> dict: continue _put(result, wire, v) + # `diarize_model` is mutually exclusive with the deprecated `diarize` and + # `diarize_version`. Deepgram does not pick a winner, it rejects outright: + # + # 400 diarize_model cannot be used together with diarize or + # diarize_version. (INVALID_QUERY_PARAMETER) + # + # `diarize_model` wins here because it is the current parameter and the only + # way to reach the v2 diarizer: the boolean `diarize` ALWAYS routes to v1, + # and `diarize_version` is legacy. The UI already makes the two controls + # exclusive; this covers the `extra` escape hatch and any saved config from + # before the field was renamed, so an old preset degrades to the modern + # parameter instead of a hard 400. + if "diarize_model" in result: + for legacy in ("diarize", "diarize_version"): + result.pop(legacy, None) + return result diff --git a/templates/index.html b/templates/index.html index 625f3cf..5cf6b91 100644 --- a/templates/index.html +++ b/templates/index.html @@ -389,6 +389,19 @@ letter-spacing: 0.06em; } + .field-hint { + font-size: 11px; + line-height: 1.45; + color: #8b93a7; + margin-top: 5px; + } + .field-hint code { + background: #1a2234; + padding: 1px 4px; + border-radius: 3px; + color: #a5b4fc; + } + .field-input { background: #1a1f2e; border: 1px solid #2d3748; @@ -1319,9 +1332,14 @@
+
- - + +
@@ -1340,17 +1358,34 @@
- - +
+ Sends diarize_model and omits diarize. + The deprecated diarize checkbox always selects v1. +
+