О проекте
Команда: DBK team
Кейс HackAlem.ai: Инновации — Самрук-Казына
Стадия: Доведённый продукт
Задача кейса: «Хаттама»: протокол и поручения по аудиозаписи совещания (каз./рус./смешанная речь)
Суть
Развёрнутый сервис автопротокола: запись или загрузка аудио, собственные STT и диаризация, извлечение поручений и саммари на своей LLM, перевод протокола на kk/ru/en, контроль сроков с email-напоминаниями, экспорт в DOCX и PDF.
Как устроено
Фронт на Next.js кладёт запись в MinIO и отправляет событие в Kafka. Обработчик (Kafka-консьюмер) распознаёт речь через faster-whisper/CTranslate2 по двум маршрутам: общий для ru/en и собственная дообученная казахская whisper-turbo-ksc2. Диаризация на nvidia diar_streaming_sortformer_4spk-v2 и titanet_large, каждое слово приписывается говорящему по середине слова. Склеенный транскрипт уходит в Qwen3.8-27B-FP8 на своём vLLM, который выделяет поручения и саммари. Субтитры Zoom .vtt дают настоящие имена говорящих, поручения хранятся в MinIO, а уведомления отправляются через HTTP-почту.
Ключевые решения
- faster-whisper CTranslate2
- fine-tuned Whisper для казахского (KSC2)
- Sortformer diarization
- TitaNet speaker embeddings
- word-midpoint speaker alignment
- Kafka event pipeline
- vLLM self-hosting
Метрики
Шала-казахский CER 0.0511 на публичном корпусе; казахский CER 0.000 на замере
Особенности
Полностью свой речевой стек в закрытом контуре: дообученный казахский Whisper, Sortformer-диаризация, собственный vLLM. Замерен CER на шала-казахском. Зафиксировано, что Zoom VTT даёт имена ответственных. Рабочая демо-версия на app.aibots.kz.
Стек
Python · Next.js · Tailwind v4 · Apache Kafka · MinIO · Docker Compose · Traefik · Caddy · Ansible · ffmpeg
Модели
Whisper (whisper-v6-ct2, whisper-turbo-ksc2-ct2) · nvidia/diar_streaming_sortformer_4spk-v2 · titanet_large · Qwen3.8-27B-FP8 (vLLM)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-47bd9c8d-dbk-team.
README
README.mdAI Meeting Copilot — автопротоколирование совещаний с фиксацией поручений
Попробовать без установки: https://app.aibots.kz
Загрузите запись совещания или запишите её прямо в браузере — через минуту получите протокол с говорящими, поручениями и саммари, готовый к выгрузке в DOCX или PDF. Разворачивать ничего не нужно, все службы уже подняты.
Руководство пользователя со скриншотами →
Краткое описание
Протоколы совещаний ведутся секретарями вручную: это долго, а поручения, сроки и ответственные теряются или искажаются. Система принимает запись совещания и возвращает готовый протокол: транскрипт с разделением по говорящим, структурированный список поручений (кто, что, к какому сроку) и краткое саммари.
Для кого: секретари совещаний и управленческие сотрудники, которые контролируют исполнительскую дисциплину.
Кейс: docs/TASK/task.md. Проектное решение с разбором предпосылок и
границ: docs/designs/meeting-protocol-agent.md.
Что реализовано
| Требование кейса | Где закрыто |
|---|---|
| 1. Распознавание речи участников | speech_stack/stt, развёрнуто на stt.aibots.kz |
| 2. Русский язык | маршрут general:whisper-v6-ct2 |
| 3. Казахский язык | маршрут ksc2:whisper-turbo-ksc2-ct2, CER 0.000 на замере |
| 4. Шала-казахский | language=auto; CER 0.0511 на публичном корпусе с человеческой расшифровкой, замер |
| 5. Поручения с ответственным и сроком | meeting-copilot-container/summarize_transcript.py, модель на vllm.aibots.kz |
| 6. Диаризация с привязкой к человеку | speech_stack/diarization + склейка merge_transcript.py; с субтитрами Zoom — имена вместо ярлыков |
| 7. Экспорт протокола в файл | front/lib/export-docx.ts, front/components/printable-protocol.tsx |
Из раздела «Дополнительно»
| Пункт | Состояние |
|---|---|
| Развёртывание в закрытом контуре | распознавание, диаризация и языковая модель свои, исходники в репозитории |
| Дашборд статусов поручений | front/components/commitments-dashboard.tsx — в работе, просрочено, выполнено |
| Автоматическая рассылка ответственным | front/lib/notifications.ts — напоминание за 3 дня до срока и при просрочке; транспорт настраивается, без настройки письма копятся в журнале |
| Классификация по срочности и направлению | колонка в таблице поручений: «Срочно · Договорная работа» |
| Голосовая идентификация по тембру | служба развёрнута (/v1/audio/identify, /v1/speakers), образцов не зарегистрировано |
| Интеграция с СЭД | не делалась, вне обязательной части |
| Рассылка выдержек ответственным | не делалась |
Сверх кейса: AI-перевод протокола. Протокол доступен на трёх языках — русском
(оригинал), казахском и английском. На все три языка переводится и саммари, и
таблица поручений: у поручения переводятся текст, цитата, срок словами и классификация,
а имена людей, названия организаций, даты ГГГГ-ММ-ДД и идентификаторы остаются как есть.
Разметка саммари — заголовки, списки, выделение — сохраняется, так что переведённая версия
читается так же, как исходная.
Перевод считается на своей модели (vllm.aibots.kz), поэтому текст совещания не покидает
контур и при переводе. Переключатель языка стоит в заголовке протокола, выбранный язык
сохраняется между обновлениями страницы, а перевод одного совещания считается один раз:
результат лежит рядом с исходным протоколом (result.<язык>.json) и в следующий раз
показывается сразу, без обращения к модели. Транскрипт не переводится: это дословная
запись сказанного, и переводить её значит подменять сказанное.
Сценарий 2 — контроль сроков и напоминания
Поручения всех совещаний собираются в общий список и переживают перезапуск: хранятся
в MinIO (results/commitments/index.json), а не в памяти процесса. Контроль сроков
измеряется неделями, и список, живущий до первого рестарта, такой задачи не решает.
Вкладка «Контроль поручений» показывает срок, ответственного, статус и остаток дней. Просроченные идут сверху с красной подложкой. Рядом с каждым поручением задаётся почта ответственного — в записи совещания адресов нет, поэтому это единственное, что вводится руками. Кнопка «выполнено» закрывает поручение.
Кнопка «Проверить сроки» запускает рассылку: напоминание уходит за три дня до срока и отдельно при просрочке. Повторно одно и то же не отправляется — отметка хранится в самом поручении. Тот же вызов годится для внешнего планировщика:
curl -X POST https://app.aibots.kz/api/commitments/notify
Настройка почты. Отправка идёт по HTTP, а не по SMTP: подходит любой провайдер, принимающий POST (Resend, Mailgun, Postmark, MailChannels), и это не тянет зависимостей в образ. Три переменные окружения:
MAIL_API_URL=https://api.resend.com/emails
MAIL_API_KEY=...
[email protected]
Переменные не заданы — письма складываются в журнал (results/commitments/outbox.json)
с пометкой «не отправлено: почта не настроена», и в интерфейсе видно, кому и что ушло бы.
Это честное состояние, а не тишина. В развёрнутой демо-версии почта не настроена.
Как пользоваться
Откройте https://app.aibots.kz. Подробно, с экранами — в руководстве пользователя.
Запись совещания прямо в браузере. Нажмите «Начать запись» — участникам проиграется предупреждение о том, что ведётся запись и транскрибация с помощью ИИ, сначала на казахском, затем на русском. По кнопке «Остановить» запись уходит в обработку.
Или загрузите готовый файл. Перетащите запись в зону загрузки: mp3, m4a, mp4, wav, ogg, flac, webm.
Приложите субтитры Zoom, если они есть. После выбора записи появится строка «Приложить .vtt». Субтитры необязательны, но меняют результат заметно: из них берутся настоящие имена участников, и в поручениях вместо «Говорящий 2» стоит фамилия ответственного. Без субтитров говорящие различаются по голосу и остаются безымянными, а различить модель умеет не больше четырёх.
Через минуту откроется протокол: транскрипт с говорящими и таймкодами, таблица поручений с ответственным, сроком и классификацией по срочности, саммари встречи. Кнопки сверху выгружают протокол в DOCX и PDF.
Вкладка «Контроль поручений» собирает поручения всех совещаний и раскладывает их по статусу: в работе, просрочено, выполнено. Впишите почту ответственного в строке поручения и нажмите «Проверить сроки» — система отправит напоминания по тем, у кого срок на подходе или уже прошёл. Это Сценарий 2 из кейса.
Прогресс не теряется при обновлении страницы. Браузер помнит, какая встреча обрабатывается, и после F5 возвращается на тот же экран, а таймер продолжает считать от начала обработки, а не с нуля.
Как работает
- Секретарь загружает файл или включает запись с микрофона прямо в интерфейсе.
К записи можно приложить субтитры Zoom — тогда имена говорящих берутся из них.
Перед началом проигрывается голосовое предупреждение участникам о том, что ведётся
запись и транскрибация с помощью ИИ — на казахском и русском
(
front/public/audio-warnings/). Запись попадает в MinIO. - В Kafka уходит
RecognitionRequestс идентификатором сообщения и ссылкой на папку. - Обработчик забирает файлы, конвертирует в MP3 и распознаёт речь целиком, с пословными метками времени.
- Та же запись отдельно диаризуется. Каждое слово приписывается тому, кто говорил в его середине: на стыке реплик начало слова часто попадает в хвост предыдущего говорящего.
- Склеенный транскрипт уходит в LLM, которая выделяет поручения с ответственным и сроком и собирает саммари.
transcript.jsonиsummary.mdвозвращаются в ту же папку MinIO, в Kafka уходитRecognitionResponse. Интерфейс показывает протокол и отдаёт файл.
Технологии
| Слой | Что используется |
|---|---|
| Распознавание речи | faster-whisper на CTranslate2; два маршрута: общий (ru, en) и казахский (собственная дообученная модель) |
| Диаризация | nvidia/diar_streaming_sortformer_4spk-v2, эмбеддер голоса titanet_large |
| Шлюз речевых служб | Caddy, один Bearer-токен на все ручки |
| Обработчик | Python, ffmpeg, Kafka-консьюмер, pydantic-контракты |
| Транспорт | Apache Kafka (топики запросов и ответов), MinIO (файлы) |
| Разбор транскрипта | Qwen3.8-27B-FP8 на vLLM, развёрнута на vllm.aibots.kz |
| Интерфейс | Next.js (App Router), Tailwind v4, каталог front/ |
| Инфраструктура | Docker Compose, Traefik с Let's Encrypt, IaC-документация в infrastructure/ansible/ |
Архитектура
front/ ──① запись──► MinIO uploads/<meeting_id>/
│ ▲
│ ② meetings.uploaded │ ⑤ result.json
▼ │
Kafka │
│ ③ │
▼ │
services/adapter ──► meeting-copilot-container ─┘
├──► stt.aibots.kz /v1/audio/transcriptions распознавание
├──► stt.aibots.kz /v1/audio/diarize диаризация
└──► vllm.aibots.kz /v1/chat/completions поручения и саммари
│
└──⑥ meetings.ready | meetings.failed ──► front/
| Компонент | Каталог | Роль |
|---|---|---|
| Веб-интерфейс | front/ | загрузка файла и запись с микрофона, субтитры Zoom, голосовое предупреждение участникам, статусы обработки, протокол, контроль поручений с напоминаниями, экспорт в DOCX и PDF |
| Доставка записей Zoom | services/zoom-ingest/ | забирает облачные записи и входит во встречу участником; отдаёт то же событие meetings.uploaded |
| Адаптер контрактов | services/adapter/ | переводит события интерфейса в формат обработчика и собирает result.json |
| Обработчик | meeting-copilot-container/ | Kafka-консьюмер: распознавание, диаризация, склейка, разбор |
| Речевые службы | speech_stack/ | исходники ASR, диаризации и шлюза |
| Транспорт и развёртывание | infrastructure/ | Kafka, MinIO, Traefik, IaC-документация |
| Утилиты и замеры | tools/ | извлечение поручений, бенчмарки распознавания |
Речевые службы: stt.aibots.kz
Собственный стек, исходники в speech_stack/, развёрнут на машине с NVIDIA
GPU. Три службы за одним шлюзом и одним токеном.
| Ручка | Назначение | Токен |
|---|---|---|
GET /health | проба распознавания | не нужен |
GET /health/diar | проба диаризации | не нужен |
POST /v1/audio/transcriptions | речь → текст, OpenAI-совместимо | нужен |
POST /v1/audio/diarize | кто когда говорил | нужен |
GET /v1/models | список моделей | нужен |
POST /v1/audio/identify, /v1/audio/verify, /v1/speakers | опознание говорящего по образцу | нужен |
Авторизация — Authorization: Bearer $STT_TOKEN. Неизвестные пути тоже отвечают 401, поэтому
снаружи не виден даже состав ручек.
Параметры распознавания, которые влияют на результат:
| Поле | Значение |
|---|---|
response_format | verbose_json — даёт пословные метки времени, без них склейка с диаризацией невозможна |
language | ru | kk | en | auto; auto возвращает route и detected_language |
hotwords | список собственных имён через запятую, повышает точность ФИО |
Замеры на записи 4 мин 34 с (русский), артефакты в
docs/TASK/records/artifacts/:
| Шаг | Время | Результат |
|---|---|---|
| Распознавание | 19.5 с | 61 сегмент, 567 слов с метками, маршрут general:whisper-v6-ct2 |
| Диаризация | 2.5 с | 55 сегментов, 4 голоса |
| Склейка | мгновенно | 30 реплик с говорящими и таймкодами |
Языковая модель: vllm.aibots.kz
Qwen3.8-27B-FP8 под vLLM, OpenAI-совместимый интерфейс. Развёрнута на той же GPU-машине, что и речевые службы. Разбор транскрипта идёт здесь, поэтому текст совещания не покидает контур — этого требует раздел «Ограничения» кейса.
from openai import OpenAI
client = OpenAI(base_url="https://vllm.aibots.kz/v1", api_key=os.environ["VLLM_API_KEY"])
Имя модели — qwen3-vl-30b-instruct. Алиас исторический и оставлен намеренно: его уже знают
существующие потребители.
| Параметр | Значение |
|---|---|
| Контекст | 65 536 токенов на запрос |
| Одновременных запросов | 6, седьмой встаёт в очередь |
| KV-кэш | fp8, доля карты 0.65 |
GET /health | 200 без токена |
GET /v1/models без токена | 401 |
Карта общая с распознаванием, диаризацией и синтезом: тяжёлый прогон разбора замедляет расшифровку. Ограничения частоты нет, единственная защита — токен, поэтому он приходит из окружения и никогда не попадает ни в репозиторий, ни в код, исполняемый в браузере.
Замер на транскрипте тестовой записи: 58 с, извлечено 10 поручений с ответственным и сроком,
результат в docs/TASK/records/artifacts/commitments.json.
Установка и запуск
Инфраструктура (Kafka, MinIO)
cd infrastructure
./local-up.sh
Скрипт создаёт .env, поднимает сервисы, дожидается готовности, проверяет что топики и
бакет созданы, и печатает адреса с паролями. Это единственная точка входа для инфраструктуры:
отдельного compose в корне репозитория нет.
Речевые службы
Разворачиваются на машине с NVIDIA GPU:
cd speech_stack
cp .env.example .env
openssl rand -hex 32 # положить в STT_TOKEN
docker compose up -d --build
Первая сборка долгая: веса распознавания конвертируются в формат CTranslate2 внутри образа, веса диаризации тянутся при первом старте.
Обработчик
cd meeting-copilot-container
cp .env.example .env # адреса Kafka и MinIO, токены речевых служб и модели
docker compose up -d --build
Веб-интерфейс
cd front
npm install
npm run dev # http://localhost:3000
Как проверить решение
Самый короткий путь — открыть развёрнутую версию
- Откройте https://app.aibots.kz.
- Перетащите в зону загрузки любую запись совещания. В репозитории лежат две готовые:
docs/TASK/records/. - Дождитесь обработки — на записи 4 мин 34 с это примерно минута.
- Проверьте протокол: транскрипт разделён по говорящим с таймкодами, в таблице поручений есть ответственный, срок и классификация, внизу саммари.
- Нажмите выгрузку в DOCX и PDF — файлы скачиваются из браузера.
Эталон того, что должно получиться, лежит в репозитории:
docs/TASK/records/artifacts/ — сырые ответы
распознавания и диаризации, собранный протокол и разобранные поручения.
Проверка служб по отдельности
Проба живости речевых служб — доступна без токена:
curl -s https://stt.aibots.kz/health
curl -s https://stt.aibots.kz/health/diar
Ответ содержит состав загруженных моделей и устройство.
Сквозной прогон одной записи, от файла до протокола с говорящими:
export STT_TOKEN=...
cd speech_stack
./tools/example.sh "../docs/TASK/records/Совещание №1.mp3" "Совещание №1" > протокол.md
Эталонный результат такого прогона лежит в репозитории и его можно сверить:
docs/TASK/records/artifacts/protocol.md,
рядом — сырые ответы распознавания и диаризации.
Распознавание смешанной речи: ничего не настраивать
curl -H "Authorization: Bearer $STT_TOKEN" \
-F file=@запись.mp3 -F language=auto -F response_format=verbose_json \
https://stt.aibots.kz/v1/audio/transcriptions
language=auto — и всё. Детектор сам уводит смешанную речь на казахский маршрут: на
31 записи из 31, без единого промаха. Указывать kk вручную не нужно, результат тот же.
Чего делать нельзя: ставить language=ru на том основании, что половина слов русские.
Это ровно вдвое хуже — 0.1147 против 0.0511.
Проверить это утверждение на публичных данных:
huggingface-cli download Tim2190/kazakh-codeswitch-asr \
--repo-type dataset --local-dir ./kazakh-codeswitch-asr
export STT_TOKEN=...
python3 tools/bench_shala.py kk ru auto
Извлечение поручений из готового протокола:
export VLLM_API_KEY=...
python3 tools/extract_commitments.py \
docs/TASK/records/artifacts/protocol.md /tmp/commitments.json
Эталон — docs/TASK/records/artifacts/commitments.json:
10 поручений с ответственным, сроком в ISO и дословной цитатой назначения.
Данные и интеграции
- Тестовые записи совещаний:
docs/TASK/records/. Записи смоделированные, что допускается условиями кейса. - Речевые службы: собственный стек
stt.aibots.kz, исходники в репозитории. - Языковая модель: собственная
vllm.aibots.kz, развёрнута на своей GPU-машине. - Транспорт: Kafka и MinIO, поднимаются из
infrastructure/.
Записи Zoom: services/zoom-ingest/
Два режима, и оба отдают одно и то же событие meetings.uploaded — дальше конвейер не
знает, откуда пришла запись, и разбор идёт одинаково.
poll — облачные записи постфактум (демон, docker compose up -d --build).
Server-to-Server OAuth (ZOOM_ACCOUNT_ID, ZOOM_CLIENT_ID, ZOOM_CLIENT_SECRET) к Zoom
Cloud Recording API. Проход каждые ZOOM_POLL_INTERVAL_SEC (120 с) по записям за
ZOOM_LOOKBACK_DAYS (1 день) у хоста ZOOM_USER_ID; пусто — по всем пользователям
аккаунта. Из recording_files берётся по одному файлу на вид, только status=completed:
аудио M4A (видео MP4 как замена, если аудио не отдано) и TRANSCRIPT — субтитры VTT,
из которых потом берутся имена участников. Файлы кладутся в MinIO как
recordings/<meeting_id>/audio.m4a и transcript.vtt, где
meeting_id = zoom-<id совещания>-<UTC ГГГГММДДTЧЧММСС> — он выводится из данных Zoom,
поэтому повторный проход по той же записи даёт тот же идентификатор.
bot — участник встречи (docker compose run --rm zoom-bot "<ссылка>" --name "...").
Chromium без окна (Playwright) входит в веб-клиент Zoom, звук встречи уходит в
null-sink PulseAudio, ffmpeg пишет его monitor. По окончании встречи или по истечении
--max-minutes (по умолчанию 180) файл уезжает в recordings/zoom-live-<id>-<ts>/live.webm
и публикуется то же событие. Микрофона у бота нет: записывается только то, что звучит во
встрече. Хост должен пустить бота из зала ожидания; самое хрупкое место — селекторы
веб-клиента Zoom, они меняются на стороне Zoom.
Повторов не будет, потерь тоже. Обработанные uuid записей лежат в state.json
бакета zoom-ingest. Запись помечается обработанной только когда аудио действительно
скачано: если Zoom ещё рендерит файл и download_url не отдан, uuid остаётся
непомеченным и запись забирается на следующем проходе. Упавший проход не убивает демон —
traceback в лог и повтор через интервал.
Связка с остальным стеком: общая сеть meeting-copilot_web, KAFKA_BROKERS=kafka:9092,
MINIO_ENDPOINT=minio:9000; бакеты recordings и zoom-ingest создаёт mc-init.
На очереди — вебхук recording.completed вместо опроса (ZOOM_WEBHOOK_SECRET_TOKEN уже
заложен в конфиг).
- Внешние платные API распознавания не используются.
Ограничения
- Рассылка напоминаний работает без почтового провайдера в режиме журнала. Логика сроков,
дедупликации и статусов проверена на живых данных, но письма никуда не уходят, пока не заданы
MAIL_API_URL,MAIL_API_KEYиMAIL_FROM. Адрес ответственного вводится руками: в записи совещания почты нет, а угадывать её по имени нельзя. - Имена участников без субтитров не определяются. Диаризация различает голоса, но не знает, кому они принадлежат, поэтому в протоколе стоят «Говорящий 1», «Говорящий 2». С приложенными субтитрами Zoom имена настоящие. Определение имён по тексту разговора (по обращениям и назначениям поручений) проверено отдельно, но в конвейер не подключено.
- Диаризующая модель различает ровно четыре голоса. Пятый участник сливается с одним из четырёх; это архитектура модели, а не настройка. В тестовой записи названы пятеро участников и получено четыре ярлыка.
- Шала-казахский замерен на публичном корпусе
Tim2190/kazakh-codeswitch-asr(31 запись, человеческая дословная расшифровка): pooled CER 0.0511 сlanguage=auto. Замер включает контроли — пустая гипотеза 1.0000, бессмыслица 0.9486, чужой эталон 0.9306, — то есть стенд умеет провалиться, и число не пустое. Корпус состоит из стендапа: чистая запись, близкий микрофон. На телефонной полосе, в зале с эхом или при перебиваниях число будет хуже, и насколько — мы не знаем. - Разговорные стяжения приводятся к литературной форме (
болад→болады). Для протокола совещания это скорее плюс, но дословной записи не даёт. Ошибки сосредоточены на стыке языков — казахская вставка в русской фразе и первые слова после переключения. Реальная телефонная речь с шумом и перебиваниями не замерялась, методика и границы — вdocs/TASK/records/kk/. - Опознание говорящего по тембру развёрнуто, но образцов голосов не зарегистрировано, поэтому имена в протоколе не проставляются автоматически.
- Поле
durationв ответе распознавания занижено; фактическая длительность считается по данным, см.speech_stack/tools/merge_transcript.py. - Формат AAC (
.m4a) не декодируется напрямую, требуется конвертация в MP3. - Языковая модель и речевые службы делят одну видеокарту: параллельная нагрузка замедляет оба тракта. Потолок — шесть одновременных запросов к модели.
- Разбор транскрипта пятиминутной записи занимает около минуты.
- Полноценная интеграция с СЭД и промышленное развёртывание в объём работ не входили.
Дальнейшее развитие
Что известно как незакрытое и что с этим делать дальше — по убыванию отдачи.
Поиск по архиву совещаний (RAG). Протоколы, транскрипты и поручения копятся в MinIO,
но каждое совещание пока живёт само по себе. Если сложить их в векторный индекс, поверх
архива можно отвечать на вопросы, ради которых сейчас перечитывают протоколы руками:
«что решили по этому поставщику», «какие поручения давали департаменту за квартал»,
«чем закончилось прошлое обсуждение». Второе применение полезнее первого: подставлять
найденное прямо в разбор новой записи — тогда модель видит, что тема тянется с прошлой
встречи, не заводит поручение-дубль и подхватывает принятые ранее формулировки и
названия. Требование «текст не покидает контур» при этом сохраняется: и эмбеддинги, и
генерация считаются на своей GPU-машине, рядом с vllm.aibots.kz.
Диаризация по сотрудникам: нужны образцы голоса. Служба опознания по тембру
развёрнута (/v1/audio/identify, /v1/speakers, модель titanet_large), но образцов
голосов не зарегистрировано, поэтому имена подставляются только из субтитров Zoom, а на
записи с телефона или из переговорной остаются ярлыки «Говорящий 1». Достаточно разового
сбора образцов сотрудников — дальше диаризация перестаёт быть безымянной: ярлык
связывается с конкретным человеком, имя в поручении берётся из голоса, столбец
«уверенность» перестаёт быть низким на обычных записях, а один и тот же сотрудник
опознаётся от совещания к совещанию, что открывает сводку поручений по людям без ручной
разметки.
Две вещи делаются до того, как этому доверять. Порог сходства по умолчанию 0.78
перемеряется на своём материале: студийная запись, зал и телефон дают разные
распределения, и порог с одного типа звука на другой не переносится. И голосовой слепок —
биометрия: согласие сотрудников получают до того, как ручка окажется в продукте.
Совещания больше четырёх голосов. Диаризация работает моделью sortformer_4spk —
четыре голоса это её потолок, пятый приклеивается к кому-то из первых четырёх. Для
совещаний на 8–10 человек нужна другая модель или кластеризация по эмбеддингам
titanet_large, которая уже развёрнута рядом.
Поручение живёт в системе, где его ведут. Сейчас поручения хранятся в MinIO и
показываются в дашборде. Отдача появится, когда они уезжают в СЭД, Jira или Bitrix —
туда, где сотрудник и так смотрит задачи. Разбор уже отдаёт структуру
(text, assignee, due_date, classification), так что это адаптер, а не переделка.
Почта в корпоративный контур. Транспорт напоминаний настраивается переменными
(MAIL_API_URL, MAIL_API_KEY, MAIL_FROM); без настройки письма копятся в журнале
results/commitments/outbox.json. Нужен корпоративный SMTP и отметка о выполнении по
ссылке из письма, чтобы исполнитель закрывал поручение не заходя в интерфейс.
Доменная лексика. Шала-казахский замерен на публичном корпусе с человеческой расшифровкой (CER 0.0511). Банковская речь — номера договоров, названия продуктов, фамилии — в замер не попадала. Дальше нужны реальные записи созвонов и дообучение на них; маршрут для собственной модели в распознавании уже есть.
Перевод транскрипта. Переводятся саммари и поручения. Транскрипт оставлен дословным осознанно, но двуязычному совещанию пригодился бы параллельный показ: исходная реплика и перевод рядом, а не вместо.
Разделение нагрузки. Языковая модель и речевые службы делят одну видеокарту, потолок — шесть одновременных запросов. Для потока совещаний это разные карты и очередь с приоритетами, а не одна машина.
Обработка по ходу встречи. Сейчас запись обрабатывается файлом целиком: протокол готов через минуту после конца. Потоковое распознавание дало бы черновик поручений уже во время совещания — можно поправить формулировку, пока участники не разошлись.
Ссылка на развёрнутую версию
Приложение: https://app.aibots.kz — загрузка записи, транскрипт с говорящими, поручения, саммари, выгрузка протокола.
| Компонент | Адрес | Открытая проба |
|---|---|---|
| Приложение | https://app.aibots.kz | / |
| Речевые службы | https://stt.aibots.kz | /health, /health/diar |
| Языковая модель | https://vllm.aibots.kz | /health |
Замер на развёрнутом стенде: запись 4 мин 34 с проходит путь целиком примерно за 60 секунд и даёт 30 реплик, 4 говорящих, 10 поручений со сроками и саммари.
Авторы коммитов
История коммитов
- 2026-09-23 17:55Merge branch 'readme'Astrohaker
- 2026-09-23 17:54README: три языка перевода, RAG и диаризация по сотрудникамAstrohaker
- 2026-09-23 17:50Печатный протокол: поля страницы, выключка, разрывыsergeyshmagin
- 2026-09-23 17:47README: доставка записей Zoomsergeyshmagin
- 2026-09-23 17:46Документация: AI-перевод, раздел дальнейшего развитияsergeyshmagin
- 2026-09-23 17:45Merge remote-tracking branch 'origin/feature/front'sergeyshmagin
- 2026-09-23 17:42Перевод в фоне, сохранение языка, починка таблицы порученийsergeyshmagin
- 2026-09-23 17:41Merge branch 'zoom_ingest' into feature/frontrusskycloud
Все коммиты (76)
- 2026-09-23 17:38Merge remote-tracking branch 'origin/main' into feature/frontrusskycloud
- 2026-09-23 17:35zoom-ingest: не помечать запись обработанной, если аудио не скачаноrusskycloud
- 2026-09-23 17:33Merge remote-tracking branch 'origin/meeting-copilot-container'sergeyshmagin
- 2026-09-23 17:33Merge remote-tracking branch 'origin/zoom_ingest'sergeyshmagin
- 2026-09-23 17:32Перевод протокола на своей модели; выравнивание Word; высота колонокsergeyshmagin
- 2026-09-23 17:28services/zoom-ingest: записи Zoom в конвейер — поллер Cloud Recording API и бот-участникrusskycloud
- 2026-09-23 17:26Руководство пользователя со скриншотами; форматирование саммариsergeyshmagin
- 2026-09-23 17:23README: что фиксируется по каждому поручениюAstrohaker
- 2026-09-23 17:18Контроль поручений: хранение и напоминания о сроках (Сценарий 2)sergeyshmagin
- 2026-09-23 17:11Прогресс переживает обновление страницы; длинные записи режутся на кускиsergeyshmagin
- 2026-09-23 17:01Субтитры Zoom в интерфейсе: имена участников вместо ярлыковsergeyshmagin
- 2026-09-23 16:54Адаптер: время числом и читаемые ярлыки говорящихsergeyshmagin
- 2026-09-23 16:48Merge branch 'main' of https://github.com/BAITC-Hacks/hack-47bd9c8d-dbk-teamsergeyshmagin
- 2026-09-23 16:47Документация приведена в соответствие с реализациейsergeyshmagin
- 2026-09-23 16:46Merge remote-tracking branch 'origin/meeting-copilot-container'sergeyshmagin
- 2026-09-23 16:46Merge remote-tracking branch 'origin/feature/front'sergeyshmagin
- 2026-09-23 16:43Merge branch 'meeting-copilot-container'Astrohaker
- 2026-09-23 16:42адаптер: классификация поручений в контракте для интерфейсаAstrohaker
- 2026-09-23 16:41Merge pull request #5 from BAITC-Hacks/feature/frontrusskycloud
- 2026-09-23 16:40Merge branch 'main' into meeting-copilot-containerAstrohaker
- 2026-09-23 16:40front: предупреждение о записи сначала на казахскомrusskycloud
- 2026-09-23 16:39README: ссылка на развёрнутое приложениеsergeyshmagin
- 2026-09-23 16:37front: контроль поручений (Сценарий 2), целостность записи, предупреждения rus/kaz, фиксы критикиrusskycloud
- 2026-09-23 16:36поручения: колонка классификации по срочности и направлениюAstrohaker
- 2026-09-23 16:30Адаптер: разбор таблицы поручений и сведение бакетовsergeyshmagin
- 2026-09-23 16:18compose: убран дубль KAFKA_INTER_BROKER_LISTENER_NAME после мержаsergeyshmagin
- 2026-09-23 16:18Merge branch 'main' of https://github.com/BAITC-Hacks/hack-47bd9c8d-dbk-teamsergeyshmagin
- 2026-09-23 16:17Серверный оверлей compose для docker-serversergeyshmagin
- 2026-09-23 16:17Merge remote-tracking branch 'origin/feature/front'sergeyshmagin
- 2026-09-23 16:17Адаптер контрактов между интерфейсом и обработчикомsergeyshmagin
- 2026-09-23 16:17Merge remote-tracking branch 'origin/meeting-copilot-container'sergeyshmagin
- 2026-09-23 16:12composerusskycloud
- 2026-09-23 16:09Merge pull request #4 from BAITC-Hacks/feature/frontrusskycloud
- 2026-09-23 16:08front: живая запись с микрофона (Сценарий 1) — чанки в MinIO, событие в Kafkarusskycloud
- 2026-09-23 16:00Merge branch 'meeting-copilot-container'Astrohaker
- 2026-09-23 15:59Merge branch 'main' into meeting-copilot-containerAstrohaker
- 2026-09-23 15:57README: правило распознавания смешанной речи в разделе проверкиsergeyshmagin
- 2026-09-23 15:55speech: подключение к своему стеку распознавания и диаризацииAstrohaker
- 2026-09-23 15:55Суммаризация переведена на свою модельsergeyshmagin
- 2026-09-23 15:54Merge branch 'meeting-copilot-container': экспорт PDF и поручения в саммариsergeyshmagin
- 2026-09-23 15:54Merge branch 'feature/front': редизайн интерфейсаsergeyshmagin
- 2026-09-23 15:52Порядок в документации: убраны заглушки, битое и устаревшееsergeyshmagin
- 2026-09-23 15:49front: редизайн в институциональной теме sk.kz (navy + бронза, светлый фон)russkycloud
- 2026-09-23 15:47Шала-казахский: замер на публичном корпусе с человеческой расшифровкойsergeyshmagin
- 2026-09-23 15:43Замер на шала-казахском: серии прогонов вместо одиночныхsergeyshmagin
- 2026-09-23 15:41Merge branch 'main' into meeting-copilot-containerAstrohaker
- 2026-09-23 15:36README: результаты замера на казахском и шала-казахскомsergeyshmagin
- 2026-09-23 15:36Замер распознавания на казахском и шала-казахскомsergeyshmagin
- 2026-09-23 15:30Merge pull request #3 from BAITC-Hacks/feature/frontrusskycloud
- 2026-09-23 15:29summary: раздел с поручениями и экспорт в PDFAstrohaker
- 2026-09-23 15:28Извлечение поручений на своей модели: vllm.aibots.kzsergeyshmagin
- 2026-09-23 15:26front: веб-интерфейс meeting-copilot (загрузка, статусы, протокол, экспорт)russkycloud
- 2026-09-23 15:26README проекта: 11 разделов по требованиям организаторовsergeyshmagin
- 2026-09-23 15:13data: тестовые записи совещаний в gitAstrohaker
- 2026-09-23 15:08Сквозной прогон записи: расшифровка, диаризация, протоколsergeyshmagin
- 2026-09-23 15:01Merge branch 'meeting-copilot-container'Astrohaker
- 2026-09-23 15:01infrastructure: локальный запуск Kafka и MinIO одной командойAstrohaker
- 2026-09-23 14:58speech_stack: собственные службы распознавания и диаризацииsergeyshmagin
- 2026-09-23 14:54Merge pull request #2 from BAITC-Hacks/feature/frontrusskycloud
- 2026-09-23 14:53sterring frontrusskycloud
- 2026-09-23 14:47Merge branch 'meeting-copilot-container'Astrohaker
- 2026-09-23 14:46Merge pull request #1 from BAITC-Hacks/feature/frontrusskycloud
- 2026-09-23 14:45README: архитектура и взаимодействие через Kafka и MinIOAstrohaker
- 2026-09-23 14:42infrastructure: локальный MVP-стек (compose+traefik+LE) и IaC-документацияrusskycloud
- 2026-09-23 14:36Постановка кейса, контракт команды и раскладка задачsergeyshmagin
- 2026-09-23 14:27inital copilotAstrohaker
- 2026-09-23 13:52infrarusskycloud
- 2026-09-23 12:11DBK team — HackAlem infrastructure stacksergeyshmagin
Структура репозитория (202 файлов)
.codex/hooks.json .env.example .gitignore .planning/config.json .planning/tasks/CONTRACT.md .planning/tasks/anton.md .planning/tasks/ruslan.md .planning/tasks/sergey.md README.md docs/GUIDE.md docs/TASK/records/artifacts/asr1.json docs/TASK/records/artifacts/commitments.json docs/TASK/records/artifacts/diar1.json docs/TASK/records/artifacts/protocol.md docs/TASK/records/kk/README.md docs/TASK/records/kk/shala-kazakh.md docs/TASK/records/Совещание №1.mp3 docs/TASK/records/Совещание №2.mp3 docs/TASK/task.md docs/designs/meeting-protocol-agent.md docs/guide/01-main.png docs/guide/02-commitments.png docs/guide/03-protocol.png docs/tecspec/zoom-cloud-recording.md docs/Активация OpenAI и NVIDIA для участников HackAlem AI.pdf docs/Инструкция для участников_Онлайн-курс Arizona State University.pdf docs/Инструкция по кибербезопасности.pdf docs/Инструкция по подготовке оборудования для участия в хакатоне.pdf docs/Инструкция_для_участников_HackAlem_AI.pdf docs/Инструкция_для_участников_HackAlem_AI.txt docs/Правила зачета участия.pdf front/.dockerignore front/.env.example front/.gitignore front/DESIGN.md front/Dockerfile front/PRODUCT.md front/README.md front/app/api/commitments/notify/route.ts front/app/api/commitments/route.ts front/app/api/health/route.ts front/app/api/meetings/[id]/cancel/route.ts front/app/api/meetings/[id]/chunk/route.ts front/app/api/meetings/[id]/finish/route.ts front/app/api/meetings/[id]/result/route.ts front/app/api/meetings/[id]/status/route.ts front/app/api/meetings/[id]/translate/route.ts front/app/api/meetings/route.ts front/app/api/meetings/start/route.ts front/app/globals.css front/app/layout.tsx front/app/page.tsx front/components/commitments-dashboard.tsx front/components/commitments-table.tsx front/components/export-buttons.tsx front/components/language-switcher.tsx front/components/live-recorder.tsx front/components/markdown-blocks.tsx front/components/meeting-progress.tsx front/components/meeting-result.tsx front/components/printable-protocol.tsx front/components/recording-notice.tsx front/components/summary-view.tsx front/components/transcript-view.tsx front/components/ui/badge.tsx front/components/ui/button.tsx front/components/ui/card.tsx front/components/ui/skeleton.tsx front/components/upload-zone.tsx front/components/warnings-banner.tsx front/docker-compose.local.yml front/docker-compose.yml front/instrumentation.ts front/lib/active-meeting.ts front/lib/commitments-store.ts front/lib/config.ts front/lib/export-docx.ts front/lib/kafka.ts front/lib/languages.ts front/lib/markdown.ts front/lib/minio.ts front/lib/notifications.ts front/lib/recording-sessions.ts front/lib/store.ts front/lib/translate.ts front/lib/types.ts front/lib/utils.ts front/mock/sample-result.json front/next.config.ts front/package-lock.json front/package.json front/postcss.config.mjs front/public/.gitkeep front/public/audio-warnings/kaz.mp3 front/public/audio-warnings/rus.mp3 front/tsconfig.json infrastructure/.env.example infrastructure/README.md infrastructure/ansible/README.md infrastructure/ansible/docs/00-architecture.md infrastructure/ansible/docs/01-kafka.md infrastructure/ansible/docs/02-minio.md infrastructure/ansible/docs/03-meeting-copilot.md infrastructure/ansible/docs/04-copilot-ui.md infrastructure/docker-compose.local.yml infrastructure/docker-compose.server.yml infrastructure/docker-compose.yml infrastructure/env.local.example infrastructure/kafka/kafka-init.sh infrastructure/local-up.sh infrastructure/minio/copilot-uploads-rw.json infrastructure/minio/mc-init.sh meeting-copilot-container/.dockerignore meeting-copilot-container/.env.example meeting-copilot-container/.gitignore meeting-copilot-container/.gitlab-ci.yml meeting-copilot-container/Dockerfile meeting-copilot-container/Dockerfile.service meeting-copilot-container/README.md meeting-copilot-container/audio_utils.py meeting-copilot-container/check_health_services.py meeting-copilot-container/chunked_transcribe.py meeting-copilot-container/config.py meeting-copilot-container/data/Совещание №1.mp3 meeting-copilot-container/data/Совещание №2.mp3 meeting-copilot-container/docker-compose.yml meeting-copilot-container/entrypoint.sh meeting-copilot-container/export_pdf.py meeting-copilot-container/kafka_service.py meeting-copilot-container/main.py meeting-copilot-container/merge_transcript.py meeting-copilot-container/model/generate_examples.py meeting-copilot-container/model/models.py meeting-copilot-container/requirements.txt meeting-copilot-container/summarize_transcript.py meeting-copilot-container/transcribers/__init__.py meeting-copilot-container/transcribers/base.py meeting-copilot-container/transcribers/factory.py meeting-copilot-container/transcribers/kdb_whisper.py meeting-copilot-container/transcribers/models.py meeting-copilot-container/transcribers/speech_stack.py services/adapter/Dockerfile services/adapter/adapter.py services/zoom-ingest/.env.example services/zoom-ingest/Dockerfile services/zoom-ingest/Dockerfile.bot services/zoom-ingest/README.md services/zoom-ingest/docker-compose.yml services/zoom-ingest/docker/bot-entrypoint.sh services/zoom-ingest/requirements.txt services/zoom-ingest/tests/test_zoom_ingest.py services/zoom-ingest/zoom_ingest/__init__.py services/zoom-ingest/zoom_ingest/__main__.py services/zoom-ingest/zoom_ingest/bot.py services/zoom-ingest/zoom_ingest/config.py services/zoom-ingest/zoom_ingest/events.py services/zoom-ingest/zoom_ingest/poller.py services/zoom-ingest/zoom_ingest/storage.py services/zoom-ingest/zoom_ingest/zoom_client.py speech_stack/.env.example speech_stack/README.md speech_stack/diarization/Dockerfile speech_stack/diarization/app.py speech_stack/diarization/config.py speech_stack/diarization/diarize.py speech_stack/diarization/models.py speech_stack/diarization/requirements.txt speech_stack/diarization/speakers.py speech_stack/docker-compose.yml speech_stack/gateway/Caddyfile speech_stack/stt/Dockerfile speech_stack/stt/app.py speech_stack/stt/asr_models.py speech_stack/stt/audio.py speech_stack/stt/config.py speech_stack/stt/decode.py speech_stack/stt/download_models.py speech_stack/stt/test_artefact_filter.py speech_stack/tools/example.sh speech_stack/tools/merge_transcript.py tools/agents_smoke.py tools/bench_shala.py tools/council.py tools/deploy.sh tools/dev-workflow-setup.sh tools/dev-workflow/AGENTS.md tools/dev-workflow/HACKATHON.md tools/dev-workflow/MODELS.md tools/dev-workflow/README-TEMPLATE.md tools/dev-workflow/TEAM-README.md tools/dev-workflow/gbrain-sync.sh tools/dev-workflow/god-file-warn.py tools/dev-workflow/skill/SKILL.md tools/dev-workflow/skills/steering/SKILL.md tools/dev-workflow/skills/steering/scripts/steering.py tools/dev-workflow/ssh-config tools/eval_asr.py tools/extract_commitments.py tools/hackathon-setup.sh tools/hackathon-watcher.sh tools/litellm.yaml tools/llm-bridge.sh
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.