О проекте
Команда: Exit 1
Кейс HackAlem.ai: Инновации — Самрук-Казына
Стадия: Рабочий MVP
Задача кейса: «Хаттама»: протокол и поручения по аудиозаписи совещания (каз./рус./смешанная речь)
Суть
Система протоколирования совещаний: загрузка аудио, асинхронная обработка, транскрипт с диаризацией, саммари, поручения с исполнителями и сроками, ручная правка, подтверждение и экспорт в DOCX.
Как устроено
Frontend на React и Vite загружает WAV, MP3 или M4A. FastAPI-бэкенд сохраняет файл и ставит задачу в очередь в PostgreSQL. Отдельный worker отправляет запись в AI-сервис в Docker, где работает цепочка faster-whisper → pyannote.audio → Qwen через Ollama. Поручения и сроки из естественного языка приводятся к датам. Каждое поручение связано с исходным фрагментом записи. Для разработки без GPU есть mock-режимы.
Ключевые решения
- faster-whisper ASR
- pyannote.audio diarization
- очередь задач в PostgreSQL
- нормализация дат из текста
- сопоставление спикеров с участниками
- mock-режимы
Особенности
Продуманная продакшн-архитектура: API и worker разделены, очередь в PostgreSQL, есть три режима AI (mock, http+mock, real) и инструкция, как разнести компоненты на два ноутбука. Весь код загружен тремя коммитами за 13 минут до конца.
Стек
React 19 · TypeScript · Vite · Python · FastAPI · PostgreSQL · Alembic · SQLAlchemy · Docker Compose · Ollama · Nginx
Модели
Whisper (faster-whisper) · pyannote.audio · Qwen via Ollama
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-bdffe61d-exit-1.
README
README.mdAlemProtocol
Локальная AI-система, которая превращает запись совещания в готовый протокол с транскриптом, кратким содержанием, поручениями, исполнителями и сроками.
AlemProtocol автоматизирует протоколирование русскоязычных, казахскоязычных и смешанных совещаний. Пользователь загружает аудиозапись, backend ставит её в очередь, AI-сервис локально распознаёт речь и формирует результат, после чего протокол можно проверить, отредактировать, подтвердить и скачать в DOCX.
Возможности
- загрузка WAV, MP3 и M4A с названием, датой и списком участников;
- асинхронная обработка записи отдельным worker-процессом;
- распознавание речи через
faster-whisper; - разделение реплик по спикерам через
pyannote.audio; - саммари и извлечение поручений локальной моделью Qwen через Ollama;
- определение исполнителей и преобразование сроков из естественного языка в даты;
- переход от поручения к исходному фрагменту записи;
- сопоставление спикеров с участниками и ручная правка поручений;
- подтверждение протокола и экспорт в DOCX;
- mock-режимы для разработки без GPU и ML-моделей;
- полностью локальная AI-обработка без передачи аудио во внешние API.
Состав проекта
| Компонент | Каталог | Назначение | Порт по умолчанию |
|---|---|---|---|
| Frontend | frontend/ | React, TypeScript, Vite | 5173 |
| Backend API | backend/ | FastAPI, загрузка файлов, REST API | 8080 |
| Backend worker | backend/ | Очередь и отправка записей в AI | отдельный процесс |
| AI-сервис | ai-service/ | ASR, диаризация, LLM, PDF/DOCX | 8000 |
| База данных | PostgreSQL | встречи, участники, задания и транскрипты | 5432 |
Архитектура
Браузер
│
▼
Frontend (React/Vite или static hosting)
│ /api/*
▼
Reverse proxy ───────────────► Backend API :8080
│ │
│ ├──► PostgreSQL
│ └──► persistent audio storage
▼
очередь в PostgreSQL
│
▼
Backend worker
│ HTTP + audio
▼
AI service :8000
│
faster-whisper → pyannote → Qwen/Ollama
API быстро сохраняет файл и создаёт задачу. Worker независимо забирает задачи из PostgreSQL, отправляет записи в AI-сервис и сохраняет результат. Поэтому для полной обработки должны работать оба backend-процесса: API и worker.
Быстрый локальный запуск
Для запуска всей системы без ML-моделей используйте встроенный mock backend. Понадобятся:
- Node.js
20.19+или22.12+и npm; - Python
3.11или3.12; - PostgreSQL;
- Git.
1. Клонирование
git clone https://github.com/BAITC-Hacks/hack-bdffe61d-exit-1.git
cd hack-bdffe61d-exit-1
2. PostgreSQL и backend
Создайте базу и пользователя PostgreSQL, затем подготовьте окружение:
cd backend
python -m venv .venv
# Linux/macOS
source .venv/bin/activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
cp .env.example .env # Windows: Copy-Item .env.example .env
Для локальной проверки без отдельного AI-сервиса укажите в backend/.env:
DATABASE_URL=postgresql+psycopg://hackalem:[email protected]:5432/hackalem
STORAGE_DIR=C:/hackalem-data
MAX_UPLOAD_MB=200
AI_BASE_URL=http://127.0.0.1:8000
AI_MODE=mock
AI_INTERNAL_TOKEN=
AI_TIMEOUT_SECONDS=3600
FRONTEND_ORIGIN=http://localhost:5173
Создайте каталог из STORAGE_DIR, примените миграции и запустите API:
python -m alembic upgrade head
python -m uvicorn app.main:app --host 0.0.0.0 --port 8080
Во втором терминале, с тем же виртуальным окружением и из каталога backend, запустите worker:
python -m app.worker
Проверка backend:
- Swagger UI: http://localhost:8080/docs;
- API healthcheck: http://localhost:8080/health;
- готовность PostgreSQL: http://localhost:8080/ready.
3. Frontend
В третьем терминале:
cd frontend
npm ci
cp .env.example .env # Windows: Copy-Item .env.example .env
npm run dev
Откройте http://localhost:5173. Frontend обращается к /api, а Vite
перенаправляет запросы на BACKEND_URL=http://127.0.0.1:8080 и удаляет префикс /api.
Проверить прокси можно по адресу http://localhost:5173/api/ready.
Подключение реального AI
Сначала запустите AI-сервис в mock-режиме, чтобы проверить транспорт между компонентами, затем
подготовьте модели и переключите его в real.
cd ai-service
cp .env.example .env # Windows: Copy-Item .env.example .env
docker compose up --build -d
Проверка: http://localhost:8000/health.
В backend/.env задайте:
AI_MODE=http
AI_BASE_URL=http://127.0.0.1:8000
AI_INTERNAL_TOKEN=replace-with-a-long-random-token
В ai-service/.env должен быть тот же токен:
AI_MODE=real
INTERNAL_TOKEN=replace-with-a-long-random-token
После изменения .env перезапустите AI-сервис, backend API и worker. Подготовка Whisper,
pyannote и Ollama, offline-режим и GPU-запуск описаны в
ai-service/README.md.
Для запуска компонентов на разных компьютерах используйте
CONNECT_TWO_LAPTOPS.md.
Режимы AI
Backend AI_MODE | AI-сервис AI_MODE | Что происходит |
|---|---|---|
mock | любой | Backend возвращает встроенный тестовый результат, HTTP-запроса нет |
http | mock | Полный HTTP-путь с тестовым ответом AI-сервиса |
http | real | Настоящее распознавание и анализ локальными моделями |
Переменные окружения
Frontend
| Переменная | Пример | Назначение |
|---|---|---|
VITE_USE_MOCK | false | Использовать реальный backend или UI-заглушку |
VITE_API_BASE_URL | /api | Публичный путь к backend API |
VITE_MAX_UPLOAD_MB | 200 | Ограничение файла в интерфейсе |
BACKEND_URL | http://127.0.0.1:8080 | Цель Vite proxy в dev/preview |
VITE_* встраиваются во frontend во время сборки. BACKEND_URL нужен только Vite dev/preview и
не используется статическими файлами после production build.
Backend
| Переменная | Пример | Назначение |
|---|---|---|
DATABASE_URL | postgresql+psycopg://... | Подключение к PostgreSQL |
STORAGE_DIR | /var/lib/alemprotocol/audio | Постоянное хранилище аудио |
MAX_UPLOAD_MB | 200 | Максимальный размер записи |
AI_BASE_URL | http://ai-host:8000 | Базовый URL AI-сервиса |
AI_MODE | http | mock, http или совместимый alias real |
AI_INTERNAL_TOKEN | секрет | Токен для AI-сервиса |
AI_TIMEOUT_SECONDS | 3600 | Таймаут долгой AI-обработки |
FRONTEND_ORIGIN | https://alem.example | Разрешённый browser origin для CORS |
Полные шаблоны находятся в frontend/.env.example,
backend/.env.example и
ai-service/.env.example.
Production deployment
Рекомендуемая схема
- Frontend: статическая сборка на Nginx, CDN, S3-compatible hosting, Netlify или Vercel;
- Backend API + worker: Linux VM или PaaS с постоянными процессами;
- PostgreSQL: managed database или отдельный сервер с резервным копированием;
- Audio storage: persistent volume, доступный одновременно API и worker;
- AI-сервис: отдельная GPU/CPU VM с Docker, локальными моделями и постоянными volumes;
- Сеть: backend и AI соединяются по private network или VPN, а не через публичный порт.
Serverless-функции без фоновых процессов и постоянного диска для backend не подходят: worker должен непрерывно опрашивать очередь, а API и worker должны видеть одни и те же аудиофайлы.
1. Сборка frontend
Создайте frontend/.env.production:
VITE_USE_MOCK=false
VITE_API_BASE_URL=/api
VITE_MAX_UPLOAD_MB=200
Соберите приложение:
cd frontend
npm ci
npm run build
Публиковать нужно содержимое frontend/dist. Веб-сервер должен:
- отдавать
index.htmlдля неизвестных frontend-маршрутов, включая/meetings/:id; - проксировать
/api/*в backend с удалением префикса/api; - разрешать запросы размером не меньше
MAX_UPLOAD_MB; - работать по HTTPS.
Пример Nginx:
server {
listen 80;
server_name alem.example;
root /var/www/alemprotocol;
index index.html;
client_max_body_size 200m;
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
}
location / {
try_files $uri $uri/ /index.html;
}
}
TLS можно завершать на Nginx, load balancer или CDN. Если frontend и API размещены на разных
доменах, задайте полный VITE_API_BASE_URL=https://api.example.com до сборки и укажите точный URL
frontend в FRONTEND_ORIGIN backend.
2. Развёртывание backend
На сервере создайте виртуальное окружение, установите зависимости и сохраните production .env
в backend/.env:
cd /opt/alemprotocol/backend
python3.12 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m alembic upgrade head
Запускайте два независимых долгоживущих процесса через systemd, Supervisor или возможности PaaS:
# Web process
.venv/bin/python -m uvicorn app.main:app --host 127.0.0.1 --port 8080
# Worker process
.venv/bin/python -m app.worker
Миграции выполняются один раз перед запуском новой версии. STORAGE_DIR должен находиться на
постоянном диске; при разнесении API и worker по разным узлам потребуется shared storage.
3. Развёртывание AI-сервиса
AI лучше размещать на отдельном узле. Подготовьте модели по инструкции AI-сервиса, задайте
AI_MODE=real, включите offline-флаги и запустите Compose:
cd /opt/alemprotocol/ai-service
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up --build -d
curl http://127.0.0.1:8000/health
Для CPU уберите docker-compose.gpu.yml. Каталоги моделей и volume Ollama должны сохраняться
между релизами. Порт 8000 разрешайте только backend-хосту. Порт Ollama 11434 не должен быть
доступен из интернета.
4. Порядок релиза и healthchecks
- проверить доступность PostgreSQL и persistent storage;
- применить Alembic-миграции;
- запустить AI-сервис и проверить
GET /health; - запустить backend API и worker;
- проверить backend
GET /healthиGET /ready; - опубликовать frontend и проверить
GET /api/readyчерез reverse proxy; - выполнить сквозной тест с тестовой записью.
Проверка проекта
Frontend
cd frontend
npm ci
npm run lint
npm run build
npm run smoke
npm run test:connected проверяет реальный путь frontend → backend → worker → AI mock, включая
аудио после перезагрузки, редактирование, подтверждение и DOCX. Для него все сервисы должны быть
запущены, backend должен использовать AI_MODE=http, а AI-сервис — AI_MODE=mock.
Backend
cd backend
python -m pip install -r requirements-dev.txt
python -m pytest -q tests
python scripts/smoke_e2e.py --audio "/path/to/meeting.wav"
AI-сервис
cd ai-service
python -m pip install -r requirements-dev.txt
pytest
ruff check app tests scripts
Структура репозитория
.
├── frontend/ # React UI и browser-тесты
├── backend/
│ ├── app/api/ # REST endpoints
│ ├── app/models/ # SQLAlchemy models
│ ├── app/services/ # AI-клиент и DOCX export
│ ├── migrations/ # Alembic migrations
│ ├── scripts/ # backend E2E smoke-test
│ └── tests/ # integration tests
├── ai-service/
│ ├── app/pipeline/ # ASR, diarization, LLM и сроки
│ ├── scripts/ # модели и test audio
│ └── tests/ # unit и API-тесты
└── CONNECT_TWO_LAPTOPS.md # запуск компонентов на разных устройствах
Безопасность и данные
- не добавляйте
.env, реальные записи, модели, базы и generated documents в Git; - используйте разные длинные случайные значения
INTERNAL_TOKEN/AI_INTERNAL_TOKENдля каждого окружения; - не публикуйте AI-сервис и Ollama напрямую в интернете;
- ограничьте доступ к PostgreSQL и storage на уровне сети и прав файловой системы;
- включите HTTPS на публичной точке входа и регулярно создавайте backup PostgreSQL и audio storage;
- для закрытого контура заранее скачайте модели и оставьте Hugging Face в offline-режиме.
Проект разработан командой Exit 1 для BAITC Hacks.
Авторы коммитов
История коммитов
- 2026-09-23 17:56feat: connect frontend and backendzalewko-droid
- 2026-09-23 17:46docs: add comprehensive project READMEzalewko-droid
- 2026-09-23 17:43Add frontend and AI servicezalewko-droid
Структура репозитория (110 файлов)
.gitignore CONNECT_TWO_LAPTOPS.md README.md ai-service/.dockerignore ai-service/.env.example ai-service/.gitignore ai-service/Dockerfile ai-service/README.md ai-service/app/__init__.py ai-service/app/audio.py ai-service/app/config.py ai-service/app/errors.py ai-service/app/exporters.py ai-service/app/main.py ai-service/app/pipeline/__init__.py ai-service/app/pipeline/asr.py ai-service/app/pipeline/dates.py ai-service/app/pipeline/diarization.py ai-service/app/pipeline/llm.py ai-service/app/pipeline/memory.py ai-service/app/pipeline/merge.py ai-service/app/pipeline/mock.py ai-service/app/pipeline/service.py ai-service/app/pipeline/speakers.py ai-service/app/schemas.py ai-service/app/timing.py ai-service/docker-compose.gpu.yml ai-service/docker-compose.yml ai-service/pyproject.toml ai-service/requirements-dev.txt ai-service/requirements-ml.txt ai-service/requirements.txt ai-service/samples/README.md ai-service/scripts/download_models.py ai-service/scripts/generate_e2e_sample.ps1 ai-service/scripts/generate_e2e_sample_espeak.sh ai-service/scripts/generate_sample.py ai-service/tests/test_api.py ai-service/tests/test_dates.py ai-service/tests/test_merge.py ai-service/tests/test_pipeline.py backend/.env.example backend/alembic.ini backend/app/__init__.py backend/app/api/__init__.py backend/app/api/meetings.py backend/app/check_ai.py backend/app/config.py backend/app/db.py backend/app/main.py backend/app/models/__init__.py backend/app/models/action_item.py backend/app/models/base.py backend/app/models/job.py backend/app/models/meeting.py backend/app/models/participant.py backend/app/models/segment.py backend/app/models/speaker.py backend/app/schemas/__init__.py backend/app/schemas/meeting.py backend/app/schemas/meeting_actions.py backend/app/services/__init__.py backend/app/services/ai_processor.py backend/app/services/docx_export.py backend/app/services/remote_ai.py backend/app/worker.py backend/migrations/env.py backend/migrations/script.py.mako backend/migrations/versions/.gitkeep backend/migrations/versions/343522380fa7_initial_domain_schema.py backend/requirements-dev.txt backend/requirements.txt backend/scripts/smoke_e2e.py backend/tests/conftest.py backend/tests/test_ai_integration.py env frontend/.env.example frontend/.gitignore frontend/.oxlintrc.json frontend/README.md frontend/index.html frontend/package-lock.json frontend/package.json frontend/public/favicon.svg frontend/public/icons.svg frontend/src/App.css frontend/src/App.tsx frontend/src/api/meetings.ts frontend/src/assets/hero.png frontend/src/assets/react.svg frontend/src/assets/vite.svg frontend/src/components/AudioPlayer.tsx frontend/src/components/ProcessingStatus.tsx frontend/src/components/Summary.tsx frontend/src/components/TasksTable.tsx frontend/src/components/Transcript.tsx frontend/src/components/UploadForm.tsx frontend/src/index.css frontend/src/main.tsx frontend/src/mocks/meeting.json frontend/src/pages/HomePage.tsx frontend/src/pages/MeetingPage.tsx frontend/src/types/meeting.ts frontend/src/utils/format.ts frontend/tests/connected.mjs frontend/tests/smoke.mjs frontend/tsconfig.app.json frontend/tsconfig.json frontend/tsconfig.node.json frontend/vite.config.ts
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.