На чём это работаети почему именно на этом.
Каждое решение здесь принято так, чтобы врачи были эффективнее, бизнес прибыльнее, а рутины меньше.
Стек и почему он такой
- Распознавание речи
Yandex SpeechKit v3
Единственный маршрут с работающей разметкой говорящих. Локальную диаризацию мерили на записи «телефон в полутора метрах» - 54-65%, уровень случайного.
T-one остался за адаптером: Apache 2.0, 14x realtime на CPU, 100% номеров зубов. Он регресс-страховка и рычаг себестоимости на объёме, но в MVP-runtime не запускается.
- Сборка черновика
YandexGPT
Температура 0, версионированные промпты, каждый вызов через детерминированные проверки. Модель с ненулевой свободой правит номера зубов, дописывает коды классификации и переворачивает отрицания - это замерено, а не предположено.
GigaChat держим резервом. Зарубежных моделей в контуре приёмов нет ни одной.
- Зубная формула
Свой разбор, без модели
«Один-шесть», «шестнадцатый» и «зуб 16» дают один номер; «сорок шесть лет» и «двадцать пять тысяч» номером не станут. На разборе висит регресс-набор из сорока с лишним тестов.
Модель к формуле не допускается совсем: поправленный номер - это чужой зуб в чужой карте.
- База данных
PostgreSQL, RLS
Изоляция клиник живёт в базе, а не в коде. Приложение ходит непривилегированной ролью, которая политики не обходит; тенант ставится через SET LOCAL из сессии и никогда из запроса.
Каждый новый маршрут обязан попасть в тест-матрицу изоляции - непокрытый маршрут роняет сборку.
- Очередь задач
Сам PostgreSQL, SKIP LOCKED
Отдельный брокер - это ещё один сервис, который надо охранять и в котором тоже окажутся данные приёма. Очередь в той же базе не добавляет ни того, ни другого.
Джобы: сборка аудио, распознавание, генерация, удаление записи.
- Фронтенд
React + TypeScript, PWA
Одно веб-приложение вместо десктопа и сторов. Телефон на подставке - основной рекордер, компьютер - второй; экраны одного врача синхронизируются через сервер.
Внешних CDN нет: шрифты и иконки лежат в сборке. Страница обязана открываться на старом железе в кабинете.
- Секреты и доступ
Lockbox, argon2id, cookie-сессии
Секретов в коде и в репозитории нет, проверка секретов - обязательный шаг сборки. Пароли - argon2id, сессии - httpOnly cookie с CSRF двойной отправкой.
Доступ к аудио - только по временной ссылке на пять минут, и каждое обращение попадает в журнал.
Путь одного приёма
- 01Браузер
MediaRecorderЧанки по 5-10 секунд, Wake Lock, очередь догрузки при обрыве связи
- 02Хранилище
Object StorageЧанки складываются в бакет с политикой жизненного цикла
- 03Сборка
ffmpeg concatСклейка демуксером: Safari отдаёт mp4, бинарная склейка ломается
- 04Распознавание
SpeechKit v3Потоковое, с разметкой говорящих; final и finalRefinement дедуплицируются
- 05Разбор формулы
extractors.pyНомера зубов - детерминированным разбором, без модели
- 06Сборка черновика
YandexGPTТемпература 0, версионированные промпты, разделы 043/у
- 07Проверки
guardrails.pyВырезают классификации и назначения без источника в транскрипте
- 08Врач подтверждает
POST /confirmЧерновик становится документом только здесь
- 09Удаление записи
job delete_audioЗадача в очереди плюс правило хранилища - два независимых способа
Что измерено
- 0фабрикацийна всех сценах и повторах
- 88% полнотыразброс повторов 85-92%
- 100% номеров зубов66 номеров на трёх сценах
- 3секундыот конца приёма до черновика
Цифры получены на постановочных сценах наших спайков, а не на пилотах. Пилотов у нас пока нет, и выдавать одно за другое мы не будем.