Initial commit: digital reception monorepo (M1-M11 + demo extensions)
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
# ТЗ. Цифровая рецепция (видеоаналитика фронт-офиса)
|
||||
|
||||
**Статус:** v0.1 (драфт для обсуждения)
|
||||
**Контекст:** компонент Платформы цифровых сервисов клиники (ПЦС), блок «Цифровые сервисы для администрации и управления».
|
||||
**Руководитель направления ПЦС:** Пётр Потураев.
|
||||
|
||||
---
|
||||
|
||||
## 1. Цели и KPI
|
||||
|
||||
**Бизнес-цели:**
|
||||
- Контроль качества обслуживания на рецепции (объективные, а не «по ощущениям» цифры).
|
||||
- Снижение времени ожидания пациента и времени простоя администратора.
|
||||
- Раннее обнаружение инцидентов (неадекватное поведение).
|
||||
- Персональная история визитов пациента на рецепции для разбора жалоб и кейс-стади.
|
||||
|
||||
**Целевые метрики (фиксируются как KPI):**
|
||||
- Среднее время ожидания в очереди (мин).
|
||||
- Среднее время обслуживания у стойки (мин).
|
||||
- Длина очереди (среднее, пиковое, по часам).
|
||||
- Время простоя администратора (мин/смена, %).
|
||||
- Количество пациентов, ушедших без обслуживания (шт/смена).
|
||||
- Количество и тип инцидентов (агрессия, скопление и т.п.).
|
||||
|
||||
**Нормативов сейчас нет.** В админке пороги делаем редактируемыми (default — пустые). Базовые значения подбираем после 1–2 недель baseline-замеров на проде в анонимном режиме (Фаза 0).
|
||||
|
||||
---
|
||||
|
||||
## 2. Сценарии наблюдения
|
||||
|
||||
**Зоны (логические, привязываются к камерам в админке):**
|
||||
- Зона A — вход в клинику.
|
||||
- Зона B — коридор / зона ожидания.
|
||||
- Зона C — стойка рецепции (рабочее место администратора).
|
||||
|
||||
**События жизненного цикла визита:**
|
||||
| Событие | Триггер |
|
||||
|---|---|
|
||||
| `arrived` | трек впервые появился в зоне A |
|
||||
| `waiting` | трек удерживается в зоне B без позиции у стойки |
|
||||
| `service_started` | трек оказался у стойки C на расстоянии < X от администратора, > N сек |
|
||||
| `service_ended` | трек покинул зону C |
|
||||
| `left_without_service` | трек ушёл из зоны A/B без `service_started`, >= Tmin времени с `arrived` |
|
||||
|
||||
Все пороги (X, N, Tmin) — настраиваемые.
|
||||
|
||||
---
|
||||
|
||||
## 3. Источники видео
|
||||
|
||||
- IP-камеры (RTSP), уже стоят в клинике. Сырое видео **не храним**.
|
||||
- В рамках Фазы 0: **инвентаризация камер** (отдельная активность с заказчиком на месте):
|
||||
- ID/имя камеры, RTSP URL, разрешение, FPS, угол обзора, освещение, привязка к зоне (A/B/C).
|
||||
- Минимум для запуска: 1 камера на вход, 1 на коридор, 1 над стойкой. Желательно с перекрытием — нужно для cross-camera re-id.
|
||||
- Подключение по локальной сети клиники. Внешний доступ — только через VPN.
|
||||
|
||||
---
|
||||
|
||||
## 4. Идентификация пациентов
|
||||
|
||||
### 4.1 Подход
|
||||
В МИС Полимед фотографий пациентов нет, поэтому базу эмбеддингов строим сами. Используется только при наличии бумажного согласия пациента (см. 4.4).
|
||||
|
||||
### 4.2 Ручной enrollment (через web-admin)
|
||||
Сценарий старшего администратора:
|
||||
1. Открывает страницу «Новые треки за смену».
|
||||
2. Видит карточки треков. Один трек = серия кадров одного и того же человека, объединённая cross-camera re-id по лицевому эмбеддингу (вход → коридор → стойка).
|
||||
3. Рядом — журнал записей на приём из Полимед за это же временное окно (REST: поиск пациентов / журнал записей).
|
||||
4. Сопоставляет трек ↔ запись на приём → ставит галочку «бумажное согласие получено» → подтверждает.
|
||||
5. Эмбеддинг сохраняется в нашей БД с привязкой к `patient_id` из Полимед.
|
||||
|
||||
Без галочки согласия эмбеддинг в долгую базу не уходит; трек живёт обезличенно до конца смены и удаляется.
|
||||
|
||||
### 4.3 Автоматическое распознавание (повторные визиты)
|
||||
- При появлении лица — поиск ближайшего эмбеддинга в pgvector (cos distance, top-5).
|
||||
- Threshold 0.35 (как в time-tracker, тюнингуем после первой партии данных).
|
||||
- При match → подтягиваем из Полимед текущий приём → метрики становятся персональными.
|
||||
|
||||
### 4.4 Согласие
|
||||
- Только бумажный носитель (договор/анкета).
|
||||
- В админке оператор ставит галочку «согласие получено».
|
||||
- Отзыв согласия → удаление эмбеддинга и персональной истории визитов в течение 24 ч. Обезличенные агрегаты остаются.
|
||||
|
||||
---
|
||||
|
||||
## 5. Приватность и 152-ФЗ
|
||||
|
||||
- Биометрические ПДн (лицевые эмбеддинги) обрабатываются только при наличии письменного согласия.
|
||||
- Сырое видео **не записывается** на диск.
|
||||
- Хранятся:
|
||||
- Лицевые эмбеддинги (512-d) — pgvector.
|
||||
- Метаданные треков (timestamps, camera_id, события).
|
||||
- Кадры-доказательства для инцидентов — MinIO, TTL 30 дней (настраиваемо).
|
||||
- ЕБС не используется.
|
||||
- Журнал доступа к биометрии (кто, когда, к чьим данным) — для аудита.
|
||||
- Контур развёртывания — внутри ЛВС клиники. Внешний доступ только через VPN.
|
||||
|
||||
---
|
||||
|
||||
## 6. Архитектура
|
||||
|
||||
### 6.1 Сервисы
|
||||
|
||||
| Сервис | Стек | Назначение |
|
||||
|---|---|---|
|
||||
| `video-ingest` | Python, OpenCV/ffmpeg, YOLOv8 (или RT-DETR), ByteTrack/BoT-SORT | На каждую RTSP-камеру отдельный воркер. Декод (по возможности NVDEC), детекция людей, трекинг внутри камеры, выдача кропов лиц и событий треков. |
|
||||
| `face-service` | Python/FastAPI, InsightFace `buffalo_l`, pgvector | Эмбеддинги лиц, поиск ближайших, эндпоинт cross-camera re-id (склейка треков с разных камер по эмбеддингу в окне T минут). Переиспользуется из `work-pcs-adm-time-tracker`. |
|
||||
| `behavior-service` | Python, action recognition (SlowFast / X3D / MoViNet) | Распознавание агрессии. **Фаза 2.** |
|
||||
| `analytics-worker` | Node.js, BullMQ | Считает метрики (очередь, время ожидания/обслуживания), формирует инциденты. |
|
||||
| `api` | Nest.js, Prisma | Коннектор к Полимед, enrollment-API, дашборд-API, RBAC. |
|
||||
| `web-admin` | Next.js 15 (App Router), shadcn/ui, Recharts | Дашборд управляющего, ручной enrollment, фиксация согласий, пороги, расписание алертов, лента инцидентов. |
|
||||
| `max-bot` | Node.js | Рассылка алертов в мессенджер Max. Фаза 2 (после `behavior-service`). |
|
||||
|
||||
### 6.2 Инфраструктура
|
||||
- PostgreSQL 16 + pgvector.
|
||||
- Redis (BullMQ).
|
||||
- MinIO (кадры-доказательства).
|
||||
- GPU-сервер (NVIDIA, CUDA, nvidia-container-toolkit) — для `video-ingest`, `face-service`, `behavior-service`.
|
||||
- Docker Compose (по образцу time-tracker, отдельный `docker-compose.prod.yml`).
|
||||
- Монорепо: pnpm + Turborepo.
|
||||
|
||||
### 6.3 Видеопайплайн (детально)
|
||||
1. `video-ingest` открывает RTSP по камере (1 воркер = 1 камера).
|
||||
2. Декодирование на GPU (NVDEC) при поддержке камеры; fallback на CPU.
|
||||
3. Детектор людей — каждый N-й кадр (целевая частота ~5 fps хватит для рецепции).
|
||||
4. Трекер (ByteTrack или BoT-SORT) — треки внутри одной камеры.
|
||||
5. На каждый трек периодически вырезается лучший по качеству кроп лица (фронтальность, размер, sharpness) → в `face-service`.
|
||||
6. `face-service` считает эмбеддинг. Если в окне последних T минут есть открытый трек с близким эмбеддингом — треки склеиваются (cross-camera re-id). Окно T — настраиваемо.
|
||||
7. События трека (`arrived` / `waiting` / `service_started` / `service_ended` / `left_without_service`) уходят в `api` → `analytics-worker`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Интеграции
|
||||
|
||||
### 7.1 МИС Полимед (REST)
|
||||
- **Read:** поиск пациента по ФИО, журнал записей на дату, статус визита.
|
||||
- **Write:** события визита на рецепции (`arrived`, `service_started`, `service_ended`) — назад в Полимед (объём write-операций уточняется со стороны Полимед).
|
||||
|
||||
### 7.2 Мессенджер Max (бот)
|
||||
- Минимально (Фаза 2): инциденты «неадекватное поведение» (агрессия) → сообщение с кадром-доказательством.
|
||||
- Получатели и расписание — настраиваются в админке.
|
||||
- Расширения (по запросу): сводки за смену, триггерные алерты по очереди и т.п.
|
||||
|
||||
### 7.3 ПЦС-портал
|
||||
- SSO и общие роли (Управляющий, Старший администратор, Безопасность, Админ системы) — на уровне ПЦС. На время Фазы 0 — локальная авторизация (как в time-tracker, JWT + refresh).
|
||||
|
||||
---
|
||||
|
||||
## 8. Роли и UI
|
||||
|
||||
| Роль | Что видит / делает |
|
||||
|---|---|
|
||||
| Управляющий клиники | Live-дашборд (текущая очередь, метрики смены), отчёты день/неделя/месяц, лента инцидентов. |
|
||||
| Старший администратор | Очередь задач на enrollment, ручная привязка треков к пациентам Полимед, фиксация согласий, отзыв согласия. |
|
||||
| Безопасность | Лента инцидентов «неадекватное поведение» + кадры. |
|
||||
| Админ системы | Камеры (RTSP, привязка к зонам), пороги метрик, расписание алертов, пользователи и роли. |
|
||||
|
||||
---
|
||||
|
||||
## 9. Фазы
|
||||
|
||||
### Фаза 0 — MVP, анонимная аналитика (2–4 нед)
|
||||
- Инвентаризация камер.
|
||||
- `video-ingest` + детекция + трекинг (без идентификации).
|
||||
- Метрики: длина очереди, время ожидания, время обслуживания, время простоя администратора, ушедшие без обслуживания.
|
||||
- Дашборд управляющего (live + отчёт за день/смену).
|
||||
- Baseline-замеры для подбора порогов.
|
||||
|
||||
**Критерий завершения:** управляющий видит реальные цифры по своей рецепции и может настроить пороги.
|
||||
|
||||
### Фаза 1 — идентификация + Полимед (+4–6 нед)
|
||||
- `face-service` + pgvector.
|
||||
- Cross-camera re-id (склейка треков по лицевому эмбеддингу).
|
||||
- Web-admin: страница ручного enrollment с журналом записей из Полимед.
|
||||
- Фиксация бумажных согласий, отзыв согласия (удаление за 24 ч).
|
||||
- Персональная история визитов пациента.
|
||||
- Write-события визитов в Полимед (если согласовано со стороны МИС).
|
||||
|
||||
**Критерий завершения:** при повторном визите пациента (после первого ручного enrollment) система автоматически узнаёт его и подтягивает текущий приём из Полимед.
|
||||
|
||||
### Фаза 2 — поведенческие сигналы (+6–8 нед)
|
||||
- `behavior-service`: action recognition на агрессию.
|
||||
- `max-bot`: алерты в Max с кадром-доказательством.
|
||||
- Логика «уход без обслуживания» (поверх треков, без отдельной модели).
|
||||
- Скопление в зоне (counter, без отдельной модели).
|
||||
|
||||
**Критерий завершения:** инцидент агрессии у стойки рецепции в течение ≤ N секунд попадает в Max нужному получателю.
|
||||
|
||||
### Фаза 3+ — по запросу
|
||||
- Дополнительные поведенческие сигналы.
|
||||
- Сводки и триггерные алерты в Max.
|
||||
- Интеграции с другими компонентами ПЦС.
|
||||
|
||||
---
|
||||
|
||||
## 10. Открытые вопросы
|
||||
|
||||
- Точная спецификация REST-эндпоинтов Полимед (методы, форматы, аутентификация).
|
||||
- Допустимость write-операций назад в Полимед и их объём.
|
||||
- Параметры Max-бота (как регистрируется бот, какой API/SDK).
|
||||
- Хостинг GPU-сервера (внутри ЛВС клиники, требования по сети и питанию).
|
||||
- Шаблон согласия на обработку биометрических ПДн (юр. отдел).
|
||||
- SSO от ПЦС: на каком этапе подключаем.
|
||||
|
||||
---
|
||||
|
||||
## Приложение A. Тех. стек = `work-pcs-adm-time-tracker` + дельта
|
||||
|
||||
| Компонент | Из time-tracker (`/Users/alekseyrazorvinm4/Project-with-LLM/work-pcs-adm-time-tracker`) | Дельта для «Цифровой рецепции» |
|
||||
|---|---|---|
|
||||
| Языки | Node.js (Nest.js, Next.js), Python (FastAPI) | + Python для `video-ingest` и `behavior-service` |
|
||||
| Распознавание лиц | InsightFace `buffalo_l` (`/apps/face-service`) | — (переиспользуем) |
|
||||
| Векторный поиск | PostgreSQL + pgvector (`/packages/db/prisma/schema.prisma`) | — (переиспользуем) |
|
||||
| Видео-вход | MediaDevices браузера, кадр раз в 2 сек | → серверный RTSP-консьюмер (OpenCV/ffmpeg), GPU |
|
||||
| Трекинг | нет | + ByteTrack / BoT-SORT |
|
||||
| Cross-camera re-id | нет | + по лицевому эмбеддингу в окне T мин |
|
||||
| Action recognition | нет | + SlowFast / X3D / MoViNet (Фаза 2) |
|
||||
| Хранилище | Postgres + pgvector, Redis | + MinIO (кадры-доказательства) |
|
||||
| Деплой | docker-compose (`/docker/docker-compose.yml`) | + GPU-runtime (nvidia-container-toolkit), `docker-compose.prod.yml` |
|
||||
| Авторизация | JWT + refresh в httpOnly cookie (`/apps/api`) | — (Ф0), → SSO от ПЦС (Ф1+) |
|
||||
| Монорепо | pnpm + Turborepo | — (переиспользуем) |
|
||||
|
||||
**Ссылки для разработки:**
|
||||
- `/Users/alekseyrazorvinm4/Project-with-LLM/work-pcs-adm-time-tracker/ARCHITECTURE.md` — техническая схема time-tracker.
|
||||
- `/Users/alekseyrazorvinm4/Project-with-LLM/work-pcs-adm-time-tracker/apps/face-service/main.py` — `/recognize` эндпоинт.
|
||||
- `/Users/alekseyrazorvinm4/Project-with-LLM/work-pcs-adm-time-tracker/apps/face-service/requirements.txt` — версии Python-зависимостей.
|
||||
- `/Users/alekseyrazorvinm4/Project-with-LLM/work-pcs-adm-time-tracker/packages/db/prisma/schema.prisma` — модель данных.
|
||||
Reference in New Issue
Block a user