Files

228 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ТЗ. Цифровая рецепция (видеоаналитика фронт-офиса)
**Статус:** 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` — модель данных.