AAYMA
RU
Войти

Qoryt

Система автопротоколирования совещаний Qoryt: загрузка записи, ASR и диаризация, нормализация стенограммы, извлечение решений и поручений, экспорт…

Рабочий MVP
Команда «SuperPuperNovaID» 7💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: 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.md

Qoryt / SuperPuperNovaID

Прототип системы автопротоколирования совещаний: загрузка записи, распознавание речи, разделение говорящих, подготовка стенограммы, выделение решений и поручений, экспорт протокола в DOCX/PDF и сохранение его версий.

Бэкенд — модульный монолит FastAPI, интерфейс — React + TypeScript + Vite + Bootstrap 5. Длительная обработка выполняется в Celery, очередь — Redis, данные — PostgreSQL. API и worker используют один Python-код и один образ. ИИ-анализ построен на OpenAI Agents SDK. Текущий облачный сценарий использует NVIDIA для речи и OpenAI для текста.

Без настройки ключей приложение запускается, но полный анализ совещания недоступен. AI_MODE=mock относится только к отдельному демонстрационному /jobs API. Он не подменяет распознавание и анализ совещания тестовыми результатами.

Содержание

Как работает проект

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: интерактивная документация всех APIhttp://localhost:8000/docs
ReDochttp://localhost:8000/redoc
OpenAPI JSONhttp://localhost:8000/openapi.json
Проверка APIhttp://localhost:8000/api/v1/health
Готовность PostgreSQL и Redishttp://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_MODEmockmock или openai только для demo jobs API
OPENAI_API_KEYпустоКлюч OpenAI для канонизации, анализа и demo в режиме openai
OPENAI_MODELgpt-4.1-miniМодель demo-агента
AGENT_TIMEOUT_SECONDS120Таймаут demo-задания, секунды
DATABASE_URLpostgresql+psycopg://app:app@localhost:5432/appURL SQLAlchemy; для БД из Compose при запуске Python на хосте замените порт на 5332
REDIS_URLredis://localhost:6379/0Брокер Celery
CORS_ORIGINS["http://localhost:5173","http://localhost:8080"]Разрешённые origin, JSON-массив
API_PROXY_TARGEThttp://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_BYTES5368709120Максимум оригинального файла, 5 ГиБ
MEDIA_ALLOWED_FORMATS["wav","mp3","flac","ogg","mov","matroska"]Семейства demuxer ffprobe, не расширения файлов
MEDIA_UPLOAD_DIR./data/media в шаблонеКаталог файлов; в Docker /data/media, относительный путь настроек считается от backend/
MEDIA_FFPROBE_TIMEOUT_SECONDS15Таймаут проверки файла
MEDIA_FFPROBE_EXECUTABLEffprobeПуть или имя бинарника
MEDIA_MAX_CONCURRENT_UPLOADS2Одновременные загрузки на процесс API
AUDIO_MAX_CONCURRENT_PROCESSES1Одновременные конвертации на процесс
AUDIO_TARGET_SAMPLE_RATE16000Частота дискретизации, Гц
AUDIO_TARGET_CHANNELS1Число каналов
AUDIO_TARGET_CODECpcm_s16leКодек нормализованного аудио
AUDIO_TARGET_FORMATwavКонтейнер; поддержана также согласованная пара FLAC/flac
AUDIO_FFMPEG_TIMEOUT_SECONDS900Таймаут FFmpeg
AUDIO_FFMPEG_EXECUTABLEffmpegПуть или имя бинарника

Лимит загрузки не равен лимиту провайдера распознавания. Например, допустимый для загрузки MP3 может после преобразования превысить предел NVIDIA в 16 МиБ WAV. При превышении локальной параллельности API возвращает 429 с Retry-After.

Распознавание и diarization

ПеременнаяПо умолчаниюНазначение
SPEECH_ENABLEDfalseВключить обработку речи
ASR_PROVIDERnemonemo, whisper или nvidia
DIARIZATION_PROVIDERnemonemo, pyannote или nvidia; облачный сценарий использует пару nvidia/nvidia
NVIDIA_API_KEYпустоКлюч NVIDIA cloud
NVIDIA_ASR_FUNCTION_ID71203149-d3b7-4460-8231-1be2543a1fcaID облачной функции речи
NVIDIA_LANGUAGE_CODEru-RUЯзык текущего облачного сценария
NVIDIA_MAX_AUDIO_BYTES16777216Максимум нормализованного аудио, не более 16 МиБ
NVIDIA_REQUEST_TIMEOUT_SECONDS180Таймаут облачного запроса
NEMO_ASR_MODELпустоЛокальная модель ASR NeMo
NEMO_DIARIZATION_MODELпустоЛокальный checkpoint Sortformer .nemo
NEMO_DEVICEcudacpu или cuda
WHISPER_MODELlarge-v3При включении замените абсолютным путём к локальной CTranslate2-модели
WHISPER_DEVICEcudacpu или cuda
WHISPER_COMPUTE_TYPEdefaultdefault, float16, float32, int8
PYANNOTE_MODELпустоАбсолютный путь к локальной community-1
PYANNOTE_DEVICEcudacpu или cuda
SPEECH_MAX_DURATION_SECONDS14400Общий предел длительности, 4 часа; предел провайдера может быть ниже
SPEECH_DIARIZATION_MAX_DECODED_BYTES536870912Лимит декодированного аудио для локальной diarization
SPEECH_MODEL_REVISION1Версия кэша; увеличивайте при замене весов/runtime

Локальные ML-провайдеры требуют отдельной установки зависимостей, весов и ресурсов. Базовый Docker-образ с лимитом API 1 ГиБ не является готовым GPU-окружением. Подробнее: Speech, NVIDIA cloud.

Канонизация стенограммы

ПеременнаяПо умолчаниюНазначение
TRANSCRIPT_CANONICALIZATION_ENABLEDfalseВключить этап
TRANSCRIPT_CANONICALIZATION_MODELпустоОтдельно заданная модель OpenAI
TRANSCRIPT_CANONICAL_LANGUAGEruЯзык обработанного текста
CANONICALIZATION_BATCH_MAX_SEGMENTS50Сегментов в пакете
CANONICALIZATION_BATCH_MAX_BYTES12000Бюджет UTF-8 JSON входа, включая контекст и ID; не токены
CANONICALIZATION_CONTEXT_SEGMENTS2Сегментов соседнего контекста
CANONICALIZATION_MAX_CONCURRENCY3Параллельные запросы
CANONICALIZATION_REQUEST_TIMEOUT_SECONDS60Таймаут запроса
CANONICALIZATION_MAX_ATTEMPTS3Максимум попыток
CANONICALIZATION_RETRY_BASE_SECONDS0.5База задержки повторов
CANONICALIZATION_MAX_OUTPUT_TOKENS4096Лимит ответа модели

Анализ совещания

ПеременнаяПо умолчаниюНазначение
MEETING_INTELLIGENCE_ENABLEDfalseВключить анализ
MEETING_SPEAKER_RESOLUTION_MODELпустоСопоставление speaker ID участникам
MEETING_EXTRACTION_MODELпустоИзвлечение поручений и решений
MEETING_RESOLVER_MODELпустоСогласование результатов извлечения
MEETING_SUMMARY_MODELпустоКраткое содержание
MEETING_REVIEW_MODELпустоПроверка результата
SPEAKER_RESOLUTION_MAX_CONTEXT_SEGMENTS60Контекст определения участников
MEETING_CHUNK_MAX_SEGMENTS50Сегментов в части стенограммы
MEETING_CHUNK_MAX_BYTES24000Бюджет части в байтах
MEETING_CHUNK_OVERLAP_SEGMENTS3Перекрытие частей
MEETING_AGENT_MAX_INPUT_BYTES120000Максимум входа агента
MEETING_MAX_OUTPUT_TOKENS8192Лимит ответа модели
AGENT_MAX_CONCURRENCY3Параллельные агентные вызовы
AGENT_MAX_REVIEW_ITERATIONS1Поддерживается одна итерация review
MEETING_AGENT_MAX_ATTEMPTS3Максимум попыток вызова
MEETING_AGENT_RETRY_BASE_SECONDS0.5База задержки повторов
MEETING_TRACING_ENABLEDtrueSDK tracing; в облачном примере выше явно выключен

Экспорт

ПеременнаяПо умолчаниюНазначение
PROTOCOL_TRANSCRIPT_TEXT_MODEcanonicalcanonical или 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_CHARACTERS2000000Лимит текста протокола
PROTOCOL_EXPORT_MAX_BYTES52428800Максимум файла экспорта, 50 МиБ

Шрифты установлены в Docker-образе. Для локального запуска задайте существующие пути к обоим TTF-файлам на своей машине.

Подготовленные настройки S3 и SMTP

Эти адаптеры не подключены к основному хранению записей и доставке напоминаний. Для стандартного запуска менять их не требуется.

ПеременнаяПо умолчаниюНазначение
S3_ENDPOINT_URLhttp://localhost:9000Endpoint S3; Compose заменяет на http://minio:9000
S3_ACCESS_KEYminioadminКлюч локального MinIO
S3_SECRET_KEYminioadminСекрет локального MinIO
S3_BUCKETprototypeBucket, создаётся отдельно
SMTP_HOSTlocalhostSMTP-сервер; Compose заменяет на mailpit
SMTP_PORT1025SMTP-порт
SMTP_FROM[email protected]Отправитель
SMTP_USERпустоЛогин, если требуется
SMTP_PASSWORDпустоПароль, если требуется
SMTP_STARTTLSfalseВключение STARTTLS

AGENT_TIMEOUT_SECONDS, SMTP-аутентификация и API_PROXY_TARGET не перечислены в текущем .env.example, но поддерживаются кодом. Vite получает API_PROXY_TARGET из окружения своего процесса; корневой .env автоматически ему не передаётся.

Работа с совещанием через API

Swagger — независимый от готовности frontend способ пройти весь сценарий. Используйте language_hint=ru для текущего NVIDIA pipeline.

  1. Создайте встречу: POST /api/v1/meetings.
  2. Загрузите аудио/видео: POST /api/v1/meetings/{id}/media, multipart-поле file.
  3. Запустите общий pipeline: POST /api/v1/meetings/{id}/process.
  4. Опрашивайте GET /api/v1/meetings/{id}/processing-run до completed или failed.
  5. Получите результат и скачайте 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/pdfPDF конкретной версии; также доступен docx

Повторный POST обработки может вернуть существующий запуск. После ошибки следующий POST создаёт новую попытку, используя сохранённые артефакты. "refresh": true создаёт новую попытку завершённого запуска, но не означает принудительный сброс всех кэшей. Не запускайте отдельные endpoints стадий параллельно с общим pipeline одной встречи.

Frontend содержит экраны встреч и поручений; подключение всех новых backend endpoints ведётся отдельно. Наличие API истории/напоминаний не означает наличие соответствующего экрана в текущей версии UI. Контракты: backend/UI, общая обработка.

Ежедневная разработка

ЗадачаКоманда
Первый запуск devmake setup-dev
Следующий запуск без сборкиmake dev
Только PostgreSQL и Redismake infra
Логи API, worker и frontendmake logs
Перезапуск worker после изменения Python-кодаmake restart-worker
Применить миграции к работающей БДmake migrate
Пересобрать после изменения зависимостей / Dockerfilemake 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 pipelinelanguage_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

Дополнительная документация

Подробные документы фиксируют также отдельные этапы разработки; для текущих параметров запуска сверяйтесь с этим README, .env.example, Compose и Swagger запущенной версии.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
14
Авторы
2
Файлы
256
Ветки
1

Авторы коммитов

daniyar 11Allyud 3

История коммитов

  • 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 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.