О проекте
Команда: SuperPuperNovaID
Кейс HackAlem.ai: Инновации — Самрук-Казына
Стадия: Рабочий MVP
Задача кейса: «Хаттама»: протокол и поручения по аудиозаписи совещания (каз./рус./смешанная речь)
Суть
Система автопротоколирования совещаний Qoryt: загрузка записи, ASR и диаризация, нормализация стенограммы, извлечение решений и поручений, экспорт протокола в DOCX/PDF с версиями и напоминаниями о сроках.
Как устроено
FastAPI-монолит ставит обработку в Celery (Redis): FFmpeg нормализует аудио в WAV 16 кГц mono, затем NVIDIA cloud ASR и диаризация дают стенограмму с таймкодами и speaker ID. Цепочка агентов OpenAI Agents SDK (gpt-4.1-mini) выполняет канонизацию стенограммы, сопоставление говорящих с участниками, Extraction → Resolver → Summary → Review; результаты этапов сохраняются в PostgreSQL и переиспользуются. Детерминированный экспорт MeetingProtocol в DOCX/PDF без вызова ИИ, неизменяемые версии протокола, доска поручений и внутренние напоминания.
Ключевые решения
- ASR + diarization
- FFmpeg нормализация
- канонизация стенограммы
- speaker resolution
- многоагентная цепочка Extraction/Resolver/Summary/Review
- валидация evidence и повтор анализа
- Celery
- Alembic
- DOCX/PDF экспорт
Особенности
Чётко разделённый поэтапный pipeline со статусами stage, кэшированием результатов каждого этапа и отдельным агентом-ревьюером; проверка, что поручения подкреплены цитатами из стенограммы, с повторным grounded-анализом. Сменные адаптеры речи (NVIDIA/Whisper/pyannote/NeMo).
Стек
Python · FastAPI · Celery · Redis · PostgreSQL · Alembic · React · TypeScript · Vite · Bootstrap 5 · Docker Compose · OpenAI Agents SDK
Модели
GPT-4.1-mini · NVIDIA cloud ASR/diarization · Whisper (опц. адаптер) · pyannote (опц. адаптер) · NeMo (опц. адаптер)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-64cc2b8c-superpupernovaid.
README
README.mdQoryt / SuperPuperNovaID
Прототип системы автопротоколирования совещаний: загрузка записи, распознавание речи, разделение говорящих, подготовка стенограммы, выделение решений и поручений, экспорт протокола в DOCX/PDF и сохранение его версий.
Бэкенд — модульный монолит FastAPI, интерфейс — React + TypeScript + Vite + Bootstrap 5. Длительная обработка выполняется в Celery, очередь — Redis, данные — PostgreSQL. API и worker используют один Python-код и один образ. ИИ-анализ построен на OpenAI Agents SDK. Текущий облачный сценарий использует NVIDIA для речи и OpenAI для текста.
Без настройки ключей приложение запускается, но полный анализ совещания недоступен.
AI_MODE=mockотносится только к отдельному демонстрационному/jobsAPI. Он не подменяет распознавание и анализ совещания тестовыми результатами.
Содержание
- Как работает проект
- Модули и структура
- Быстрый запуск через Docker
- Настройка .env
- Работа с совещанием через API
- Ежедневная разработка
- Запуск Python и React вне Docker
- Хранение, версии и напоминания
- Ограничения и диагностика
- Дополнительная документация
Как работает проект
React → FastAPI → PostgreSQL (совещание и состояние обработки)
│
├─ загрузка записи → общее файловое хранилище
│
└─ запуск обработки → Redis → Celery worker
│
FFmpeg: нормализация аудио
↓
ASR + diarization
текст + метки говорящих
↓
Canonicalization
нормализованная стенограмма
↓
Speaker resolution
сопоставление говорящих участникам
↓
Extraction → Resolver → Summary → Review
поручения, решения, краткое содержание
↓
MeetingProtocol → DOCX / PDF
↓
сохранённая версия протокола
Порядком этапов управляет обычный Python-сервис MeetingProcessingService.
В очередь передаются идентификаторы, а не содержимое аудио или стенограммы.
Результаты этапов сохраняются и могут повторно использоваться при следующем запуске.
Экспорт строится из сохранённых данных и сам не вызывает ИИ.
У запуска обработки состояния queued → running → completed / failed.
Поле stage показывает текущий этап: preprocessing, transcribing, diarizing,
canonicalizing, resolving_speakers, analyzing, exporting.
У самой встречи успешное финальное состояние называется ready.
Модули и структура
Все пути модулей ниже находятся в backend/src/app/.
| Модуль | Ответственность |
|---|---|
meetings/ | Совещания, участники, стенограмма и представление прогресса для UI |
media/ | Загрузка, проверка формата через ffprobe, оригинальные файлы и их метаданные |
audio/ | Нормализация через FFmpeg: по умолчанию WAV, PCM16, 16 кГц, mono |
speech/ | ASR, diarization и AttributedTranscript с таймкодами и speaker ID |
canonicalization/ | CanonicalTranscript: исходный текст сохраняется рядом с обработанным |
intelligence/ | Сопоставление участников, извлечение поручений, согласование результатов, summary и review |
processing/ | Общий pipeline, очередь, сохранённое состояние текущей попытки и обработка ошибок |
tasks/ | Поручения, ответственные, сроки и статусы выполнения |
protocols/ | Сборка MeetingProtocol, DOCX/PDF, неизменяемые снимки версий |
notifications/ | Внутренние напоминания о приближении срока и просрочке, без отправки почты |
domain/, application/ | Сущности, сценарии и порты первоначального demo jobs API |
infrastructure/ | Подключения к БД, Celery, demo-агентам; подготовленные адаптеры SMTP/S3 |
entrypoints/ | Сборка HTTP API и регистрация Celery-задач |
config.py, bootstrap.py | Настройки и связывание зависимостей |
backend/
src/app/ # модули выше
migrations/ # Alembic, включая 0010: версии протоколов и напоминания
tests/ # модульные, контрактные и опциональные интеграционные проверки
pyproject.toml # зависимости Python
uv.lock # зафиксированные версии зависимостей
frontend/
src/
components/layout/ # оболочка приложения
components/ui/ # общие компоненты
features/meetings/ # создание и рабочая область совещания
features/tasks/ # доска поручений
features/jobs/ # первоначальный demo-экран агентов
lib/ # HTTP-клиент
package-lock.json
compose.infra.yaml # PostgreSQL, Redis; опционально MinIO и Mailpit
compose.yaml # API, worker, миграции, frontend; включает инфраструктуру
compose.dev.yaml # исходники с хоста, Uvicorn reload и Vite HMR
.env.example # шаблон настроек без секретов
Makefile # сокращения для команд Docker и проверок
docs/ # подробные контракты и ограничения модулей
Бизнес-правила располагаются в сервисах модулей; HTTP-роуты и Celery-задачи вызывают эти сервисы. Внешние провайдеры подключаются через адаптеры. API и worker — разные процессы одного монолита, а не независимые микросервисы.
Быстрый запуск через Docker
Нужны Git и работающий Docker Desktop / Docker Engine с Compose 2.24.4+. Установка Python, Node.js и моделей на хост для облачного Docker-сценария не требуется. Все команды выполняются из корня репозитория.
1. Получить проект и создать настройки
git clone https://github.com/BAITC-Hacks/hack-64cc2b8c-superpupernovaid.git
cd hack-64cc2b8c-superpupernovaid
Скопируйте .env.example в .env, только если .env ещё не существует.
macOS / Linux / Git Bash:
test -f .env || cp .env.example .env
Windows PowerShell:
if (!(Test-Path .env)) { Copy-Item .env.example .env }
Для полного pipeline заполните ключи и включите этапы по примеру в следующем разделе. Без этого можно проверить запуск API/UI и загрузку файлов, но не полный ИИ-анализ.
2. Собрать и запустить режим разработки
docker compose -f compose.yaml -f compose.dev.yaml build backend frontend
docker compose -f compose.yaml -f compose.dev.yaml up -d --no-build --wait backend worker frontend
Эквивалент при установленном make: make setup-dev.
При старте сервис migrate применяет миграции; затем запускаются API и worker.
Первая сборка загружает зависимости. При последующих стартах достаточно make dev
или второй команды выше: повторная сборка не нужна.
| Что открыть | Адрес |
|---|---|
| React в режиме разработки | http://localhost:5173 |
| Swagger: интерактивная документация всех API | http://localhost:8000/docs |
| ReDoc | http://localhost:8000/redoc |
| OpenAPI JSON | http://localhost:8000/openapi.json |
| Проверка API | http://localhost:8000/api/v1/health |
| Готовность PostgreSQL и Redis | http://localhost:8000/api/v1/ready |
3. Упакованный режим для демонстрации
Здесь исходники входят в образы, а frontend раздаётся через nginx:
docker compose build backend frontend
docker compose up -d --no-build --wait backend worker frontend
Эквивалент: make build, затем make up. Интерфейс: http://localhost:8080.
Dev и упакованный режим используют один Compose project и одни volumes: это
альтернативные режимы, не два одновременно работающих окружения.
Настройка .env
.env содержит локальные настройки и секреты, исключён из Git и не приходит через
git pull. Каждый разработчик создаёт его самостоятельно. Шаблон — .env.example,
источник значений по умолчанию — backend/src/app/config.py.
Ключи должны находиться только на бэкенде: не помещайте их в VITE_*.
Минимальные изменения для облачного pipeline
Добавьте или замените эти строки в копии .env.example, без дублирования имён:
# Первоначальный demo jobs API; основной pipeline имеет отдельные флаги ниже.
AI_MODE=openai
OPENAI_API_KEY=replace-with-your-openai-key
OPENAI_MODEL=gpt-4.1-mini
# Распознавание речи и разделение говорящих в NVIDIA cloud.
SPEECH_ENABLED=true
ASR_PROVIDER=nvidia
DIARIZATION_PROVIDER=nvidia
NVIDIA_API_KEY=replace-with-your-nvidia-key
NVIDIA_LANGUAGE_CODE=ru-RU
# Обработка стенограммы через OpenAI.
TRANSCRIPT_CANONICALIZATION_ENABLED=true
TRANSCRIPT_CANONICALIZATION_MODEL=gpt-4.1-mini
TRANSCRIPT_CANONICAL_LANGUAGE=ru
# Все пять моделей необходимо задать явно.
MEETING_INTELLIGENCE_ENABLED=true
MEETING_SPEAKER_RESOLUTION_MODEL=gpt-4.1-mini
MEETING_EXTRACTION_MODEL=gpt-4.1-mini
MEETING_RESOLVER_MODEL=gpt-4.1-mini
MEETING_SUMMARY_MODEL=gpt-4.1-mini
MEETING_REVIEW_MODEL=gpt-4.1-mini
MEETING_TRACING_ENABLED=false
Имена моделей в примере соответствуют стартовой конфигурации проекта; доступ к ним
должен быть у вашего OpenAI-проекта. OPENAI_MODEL не заменяет настройки моделей
канонизации и анализа. Переменная API_KEY не распознаётся: нужна OPENAI_API_KEY.
NVIDIA_API_KEY — отдельный ключ другого провайдера.
После изменения .env пересоздайте процессы, чтобы они получили новые значения:
docker compose -f compose.yaml -f compose.dev.yaml up -d --no-build --no-deps --force-recreate backend worker
Для упакованного режима уберите -f compose.yaml -f compose.dev.yaml.
Если включён планировщик reminders, пересоздайте и его. Обычный restart новые
переменные контейнера не загружает; пересборка образа для изменения .env не нужна.
Подключения и базовые настройки
В таблицах указаны значения шаблона/настроек по умолчанию; «пусто» означает, что значение нужно задать при включении соответствующей функции.
| Переменная | По умолчанию | Назначение |
|---|---|---|
AI_MODE | mock | mock или openai только для demo jobs API |
OPENAI_API_KEY | пусто | Ключ OpenAI для канонизации, анализа и demo в режиме openai |
OPENAI_MODEL | gpt-4.1-mini | Модель demo-агента |
AGENT_TIMEOUT_SECONDS | 120 | Таймаут demo-задания, секунды |
DATABASE_URL | postgresql+psycopg://app:app@localhost:5432/app | URL SQLAlchemy; для БД из Compose при запуске Python на хосте замените порт на 5332 |
REDIS_URL | redis://localhost:6379/0 | Брокер Celery |
CORS_ORIGINS | ["http://localhost:5173","http://localhost:8080"] | Разрешённые origin, JSON-массив |
API_PROXY_TARGET | http://localhost:8000 | Настройка Vite, не FastAPI; dev Compose передаёт http://backend:8000 |
Compose передаёт корневой .env в Python-контейнеры и переопределяет DATABASE_URL,
REDIS_URL, MEDIA_UPLOAD_DIR, S3_ENDPOINT_URL, SMTP_HOST внутренними адресами.
Поэтому localhost:5332 нужен только Python-процессу на хосте; внутри Docker БД —
postgres:5432. Изменение этих пяти строк только в .env не меняет значения внутри
контейнеров: для внешней БД/SMTP/S3 потребуется также изменить Compose override.
Загрузка и подготовка аудио
| Переменная | По умолчанию | Назначение |
|---|---|---|
MEDIA_MAX_FILE_SIZE_BYTES | 5368709120 | Максимум оригинального файла, 5 ГиБ |
MEDIA_ALLOWED_FORMATS | ["wav","mp3","flac","ogg","mov","matroska"] | Семейства demuxer ffprobe, не расширения файлов |
MEDIA_UPLOAD_DIR | ./data/media в шаблоне | Каталог файлов; в Docker /data/media, относительный путь настроек считается от backend/ |
MEDIA_FFPROBE_TIMEOUT_SECONDS | 15 | Таймаут проверки файла |
MEDIA_FFPROBE_EXECUTABLE | ffprobe | Путь или имя бинарника |
MEDIA_MAX_CONCURRENT_UPLOADS | 2 | Одновременные загрузки на процесс API |
AUDIO_MAX_CONCURRENT_PROCESSES | 1 | Одновременные конвертации на процесс |
AUDIO_TARGET_SAMPLE_RATE | 16000 | Частота дискретизации, Гц |
AUDIO_TARGET_CHANNELS | 1 | Число каналов |
AUDIO_TARGET_CODEC | pcm_s16le | Кодек нормализованного аудио |
AUDIO_TARGET_FORMAT | wav | Контейнер; поддержана также согласованная пара FLAC/flac |
AUDIO_FFMPEG_TIMEOUT_SECONDS | 900 | Таймаут FFmpeg |
AUDIO_FFMPEG_EXECUTABLE | ffmpeg | Путь или имя бинарника |
Лимит загрузки не равен лимиту провайдера распознавания. Например, допустимый для
загрузки MP3 может после преобразования превысить предел NVIDIA в 16 МиБ WAV.
При превышении локальной параллельности API возвращает 429 с Retry-After.
Распознавание и diarization
| Переменная | По умолчанию | Назначение |
|---|---|---|
SPEECH_ENABLED | false | Включить обработку речи |
ASR_PROVIDER | nemo | nemo, whisper или nvidia |
DIARIZATION_PROVIDER | nemo | nemo, pyannote или nvidia; облачный сценарий использует пару nvidia/nvidia |
NVIDIA_API_KEY | пусто | Ключ NVIDIA cloud |
NVIDIA_ASR_FUNCTION_ID | 71203149-d3b7-4460-8231-1be2543a1fca | ID облачной функции речи |
NVIDIA_LANGUAGE_CODE | ru-RU | Язык текущего облачного сценария |
NVIDIA_MAX_AUDIO_BYTES | 16777216 | Максимум нормализованного аудио, не более 16 МиБ |
NVIDIA_REQUEST_TIMEOUT_SECONDS | 180 | Таймаут облачного запроса |
NEMO_ASR_MODEL | пусто | Локальная модель ASR NeMo |
NEMO_DIARIZATION_MODEL | пусто | Локальный checkpoint Sortformer .nemo |
NEMO_DEVICE | cuda | cpu или cuda |
WHISPER_MODEL | large-v3 | При включении замените абсолютным путём к локальной CTranslate2-модели |
WHISPER_DEVICE | cuda | cpu или cuda |
WHISPER_COMPUTE_TYPE | default | default, float16, float32, int8 |
PYANNOTE_MODEL | пусто | Абсолютный путь к локальной community-1 |
PYANNOTE_DEVICE | cuda | cpu или cuda |
SPEECH_MAX_DURATION_SECONDS | 14400 | Общий предел длительности, 4 часа; предел провайдера может быть ниже |
SPEECH_DIARIZATION_MAX_DECODED_BYTES | 536870912 | Лимит декодированного аудио для локальной diarization |
SPEECH_MODEL_REVISION | 1 | Версия кэша; увеличивайте при замене весов/runtime |
Локальные ML-провайдеры требуют отдельной установки зависимостей, весов и ресурсов. Базовый Docker-образ с лимитом API 1 ГиБ не является готовым GPU-окружением. Подробнее: Speech, NVIDIA cloud.
Канонизация стенограммы
| Переменная | По умолчанию | Назначение |
|---|---|---|
TRANSCRIPT_CANONICALIZATION_ENABLED | false | Включить этап |
TRANSCRIPT_CANONICALIZATION_MODEL | пусто | Отдельно заданная модель OpenAI |
TRANSCRIPT_CANONICAL_LANGUAGE | ru | Язык обработанного текста |
CANONICALIZATION_BATCH_MAX_SEGMENTS | 50 | Сегментов в пакете |
CANONICALIZATION_BATCH_MAX_BYTES | 12000 | Бюджет UTF-8 JSON входа, включая контекст и ID; не токены |
CANONICALIZATION_CONTEXT_SEGMENTS | 2 | Сегментов соседнего контекста |
CANONICALIZATION_MAX_CONCURRENCY | 3 | Параллельные запросы |
CANONICALIZATION_REQUEST_TIMEOUT_SECONDS | 60 | Таймаут запроса |
CANONICALIZATION_MAX_ATTEMPTS | 3 | Максимум попыток |
CANONICALIZATION_RETRY_BASE_SECONDS | 0.5 | База задержки повторов |
CANONICALIZATION_MAX_OUTPUT_TOKENS | 4096 | Лимит ответа модели |
Анализ совещания
| Переменная | По умолчанию | Назначение |
|---|---|---|
MEETING_INTELLIGENCE_ENABLED | false | Включить анализ |
MEETING_SPEAKER_RESOLUTION_MODEL | пусто | Сопоставление speaker ID участникам |
MEETING_EXTRACTION_MODEL | пусто | Извлечение поручений и решений |
MEETING_RESOLVER_MODEL | пусто | Согласование результатов извлечения |
MEETING_SUMMARY_MODEL | пусто | Краткое содержание |
MEETING_REVIEW_MODEL | пусто | Проверка результата |
SPEAKER_RESOLUTION_MAX_CONTEXT_SEGMENTS | 60 | Контекст определения участников |
MEETING_CHUNK_MAX_SEGMENTS | 50 | Сегментов в части стенограммы |
MEETING_CHUNK_MAX_BYTES | 24000 | Бюджет части в байтах |
MEETING_CHUNK_OVERLAP_SEGMENTS | 3 | Перекрытие частей |
MEETING_AGENT_MAX_INPUT_BYTES | 120000 | Максимум входа агента |
MEETING_MAX_OUTPUT_TOKENS | 8192 | Лимит ответа модели |
AGENT_MAX_CONCURRENCY | 3 | Параллельные агентные вызовы |
AGENT_MAX_REVIEW_ITERATIONS | 1 | Поддерживается одна итерация review |
MEETING_AGENT_MAX_ATTEMPTS | 3 | Максимум попыток вызова |
MEETING_AGENT_RETRY_BASE_SECONDS | 0.5 | База задержки повторов |
MEETING_TRACING_ENABLED | true | SDK tracing; в облачном примере выше явно выключен |
Экспорт
| Переменная | По умолчанию | Назначение |
|---|---|---|
PROTOCOL_TRANSCRIPT_TEXT_MODE | canonical | canonical или original в экспортируемой стенограмме |
PROTOCOL_PDF_FONT_PATH | /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf | Основной Unicode-шрифт PDF |
PROTOCOL_PDF_BOLD_FONT_PATH | /usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf | Полужирный шрифт PDF |
PROTOCOL_EXPORT_MAX_CHARACTERS | 2000000 | Лимит текста протокола |
PROTOCOL_EXPORT_MAX_BYTES | 52428800 | Максимум файла экспорта, 50 МиБ |
Шрифты установлены в Docker-образе. Для локального запуска задайте существующие пути к обоим TTF-файлам на своей машине.
Подготовленные настройки S3 и SMTP
Эти адаптеры не подключены к основному хранению записей и доставке напоминаний. Для стандартного запуска менять их не требуется.
| Переменная | По умолчанию | Назначение |
|---|---|---|
S3_ENDPOINT_URL | http://localhost:9000 | Endpoint S3; Compose заменяет на http://minio:9000 |
S3_ACCESS_KEY | minioadmin | Ключ локального MinIO |
S3_SECRET_KEY | minioadmin | Секрет локального MinIO |
S3_BUCKET | prototype | Bucket, создаётся отдельно |
SMTP_HOST | localhost | SMTP-сервер; Compose заменяет на mailpit |
SMTP_PORT | 1025 | SMTP-порт |
SMTP_FROM | [email protected] | Отправитель |
SMTP_USER | пусто | Логин, если требуется |
SMTP_PASSWORD | пусто | Пароль, если требуется |
SMTP_STARTTLS | false | Включение STARTTLS |
AGENT_TIMEOUT_SECONDS, SMTP-аутентификация и API_PROXY_TARGET не перечислены
в текущем .env.example, но поддерживаются кодом. Vite получает API_PROXY_TARGET
из окружения своего процесса; корневой .env автоматически ему не передаётся.
Работа с совещанием через API
Swagger — независимый от готовности frontend способ пройти весь сценарий.
Используйте language_hint=ru для текущего NVIDIA pipeline.
- Создайте встречу:
POST /api/v1/meetings. - Загрузите аудио/видео:
POST /api/v1/meetings/{id}/media, multipart-полеfile. - Запустите общий pipeline:
POST /api/v1/meetings/{id}/process. - Опрашивайте
GET /api/v1/meetings/{id}/processing-runдоcompletedилиfailed. - Получите результат и скачайте DOCX/PDF.
Пример тела создания встречи:
{
"title": "Рабочее совещание",
"language_hint": "ru",
"expected_participant_count": 3,
"recording_consent_confirmed": true
}
recording_consent_confirmed устанавливается при подтверждённом согласии на запись.
Используйте возвращённый id: произвольный UUID не создаёт встречу автоматически.
В запрос обработки подставьте id загруженного MediaAsset:
{
"media_id": "UUID_ИЗ_ОТВЕТА_ЗАГРУЗКИ",
"export_formats": ["docx", "pdf"]
}
| Метод и путь | Результат |
|---|---|
GET /api/v1/meetings | Сохранённые совещания |
GET /api/v1/meetings/{id}/processing-run | Текущая попытка, этапы и ошибка |
GET /api/v1/meetings/{id}/result | Сохранённый результат анализа |
GET /api/v1/meetings/{id}/transcript | Сегменты стенограммы |
GET /api/v1/meetings/{id}/exports/docx | Текущий протокол DOCX |
GET /api/v1/meetings/{id}/exports/pdf | Текущий протокол PDF |
GET /api/v1/meetings/{id}/protocol-versions | История версий |
GET /api/v1/meetings/{id}/protocol-versions/{version_id}/exports/pdf | PDF конкретной версии; также доступен docx |
Повторный POST обработки может вернуть существующий запуск. После ошибки следующий
POST создаёт новую попытку, используя сохранённые артефакты. "refresh": true создаёт
новую попытку завершённого запуска, но не означает принудительный сброс всех кэшей.
Не запускайте отдельные endpoints стадий параллельно с общим pipeline одной встречи.
Frontend содержит экраны встреч и поручений; подключение всех новых backend endpoints ведётся отдельно. Наличие API истории/напоминаний не означает наличие соответствующего экрана в текущей версии UI. Контракты: backend/UI, общая обработка.
Ежедневная разработка
| Задача | Команда |
|---|---|
| Первый запуск dev | make setup-dev |
| Следующий запуск без сборки | make dev |
| Только PostgreSQL и Redis | make infra |
| Логи API, worker и frontend | make logs |
| Перезапуск worker после изменения Python-кода | make restart-worker |
| Применить миграции к работающей БД | make migrate |
| Пересобрать после изменения зависимостей / Dockerfile | make rebuild-dev |
| Остановить API, worker и frontend, оставить инфраструктуру | make stop-app |
| Остановить весь стек | make down |
Uvicorn и Vite автоматически подхватывают изменения исходников. Celery worker требует
перезапуска. Если включён reminders, make stop-app его не останавливает — остановите
его отдельно. Команды Makefile — сокращения для Compose; Windows может использовать
прямые команды из раздела запуска без установки make.
После обновления кода через git pull проверьте новые строки .env.example.
В dev при неизменных зависимостях достаточно применить миграции и перезапустить worker:
docker compose -f compose.yaml -f compose.dev.yaml run --rm --no-deps migrate
docker compose -f compose.yaml -f compose.dev.yaml restart worker
Здесь PostgreSQL уже должен работать. При изменении зависимостей используйте
make rebuild-dev; в упакованном режиме любые изменения исходников требуют сборки.
Команды для разработчика, когда нужны проверки:
cd backend
uv sync --frozen
uv run ruff check .
uv run pytest
Из frontend/: npm ci, затем npm run build. Обычные проверки используют подменённые
внешние адаптеры; live/GPU/benchmark проверки требуют отдельной настройки.
Список маркеров находится в backend/pyproject.toml.
Запуск Python и React вне Docker
Потребуются Python 3.12–3.14, uv, Node.js 22.12+, npm, FFmpeg/ffprobe и Unicode-шрифты для PDF. БД и Redis можно оставить в Docker:
docker compose -f compose.infra.yaml up -d postgres redis
В корневом .env для этого режима задайте:
DATABASE_URL=postgresql+psycopg://app:app@localhost:5332/app
REDIS_URL=redis://localhost:6379/0
Также настройте пути PROTOCOL_PDF_FONT_PATH и PROTOCOL_PDF_BOLD_FONT_PATH.
Настройки Python по умолчанию ищут файл backend/.env; чтобы использовать единый
корневой файл, явно передавайте его через uv run --env-file ../.env.
Терминал API, из корня проекта:
cd backend
uv sync --frozen
uv run --env-file ../.env alembic upgrade head
uv run --env-file ../.env uvicorn app.entrypoints.api:app --reload
Терминал worker, из backend/:
uv run --env-file ../.env celery -A app.infrastructure.queue:celery_app worker --loglevel=info --pool=solo
solo удобен для локального запуска, в том числе на macOS. Основной проверяемый
способ запуска worker — Linux-контейнер с prefork и --concurrency=1.
Терминал frontend, из frontend/:
npm ci
npm run dev
Vite проксирует /api на localhost:8000; браузер открывайте на localhost:5173.
Хранение, версии и напоминания
PostgreSQL хранит встречи, участников, метаданные записей, стенограммы, результаты
анализа, поручения, состояние текущего запуска, версии протоколов и напоминания.
Оригиналы, нормализованное аудио и экспорты хранятся в общем volume media-data.
API и worker должны видеть одно и то же файловое хранилище.
docker compose down сохраняет named volumes. docker compose down -v удаляет
данные volumes, поэтому не используйте его как обычную команду перезапуска.
Для резервной копии нужны и PostgreSQL, и файловое хранилище.
При экспорте сохраняется снимок MeetingProtocol. Одинаковое содержимое использует
одну версию; изменения создают новую. Старый снимок не перезаписывается.
Исходное выражение срока («до пятницы») сохраняется рядом с уточнённой датой.
Файлы, созданные до миграции 0010, не получают исторический снимок задним числом.
Напоминания создаются для актуальных незавершённых поручений с точным due_at:
за 24 часа до срока и после просрочки. Это записи внутренней ленты, не email.
Проверка вручную: POST /api/v1/notifications/scan; просмотр:
GET /api/v1/notifications; прочтение: POST /api/v1/notifications/{id}/read.
Для автоматической проверки раз в 5 минут включите один Celery Beat при уже работающем основном dev-стеке:
docker compose -f compose.yaml -f compose.dev.yaml --profile reminders up -d --no-build --no-deps reminders
Остановка планировщика:
docker compose -f compose.yaml -f compose.dev.yaml --profile reminders stop reminders
Для упакованного режима уберите два -f. SMTP настраивать не нужно.
Подробности: версии и напоминания.
MinIO и Mailpit доступны опционально:
docker compose --profile storage --profile mail up -d minio mailpit
MinIO: API localhost:9000, консоль localhost:9001, локальные учётные данные
minioadmin / minioadmin; bucket prototype создаётся отдельно.
Mailpit: SMTP localhost:1025, просмотр писем localhost:8025.
Запуск этих сервисов сам по себе не переключает media storage на S3 и не включает
отправку напоминаний. Для ссылок S3 браузеру нужен доступный извне endpoint,
а не внутреннее имя контейнера minio.
Ограничения и диагностика
Текущий облачный pipeline ориентирован на русский язык: language_hint=ru.
Казахский и mixed не покрыты этим режимом. NVIDIA-путь ограничен 16 МиБ
нормализованного WAV (примерно 8 мин 44 с при 16 кГц, mono, PCM16) и четырьмя говорящими.
Канонизация текста не компенсирует отсутствие поддерживаемого распознавания языка.
Облачная конфигурация передаёт аудио NVIDIA, текст — OpenAI. Она не выполняет требование исходного ТЗ о закрытом контуре. Подготовленные локальные адаптеры требуют отдельного развёртывания и проверки качества. Интеграции с Zoom/Teams/Meet и live-захват не реализованы; текущий вход — загруженный файл.
Нет авторизации и разграничения доступа по пользователям. Автоматическая отправка уведомлений и восстановление зависшего запуска после полной потери worker-хоста не реализованы. Хранится текущая попытка обработки, а не история всех попыток; transactional outbox отсутствует. Качество ИИ требует отдельного benchmark и ручной проверки ответственных/сроков, оно не гарантируется прохождением unit-тестов.
| Симптом | Что проверить |
|---|---|
Речь работает, анализ недоступен / 503 при запуске | OPENAI_API_KEY, оба флага canonicalization/intelligence и все шесть моделей: одна канонизации + пять анализа |
| Ключ указан, но бэкенд его не видит | Имя OPENAI_API_KEY, не API_KEY; после изменения .env пересоздайте backend и worker |
422 при NVIDIA pipeline | language_hint=ru, корректный media ID и ограничения входа |
429 при загрузке/конвертации | Дождитесь свободного слота; лимиты действуют на процесс |
Запуск остаётся queued | Проверьте Redis и логи worker; /ready не проверяет worker или ключи провайдеров |
409 при экспорте | Для текущей стенограммы ещё нет сохранённого анализа |
| Ошибка PDF при запуске на хосте | Проверьте существование обоих файлов шрифтов |
| Локальный Python не подключается к PostgreSQL | Порт хоста 5332, внутри Compose 5432; передан ли --env-file |
| Новая таблица отсутствует | Примените alembic upgrade head через сервис migrate |
Для диагностики dev:
docker compose -f compose.yaml -f compose.dev.yaml ps
docker compose -f compose.yaml -f compose.dev.yaml logs --tail=100 backend worker migrate
Дополнительная документация
- Приём файлов и подготовка аудио, лимиты памяти.
- Speech providers и NVIDIA cloud.
- Канонизация и агентный анализ.
- Общий pipeline и повторные попытки.
- Экспорт DOCX/PDF, история и напоминания.
- Контракт backend/UI и frontend.
- Режимы разработки.
- Benchmark и разбор качества.
- Контекст проекта и исходные требования.
Подробные документы фиксируют также отдельные этапы разработки; для текущих параметров
запуска сверяйтесь с этим README, .env.example, Compose и Swagger запущенной версии.
Авторы коммитов
История коммитов
- 2026-09-23 17:53chore: include requested runtime environment configurationAllyud
- 2026-09-23 17:53feat: connect frontend to processing, protocol history and remindersAllyud
- 2026-09-23 17:53fix: validate agent evidence and retry grounded analysisAllyud
- 2026-09-23 17:29feat: preserve protocol versions and add task remindersdaniyar
- 2026-09-23 17:12feat: integrate meeting intelligence and end-to-end processingdaniyar
- 2026-09-23 16:50feat: add deterministic DOCX and PDF protocol exportsdaniyar
- 2026-09-23 16:25feat: align backend meeting and task APIs with Qoryt UIdaniyar
- 2026-09-23 15:58feat: add speech processing and transcript canonicalizationdaniyar
Все коммиты (14)
- 2026-09-23 15:58Merge remote-tracking branch 'origin/main'daniyar
- 2026-09-23 15:50feat(ui): add Qoryt meeting assistant interface and development structuredaniyar
- 2026-09-23 14:54feat: add audio preprocessing and streamline Docker developmentdaniyar
- 2026-09-23 14:24feat(media): implement meeting recording ingestiondaniyar
- 2026-09-23 13:54feat: scaffold FastAPI and React prototype with agent workerdaniyar
- 2026-09-23 12:59added gitignoredaniyar
Структура репозитория (256 файлов)
.env .env.example .gitignore Makefile README.md backend/.dockerignore backend/Dockerfile backend/alembic.ini backend/benchmarks/__init__.py backend/benchmarks/run_meeting.py backend/migrations/env.py backend/migrations/script.py.mako backend/migrations/versions/0001_jobs.py backend/migrations/versions/0002_media_assets.py backend/migrations/versions/0003_normalized_audio.py backend/migrations/versions/0004_speech_transcripts.py backend/migrations/versions/0005_canonical_transcripts.py backend/migrations/versions/0006_meeting_workspace.py backend/migrations/versions/0007_protocol_exports.py backend/migrations/versions/0008_agent_integration.py backend/migrations/versions/0009_meeting_processing.py backend/migrations/versions/0010_protocol_versions_reminders.py backend/pyproject.toml backend/requirements/speech-nemo.txt backend/requirements/speech-pyannote.txt backend/requirements/speech-whisper.txt backend/src/app/__init__.py backend/src/app/application/__init__.py backend/src/app/application/jobs.py backend/src/app/application/ports.py backend/src/app/audio/__init__.py backend/src/app/audio/config.py backend/src/app/audio/converter.py backend/src/app/audio/errors.py backend/src/app/audio/ffmpeg.py backend/src/app/audio/models.py backend/src/app/audio/repository.py backend/src/app/audio/router.py backend/src/app/audio/service.py backend/src/app/bootstrap.py backend/src/app/canonicalization/__init__.py backend/src/app/canonicalization/agent.py backend/src/app/canonicalization/batching.py backend/src/app/canonicalization/dependencies.py backend/src/app/canonicalization/errors.py backend/src/app/canonicalization/models.py backend/src/app/canonicalization/repository.py backend/src/app/canonicalization/router.py backend/src/app/canonicalization/service.py backend/src/app/config.py backend/src/app/domain/__init__.py backend/src/app/domain/jobs.py backend/src/app/entrypoints/__init__.py backend/src/app/entrypoints/api.py backend/src/app/entrypoints/worker.py backend/src/app/infrastructure/__init__.py backend/src/app/infrastructure/agents.py backend/src/app/infrastructure/database.py backend/src/app/infrastructure/mail.py backend/src/app/infrastructure/queue.py backend/src/app/infrastructure/storage.py backend/src/app/intelligence/__init__.py backend/src/app/intelligence/dependencies.py backend/src/app/intelligence/integration.py backend/src/app/intelligence/models.py backend/src/app/intelligence/pipeline/__init__.py backend/src/app/intelligence/pipeline/agents/__init__.py backend/src/app/intelligence/pipeline/agents/extraction.py backend/src/app/intelligence/pipeline/agents/resolver.py backend/src/app/intelligence/pipeline/agents/reviewer.py backend/src/app/intelligence/pipeline/agents/speaker_resolution.py backend/src/app/intelligence/pipeline/agents/summary.py backend/src/app/intelligence/pipeline/chunking.py backend/src/app/intelligence/pipeline/dependencies.py backend/src/app/intelligence/pipeline/errors.py backend/src/app/intelligence/pipeline/models.py backend/src/app/intelligence/pipeline/output_schema.py backend/src/app/intelligence/pipeline/repository.py backend/src/app/intelligence/pipeline/runner.py backend/src/app/intelligence/pipeline/service.py backend/src/app/intelligence/pipeline/speaker_context.py backend/src/app/intelligence/pipeline/speaker_repository.py backend/src/app/intelligence/pipeline/speaker_resolution.py backend/src/app/intelligence/pipeline/validation.py backend/src/app/intelligence/repository.py backend/src/app/intelligence/router.py backend/src/app/media/__init__.py backend/src/app/media/errors.py backend/src/app/media/models.py backend/src/app/media/probe.py backend/src/app/media/repository.py backend/src/app/media/router.py backend/src/app/media/service.py backend/src/app/media/storage.py backend/src/app/media/validation.py backend/src/app/meetings/__init__.py backend/src/app/meetings/identifiers.py backend/src/app/meetings/models.py backend/src/app/meetings/progress.py backend/src/app/meetings/repository.py backend/src/app/meetings/router.py backend/src/app/meetings/schemas.py backend/src/app/notifications/README.md backend/src/app/notifications/__init__.py backend/src/app/notifications/models.py backend/src/app/notifications/router.py backend/src/app/notifications/service.py backend/src/app/processing/__init__.py backend/src/app/processing/dependencies.py backend/src/app/processing/errors.py backend/src/app/processing/models.py backend/src/app/processing/queue.py backend/src/app/processing/repository.py backend/src/app/processing/router.py backend/src/app/processing/service.py backend/src/app/protocols/__init__.py backend/src/app/protocols/dependencies.py backend/src/app/protocols/docx.py backend/src/app/protocols/errors.py backend/src/app/protocols/interfaces.py backend/src/app/protocols/loader.py backend/src/app/protocols/models.py backend/src/app/protocols/pdf.py backend/src/app/protocols/presentation.py backend/src/app/protocols/repository.py backend/src/app/protocols/router.py backend/src/app/protocols/service.py backend/src/app/protocols/versions.py backend/src/app/speech/__init__.py backend/src/app/speech/adapters/__init__.py backend/src/app/speech/adapters/asr.py backend/src/app/speech/adapters/audio.py backend/src/app/speech/adapters/base.py backend/src/app/speech/adapters/diarization.py backend/src/app/speech/adapters/nvidia.py backend/src/app/speech/alignment.py backend/src/app/speech/dependencies.py backend/src/app/speech/errors.py backend/src/app/speech/interfaces.py backend/src/app/speech/models.py backend/src/app/speech/repository.py backend/src/app/speech/router.py backend/src/app/speech/service.py backend/src/app/tasks/__init__.py backend/src/app/tasks/models.py backend/src/app/tasks/repository.py backend/src/app/tasks/router.py backend/src/app/tasks/schemas.py backend/src/app/tasks/visibility.py backend/tests/agent_pipeline/conftest.py backend/tests/agent_pipeline/fixtures/scenarios.json backend/tests/agent_pipeline/test_fixtures.py backend/tests/agent_pipeline/test_openai_integration.py backend/tests/agent_pipeline/test_output_schema.py backend/tests/agent_pipeline/test_pipeline.py backend/tests/agent_pipeline/test_runner.py backend/tests/agent_pipeline/test_speaker_openai.py backend/tests/agent_pipeline/test_speaker_resolution.py backend/tests/audio/conftest.py backend/tests/audio/test_converter.py backend/tests/audio/test_integration.py backend/tests/audio/test_router.py backend/tests/audio/test_service.py backend/tests/canonicalization/conftest.py backend/tests/canonicalization/test_agent.py backend/tests/canonicalization/test_integration.py backend/tests/canonicalization/test_router.py backend/tests/canonicalization/test_service.py backend/tests/conftest.py backend/tests/media/conftest.py backend/tests/media/test_integration.py backend/tests/media/test_probe.py backend/tests/media/test_router.py backend/tests/media/test_service.py backend/tests/media/test_storage.py backend/tests/meetings/test_contract.py backend/tests/processing/test_pipeline.py backend/tests/protocols/__init__.py backend/tests/protocols/conftest.py backend/tests/protocols/fixtures.py backend/tests/protocols/test_analysis_integration.py backend/tests/protocols/test_api_loader.py backend/tests/protocols/test_http_flow.py backend/tests/protocols/test_renderers.py backend/tests/protocols/test_service.py backend/tests/protocols/test_versions_reminders.py backend/tests/speech/conftest.py backend/tests/speech/test_adapters.py backend/tests/speech/test_alignment.py backend/tests/speech/test_config.py backend/tests/speech/test_integration.py backend/tests/speech/test_nvidia.py backend/tests/speech/test_router.py backend/tests/speech/test_service.py backend/tests/test_jobs.py backend/tests/test_meeting_benchmark.py backend/uv.lock compose.dev.yaml compose.infra.yaml compose.yaml docs/audio-preprocessing.md docs/backend-ui-contract.md docs/development.md docs/frontend-backend-contract.md docs/frontend-ui.md docs/media-ingestion.md docs/meeting-analysis-integration.md docs/meeting-benchmark.md docs/meeting-processing.md docs/meeting-quality-review.md docs/nvidia-cloud-speech.md docs/project-context.md docs/protocol-export.md docs/protocol-history-reminders.md docs/speech-processing.md docs/transcript-canonicalization.md frontend/.dockerignore frontend/Dockerfile frontend/index.html frontend/nginx.conf frontend/package-lock.json frontend/package.json frontend/src/App.tsx frontend/src/components/layout/AppShell.tsx frontend/src/components/ui/AppCard.tsx frontend/src/components/ui/Icon.tsx frontend/src/components/ui/StatusBadge.tsx frontend/src/features/jobs/AgentWorkspace.tsx frontend/src/features/jobs/api.ts frontend/src/features/jobs/useJob.ts frontend/src/features/meetings/AnalysisNotes.tsx frontend/src/features/meetings/Dashboard.tsx frontend/src/features/meetings/LiveDashboard.tsx frontend/src/features/meetings/LiveWorkspace.tsx frontend/src/features/meetings/MeetingWorkspace.tsx frontend/src/features/meetings/NewMeeting.tsx frontend/src/features/meetings/ProtocolExport.tsx frontend/src/features/meetings/ProtocolHistory.tsx frontend/src/features/meetings/api.ts frontend/src/features/meetings/data.ts frontend/src/features/meetings/groupTranscript.ts frontend/src/features/meetings/liveApi.ts frontend/src/features/tasks/LiveTasks.tsx frontend/src/features/tasks/Notifications.tsx frontend/src/features/tasks/TaskBoard.tsx frontend/src/lib/errorMessage.ts frontend/src/lib/http.ts frontend/src/lib/navigation.ts frontend/src/lib/useRemote.tsx frontend/src/main.tsx frontend/src/style.css frontend/tests/api.test.mjs frontend/tests/navigation.test.mjs frontend/tests/transcript.test.mjs frontend/tsconfig.json frontend/vite.config.ts
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.