О проекте
Команда: SOCBrain
Кейс HackAlem.ai: Инновации — Самрук-Казына
Стадия: Рабочий MVP
Задача кейса: «Хаттама»: протокол и поручения по аудиозаписи совещания (каз./рус./смешанная речь)
Суть
Веб-система автопротоколирования: загрузка аудиозаписи совещания, распознавание речи и извлечение поручений (ответственный, срок, суть) LLM, с хранением совещаний и задач и коннекторами Zoom/Cisco CMS.
Как устроено
Аудио загружается через frontend (meetings.html) в FastAPI, где провайдер STT выбирается из подключений в БД: OpenAI Whisper API, NVIDIA Riva (whisper-large-v3 через NVCF) или self-hosted faster-whisper large-v3. Все три возвращают единый TranscriptResult с сегментами и таймкодами. Текст сохраняется в SQLite. Затем gpt-4o-mini в JSON-режиме с temperature=0 извлекает массив {assignee, task, deadline}, и промпт запрещает выдумывать поручения. Если подключение не настроено, API возвращает 400, а не молча берёт ключ из .env. Отдельно сделаны HTTP-приёмник записей с идемпотентной SQLite-очередью и STT-worker'ом, а также Docker-коннекторы Zoom (Cloud Recording, RTMS) и Cisco CMS (SIP-запись).
Ключевые решения
- STTProvider abstraction
- faster-whisper large-v3
- NVIDIA Riva gRPC
- JSON-mode extraction
- bcrypt auth + lockout
- SQLite ingest queue
- Zoom RTMS
- Cisco CMS SIP recording
Особенности
Три взаимозаменяемых STT-провайдера за одним интерфейсом, от облачного до полностью on-prem. Без настроенного подключения продуктовый API явно отказывает, а не тратит ключ разработчика из .env. Сделаны реальные коннекторы Zoom RTMS и Cisco CMS для автоматического сбора записей. Результат сверен с эталонными протоколами организаторов.
Стек
Python · FastAPI · uvicorn · SQLite · HTML/CSS/JS · Docker Compose · GitHub Actions
Модели
OpenAI Whisper-1 · NVIDIA Riva whisper-large-v3 · faster-whisper large-v3 · gpt-4o-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-c449499f-socbrain.
README
README.mdJinalys AI — автопротоколирование совещаний
Хакатонный проект по кейсу «Система автопротоколирования совещаний с фиксацией поручений».
Jinalys AI предназначен для секретарей совещаний, руководителей и ответственных за исполнение поручений. Ручное составление протоколов занимает время и создаёт риск потерять или неверно записать задачу, срок и ответственного. Цель — превращать запись совещания в текст и структурированный список поручений (ответственный, срок, суть) для последующего контроля.
Что уже проверено вживую, не только написано в коде: загрузка аудио через сайт → реальное распознавание речи (OpenAI Whisper API либо NVIDIA Riva, self-hosted faster-whisper — следующий шаг) → сохранение текста как совещания → извлечение поручений LLM'ом. Результат сверен с эталонными протоколами из Тех_задание/ — текст и список поручений совпадают почти дословно.
Что реализовано
| Компонент | Состояние | Где смотреть |
|---|---|---|
| Загрузка аудио на сайте → распознавание | Работает end-to-end, проверено на реальных записях | frontend/meetings.html → POST /api/transcribe |
| Извлечение поручений (LLM) | Работает, сверено с эталонным протоколом | POST /api/meetings/{id}/extract-tasks, tasks_extraction.py |
| Выбор модели распознавания/ИИ | Работает через интерфейс — добавление подключения, кнопка "Тест", "Сделать по умолчанию"; без настроенного подключения API честно отказывает (не молчит на .env) | frontend/settings.html (вкладка «Распознавание речи и ИИ»), ai_connections.py |
| STT-провайдеры | Три реализации одного интерфейса STTProvider: external_openai, external_nvidia (Riva/NVCF), local (self-hosted faster-whisper, large-v3) | backend/app/stt/ |
| Вход и журнал доступа | Реальный логин (bcrypt, блокировка после подбора) и логирование каждой попытки входа и действия | auth.py, access_log.py |
| CLI-распознавание | Тот же провайдерный слой, вызывается из консоли | app/transcribe.py |
| Приём записей от коннекторов | Авторизованная загрузка, идемпотентная SQLite-очередь, локальный STT-worker | backend/INGEST.md |
| Cisco CMS коннектор | Календарь CMS Scheduler, SIP-ассистент, запись и доставка в приёмник | integrations/cisco-connector/ |
| Zoom коннектор | Cloud Recording, календарь, RTMS live-аудио с именами участников | integrations/zoom-connector/ |
| Веб-интерфейс | Вход, дашборд, список/карточка совещаний, поручения, настройки (44 → 23 отобранных вкладки) | frontend/ |
| Материалы для проверки | 2 аудиозаписи + 2 эталонных протокола DOCX | Тех_задание/ |
Распознавание речи (STT)
Один интерфейс STTProvider (base.py) и три независимые реализации:
external_openai— OpenAI Whisper API (whisper-1), ответverbose_jsonс сегментами и таймкодами. Проверено на обеих тестовых записях, текст совпадает с эталоном.external_nvidia— NVIDIA Riva (whisper-large-v3) через NVCF (grpc.nvcf.nvidia.com). Требуетffmpegв PATH — Riva принимает только mono WAV/OPUS/FLAC, конвертация из исходного формата идёт перед отправкой. Проверено.local— self-hostedfaster-whisper(large-v3, CTranslate2). Работает полностью в своей инфраструктуре, без обращения к внешним сервисам — устанавливается отдельнымrequirements-local.txt.
Каждый провайдер возвращает одинаковую структуру (TranscriptResult: язык + список TranscriptSegment(start, end, text)), поэтому весь остальной код (сохранение, показ на фронте) не знает и не должен знать, какая именно модель распознавала речь.
Извлечение поручений (LLM)
tasks_extraction.py отправляет текст расшифровки в OpenAI Chat Completions (gpt-4o-mini, JSON-режим, temperature=0) с промптом, который просит вернуть строго JSON-массив {"assignee", "task", "deadline"} и явно запрещает придумывать поручения, которых нет в тексте. Проверено на обеих тестовых записях — извлечённые поручения (ответственный, срок, суть) сверены построчно с эталонными протоколами, совпадение почти полное (включая относительные сроки вроде "до пятницы", "к среде").
Совещания и поручения — хранение
SQLite-таблицы meetings (текст расшифровки, язык, дата) и tasks (ответственный, срок, суть, статус, ссылка на совещание) — meetings.py. При успешном /api/transcribe совещание сразу сохраняется и возвращает meeting_id, на который затем ссылается /api/meetings/{id}/extract-tasks.
Управление ИИ-подключениями
По образцу связки "список подключений → карточка → проверка → default", знакомой по подобным разделам корпоративных панелей настроек: подключения (тип, модель, ключ) хранятся в БД, добавляются и переключаются через интерфейс (ai_connections.py), без правки .env и перезапуска процесса.
POST /api/ai-connections— добавить подключение.POST /api/ai-connections/{id}/test— собрать провайдера с текущими настройками, поймать ошибку раньше реального запроса.POST /api/ai-connections/{id}/default— сделать активным.- Секрет (
api_key) никогда не отдаётся обратно вGET-ответах — только запись поверх.
Важно для ТЗ: продуктовый API (get_default_provider()) не имеет тихого фолбэка на .env — без настроенного подключения он честно возвращает 400. Фолбэк на .env есть только у CLI (get_default_provider_or_env_fallback()) — это инструмент разработчика, не часть продукта, иначе каждый пользователь молча расходовал бы личный ключ разработчика.
Авторизация и журнал доступа
auth.py: пароли хранятся как bcrypt-хеш, 5 неверных попыток подряд блокируют вход на 15 минут, ответ на "нет такого логина" и "неверный пароль" одинаковый (чтобы нельзя было перебором узнать список существующих учёток). Каждая попытка входа, каждое действие с ИИ-подключениями и каждая расшифровка пишутся в access_log (access_log.py) — время, кто, действие, исход, сообщение.
POST /api/login, POST /api/logout, GET /api/access-log — реализованы и проверены через API.
Веб-интерфейс
Пять страниц, единый стиль (frontend/css/style.css, ни одной внешней CSS-библиотеки):
login.html— экран входа.index.html— дашборд: метрики, разбивка по языку (ru/kk/mixed), последние совещания, ближайшие сроки.meetings.html— список совещаний плюс два живых блока: загрузка аудио с распознаванием и извлечение поручений после него.meeting.html— карточка одного совещания: саммари, таблица поручений, реплики, полная расшифровка.settings.html— 23 вкладки (из 44 разобранных и осознанно урезанных до нужных кейсу): Безопасность целиком, Пользователи и доступ целиком, плюс Почта/ИИ/Внешние системы/Вход/Тема/Версия. Вкладки «Распознавание речи и ИИ» и «Журнал доступа» — не макет, тянут и пишут данные черезfrontend/js/api.js.
Приём записей и коннекторы
backend/INGEST.md — HTTP-приёмник, принимающий готовые записи от внешних коннекторов (идемпотентная SQLite-очередь, локальный STT-worker). Zoom- и Cisco CMS-коннекторы (integrations/) — отдельные Docker-сервисы команды, описаны в «Настройки → Внешние системы».
Как это работает
flowchart TD
U["Браузер: meetings.html"] -->|"POST /api/transcribe (файл)"| API["FastAPI: app/main.py"]
API --> AC["ai_connections.get_default_provider()"]
AC -->|"есть подключение в БД"| P1["STTProvider (OpenAI / NVIDIA / local)"]
AC -->|"подключения нет"| ERR["400: настрой модель в Настройках"]
P1 --> M["meetings: сохранить текст"]
M -->|"POST /api/meetings/{id}/extract-tasks"| LLM["tasks_extraction.py: OpenAI chat completions"]
LLM --> T["tasks: сохранить поручения"]
T --> U2["Браузер: таблица поручений"]
Ключевой принцип, важный для ТЗ: нет тихого фолбэка на .env в продуктовом API. Если в «Настройках» не добавлена ни одна модель — /api/transcribe и /api/meetings/{id}/extract-tasks честно возвращают 400 с просьбой настроить модель, а не незаметно тратят ключ разработчика. Фолбэк на .env оставлен только у CLI-скрипта transcribe.py — это личный инструмент разработчика, не часть продукта.
Технологии
| Область | Технологии |
|---|---|
| Backend API | Python 3.12, FastAPI, uvicorn, SQLite |
| Авторизация | bcrypt, сессии в памяти процесса |
| STT | OpenAI Whisper API (whisper-1), NVIDIA Riva (whisper-large-v3 через NVCF), faster-whisper (self-hosted, large-v3) |
| Извлечение поручений | OpenAI Chat Completions (gpt-4o-mini), JSON-режим |
| Frontend | HTML, CSS, JavaScript (без сборки/фреймворка) |
| Коннекторы | Python, FastAPI, Docker Compose, SIP/FFmpeg (Cisco), официальный Zoom RTMS SDK |
Зависимости — в requirements.txt, requirements-local.txt (self-hosted STT).
Установка и запуск (для проверяющего)
1. Клонировать
git clone https://github.com/BAITC-Hacks/hack-c449499f-socbrain.git
cd hack-c449499f-socbrain
2. Поднять backend
Windows (cmd/PowerShell):
cd backend
py -3.12 -m venv .venv
.venv\Scripts\activate
python -m pip install -r requirements.txt
copy .env.example .env
macOS / Linux:
cd backend
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
cp -n .env.example .env
Завести первого пользователя (нужен для входа и журнала доступа; для сценария "загрузить и распознать" на сайте — не обязателен, эти ручки работают и без входа):
python seed.py artem "Артём Е." <свой пароль>
Запустить сервер:
uvicorn app.main:app --reload --port 8001
Если порт занят (WinError/Address already in use) — взять другой (--port 8002) и поменять const API_BASE в frontend/js/api.js на тот же номер.
3. Настроить модель распознавания
Открыть frontend/settings.html двойным кликом (это статический файл, отдельный сервер не нужен) → вкладка «Распознавание речи и ИИ» → форма внизу:
- Тип
external_openai, модельwhisper-1, свойOPENAI_API_KEY— самый быстрый путь для проверки. - Или
external_nvidia(нужен ключ с build.nvidia.com) — тоже облачный, для теста. local_faster_whisper— self-hosted, требуетpip install -r requirements-local.txtи GPU/CPU достаточной мощности; модель скачивается при первом запуске (несколько ГБ).
Добавленное подключение сразу становится активным — редактирования пока нет, только добавление новых и переключение "по умолчанию".
4. Распознать тестовую запись и извлечь поручения
Открыть frontend/meetings.html → блок «Загрузить и распознать»:
- Выбрать
Тех_задание/Совещание №1.mp3→ «Распознать» (может занять минуту). - После готовности — «Извлечь поручения».
- Сравнить результат с Протокол_совещания№1.docx — эталонный текст и список поручений (ответственный/срок/суть) для сверки.
- Повторить со второй записью и Протокол_совещания№2.docx.
Альтернатива — CLI без браузера
python -m app.transcribe "../Тех_задание/Совещание №1.mp3"
Использует то же подключение из БД, а если оно не настроено — .env (STT_PROVIDER=external_openai|external_nvidia|local). Результат сохраняется как <имя>.transcript.txt рядом с аудио.
Если что-то не завелось
| Симптом | Что проверить |
|---|---|
No module named app | Команда должна выполняться из каталога backend с активированным .venv |
WinError 10013 / Address already in use | Порт занят другим процессом (в т.ч. "зависшим" после Ctrl+C на Windows) — взять другой порт |
NetworkError на фронте | Backend не поднят, либо порт в frontend/js/api.js не совпадает с реальным |
400: Ни одна модель распознавания не настроена | Ожидаемо без подключения — добавить его в «Настройках» (шаг 3) |
401 Incorrect API key от OpenAI | Ключ неверный/просрочен — обнови в «Настройках» |
model_not_found | В поле «Модель» опечатка — для OpenAI нужно whisper-1, не whisper |
No module named 'faster_whisper' | Для local нужно pip install -r requirements-local.txt |
Данные для проверки
| Файл | Назначение |
|---|---|
| HackAlem AI_ Система автопротоколирования совещаний с фиксацией поручений.docx | Исходное ТЗ, критерии оценки |
| Совещание №1.mp3 / №2 | Тестовые записи |
| Протокол_совещания№1.docx / №2 | Эталонные протоколы для сверки текста и поручений |
Структура репозитория
backend/ Python API (FastAPI), STT-провайдеры, извлечение поручений, CLI
frontend/ Статический веб-интерфейс (HTML/CSS/JS, без сборки)
integrations/ Коннекторы Zoom и Cisco CMS (отдельные Docker-сервисы)
Тех_задание/ ТЗ, тестовые аудио и эталонные протоколы
.github/workflows/ CI для коннекторов
Подробнее по backend — backend/README.md и backend/INGEST.md.
Авторы коммитов
История коммитов
- 2026-09-23 17:52Update README.mdnetworkyeldar
- 2026-09-23 17:49Merge remote-tracking branch 'origin/main'socbarain-Artem
- 2026-09-23 17:49Expand README with implementation details, tighten jury-facing tonesocbarain-Artem
- 2026-09-23 17:48chore: empty commitnetworkyeldar
- 2026-09-23 17:45Allow pasting API keys and passwords directly in settingsKBM85
- 2026-09-23 17:42Rename product to Jinalys AI; add task extraction and reviewer READMEsocbarain-Artem
- 2026-09-23 17:22Merge pull request #1 from BAITC-Hacks/feat/cisco-cms-connectorKBM85
- 2026-09-23 17:17Add Zoom cloud recording, RTMS and calendar connectorKBM85
Все коммиты (28)
- 2026-09-23 17:13Add Cisco CMS connector, SIP recording assistant and local ingestionKBM85
- 2026-09-23 17:10Fix README: remove merge conflict markers, describe the working prototypeKBM85
- 2026-09-23 17:09Merge remote-tracking branch 'origin/main' into feature/pipeline-dockerKBM85
- 2026-09-23 17:08Make settings functional: theme, mail, AI, integrations, processingKBM85
- 2026-09-23 17:07docs: document current SOCBrain prototype and jury setup in Russiannetworkyeldar
- 2026-09-23 16:56Add NVIDIA connection template and LLM check to AI settingsKBM85
- 2026-09-23 16:55docs: link backend setup instructions in READMEnetworkyeldar
- 2026-09-23 16:42Merge remote-tracking branch 'origin/main' into feature/pipeline-dockerKBM85
- 2026-09-23 16:41Add end-to-end meeting minutes pipeline, API and Docker setupKBM85
- 2026-09-23 16:32docs: add repository structure to READMEnetworkyeldar
- 2026-09-23 16:02Merge remote-tracking branch 'origin/main'socbarain-Artem
- 2026-09-23 16:01Expand settings to cover Security and Users&Access in fullsocbarain-Artem
- 2026-09-23 16:00docs: describe SOCBrain meeting minutes MVPnetworkyeldar
- 2026-09-23 15:57Add settings UI shell and OpenAI-backed transcription backendsocbarain-Artem
- 2026-09-23 15:05Merge branch 'main' of https://github.com/BAITC-Hacks/hack-c449499f-socbrainsocbarain-Artem
- 2026-09-23 15:04Add temporary static frontend skeletonsocbarain-Artem
- 2026-09-23 14:00docs: add initial project next stepsKBM85
- 2026-09-23 13:59Merge remote-tracking branch 'origin/main'socbarain-Artem
- 2026-09-23 13:58docs: initialize SOCBrain project READMEnetworkyeldar
- 2026-09-23 13:58Add task assignment and reference materialssocbarain-Artem
Структура репозитория (107 файлов)
.github/workflows/cisco-connector.yml .github/workflows/zoom-connector.yml .gitignore README.md backend/.dockerignore backend/.env.example backend/.env.ingest.example backend/.gitignore backend/Dockerfile.ingest backend/INGEST.md backend/README.md backend/app/__init__.py backend/app/access_log.py backend/app/ai_connections.py backend/app/auth.py backend/app/db.py backend/app/ingest_store.py backend/app/ingest_worker.py backend/app/main.py backend/app/meetings.py backend/app/receiver.py backend/app/stt/__init__.py backend/app/stt/base.py backend/app/stt/external_nvidia_riva.py backend/app/stt/external_openai.py backend/app/stt/local_faster_whisper.py backend/app/tasks_extraction.py backend/app/transcribe.py backend/compose.ingest.yml backend/requirements-ingest.txt backend/requirements-local.txt backend/requirements.txt backend/scripts/init_ingest.py backend/seed.py backend/tests/test_receiver.py frontend/css/style.css frontend/index.html frontend/js/api.js frontend/js/app.js frontend/login.html frontend/meeting.html frontend/meetings.html frontend/settings.html frontend/tasks.html integrations/cisco-connector/.dockerignore integrations/cisco-connector/.env.example integrations/cisco-connector/.gitattributes integrations/cisco-connector/.gitignore integrations/cisco-connector/Dockerfile integrations/cisco-connector/README.md integrations/cisco-connector/certs/README.md integrations/cisco-connector/compose.yml integrations/cisco-connector/docs/API.md integrations/cisco-connector/docs/APP_INTEGRATION.md integrations/cisco-connector/docs/AUTOMATION.md integrations/cisco-connector/docs/CISCO_SETUP.md integrations/cisco-connector/docs/CONFIGURATION.md integrations/cisco-connector/docs/LIVE_TRANSCRIPTION.md integrations/cisco-connector/docs/SOURCES.md integrations/cisco-connector/docs/TEST_LAB.md integrations/cisco-connector/meeting_gateway/__init__.py integrations/cisco-connector/meeting_gateway/api.py integrations/cisco-connector/meeting_gateway/automation.py integrations/cisco-connector/meeting_gateway/automation_config.py integrations/cisco-connector/meeting_gateway/check.py integrations/cisco-connector/meeting_gateway/config.py integrations/cisco-connector/meeting_gateway/jobs.py integrations/cisco-connector/meeting_gateway/providers.py integrations/cisco-connector/meeting_gateway/scheduler.py integrations/cisco-connector/meeting_gateway/sip_record.py integrations/cisco-connector/meeting_gateway/worker_health.py integrations/cisco-connector/requirements-dev.txt integrations/cisco-connector/requirements.txt integrations/cisco-connector/scripts/init_config.py integrations/cisco-connector/tests/sip_smoke.py integrations/cisco-connector/tests/test_connector.py integrations/zoom-connector/.dockerignore integrations/zoom-connector/.env.example integrations/zoom-connector/.gitignore integrations/zoom-connector/Dockerfile integrations/zoom-connector/README.md integrations/zoom-connector/compose.yml integrations/zoom-connector/docs/AUTOMATION.md integrations/zoom-connector/docs/CALENDAR.md integrations/zoom-connector/docs/SOURCES.md integrations/zoom-connector/docs/ZOOM_SETUP.md integrations/zoom-connector/requirements-dev.txt integrations/zoom-connector/requirements-rtms.txt integrations/zoom-connector/requirements.txt integrations/zoom-connector/scripts/init_config.py integrations/zoom-connector/tests/test_zoom_connector.py integrations/zoom-connector/zoom_connector/__init__.py integrations/zoom-connector/zoom_connector/api.py integrations/zoom-connector/zoom_connector/config.py integrations/zoom-connector/zoom_connector/delivery.py integrations/zoom-connector/zoom_connector/events.py integrations/zoom-connector/zoom_connector/rtms_worker.py integrations/zoom-connector/zoom_connector/security.py integrations/zoom-connector/zoom_connector/store.py integrations/zoom-connector/zoom_connector/worker.py integrations/zoom-connector/zoom_connector/zoom_api.py Тех_задание/HackAlem AI_ Система автопротоколирования совещаний с фиксацией поручений.docx Тех_задание/Протокол_совещания№1.docx Тех_задание/Протокол_совещания№2.docx Тех_задание/Совещание №1.mp3 Тех_задание/Совещание №1.transcript.txt Тех_задание/Совещание №2.mp3
Ветки (2)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.