Команда «Синергия»ХАКАТОН
Команда «Синергия»
Хакатон «Точка сборки» · кейс № 2 · DBI

MedOperatorAI

Голосовой ассистент регистратуры поликлиники

Концепция для чекпоинтаСостояние на 15.10.2026Пациенты стенда вымышленные

Главная задача кейса — быстрый ответ и меньше пропущенных звонков. Наше условие — ноль ошибочных записей. Ассистент лучше честно скажет «не удалось» и передаст звонок оператору, чем запишет не того пациента, не к тому врачу или не на то время.

Кратко

Мы делаем голосового ассистента для регистратуры поликлиники. Пациент звонит в поликлинику по IP/SIP. Ассистент понимает запрос и находит врача и свободное время. Он записывает, переносит или отменяет приём в системе «Регистратура». Каждое изменение выполняется только после явного подтверждения пациента. За рабочий день до приёма ассистент сам звонит пациенту и уточняет, придёт ли он. Жалобы, медицинские вопросы, острую боль и всё нестандартное ассистент передаёт человеку.

Как проходит звонок

Пример записи к врачу. Сверху — карта всей архитектуры: она подсвечивает компонент, который работает в эту секунду. Слева — разговор. Справа — что делает каждый компонент: Asterisk, медиашлюз, распознавание речи Whisper, языковая модель (LLM), сервер, адаптер стенда, синтез речи Piper и архив.

Звонок завершён · запись создана
Пример сценария · вымышленные данные
Архитектура · подсвечен компонент, который работает сейчас
СофтфонAsteriskМедиашлюзWhisperLLM-проверкиLLM-диалогСервер операцийАдаптер стендаСтенд «Регистратура»
ответ:Piper · очередь речиМедиашлюзAsteriskпациентжурнал:Архив и панель
АссистентЗдравствуйте! Регистратура поликлиники, виртуальный помощник. Чем могу помочь?
ПациентЗапишите меня к терапевту на завтра, после обеда.
АссистентХорошо. Назовите, пожалуйста, фамилию, имя и дату рождения.
ПациентПетрова Анна, пятое мая девяностого года.
АссистентЗавтра, в четверг, у терапевта Малаховой есть время в двенадцать сорок, в четырнадцать двадцать и в шестнадцать сорок. Какое удобно?
ПациентДавайте в четырнадцать двадцать.
АссистентЗаписываю: терапевт Малахова Оксана Григорьевна, четверг, пятнадцатое октября, четырнадцать двадцать, кабинет сто шесть. Верно?
ПациентДа, верно.
АссистентГотово, вы записаны к терапевту на четверг, четырнадцать двадцать, кабинет сто шесть. Могу ещё чем-то помочь?
Внутри системы
AsteriskWhisperLLMСерверСтендPiper
Asteriskвходящий SIP-звонок · ARI StasisStart · звук по WebSocket, 16 кГц
Серверприветствие — готовый шаблон сервера, а не текст модели
Piperсинтез приветствия → Asterisk проигрывает звук
Медиашлюзконец фразы пациента → звук на распознавание · если пациент перебьёт бота, речь бота остановится (FLUSH_MEDIA)
Whisperfaster-whisper small, int8 → «запишите меня к терапевту на завтра после обеда»
LLMпроверка срочности (screen) → not_detected · JSON-схема · до 1,2 с
LLMнамерение (classify), параллельно → unrelated: понятный запрос
LLMдиалог → resolve_need(text: «терапевт») → услуга найдена
LLMдиалог → parse_datetime(text: «завтра после обеда») → 15.10, после обеда
Piperсинтез вопроса → Asterisk
Whisper→ «петрова анна пятое мая девяностого года»
LLMсрочность → not_detected · намерение → unrelated
Серверличность: «Петрова», «Анна», 05.05.1990 — имя приведено к форме стенда
СтендGET /clients?last_name=Петрова&first_name=Анна&birth_date=05.05.1990 200 · не найден
СтендPOST /clients 201 · client_id 57
LLMдиалог → find_slots(услуга, дата) → 3 варианта
Серверрасписание Excel: у терапевта Малаховой 3 свободных слота по 20 мин · минус занятость и резервы
Whisper→ «давайте в четырнадцать двадцать»
LLMсрочность → not_detected · намерение → unrelated
LLMдиалог → select_and_prepare_booking(вариант 2) → сводка, записи ещё нет
Серверслот 14:20 зарезервирован · сводку произносит шаблон сервера
Whisper→ «да верно»
LLMсрочность → not_detected
LLMнамерение → affirm: подтверждение текущей сводки
LLMпроверка действия (ACTION_REVIEW) → разрешает
Серверсогласие принято · операция в журнале, отправка один раз
СтендPOST /visits {"client_id": 57, "doctor_id": 3, "scheduled_at": "15.10.2026 14:20"} 201 · id 1042
Серверответ стенда проверен: пациент, врач и время совпадают
Запись № 1042Запланирована
Пациент
Петрова Анна · 05.05.1990
Врач
Малахова Оксана Григорьевна · терапевт · каб. 106
Приём
15.10.2026 14:20 (GMT+4)
Архивкарточка звонка: итог «Запись создана», операции и хронология · аудио и текст — только по политике хранения
Запросов к стенду за минуту3 из 10

Это иллюстрация сценария на вымышленных данных, а не запись реального звонка. Живой SIP-звонок появится на следующем этапе работы.

Проблема

Мы проанализировали журналы кейса: 17 772 звонка за три месяца и 35 470 приёмов за полгода. Данные подтверждают задачу.

ПоказательЗаданиеРасчёт по журналам
Пропущенные звонки в часы пик30–40%24,9% (весь журнал — 20,7%)
Неявки на приём18–25%13,1%
Типовые обращенияоколо 60%70,6% — запись или справка
Разговор с записью4–5 мин166,6 с
Звонков в деньдо 200193 в среднем, до 359

Типовые звонки составляют основную долю. Значит, ассистент может снять большую часть нагрузки с регистраторов. Запись через ассистента должна занимать меньше 166,6 с. Регламент поликлиники ставит цель 2,5 минуты.

Что считаем успехом

Решение работает, если после голосового разговора в стенде «Регистратура» появляется нужное изменение. Изменение сделано токеном нашей команды, для того пациента, с которым говорил ассистент, и для врача, которого он просил. Наш первый приоритет — ноль ошибок в записи. Второй — как можно больше звонков без участия оператора.

ДействиеЧто должно появиться в стенде
ЗаписьНовая запись: правильные пациент, врач, дата и время, статус «Запланирована»
ПереносТот же ID записи с новой датой или новым врачом
ОтменаТот же ID записи со статусом «Отменена»

Запрос к API сам по себе успехом не считается. Целевые показатели кейса мы считаем отчётом из журнала звонков:

ПоказательЦельКак считаем
Пропущенные звонки≤ 15%Все входящие в окне замера
Неявки≤ 12%Состоявшиеся и неявки, без отменённых
Звонки без человека≥ 60%Только с подтверждённым результатом
Ожидание ответа≤ 30 сСреднее, от поступления до первого ответа по сути
Оценка пациента≥ 4 из 5Добровольный опрос после звонка

Пустая выборка даёт «не измерено», а не ноль. Результаты тестовых звонков мы не выдаём за эффект в реальной клинике.

Как работает ассистент

Входящий звонок

  1. Ассистент здоровается и называет себя виртуальным помощником.
  2. Пациент говорит своими словами. Меню «нажмите 1» нет.
  3. Ассистент определяет цель: запись, перенос, отмена, статус записи или справка.
  4. Пациент называет фамилию, имя и дату рождения. Ассистент находит или создаёт карточку в стенде.
  5. Ассистент предлагает свободное время: по регламенту не больше трёх вариантов за раз.
  6. Ассистент зачитывает полную сводку: врач, дата, время, кабинет. Пациент подтверждает её явно. «Спасибо» не считается подтверждением.
  7. Сервер выполняет изменение в стенде и сообщает пациенту фактический результат.

Исходящее напоминание

Перевод на человека

Перевод — обязательная возможность. Маршруты звонков мы взяли из матрицы маршрутизации регламента регистратуры поликлиники (РГ-ТЕЛ-01, раздел 7.3). В матрице 17 правил, R01–R17: каждое задаёт условие, адресата и приоритет. Главные правила:

ПравилоСитуацияЧто делает ассистент
R01, R11Угроза жизни, острое состояниеСразу говорит «звоните 103 или 112» и переводит с наивысшим приоритетом. Обратный звонок запрещён
R02Просьба позвать человека (у нас ещё и клавиша «0»)Переводит сразу, без уговоров
R03ЖалобаПереводит старшему администратору
R04Медицинский вопросНе консультирует, переводит регистратору
R05Ассистент дважды не понял пациентаПредлагает оператора, на третий раз переводит сам
R06Сбой системы записи дваждыПереводит, незавершённая операция сохраняется

Оператор получает карточку перевода: цель звонка, собранные данные, причину и приоритет. Пациенту не нужно повторять всё заново. Если оператор не отвечает, ассистент предлагает обратный звонок. В экстренных случаях обратный звонок запрещён.

Справки

Ассистент отвечает на вопросы о режиме работы, адресе, ценах и документах по базе знаний из регламента поликлиники. Результаты анализов ассистент не называет и не толкует.

Как мы обеспечиваем ноль ошибок

РискЗащита
Пациента поняли неправильноПолная сводка и явное подтверждение. Отказ, условие или сомнение отменяют действие
Модель «решила» записать самаМодель не может выполнить запись. Запись делает только сервер после проверок
Стенд не проверяет занятостьНаш календарь резервирует слот атомарно. Два звонка не займут одно время
Ответ стенда потерянЗапрос записи уходит один раз. Неизвестный исход сверяется по записям пациента. Слепого повтора и дубля нет
Чужие данныеАссистент не называет данные записи, пока пациент сам не назвал свои
Лимит 10 запросов в минутуОбщий бюджет для всех звонков и кэш справочника врачей. Справочник врачей и расписание берём из локальной копии. В стенд уходят только поиск пациента и изменения
Медицинский рискПроверка срочности на каждой фразе пациента. Нет диагнозов, лекарств и оценки симптомов

Архитектура

Телефония
Софтфон → SIP → Asterisk 22 LTS

PJSIP, очередь операторов, клавиша «0» для перехода к человеку. Команды и события звонка идут через ARI. Звук идёт через канал WebSocket, 16 кГц.

Медиашлюз
Буфер звука, конец фразы, перебивание

Шлюз собирает фразу пациента и отдаёт её на распознавание. Если пациент заговорил во время ответа, шлюз сразу останавливает речь бота командой FLUSH_MEDIA.

Whisper
Распознавание речи

faster-whisper small на CPU: int8, beam 5, русский язык. Работает локально, звук не уходит за пределы контура.

LLM-проверки
Срочность, намерение и проверка действия

Qwen3-4B (Q4_K_M) в llama.cpp на 127.0.0.1, temperature 0, ответ по строгой JSON-схеме. Срочность и намерение проверяются параллельно на каждой фразе, за 1,2 с. Для «да», «завершить» и «позовите человека» есть отдельная проверка действия.

LLM-диалог
Ведёт разговор и вызывает инструменты

Та же модель с вызовом функций, один вызов за шаг, ход до 12 с. Инструменты: поиск услуги и врача, разбор даты, свободные слоты, подготовка записи, переноса и отмены, записи пациента. Модель готовит сводку, но не может выполнить запись.

Сервер
Сервер операций

Права пациента, доставка сводки и согласие, маршрутизация R01–R17, календарь и резервы, журнал операций с однократной отправкой. Только сервер решает, выполнять ли действие.

Стенд
Адаптер стенда → «Регистратура»

Общий лимит 10 запросов в минуту, кэш справочника врачей, сверка неизвестного исхода. В стенде — пациенты, врачи и записи.

Piper
Ответ пациенту

Шаблон сервера (приветствие, сводка, итог) или текст модели → одна очередь речи → синтез Piper → Asterisk.

Архив
Архив и панель администратора

Карточки звонков, операции и ошибки. Аудио и текст сохраняются только при включённой политике хранения.

КомпонентРешение
СерверPython 3.13, ядро без внешних зависимостей, SQLite
МоделиСейчас локально: faster-whisper small, Qwen3-4B, Piper. Для сравнения — другие локальные модели и облачные сервисы Yandex, Cloud.ru и SaluteSpeech. Готовы программа сравнения и адаптеры 9 языковых моделей, прогонов ещё нет. Реальные данные пациентов — только на платформе с уровнем защищённости УЗ-1 и аттестатом ИСПДн
РасписаниеФайл Excel кейса: 85 врачей, 40 профилей, 136 973 слота на 25.06–31.12.2026, приёмы по 20–60 минут, отпуска и больничные. Файл уже прочитан и проверен. Пациенту предлагаем свободные слоты на 14 дней вперёд, не позже чем за 30 минут до начала
ПанельВеб-панель администратора: звонки, аудио, расшифровки, ошибки. Это рабочий инструмент администратора. Главный результат проекта — голосовой сценарий

Основной стек открытый и работает локально. Облачные модели — только опция. При сбое облака звонок продолжит локальная модель.

Данные и 152-ФЗ

Что уже сделано

Мы разобрали задание и материалы кейса: журналы, регламент регистратуры, OpenAPI стенда. Все 97 утверждений задания мы сверили с проектом. Мы написали контракт продукта 2.2.0, таблицу маршрутизации R01–R17, 12 сценариев приёмки и 16 контрольных диалогов по регламенту. Мы выбрали телефонию: Asterisk 22 LTS.

1 529 / 1 529офлайн-тестов прошли в последней принятой проверке. Мы сделали 21 модуль, каждый прошёл отдельную приёмку

Диалог, голос и модели офлайн

Маршрутизация R01–R17 и права вымышленных пациентов. Запись, перенос и отмена через имитацию речи и модели. Программа сравнения и адаптеры 9 языковых моделей

Запись в стенд офлайн

Чтение и проверка Excel-расписания. Календарь и подготовка записи. Создание записи с однократной отправкой. Перенос и отмена одним PATCH. Кодек API, общий лимит, поиск и создание пациента

Телефония офлайн

Управление звонком через ARI, аудиопоток с перебиванием, восстановление аудиосоединения, сетевой адаптер ARI. Живое подключение пока закрыто

Архив и панель офлайн

Карточки звонков, рабочие отметки, хранение аудио и расшифровок, журнал доступа, вход, список звонков, просмотр аудио и текста

Что ещё не сделано

План до финала

Шаги идут по порядку. Сначала мы выбираем модели, затем собираем голос, телефонию и стенд.

ШагРаботаРезультат шага
1Сравнение локальных и облачных моделей: LLM, распознавание и синтез речи. Один корпус: 20 сценариев и 16 контрольных диалоговВыбор моделей по качеству, задержке и стоимости. Главный критерий — ноль ошибочных действий
2Голосовой сценарий на реальных моделях: запись, перенос, отмена. Повторная проверка дефекта «спасибо»Голосовой диалог проходит контрольные диалоги, задержки измерены
3Asterisk на сервере, звонок с софтфона, перебивание, клавиша «0», очередь оператораЖивой SIP-звонок доходит до ассистента и до оператора
4Подключение к стенду: токен, сопоставление врачей Excel и стенда, запись в стенд только через наш серверПервые запись, перенос и отмена в стенде из тестового контура
5Исходящее напоминание и обратный звонок на софтфонПодтверждение, перенос, отмена по звонку ассистента
6Сквозная демонстрация: запись и напоминание, затем перенос, отмена, перевод. Отчёт KPI по тестовым звонкамЗвонок → изменение в стенде → запись в журнале API стенда. JSON-отчёт с явными знаменателями

Сценарий показа жюри

  1. Участник звонит с софтфона и просит записать его к терапевту на завтра после обеда.
  2. Ассистент находит время, зачитывает сводку и получает «да».
  3. В панели стенда появляется новая запись.
  4. Второй звонок: перенос на другой день. У той же записи меняется время.
  5. Исходящее напоминание: пациент отказывается от визита. Запись получает статус «Отменена».
  6. Звонок с жалобой переводится на софтфон оператора с карточкой.

Риски

РискМера
Распознавание ошибается в именах и датахПодтверждение полной сводки. Перевод после двух непонятых фраз
Локальные модели отвечают медленноЦель: ответ без поиска — p50 ≤ 1,5 с, с поиском — p95 ≤ 5 с. Короткие фразы ожидания. Сравнение с облачными моделями. Замер на живом звонке
Лимит 10 запросов в минутуОбщий бюджет, кэш, локальная копия данных, приоритет входящих звонков
Потерян ответ стендаНеизвестный исход и сверка, без повторной записи
Врачи в файле расписания и в стенде не совпадутТочное сопоставление по ФИО и профилю. Без сопоставления ассистент не предлагает слот
Формат перевода на оператора для стенда не описанСейчас перевод идёт в очередь Asterisk с карточкой. Если у стенда появится API заявок, мы подключим его
Сложность телефонииРешение зафиксировано. Адаптеры уже проверены без сети

Что нам нужно от организаторов

Как сдаём