docs(backlog): gate streaming dictation behind a feature toggle (default off)
Design entry: hide the silence-cut streaming dictation path behind a per- workspace settings.ai.dictationStreaming flag, default false, with batch dictation as the default and fallback. Reuses the existing STT model and /ai-chat/transcribe — no new provider/model/endpoint fields. Lists the server + client touch points, acceptance criteria, and edge cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
106
docs/backlog/streaming-dictation-feature-toggle.md
Normal file
106
docs/backlog/streaming-dictation-feature-toggle.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Стриминговая (по тишине) диктовка под фиче-тогглом, по умолчанию ВЫКЛ
|
||||
|
||||
Статус: **открыто.**
|
||||
|
||||
## Контекст
|
||||
|
||||
Стриминговая диктовка (нарезка по тишине через Silero VAD,
|
||||
`@ricky0123/vad-web`) уже в `develop` и сейчас **жёстко включена**: `MicButton`
|
||||
получает проп `streaming` литералом `true` в двух местах — редактор
|
||||
([dictation-group.tsx](../../apps/client/src/features/editor/components/fixed-toolbar/groups/dictation-group.tsx))
|
||||
и чат
|
||||
([chat-input.tsx](../../apps/client/src/features/ai-chat/components/chat-input.tsx)).
|
||||
Фича экспериментальная:
|
||||
|
||||
- тяжёлые ассеты (ONNX-модель + ORT-wasm, 13–26 МБ, грузятся в браузер при
|
||||
первом использовании);
|
||||
- задержка инициализации модели на первом клике (компиляция wasm + подъём
|
||||
inference-сессии — повторяется на каждую загрузку страницы);
|
||||
- много мелких запросов на `/ai-chat/transcribe` (по одному на сегмент речи)
|
||||
вместо одного на запись.
|
||||
|
||||
Её нужно сделать **opt-in на воркспейс, по умолчанию выключенной**, с обычной
|
||||
батч-диктовкой как дефолтом и фолбэком.
|
||||
|
||||
## Цель
|
||||
|
||||
Спрятать стриминговый путь за булевым флагом воркспейса
|
||||
`settings.ai.dictationStreaming` (default `false`). Выкл → текущая стабильная
|
||||
батч-диктовка. Вкл → стриминговая.
|
||||
|
||||
**Минимализм (явно):** один булев флаг, переиспользуем существующую STT-модель
|
||||
и эндпоинт `/ai-chat/transcribe`, **без новых полей провайдера / модели /
|
||||
эндпоинта / секретов** — осознанное требование после претензий к realtime-PR
|
||||
(#118) за лишние поля настроек.
|
||||
|
||||
## Дизайн
|
||||
|
||||
### Сервер
|
||||
|
||||
- В типе AI-настроек
|
||||
([integrations/ai/ai.types.ts](../../apps/server/src/integrations/ai/ai.types.ts))
|
||||
и в
|
||||
[dto/update-ai-settings.dto.ts](../../apps/server/src/integrations/ai/dto/update-ai-settings.dto.ts)
|
||||
добавить `dictationStreaming?: boolean` рядом с уже существующим флагом
|
||||
`dictation`. Проверить, валидируется ли апдейт настроек по whitelist
|
||||
(`ai-settings.service.ts`) — если да, внести ключ; иначе passthrough.
|
||||
- Это **только клиентский поведенческий флаг**: эндпоинт транскрипции и
|
||||
STT-модель не меняются (стриминг переиспользует `/ai-chat/transcribe`).
|
||||
Флаг просто отдаётся в составе `settings.ai`, который клиент уже читает.
|
||||
|
||||
### Клиент
|
||||
|
||||
- Тип
|
||||
[features/workspace/types/workspace.types.ts](../../apps/client/src/features/workspace/types/workspace.types.ts)
|
||||
(`settings.ai`, рядом с `dictation?: boolean`): добавить
|
||||
`dictationStreaming?: boolean`.
|
||||
- UI
|
||||
[ai-provider-settings.tsx](../../apps/client/src/features/workspace/components/settings/components/ai-provider-settings.tsx):
|
||||
добавить Switch «Streaming dictation (cut on pauses)» **внутри/рядом** с
|
||||
тумблером «Voice dictation» — активен только когда `dictation` включена (это
|
||||
под-режим диктовки). Оптимистичный апдейт по образцу `dictation`
|
||||
(см. `handleDictationToggle` и запись `ai: { ...ai, dictation: value }`),
|
||||
пишет `settings.ai.dictationStreaming`. Default off. Новый i18n-ключ.
|
||||
- Гейтинг: в `dictation-group.tsx` и `chat-input.tsx` заменить жёсткий
|
||||
`streaming` (литерал `true`) на `streaming={settings.ai.dictationStreaming === true}`.
|
||||
Проп `streaming` у `MicButton` уже выбирает хук (`useStreamingDictation` vs
|
||||
`useDictation`) — там менять ничего не нужно.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- Свежий воркспейс (флага нет) → mic-кнопка использует **батч**-диктовку;
|
||||
ассеты VAD (ONNX/wasm) **не грузятся** (ленивый `import()` в
|
||||
`useStreamingDictation.start()` срабатывает только при `streaming` и клике,
|
||||
которого при выкл не будет — оба хука инертны до `start()`).
|
||||
- Тоггл вкл → стриминговая диктовка работает и в редакторе, и в чате.
|
||||
- Тоггл выкл → возврат к батчу; стриминговые ассеты не подгружаются.
|
||||
- Нет новых полей модели / эндпоинта / секрета — переиспользуется
|
||||
диктовочная STT-модель и `/ai-chat/transcribe`.
|
||||
- Флаг персистится на воркспейс и гейтится как прочие `settings.ai.*`.
|
||||
|
||||
## Затрагиваемые файлы (указатели)
|
||||
|
||||
- **Сервер:** `integrations/ai/ai.types.ts`,
|
||||
`integrations/ai/dto/update-ai-settings.dto.ts`,
|
||||
`integrations/ai/ai-settings.service.ts` (если есть нормализация/whitelist).
|
||||
- **Клиент:** `features/workspace/types/workspace.types.ts`,
|
||||
`features/workspace/components/settings/components/ai-provider-settings.tsx`
|
||||
(Switch + i18n), `features/editor/components/fixed-toolbar/groups/dictation-group.tsx`,
|
||||
`features/ai-chat/components/chat-input.tsx`.
|
||||
|
||||
## Заметки / краевые случаи
|
||||
|
||||
- Батч-диктовка остаётся дефолтом и фолбэком (в т.ч. если стриминговая
|
||||
инициализация падает).
|
||||
- Подтвердить, что выкл-состояние не тянет ни одного VAD-байта: `MicButton`
|
||||
хоть и вызывает оба хука безусловно (правило хуков), оба инертны до
|
||||
`start()`, поэтому при `streaming=false` модель/wasm не запрашиваются.
|
||||
- **Не** добавлять отдельные модель/эндпоинт под стриминг — переиспользовать
|
||||
диктовочные (явное требование после realtime-PR).
|
||||
|
||||
## Вне scope
|
||||
|
||||
- Preload / мгновенный старт и латентность инициализации модели — отдельный
|
||||
follow-up.
|
||||
- Realtime-websocket путь (PR #118, [streaming-dictation-plan.md](../streaming-dictation-plan.md))
|
||||
— не мержится.
|
||||
Reference in New Issue
Block a user