Правила принятия OpenJev
September 20, 2026 · View on GitHub
Что оценивает модель
OpenJev — NLI cross-encoder. Он не слышит аудио и не знает, кому в реальном мире адресована фраза. Ему подаётся пара «предпосылка / гипотеза», а результатом являются вероятности классов:
0: contradiction;1: entailment;2: neutral.
В gate сравниваются две пары и используется P(entailment):
«... вопрос или просьба?» → «Ответ: да.»
«... вопрос или просьба?» → «Ответ: нет.»
Первый запрос
Когда активного диалога нет, оценивайте полезное, проверяемое свойство:
Фраза: «<transcript>»
Вопрос: является ли фраза вопросом или просьбой?
Это принимает вопросы и просьбы без обязательного имени ассистента. Оно также может принять вопрос, обращённый к человеку рядом — это фундаментальное ограничение подхода без wake word.
Продолжение диалога
После принятого ответа держите последнюю реплику и последний ответ в RAM, не более короткого TTL. Для следующей реплики проводите две независимые проверки:
- связана ли фраза с этим контекстом;
- является ли она сама вопросом или просьбой.
Принимайте фразу, если прошла хотя бы одна проверка. Это важно: активный контекст не должен отклонять новый вопрос только потому, что он меняет тему.
Контекстная проверка:
Предыдущая реплика пользователя: «<user>»
Предыдущий ответ ассистента: «<assistant>»
Новая фраза: «<transcript>»
Вопрос: новая фраза является продолжением этого диалога?
Независимая проверка вопроса/просьбы использует тот же prompt, что и первый запрос. Рекомендуемый начальный TTL: 45 секунд. При истечении TTL используйте только проверку первого запроса.
Решение
Стартовое правило:
accepted = yes_score >= 0.40 and yes_score - no_score >= 0.22
Если accepted == False, не отправляйте транскрипт агенту, не выдавайте отрицательный звуковой сигнал и не создавайте сетевой запрос. Тишина уменьшает раздражение и не раскрывает окружающим распознанный текст.
При accepted == True подайте короткий локальный положительный звук. Закройте аудиопоток до воспроизведения, иначе динамик может попасть обратно в VAD/ASR.
Стоп-лист до JEV
Если транскрипт содержит целое слово или фразу из локального стоп-листа, отбрасывайте его до JEV, агента и Telegram. Это полезно для устойчивых ложных транскрипций и известных домашних реплик.
Начальный список из реального теста:
STOP_PHRASES = ('Мирон', 'Мерон', 'Аврора', 'Продолжение следует')
STOP_PATTERN = re.compile(
r'(?iu)(?<!\\w)(?:' + '|'.join(map(re.escape, STOP_PHRASES)) + r')(?!\\w)'
)
Границы предотвращают ложное совпадение Миронов по слову Мирон. Логируйте причину stop_phrase локально, но не отправляйте отказ в чат и не проигрывайте отрицательный звук. Дополняйте список только после проверки реальных ошибок: чрезмерный стоп-лист станет скрытым фильтром обычных запросов.
Калибровка
Соберите датасет из реальных, но обезличенных транскриптов:
- вопросы агенту без имени;
- просьбы агенту;
- разговоры с человеком рядом;
- фрагменты телевизора, видео и музыки;
- однословные ответы: «да», «нет», «спасибо»;
- продолжения: «а подробнее?», «покажи пример»;
- плохое ASR и шум.
Для каждого примера сохраните: ожидаемый класс, ASR-текст, yes_score, no_score, режим (first_request или continuation) и итог. Подбирайте пороги на отложенной выборке, ориентируясь прежде всего на ложные допуски, если доступ к инструментам возможен.
Не называйте yes_score калиброванной вероятностью намерения. Это оценка NLI-модели для выбранной формулировки.