docs(domain D): v2 — ретро-ревью pass-2 (9 находок) + кросс-док
- AEC (эхоподавление, loopback-ref из PipeWire) добавлен в пайплайн — нужен для wake-word во время воспроизведения и barge-in (был полностью пропущен) - auto-fallback: v1 = online degradation UX, офлайн-фолбэк (llama.cpp) = v3 (раньше фолбэкать в v1 было некуда); offline-first (#3) в v1 частично, полный — v3 - инференс: ONNX (Silero) + Vosk через нативный Kaldi (не «всё через ONNX») - vehicle-context: контракт инъектора — только quality=valid, гейт по состоянию машины, ассистент декларирует vehicle_read через прокси; деградация на простых авто - wake-word по состояниям питания (не безусловно always-on, риск разряда; Stage 2; гейт Power/B) - distraction: owner Shell §7, скорость K(GPS v1)/E(OBD v2); журнал wake-word/mic - кросс-док: tech-stack (Porcupine отвергнут), principles #3 (фазировка офлайн-диалога) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+51
-28
@@ -4,8 +4,8 @@
|
|||||||
> их по-человечески. Интегрирован в UI лаконично (как Grok в Tesla). Вторая половина
|
> их по-человечески. Интегрирован в UI лаконично (как Grok в Tesla). Вторая половина
|
||||||
> killer-фичи. First-party ап на SDK (Rust + ONNX Runtime).
|
> killer-фичи. First-party ап на SDK (Rust + ONNX Runtime).
|
||||||
|
|
||||||
Статус: **v1 (на ревью).**
|
Статус: **v2 (на ревью).** v2 — после ретро-ревью (9 находок).
|
||||||
Связано с: домен E (Vehicle-Data) · [ipc.md](../contracts/ipc.md) (`Assistant`) · [plugin-sdk.md](../contracts/plugin-sdk.md) (интенты) · [security-privacy.md](../contracts/security-privacy.md) (mic, приватность) · [tech-stack.md](../tech-stack.md) · [principles.md](../principles.md) (#3,#6,#7,#8)
|
Связано с: домены E (Vehicle-Data), **K (GPS/Location)**, **B (power-гейт wake-word)** · [ipc.md](../contracts/ipc.md) (`Assistant`) · [plugin-sdk.md](../contracts/plugin-sdk.md) (интенты) · [security-privacy.md](../contracts/security-privacy.md) · [tech-stack.md](../tech-stack.md) · [principles.md](../principles.md) (#3,#5,#6,#7,#8)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -19,16 +19,19 @@
|
|||||||
## 2. Пайплайн
|
## 2. Пайплайн
|
||||||
|
|
||||||
```
|
```
|
||||||
Mic-массив → Wake-word → VAD → STT(RU) → Intent router
|
Mic-массив → AEC → Wake-word → VAD → STT(RU) → Intent router
|
||||||
→ [локальные интенты] (громче/домой/… — без LLM, низкая латентность)
|
→ [локальные интенты] (громче/домой/… — без LLM, низкая латентность)
|
||||||
→ [LLM backend] (свободный диалог + объяснения + контекст машины)
|
→ [LLM backend] (свободный диалог + объяснения + контекст машины)
|
||||||
→ TTS(RU) → Audio out
|
→ TTS(RU) → Audio out
|
||||||
```
|
```
|
||||||
|
*(AEC = эхоподавление с loopback-референсом TTS/медиа-выхода из PipeWire — нужно для
|
||||||
|
wake-word во время воспроизведения и для barge-in.)*
|
||||||
|
|
||||||
Компоненты: wake-word (**openWakeWord**, Apache-2.0, RU-фраза «Штурман»; Porcupine —
|
Компоненты: **AEC** (loopback-ref выхода) · wake-word (**openWakeWord**, Apache-2.0, RU-фраза
|
||||||
коммерческий/проприетарный → конфликт с принципом #12, избегаем) · VAD (Silero) ·
|
«Штурман»; Porcupine проприетарный → #12, избегаем) · VAD (Silero) · STT (Vosk/Silero, **офлайн**) ·
|
||||||
STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable) · TTS (Silero, офлайн).
|
intent router · LLM backend (pluggable) · TTS (Silero, офлайн).
|
||||||
Инференс — через ONNX Runtime (`ort`); см. [tech-stack.md](../tech-stack.md).
|
**Инференс:** ONNX-модели (Silero VAD/STT/TTS) — через ONNX Runtime (`ort`); **Vosk — нативный
|
||||||
|
движок Kaldi** (крейт `vosk`). См. [tech-stack.md](../tech-stack.md).
|
||||||
|
|
||||||
## 3. Функции
|
## 3. Функции
|
||||||
|
|
||||||
@@ -44,12 +47,12 @@ STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable)
|
|||||||
| LLM online (GigaChat/YandexGPT) | **MVP** | Connectivity | v1 |
|
| LLM online (GigaChat/YandexGPT) | **MVP** | Connectivity | v1 |
|
||||||
| Multi-turn контекст | **MVP** | — | v1 |
|
| Multi-turn контекст | **MVP** | — | v1 |
|
||||||
| **Vehicle-context injection** | **MVP (killer)** | E, data-model | v2 |
|
| **Vehicle-context injection** | **MVP (killer)** | E, data-model | v2 |
|
||||||
| Provider auto-fallback | **MVP** | — | v1 |
|
| Online degradation/timeout UX («думаю…»/«нет сети») | **MVP** | — | v1 |
|
||||||
| Driver-distraction (приоритет голосу на скорости) | **MVP** | Shell, E(speed) | v1/v2 |
|
| Driver-distraction (приоритет голосу) | **MVP** | Shell (owner); K (GPS) v1; E (OBD) v2 | v1/v2 |
|
||||||
| LLM offline fallback (локальная модель) | later | — | v3 |
|
| Provider switch + офлайн-фолбэк (llama.cpp) | later | — | v3 |
|
||||||
| Память о водителе (`.md`) | later | storage | v3 |
|
| Память о водителе (`.md`) | later | storage | v3 |
|
||||||
| Plugin-интенты (dispatch в IntentHandler) | later | plugin-sdk | v3 |
|
| Plugin-интенты (dispatch в IntentHandler) | later | plugin-sdk | v3 |
|
||||||
| Barge-in (прерывание TTS голосом) | later | — | later |
|
| Barge-in (прерывание TTS голосом) | later | **AEC**, PipeWire loopback | later |
|
||||||
|
|
||||||
## 4. Vehicle-context injection (killer-фича)
|
## 4. Vehicle-context injection (killer-фича)
|
||||||
|
|
||||||
@@ -59,17 +62,27 @@ STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable)
|
|||||||
```
|
```
|
||||||
[SYSTEM] Ты — Штурман, голосовой со-пилот. Кратко, по-русски, для водителя в движении.
|
[SYSTEM] Ты — Штурман, голосовой со-пилот. Кратко, по-русски, для водителя в движении.
|
||||||
Не давай советов, опасных для вождения.
|
Не давай советов, опасных для вождения.
|
||||||
Данные машины (только чтение, могут быть неточны):
|
Данные машины (только валидные/свежие; недоступные опущены):
|
||||||
Скорость 64 км/ч · Обороты 2100 · Охлаждайка 92°C · Бортсеть 14.1В
|
Скорость 64 км/ч · Обороты 2100 · Охлаждайка 92°C · Бортсеть 14.1В
|
||||||
Лампа Check: горит · Ошибки: P0420 (катализатор, банк 1 — низкая эффективность)
|
Лампа Check: горит · Ошибки: P0420 (катализатор, банк 1 — низкая эффективность)
|
||||||
|
(расход: нет данных)
|
||||||
[Память о водителе]: …
|
[Память о водителе]: …
|
||||||
[USER] Почему горит чек?
|
[USER] Почему горит чек?
|
||||||
[ASSISTANT] Из-за P0420 — система считает, что катализатор работает неэффективно.
|
[ASSISTANT] Из-за P0420 — система считает, что катализатор работает неэффективно.
|
||||||
Часто это датчик кислорода или сам катализатор. Машина поедет, но на диагностику стоит заехать.
|
Часто это датчик кислорода или сам катализатор. Машина поедет, но на диагностику стоит заехать.
|
||||||
```
|
```
|
||||||
|
|
||||||
Снимок берётся из `VehicleData` (E); коды → стандартное описание из базы, человеческое
|
Снимок берётся из `VehicleData` (E); коды → стандартное описание из базы, человеческое объяснение — LLM.
|
||||||
объяснение — LLM.
|
|
||||||
|
**Контракт инъектора контекста:**
|
||||||
|
- Ассистент — first-party SDK-ап, **декларирует `vehicle_read:[…]`** (speed, rpm, coolant_temp,
|
||||||
|
module_voltage, fuel_level, **mil_on, dtc_count**) + `GetDtcs()`; доступ гейтится тем же
|
||||||
|
VehicleData-прокси, что и у плагинов (ipc §5) — first-party = авто-грант, не «свободный доступ».
|
||||||
|
- В промпт — **только сигналы `quality=valid`** (data-model §2/§3); `stale`/`unavailable` —
|
||||||
|
исключаются или помечаются «нет данных» (LLM не утверждает устаревшее).
|
||||||
|
- Состав гейтится **состоянием машины** (`off`/`accessory`/`running`).
|
||||||
|
- **Деградация на простых авто (Lada):** богатые PID часто Unavailable → снимок схлопывается
|
||||||
|
до `mil_on` + DTC — это всегда-доступный MVP-базис.
|
||||||
|
|
||||||
## 5. LLM backend (pluggable, provider-agnostic)
|
## 5. LLM backend (pluggable, provider-agnostic)
|
||||||
|
|
||||||
@@ -79,9 +92,11 @@ STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable)
|
|||||||
- **Авто-fallback:** ошибка/нет сети → офлайн; восстановилась — обратно.
|
- **Авто-fallback:** ошибка/нет сети → офлайн; восстановилась — обратно.
|
||||||
- **Креды — свои у пользователя:** проект не шипит ключи; пользователь подключает
|
- **Креды — свои у пользователя:** проект не шипит ключи; пользователь подключает
|
||||||
свой GigaChat/YandexGPT (токены в защищённом хранилище, refresh; облако — за его счёт).
|
свой GigaChat/YandexGPT (токены в защищённом хранилище, refresh; облако — за его счёт).
|
||||||
- **До офлайн-фолбэка (v1 online-only):** сеть в движении нестабильна → мягкая
|
- **До офлайн-фолбэка (v1 online-only):** сеть в движении нестабильна → мягкая деградация:
|
||||||
деградация: «думаю…», таймаут → «нет сети», без зависаний. Офлайн-фолбэк (v3) и
|
«думаю…», таймаут → «нет сети», без зависаний. Офлайн-фолбэк (v3) делает ассистента надёжным.
|
||||||
делает ассистента по-настоящему надёжным.
|
- **Принцип #3 (offline-first) в v1 — частично:** wake-word, STT/TTS и локальные интенты
|
||||||
|
(громче/домой) работают офлайн, ассистент не немеет без сети; офлайн-**диалог** (llama.cpp) — v3.
|
||||||
|
(Полное #3-соответствие — v3; см. principles #3.)
|
||||||
|
|
||||||
## 6. Интенты (routing)
|
## 6. Интенты (routing)
|
||||||
|
|
||||||
@@ -103,15 +118,19 @@ STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable)
|
|||||||
## 8. Приватность
|
## 8. Приватность
|
||||||
|
|
||||||
- Голос обрабатывается **локально** (STT) до отправки чего-либо; в облако — только
|
- Голос обрабатывается **локально** (STT) до отправки чего-либо; в облако — только
|
||||||
**текст запроса** при онлайн-LLM. Микрофон always-on для wake-word, но локально +
|
**текст запроса** при онлайн-LLM. Контекст машины уходит провайдеру только онлайн и по запросу (security-privacy §7).
|
||||||
**видимый индикатор** прослушки. Контекст машины уходит провайдеру только онлайн и
|
- **Wake-word по состояниям питания (не безусловно always-on):** работает при заведённом /
|
||||||
по запросу (security-privacy §7).
|
ACC-on; в sleep/off — выключен (риск разряда АКБ на стоянке, принцип #5). Доступен только с
|
||||||
|
**Stage 2** (в boot-окне голоса нет). Гейтится сигналами Power (`AccChanged`/`Sleep`/`Wake`, ipc).
|
||||||
|
Включённый микрофон — **видимый индикатор**. Политика прослушки на ACC-off + бюджет разряда — ◻️ домен B/hardware.
|
||||||
|
|
||||||
## 9. Зависимости
|
## 9. Зависимости
|
||||||
|
|
||||||
- **Вниз/вбок:** E (контекст машины), Connectivity (online LLM), PipeWire (`audio_in`/`audio_out`),
|
- **Вниз/вбок:** E (контекст машины, `vehicle_read`+`GetDtcs` через прокси), **K** (GPS-скорость
|
||||||
Settings, Shell (UI-интеграция, driver-distraction), security-privacy (mic-индикатор),
|
для distraction v1), Connectivity (online LLM), **PipeWire** (`audio_in`/`audio_out` +
|
||||||
tech-stack (ONNX Runtime, llama.cpp), data-model (коды/сигналы для контекста).
|
**loopback-tap выхода для AEC**), **Power/B** (гейт wake-word по ACC/sleep), Settings, Shell
|
||||||
|
(UI; политику distraction владеет Shell §7), security-privacy (mic-индикатор), tech-stack
|
||||||
|
(ONNX Runtime, `vosk`, llama.cpp), data-model (коды/сигналы/quality для контекста).
|
||||||
|
|
||||||
## 10. Открытые вопросы
|
## 10. Открытые вопросы
|
||||||
|
|
||||||
@@ -123,8 +142,10 @@ STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable)
|
|||||||
- ◻️ **Barge-in** (прерывание TTS) — later.
|
- ◻️ **Barge-in** (прерывание TTS) — later.
|
||||||
- ◻️ **Размер контекста:** машина + память + история → токены (особенно у офлайн-модели
|
- ◻️ **Размер контекста:** машина + память + история → токены (особенно у офлайн-модели
|
||||||
с маленьким окном); нужна обрезка/суммаризация. → реализация.
|
с маленьким окном); нужна обрезка/суммаризация. → реализация.
|
||||||
- ◻️ **Точность офлайн-STT в шуме:** приватность фиксирует офлайн-STT → критичен
|
- ◻️ **AEC (эхоподавление):** подавление собственного TTS/медиа-выхода (loopback-ref из
|
||||||
**mic-массив** (beamforming/шумоподавление). → этот домен + [hardware.md](../contracts/hardware.md).
|
PipeWire) — нужно для wake-word во время воспроизведения и barge-in; место (WirePlumber/
|
||||||
|
filter-chain vs внутри ассистента). → этот домен + architecture (audio plane).
|
||||||
|
- ◻️ **Beamforming/денойз** (внешний шум салона): mic-массив; офлайн-STT фиксирован приватностью. → [hardware.md](../contracts/hardware.md).
|
||||||
- ◻️ **Plugin-интенты как function-calling** (tool-use LLM) vs фразы — зависит от
|
- ◻️ **Plugin-интенты как function-calling** (tool-use LLM) vs фразы — зависит от
|
||||||
поддержки провайдером (у GigaChat/YandexGPT может быть ограничена). → реализация.
|
поддержки провайдером (у GigaChat/YandexGPT может быть ограничена). → реализация.
|
||||||
- ◻️ **Обучение wake-word «Штурман»** (openWakeWord) — сбор данных/тренировка. → реализация.
|
- ◻️ **Обучение wake-word «Штурман»** (openWakeWord) — сбор данных/тренировка. → реализация.
|
||||||
@@ -135,8 +156,10 @@ STT (Vosk/Silero, **офлайн**) · intent router · LLM backend (pluggable)
|
|||||||
|
|
||||||
| Решение | Выбор | Дата |
|
| Решение | Выбор | Дата |
|
||||||
|---------|-------|------|
|
|---------|-------|------|
|
||||||
| Пайплайн | wake→VAD→STT→router→(локальные/LLM)→TTS; ONNX Runtime | 2026-06-16 |
|
| Пайплайн | Mic→AEC→wake→VAD→STT→router→(локальные/LLM)→TTS; ONNX (Silero) + Vosk (Kaldi) | 2026-06-16 |
|
||||||
| LLM | provider-agnostic; online GigaChat/YandexGPT + offline llama.cpp; авто-fallback | 2026-06-16 |
|
| LLM | provider-agnostic; online (v1) + офлайн-диалог (v3, llama.cpp); деградация UX в v1 | 2026-06-16 |
|
||||||
| Контекст машины | live-снимок из E в системный промпт (killer-фича) | 2026-06-16 |
|
| Контекст-инъекция | только `quality=valid`, гейт по состоянию машины; `vehicle_read` через прокси | 2026-06-16 |
|
||||||
| Память о водителе | локальные `.md` в приватном хранилище; не в облако без согласия | 2026-06-16 |
|
| Память о водителе | локальные `.md` в приватном хранилище; не в облако без согласия | 2026-06-16 |
|
||||||
| Локальные интенты | латентно-критичные — без LLM | 2026-06-16 |
|
| Локальные интенты | латентно-критичные — без LLM | 2026-06-16 |
|
||||||
|
| Wake-word | openWakeWord (Apache-2.0); Porcupine отвергнут (проприетарный, #12) | 2026-06-16 |
|
||||||
|
| Микрофон | wake-word по состояниям питания (не always-on), с Stage 2; AEC обязателен | 2026-06-16 |
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
### 3. Offline-first
|
### 3. Offline-first
|
||||||
- **Почему:** салон часто без сети (тоннели, глушь); ассистент не должен умолкать, навигация — теряться.
|
- **Почему:** салон часто без сети (тоннели, глушь); ассистент не должен умолкать, навигация — теряться.
|
||||||
- **Как держим:** STT/TTS локальны; у ассистента офлайн-LLM фолбэк; карты офлайн; ключевые функции **деградируют, а не падают** без сети.
|
- **Как держим:** STT/TTS локальны; у ассистента офлайн-LLM фолбэк; карты офлайн; ключевые функции **деградируют, а не падают** без сети. *(Фазировка: STT/TTS-офлайн + локальные интенты держат принцип с v1; офлайн-**диалог** LLM — v3, см. домен D §5.)*
|
||||||
|
|
||||||
### 4. Изоляция и graceful degradation
|
### 4. Изоляция и graceful degradation
|
||||||
- **Почему:** устойчивость; падение одного компонента не должно ронять систему.
|
- **Почему:** устойчивость; падение одного компонента не должно ронять систему.
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@
|
|||||||
| **OS base** | Armbian/Debian (RK3588), ядро ближе к mainline | read-only rootfs + overlay |
|
| **OS base** | Armbian/Debian (RK3588), ядро ближе к mainline | read-only rootfs + overlay |
|
||||||
| **Init / lifecycle** | **systemd** | ядро; апы/плагины — App-Host |
|
| **Init / lifecycle** | **systemd** | ядро; апы/плагины — App-Host |
|
||||||
| **CAN/OBD (read-only)** | **SocketCAN** (крейт `socketcan`) | ELM327 на старте; `python-OBD` — только в симуляторе |
|
| **CAN/OBD (read-only)** | **SocketCAN** (крейт `socketcan`) | ELM327 на старте; `python-OBD` — только в симуляторе |
|
||||||
| **Wake-word** | openWakeWord / Porcupine | кастомная RU-фраза |
|
| **Wake-word** | **openWakeWord** | RU-фраза «Штурман»; Porcupine отвергнут (проприетарный, #12) |
|
||||||
| **VAD** | Silero VAD | через ONNX Runtime |
|
| **VAD** | Silero VAD | через ONNX Runtime |
|
||||||
| **STT** | Vosk · Silero | офлайн, RU; через биндинги / `ort` |
|
| **STT** | Vosk · Silero | офлайн, RU; через биндинги / `ort` |
|
||||||
| **TTS** | Silero | офлайн, RU |
|
| **TTS** | Silero | офлайн, RU |
|
||||||
|
|||||||
Reference in New Issue
Block a user