VEU.WathBody/1-docs/4-modules/m11-voice-input/api_specs/01-voice-command-parser.md

6.3 KiB
Raw Permalink Blame History

Спецификация 01: VoiceCommandParser — грамматика Ф-1.2

Источники: Ф-1.2 (грамматика), Ф-1.3 (отклонение), О-2-Б («с половиной» → +0,5 кг), tech-req 5 (постобработка чисел). Единица 1. Чистая функция JVM — без Android-зависимостей.

1. Интерфейс

sealed interface VoiceCommand {
    data class Approach(val weightKg: Double, val reps: Int) : VoiceCommand
    data class Weight(val weightKg: Double) : VoiceCommand
    data class Rest(val seconds: Int) : VoiceCommand
    data class Rpe(val rpe: Int) : VoiceCommand
    data class Rejected(val reason: String, val attempted: JsonObject?) : VoiceCommand
}

object VoiceCommandParser {
    fun parse(alternatives: List<String>): VoiceCommand?
    // null — ни одна гипотеза не содержит распознаваемой команды
    fun semantics(cmd: VoiceCommand): JsonObject   // для журнала Ф-1.5
}

parse получает список финальных гипотез Vosk (спец 02, до 3; режим одного варианта — список из одного) и возвращает первую успешно разобранную команду; если все гипотезы мусор — Rejected из первой гипотезы. Отклонённая команда — тоже результат (журнал Ф-1.3/1.5), «не было команды вообще» (тишина/чужая речь) — null, в журнал не пишется.

2. Предобработка текста

  • нижний регистр, ё→е, удаление знаков препинания, сжатие пробелов;
  • нормализация аббревиатуры RPE: «эр пэ э», «эрпэ» → «рпэ» (свободное распознавание слышит буквы по отдельности);
  • токены — слова и цифровые группы.

3. Числа (NumberRu, 0–999)

  • словами: [сотни] [десятки] [единицы] → сумма. Словари: ноль; один/одна/одно, два/две, три…девятнадцать; десятки двадцать…девяносто; сотни сто, двести, триста, четыреста, пятьсот…девятьсот. Составное число — подряд стоящие разряды («сто двадцать три» → 123); постобработка «сто двадцать» → 120 (tech-req 5);
  • цифрами: 120, дробное 120,5 / 120.5 (= только 5 после разделителя — шаг 0,5);
  • «с половиной» после числа → +0,5 (О-2-Б); допустимо ТОЛЬКО в позиции веса W (команды Approach/Weight); «с половиной» в позиции R/S/N — грамматическая ошибка (отклонение);
  • порядок разрядов нарушен («двадцать сто») — грамматическая ошибка.

4. Грамматика команд (Ф-1.2)

Команда Шаблон Диапазоны
Approach подход W [с половиной] на R W 0–500 (шаг 0,5), R 1–100
Weight вес W [с половиной] W 0–500 (шаг 0,5)
Rest отдых S [секунд / секунды] S 5–600
Rpe рпэ N N 1–10
  • ключевые слова обязательны и однозначны; на, секунд — по шаблону (секунды склоняются: «девяносто секунд» / «тридцать секунд» — Vosk может выдать и «секунды» — принимать секунд|секунды);
  • лишние слова до/после шаблона — грамматическая ошибка (узкая грамматика, Ф-1.3);
  • число разобрано, но вне диапазона → Rejected(reason= "out_of_range", attempted={…значения…});
  • шаблон не совпал → Rejected(reason="out_of_grammar", attempted=null).

5. Семантика для журнала (Ф-1.5, контракт m09 spec 04)

{"cmd":"set","weight_kg":120.0,"reps":8}
{"cmd":"weight","weight_kg":62.5}
{"cmd":"rest","sec":90}
{"cmd":"rpe","rpe":7}
{"cmd":"rejected","reason":"out_of_range","weight_kg":600.0,"reps":8}
  • semantics — объект (как в PayloadFactory.commandLog m09); rejected сохраняет распознанные значения — разбор ошибок при анализе журнала;
  • исходный текст гипотезы пишется в recognized_text исполнителем (спец 03).

6. Тесты (unit, pure JVM)

  1. Четыре команды — числа словами: «подход сто двадцать на восемь» → Approach(120,8); «вес шестьдесят два с половиной» → Weight(62.5); «отдых девяносто секунд» → Rest(90); «рпэ семь» / «эр пэ э семь» → Rpe(7).
  2. Цифрами: «подход 120 на 8», «вес 62,5», «отдых 90», «120.5».
  3. Границы: W=0 и W=500 приняты; W=500,5 / R=0 / R=101 / S=4 / S=601 / N=0 / N=11 → out_of_range (attempted заполнен).
  4. Отклонения: «погнали» → out_of_grammar; «подход сто двадцать» (нет «на») → out_of_grammar; «отдых тридцать с половиной» → out_of_grammar («с половиной» не у веса); «подход двадцать сто на пять» → out_of_grammar.
  5. NumberRu: крайние числа — ноль, сто, девятьсот девяносто девять, «двести двадцать два»; регистр и пунктуация («Подход 120, на 8!»); формы «два»/«две».
  6. Alternatives: первая гипотеза мусор, вторая валидна → команда из второй; все мусор → Rejected из первой.