docs: initial spec and implementation plan
This commit is contained in:
@@ -0,0 +1,87 @@
|
|||||||
|
<h2>Архитектурные подходы</h2>
|
||||||
|
<p class="subtitle">Выбери подход к построению сервиса транскрибации и протоколирования</p>
|
||||||
|
|
||||||
|
<div class="options">
|
||||||
|
<div class="option" data-choice="a" onclick="toggleSelect(this)">
|
||||||
|
<div class="letter">A</div>
|
||||||
|
<div class="content">
|
||||||
|
<h3>Монолит на Python (FastAPI)</h3>
|
||||||
|
<p><strong>Стек:</strong> FastAPI + Celery + PostgreSQL + Redis + React</p>
|
||||||
|
<p>Единое приложение: API, обработка задач, боты, веб-интерфейс — всё в одном репозитории и процессе (+ воркеры Celery для тяжёлых задач).</p>
|
||||||
|
<div class="pros-cons">
|
||||||
|
<div class="pros">
|
||||||
|
<h4>✓ Плюсы</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Простота разработки и деплоя</li>
|
||||||
|
<li>Один язык, одна кодовая база</li>
|
||||||
|
<li>Быстрый старт — MVP за недели</li>
|
||||||
|
<li>Легко отлаживать</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="cons">
|
||||||
|
<h4>✗ Минусы</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Масштабирование — только вертикальное</li>
|
||||||
|
<li>Боты, API, обработка связаны — падение одного влияет на всё</li>
|
||||||
|
<li>При росте код станет сложным</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option" data-choice="b" onclick="toggleSelect(this)">
|
||||||
|
<div class="letter">B</div>
|
||||||
|
<div class="content">
|
||||||
|
<h3>Модульный монолит с очередями (рекомендация)</h3>
|
||||||
|
<p><strong>Стек:</strong> FastAPI + Celery + PostgreSQL + Redis + React/Vue</p>
|
||||||
|
<p>Единый деплой, но внутри — изолированные модули: API, транскрибация, генерация протоколов, боты мессенджеров. Общение между модулями — через очереди задач (Celery/Redis). Каждый модуль можно выделить в отдельный сервис позже.</p>
|
||||||
|
<div class="pros-cons">
|
||||||
|
<div class="pros">
|
||||||
|
<h4>✓ Плюсы</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Баланс простоты и масштабируемости</li>
|
||||||
|
<li>Модули изолированы — падение воркера не роняет API</li>
|
||||||
|
<li>Легко выделить модуль в микросервис при росте</li>
|
||||||
|
<li>Один деплой, но чистая архитектура</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="cons">
|
||||||
|
<h4>✗ Минусы</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Чуть больше начальной настройки чем чистый монолит</li>
|
||||||
|
<li>Нужна дисциплина разделения модулей</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option" data-choice="c" onclick="toggleSelect(this)">
|
||||||
|
<div class="letter">C</div>
|
||||||
|
<div class="content">
|
||||||
|
<h3>Микросервисы (Docker Compose)</h3>
|
||||||
|
<p><strong>Стек:</strong> FastAPI сервисы + RabbitMQ/Redis + PostgreSQL + React + Docker</p>
|
||||||
|
<p>Каждый компонент — отдельный контейнер: API Gateway, Transcription Service, Protocol Generator, Telegram Bot, Lensa Bot, Web Frontend.</p>
|
||||||
|
<div class="pros-cons">
|
||||||
|
<div class="pros">
|
||||||
|
<h4>✓ Плюсы</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Максимальная гибкость и масштабируемость</li>
|
||||||
|
<li>Независимый деплой каждого сервиса</li>
|
||||||
|
<li>Полная изоляция компонентов</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="cons">
|
||||||
|
<h4>✗ Минусы</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Сложность: сеть, мониторинг, логи, оркестрация</li>
|
||||||
|
<li>Оверкилл для одного сервера</li>
|
||||||
|
<li>Долгий старт разработки</li>
|
||||||
|
<li>Сложная отладка</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<h2>Секция 1: Общая архитектура</h2>
|
||||||
|
<p class="subtitle">Модульный монолит — компоненты и потоки данных</p>
|
||||||
|
|
||||||
|
<div class="mockup">
|
||||||
|
<div class="mockup-header">Архитектура системы</div>
|
||||||
|
<div class="mockup-body" style="padding: 24px; font-family: monospace; font-size: 13px; line-height: 1.6;">
|
||||||
|
<div style="display: flex; gap: 16px; justify-content: center; margin-bottom: 20px;">
|
||||||
|
<div style="background: #3b82f6; color: white; padding: 10px 16px; border-radius: 8px; text-align: center;">
|
||||||
|
🌐 Web UI<br><small>React/Vue SPA</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #8b5cf6; color: white; padding: 10px 16px; border-radius: 8px; text-align: center;">
|
||||||
|
💬 Telegram Bot<br><small>aiogram</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #8b5cf6; color: white; padding: 10px 16px; border-radius: 8px; text-align: center;">
|
||||||
|
💬 Lensa Bot<br><small>SDK/webhook</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center; color: #666; margin: 8px 0;">▼ HTTP / WebSocket ▼</div>
|
||||||
|
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 16px; border-radius: 8px; margin-bottom: 16px;">
|
||||||
|
<div style="text-align: center; font-weight: bold; margin-bottom: 12px; color: #60a5fa;">⚙️ FastAPI Backend (модульный монолит)</div>
|
||||||
|
<div style="display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;">
|
||||||
|
<div style="background: #334155; padding: 8px 12px; border-radius: 6px; border-left: 3px solid #3b82f6;">
|
||||||
|
<strong>API модуль</strong><br>
|
||||||
|
<small>REST endpoints<br>Auth (JWT)<br>Upload файлов</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #334155; padding: 8px 12px; border-radius: 6px; border-left: 3px solid #f59e0b;">
|
||||||
|
<strong>Транскрибация</strong><br>
|
||||||
|
<small>Whisper large-v3<br>FFmpeg конвертация<br>GPU обработка</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #334155; padding: 8px 12px; border-radius: 6px; border-left: 3px solid #10b981;">
|
||||||
|
<strong>Протоколирование</strong><br>
|
||||||
|
<small>LLM обработка<br>Шаблоны промптов<br>Экспорт DOCX/PDF/MD</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #334155; padding: 8px 12px; border-radius: 6px; border-left: 3px solid #8b5cf6;">
|
||||||
|
<strong>Мессенджеры</strong><br>
|
||||||
|
<small>Telegram бот<br>Lensa бот<br>Unified interface</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 16px; justify-content: center; margin-top: 16px;">
|
||||||
|
<div style="text-align: center; color: #666; margin: 8px 0;">▼ Celery задачи через Redis ▼</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 12px; justify-content: center; margin-top: 12px;">
|
||||||
|
<div style="background: #dc2626; color: white; padding: 10px 16px; border-radius: 8px; text-align: center;">
|
||||||
|
🔴 Redis<br><small>Очередь задач<br>+ кэш</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #2563eb; color: white; padding: 10px 16px; border-radius: 8px; text-align: center;">
|
||||||
|
🐘 PostgreSQL<br><small>Записи, протоколы<br>пользователи</small>
|
||||||
|
</div>
|
||||||
|
<div style="background: #6b7280; color: white; padding: 10px 16px; border-radius: 8px; text-align: center;">
|
||||||
|
📁 File Storage<br><small>Аудио/видео<br>экспорт файлы</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Поток обработки записи</h3>
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; font-size: 14px;">
|
||||||
|
<div style="display: flex; align-items: center; flex-wrap: wrap; gap: 8px;">
|
||||||
|
<span style="background: #dbeafe; padding: 6px 12px; border-radius: 6px;">1. Загрузка файла</span>
|
||||||
|
<span style="color: #666;">→</span>
|
||||||
|
<span style="background: #fef3c7; padding: 6px 12px; border-radius: 6px;">2. Извлечение аудио (FFmpeg)</span>
|
||||||
|
<span style="color: #666;">→</span>
|
||||||
|
<span style="background: #fef3c7; padding: 6px 12px; border-radius: 6px;">3. Транскрибация (Whisper GPU)</span>
|
||||||
|
<span style="color: #666;">→</span>
|
||||||
|
<span style="background: #d1fae5; padding: 6px 12px; border-radius: 6px;">4. Генерация протокола (LLM)</span>
|
||||||
|
<span style="color: #666;">→</span>
|
||||||
|
<span style="background: #e0e7ff; padding: 6px 12px; border-radius: 6px;">5. Экспорт (DOCX/PDF/MD)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Ключевые решения</h3>
|
||||||
|
<ul style="font-size: 14px; line-height: 1.8;">
|
||||||
|
<li><strong>Whisper large-v3</strong> — локально на GPU (RTX 3070 Ti, 8GB VRAM достаточно)</li>
|
||||||
|
<li><strong>Celery + Redis</strong> — асинхронная обработка, транскрибация и LLM не блокируют API</li>
|
||||||
|
<li><strong>PostgreSQL</strong> — записи, протоколы, пользователи, шаблоны</li>
|
||||||
|
<li><strong>LLM через внешний API</strong> — OpenRouter/Groq/Together с возможностью подключить платные модели</li>
|
||||||
|
<li><strong>FFmpeg</strong> — извлечение аудио из видео, нормализация форматов</li>
|
||||||
|
<li><strong>Docker Compose</strong> — для деплоя всех компонентов на сервере</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
<h2>Секция 2: Модель данных</h2>
|
||||||
|
<p class="subtitle">Основные сущности и связи в PostgreSQL</p>
|
||||||
|
|
||||||
|
<div class="mockup">
|
||||||
|
<div class="mockup-header">ER-диаграмма</div>
|
||||||
|
<div class="mockup-body" style="padding: 24px; font-size: 13px;">
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 16px; flex-wrap: wrap; justify-content: center;">
|
||||||
|
|
||||||
|
<!-- User -->
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 14px; border-radius: 8px; min-width: 200px; border-top: 3px solid #3b82f6;">
|
||||||
|
<div style="font-weight: bold; color: #60a5fa; margin-bottom: 8px;">👤 User</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<code>id</code> UUID PK<br>
|
||||||
|
<code>username</code> str unique<br>
|
||||||
|
<code>email</code> str unique<br>
|
||||||
|
<code>password_hash</code> str<br>
|
||||||
|
<code>role</code> enum (admin, user)<br>
|
||||||
|
<code>is_active</code> bool<br>
|
||||||
|
<code>created_at</code> timestamp
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Recording -->
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 14px; border-radius: 8px; min-width: 220px; border-top: 3px solid #f59e0b;">
|
||||||
|
<div style="font-weight: bold; color: #fbbf24; margin-bottom: 8px;">🎬 Recording</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<code>id</code> UUID PK<br>
|
||||||
|
<code>user_id</code> FK → User<br>
|
||||||
|
<code>title</code> str<br>
|
||||||
|
<code>file_path</code> str<br>
|
||||||
|
<code>file_size</code> bigint<br>
|
||||||
|
<code>duration</code> interval<br>
|
||||||
|
<code>format</code> str (mp4, webm, mp3…)<br>
|
||||||
|
<code>source</code> enum (web, telegram, lensa)<br>
|
||||||
|
<code>status</code> enum (uploaded, processing, done, error)<br>
|
||||||
|
<code>created_at</code> timestamp
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Transcription -->
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 14px; border-radius: 8px; min-width: 220px; border-top: 3px solid #10b981;">
|
||||||
|
<div style="font-weight: bold; color: #34d399; margin-bottom: 8px;">📝 Transcription</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<code>id</code> UUID PK<br>
|
||||||
|
<code>recording_id</code> FK → Recording<br>
|
||||||
|
<code>text</code> text<br>
|
||||||
|
<code>segments</code> JSONB (таймкоды)<br>
|
||||||
|
<code>language</code> str<br>
|
||||||
|
<code>whisper_model</code> str<br>
|
||||||
|
<code>processing_time</code> interval<br>
|
||||||
|
<code>created_at</code> timestamp
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Protocol -->
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 14px; border-radius: 8px; min-width: 220px; border-top: 3px solid #8b5cf6;">
|
||||||
|
<div style="font-weight: bold; color: #a78bfa; margin-bottom: 8px;">📋 Protocol</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<code>id</code> UUID PK<br>
|
||||||
|
<code>transcription_id</code> FK → Transcription<br>
|
||||||
|
<code>template_id</code> FK → PromptTemplate<br>
|
||||||
|
<code>content</code> JSONB (структурированный)<br>
|
||||||
|
<code>raw_text</code> text<br>
|
||||||
|
<code>llm_model</code> str<br>
|
||||||
|
<code>status</code> enum (generating, done, error)<br>
|
||||||
|
<code>created_at</code> timestamp<br>
|
||||||
|
<code>updated_at</code> timestamp
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PromptTemplate -->
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 14px; border-radius: 8px; min-width: 220px; border-top: 3px solid #ec4899;">
|
||||||
|
<div style="font-weight: bold; color: #f472b6; margin-bottom: 8px;">📐 PromptTemplate</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<code>id</code> UUID PK<br>
|
||||||
|
<code>name</code> str<br>
|
||||||
|
<code>description</code> str<br>
|
||||||
|
<code>type</code> enum (client_survey, internal, standup, custom)<br>
|
||||||
|
<code>system_prompt</code> text<br>
|
||||||
|
<code>user_prompt</code> text<br>
|
||||||
|
<code>output_schema</code> JSONB<br>
|
||||||
|
<code>is_default</code> bool<br>
|
||||||
|
<code>created_at</code> timestamp
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ExportFile -->
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 14px; border-radius: 8px; min-width: 200px; border-top: 3px solid #6b7280;">
|
||||||
|
<div style="font-weight: bold; color: #9ca3af; margin-bottom: 8px;">📄 ExportFile</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<code>id</code> UUID PK<br>
|
||||||
|
<code>protocol_id</code> FK → Protocol<br>
|
||||||
|
<code>format</code> enum (docx, pdf, md)<br>
|
||||||
|
<code>file_path</code> str<br>
|
||||||
|
<code>file_size</code> bigint<br>
|
||||||
|
<code>created_at</code> timestamp
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Relations -->
|
||||||
|
<div style="margin-top: 20px; padding: 12px; background: #f1f5f9; border-radius: 8px; font-size: 13px;">
|
||||||
|
<strong>Связи:</strong>
|
||||||
|
User 1→N Recording → 1→1 Transcription → 1→N Protocol → 1→N ExportFile<br>
|
||||||
|
PromptTemplate 1→N Protocol
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Управление хранилищем</h3>
|
||||||
|
<div style="background: #fefce8; border: 1px solid #fde047; border-radius: 8px; padding: 16px; font-size: 14px;">
|
||||||
|
<ul style="line-height: 1.8; margin: 0;">
|
||||||
|
<li><strong>Retention policies</strong> — настраиваемый срок хранения для записей, транскрипций и экспортов (по умолчанию: 90 дней)</li>
|
||||||
|
<li><strong>Ручная очистка</strong> — админ может удалить старые данные из UI (записи + связанные файлы)</li>
|
||||||
|
<li><strong>Автоочистка</strong> — Celery beat задача по расписанию удаляет данные старше retention period</li>
|
||||||
|
<li><strong>Дашборд хранилища</strong> — в админке видно занятое место (файлы + БД) с разбивкой по типам</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
<h2>Секция 5: Деплой и технологический стек</h2>
|
||||||
|
<p class="subtitle">Развёртывание на сервере 78.153.7.224</p>
|
||||||
|
|
||||||
|
<div class="mockup">
|
||||||
|
<div class="mockup-header">Docker Compose — контейнеры на сервере</div>
|
||||||
|
<div class="mockup-body" style="padding: 24px; font-size: 13px;">
|
||||||
|
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 16px; border-radius: 8px; margin-bottom: 16px;">
|
||||||
|
<div style="font-weight: bold; color: #60a5fa; margin-bottom: 12px;">🖥️ Сервер 78.153.7.224 — i9-10900 / 32GB RAM / RTX 3070 Ti</div>
|
||||||
|
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
||||||
|
|
||||||
|
<div style="background: #334155; padding: 10px; border-radius: 6px; border-top: 3px solid #3b82f6; flex: 1; min-width: 140px;">
|
||||||
|
<strong style="color: #60a5fa;">app</strong><br>
|
||||||
|
<small>FastAPI + Uvicorn<br>API + Web serving<br>Port 8000</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #334155; padding: 10px; border-radius: 6px; border-top: 3px solid #f59e0b; flex: 1; min-width: 140px;">
|
||||||
|
<strong style="color: #fbbf24;">worker</strong><br>
|
||||||
|
<small>Celery worker<br>Whisper (GPU)<br>LLM вызовы</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #334155; padding: 10px; border-radius: 6px; border-top: 3px solid #8b5cf6; flex: 1; min-width: 140px;">
|
||||||
|
<strong style="color: #a78bfa;">beat</strong><br>
|
||||||
|
<small>Celery beat<br>Автоочистка<br>Scheduled tasks</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #334155; padding: 10px; border-radius: 6px; border-top: 3px solid #dc2626; flex: 1; min-width: 140px;">
|
||||||
|
<strong style="color: #f87171;">redis</strong><br>
|
||||||
|
<small>Redis 7<br>Брокер задач<br>Кэш</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #334155; padding: 10px; border-radius: 6px; border-top: 3px solid #2563eb; flex: 1; min-width: 140px;">
|
||||||
|
<strong style="color: #60a5fa;">db</strong><br>
|
||||||
|
<small>PostgreSQL 16<br>Данные<br>Port 5432</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #334155; padding: 10px; border-radius: 6px; border-top: 3px solid #10b981; flex: 1; min-width: 140px;">
|
||||||
|
<strong style="color: #34d399;">nginx</strong><br>
|
||||||
|
<small>Reverse proxy<br>Static files<br>Port 80/443</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Полный стек технологий</h3>
|
||||||
|
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong style="color: #3b82f6;">Backend</strong><br>
|
||||||
|
Python 3.11+<br>
|
||||||
|
FastAPI + Uvicorn<br>
|
||||||
|
Celery + Redis<br>
|
||||||
|
SQLAlchemy + Alembic<br>
|
||||||
|
Pydantic v2
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong style="color: #f59e0b;">AI / ML</strong><br>
|
||||||
|
Whisper large-v3 (faster-whisper)<br>
|
||||||
|
CUDA 12 + cuDNN<br>
|
||||||
|
FFmpeg (извлечение аудио)<br>
|
||||||
|
LiteLLM (unified LLM API)<br>
|
||||||
|
OpenRouter / Groq / платные
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong style="color: #10b981;">Frontend</strong><br>
|
||||||
|
React + TypeScript<br>
|
||||||
|
Vite (сборка)<br>
|
||||||
|
Tailwind CSS<br>
|
||||||
|
React Query (API)<br>
|
||||||
|
React Router
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong style="color: #8b5cf6;">Мессенджеры</strong><br>
|
||||||
|
aiogram 3.x (Telegram)<br>
|
||||||
|
Lensa SDK/webhook<br>
|
||||||
|
Общий MessengerService
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong style="color: #dc2626;">Экспорт</strong><br>
|
||||||
|
python-docx (DOCX)<br>
|
||||||
|
WeasyPrint (PDF)<br>
|
||||||
|
Jinja2 (шаблоны)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong style="color: #6b7280;">Инфра</strong><br>
|
||||||
|
Docker + Docker Compose<br>
|
||||||
|
NVIDIA Container Toolkit<br>
|
||||||
|
Nginx (reverse proxy)<br>
|
||||||
|
Gitea (http://78.153.7.224:3000)<br>
|
||||||
|
Alembic (миграции БД)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Распределение ресурсов сервера</h3>
|
||||||
|
<div style="background: #fefce8; border: 1px solid #fde047; border-radius: 8px; padding: 16px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<ul style="margin: 0;">
|
||||||
|
<li><strong>GPU (8 GB VRAM)</strong> — целиком для Whisper (faster-whisper загружает модель ~3 GB, остальное — буфер обработки)</li>
|
||||||
|
<li><strong>RAM (32 GB)</strong> — ~4 GB PostgreSQL, ~2 GB Redis, ~4 GB FastAPI + workers, ~8 GB Whisper worker, остальное — ОС и запас</li>
|
||||||
|
<li><strong>CPU (i9-10900, 10 ядер)</strong> — хватит для параллельной обработки API + воркеры</li>
|
||||||
|
<li><strong>SSD 1 TB</strong> — ОС, Docker, БД, активные файлы</li>
|
||||||
|
<li><strong>HDD 1 TB</strong> — архивное хранение старых записей (перемещение по retention policy)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>CI/CD</h3>
|
||||||
|
<div style="background: #f1f5f9; padding: 16px; border-radius: 8px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<ul style="margin: 0;">
|
||||||
|
<li>Код хранится в <strong>Gitea</strong> на http://78.153.7.224:3000</li>
|
||||||
|
<li>Деплой — <code>docker compose up -d --build</code> на сервере (ручной или через Gitea webhook)</li>
|
||||||
|
<li>Миграции БД — <code>alembic upgrade head</code> при старте контейнера app</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
<h2>Секция 4: Интеграция с мессенджерами</h2>
|
||||||
|
<p class="subtitle">Telegram и Lensa боты — полный цикл работы</p>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h3>Сценарий взаимодействия с ботом</h3>
|
||||||
|
<div class="mockup">
|
||||||
|
<div class="mockup-header">Telegram / Lensa — диалог с ботом</div>
|
||||||
|
<div class="mockup-body" style="padding: 20px; background: #0e1621; color: #e2e8f0; font-size: 13px; line-height: 1.8;">
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px;">
|
||||||
|
<div style="background: #2b5278; padding: 8px 14px; border-radius: 12px 12px 12px 4px; display: inline-block; max-width: 80%;">
|
||||||
|
👤 <em>Пользователь отправляет видео/аудио файл</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; text-align: right;">
|
||||||
|
<div style="background: #2b5278; padding: 8px 14px; border-radius: 12px 12px 4px 12px; display: inline-block; max-width: 80%; text-align: left; background: #1e3a5f;">
|
||||||
|
🤖 Файл получен! Выберите тип протокола:<br><br>
|
||||||
|
<span style="display: inline-flex; gap: 6px; flex-wrap: wrap;">
|
||||||
|
<span style="background: #3b82f6; padding: 4px 12px; border-radius: 6px; font-size: 12px;">📋 Обследование процессов</span>
|
||||||
|
<span style="background: #3b82f6; padding: 4px 12px; border-radius: 6px; font-size: 12px;">🤝 Вводная встреча</span>
|
||||||
|
<span style="background: #3b82f6; padding: 4px 12px; border-radius: 6px; font-size: 12px;">🏢 Внутренняя встреча</span>
|
||||||
|
<span style="background: #3b82f6; padding: 4px 12px; border-radius: 6px; font-size: 12px;">⚙️ Кастомный</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px;">
|
||||||
|
<div style="background: #2b5278; padding: 8px 14px; border-radius: 12px 12px 12px 4px; display: inline-block;">
|
||||||
|
👤 <em>Нажимает «Обследование процессов»</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; text-align: right;">
|
||||||
|
<div style="background: #1e3a5f; padding: 8px 14px; border-radius: 12px 12px 4px 12px; display: inline-block; max-width: 80%; text-align: left;">
|
||||||
|
🤖 ⏳ Принято! Обработка займёт несколько минут.<br>
|
||||||
|
<span style="color: #94a3b8;">Транскрибация: ▓▓▓▓░░░░ 50%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; text-align: right;">
|
||||||
|
<div style="background: #1e3a5f; padding: 8px 14px; border-radius: 12px 12px 4px 12px; display: inline-block; max-width: 80%; text-align: left;">
|
||||||
|
🤖 ✅ Протокол готов!<br><br>
|
||||||
|
<strong>Тема:</strong> Обследование процесса закупок ООО «Клиент»<br>
|
||||||
|
<strong>Дата:</strong> 01.04.2026<br>
|
||||||
|
<strong>Участники:</strong> Иванов И.И., Петров П.П., ...<br><br>
|
||||||
|
<em style="color: #94a3b8;">[показан полный текст протокола]</em><br><br>
|
||||||
|
<span style="display: inline-flex; gap: 6px; flex-wrap: wrap;">
|
||||||
|
<span style="background: #10b981; padding: 4px 12px; border-radius: 6px; font-size: 12px;">📄 DOCX</span>
|
||||||
|
<span style="background: #10b981; padding: 4px 12px; border-radius: 6px; font-size: 12px;">📕 PDF</span>
|
||||||
|
<span style="background: #10b981; padding: 4px 12px; border-radius: 6px; font-size: 12px;">📝 MD</span>
|
||||||
|
<span style="background: #f59e0b; padding: 4px 12px; border-radius: 6px; font-size: 12px;">🔄 Перегенерировать</span>
|
||||||
|
<span style="background: #6366f1; padding: 4px 12px; border-radius: 6px; font-size: 12px;">🌐 Открыть в вебе</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Команды бота</h3>
|
||||||
|
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong>Основные</strong><br>
|
||||||
|
<code>/start</code> — авторизация (логин/пароль)<br>
|
||||||
|
<code>/upload</code> — загрузить файл (или просто отправить)<br>
|
||||||
|
<code>/list</code> — список записей<br>
|
||||||
|
<code>/protocols</code> — список протоколов
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong>Работа с протоколами</strong><br>
|
||||||
|
<code>/view [id]</code> — просмотреть протокол<br>
|
||||||
|
<code>/export [id] [формат]</code> — экспорт<br>
|
||||||
|
<code>/regenerate [id]</code> — перегенерировать<br>
|
||||||
|
<code>/templates</code> — список шаблонов
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px; border-radius: 8px; flex: 1; min-width: 220px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<strong>Настройки</strong><br>
|
||||||
|
<code>/settings</code> — шаблон по умолчанию<br>
|
||||||
|
<code>/help</code> — справка<br>
|
||||||
|
<code>/logout</code> — выход
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 24px;">
|
||||||
|
<h3>Технические детали</h3>
|
||||||
|
<div style="background: #f1f5f9; padding: 16px; border-radius: 8px; font-size: 13px; line-height: 1.8;">
|
||||||
|
<ul style="margin: 0;">
|
||||||
|
<li><strong>Telegram</strong> — aiogram 3.x, webhook mode (через FastAPI), inline-кнопки для навигации</li>
|
||||||
|
<li><strong>Lensa</strong> — SDK/webhook интеграция (аналогичный интерфейс)</li>
|
||||||
|
<li><strong>Общий слой</strong> — единый MessengerService абстрагирует логику от конкретного мессенджера</li>
|
||||||
|
<li><strong>Лимит файлов</strong> — Telegram ограничивает загрузку 50 МБ через бот API; для больших файлов — ссылка на веб-загрузку</li>
|
||||||
|
<li><strong>Авторизация</strong> — привязка аккаунта мессенджера к учётной записи через /start</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
<h2>Секция 3: Шаблоны протоколов и веб-интерфейс</h2>
|
||||||
|
<p class="subtitle">Предустановленные промпты и структура UI</p>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h3>Предустановленные шаблоны протоколов</h3>
|
||||||
|
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
|
||||||
|
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 16px; border-radius: 8px; flex: 1; min-width: 250px; border-left: 4px solid #8b5cf6;">
|
||||||
|
<div style="font-weight: bold; color: #a78bfa; margin-bottom: 8px;">📋 Обследование процессов клиента</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<div style="color: #94a3b8; margin-bottom: 4px;">Разделы протокола:</div>
|
||||||
|
1. Дата, участники, тема встречи<br>
|
||||||
|
2. Описание обследуемого процесса<br>
|
||||||
|
<small style="color: #64748b;"> (задачи бизнеса, подпроцесс)</small><br>
|
||||||
|
3. Текущее состояние (as-is)<br>
|
||||||
|
4. Выявленные проблемы / узкие места<br>
|
||||||
|
5. Договорённости и решения<br>
|
||||||
|
6. Открытые вопросы<br>
|
||||||
|
7. Задачи с ответственными и сроками<br>
|
||||||
|
8. Следующие шаги
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 16px; border-radius: 8px; flex: 1; min-width: 250px; border-left: 4px solid #3b82f6;">
|
||||||
|
<div style="font-weight: bold; color: #60a5fa; margin-bottom: 8px;">🏢 Внутренняя рабочая встреча</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<div style="color: #94a3b8; margin-bottom: 4px;">Разделы протокола:</div>
|
||||||
|
1. Дата, участники, тема<br>
|
||||||
|
2. Обсуждённые вопросы<br>
|
||||||
|
3. Принятые решения<br>
|
||||||
|
4. Задачи с ответственными и сроками<br>
|
||||||
|
5. Следующие шаги
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: #1e293b; color: #e2e8f0; padding: 16px; border-radius: 8px; flex: 1; min-width: 250px; border-left: 4px solid #10b981;">
|
||||||
|
<div style="font-weight: bold; color: #34d399; margin-bottom: 8px;">⚡ Стендап / короткая встреча</div>
|
||||||
|
<div style="font-size: 12px; line-height: 1.8;">
|
||||||
|
<div style="color: #94a3b8; margin-bottom: 4px;">Разделы протокола:</div>
|
||||||
|
1. Дата, участники<br>
|
||||||
|
2. Статус по задачам (кто / что сделал)<br>
|
||||||
|
3. Блокеры и проблемы<br>
|
||||||
|
4. План на следующий период
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 12px; font-size: 13px; color: #64748b;">
|
||||||
|
+ Возможность создать кастомный шаблон с произвольными разделами и промптом
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 28px;">
|
||||||
|
<h3>Структура веб-интерфейса</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mockup">
|
||||||
|
<div class="mockup-header">Основные экраны</div>
|
||||||
|
<div class="mockup-body" style="padding: 0;">
|
||||||
|
|
||||||
|
<!-- Nav -->
|
||||||
|
<div style="background: #1e293b; color: white; padding: 10px 20px; display: flex; justify-content: space-between; align-items: center; font-size: 13px;">
|
||||||
|
<div style="display: flex; gap: 20px; align-items: center;">
|
||||||
|
<strong style="color: #60a5fa;">MeetingProto</strong>
|
||||||
|
<span>Записи</span>
|
||||||
|
<span>Протоколы</span>
|
||||||
|
<span>Шаблоны</span>
|
||||||
|
<span style="color: #94a3b8;">Настройки</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 12px; font-size: 12px;">
|
||||||
|
<span style="color: #64748b;">Занято: 45.2 ГБ</span>
|
||||||
|
<span>👤 admin</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Recordings list -->
|
||||||
|
<div style="padding: 20px;">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||||||
|
<h3 style="margin: 0;">Записи</h3>
|
||||||
|
<div style="display: flex; gap: 8px;">
|
||||||
|
<button style="background: #3b82f6; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer;">+ Загрузить</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="font-size: 13px;">
|
||||||
|
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 8px 0; border-bottom: 1px solid #e2e8f0; font-weight: bold; color: #64748b;">
|
||||||
|
<span>Название</span>
|
||||||
|
<span>Источник</span>
|
||||||
|
<span>Длительность</span>
|
||||||
|
<span>Статус</span>
|
||||||
|
<span>Действия</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 10px 0; border-bottom: 1px solid #f1f5f9;">
|
||||||
|
<span>Обследование_КлиентА_2026-04-01.mp4</span>
|
||||||
|
<span style="color: #8b5cf6;">🌐 Web</span>
|
||||||
|
<span>01:23:45</span>
|
||||||
|
<span><span style="background: #d1fae5; color: #065f46; padding: 2px 8px; border-radius: 10px; font-size: 11px;">Готово</span></span>
|
||||||
|
<span style="color: #3b82f6;">Протокол | Скачать</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 10px 0; border-bottom: 1px solid #f1f5f9;">
|
||||||
|
<span>standup_2026-04-02.ogg</span>
|
||||||
|
<span style="color: #8b5cf6;">💬 Telegram</span>
|
||||||
|
<span>00:15:32</span>
|
||||||
|
<span><span style="background: #fef3c7; color: #92400e; padding: 2px 8px; border-radius: 10px; font-size: 11px;">Транскрибация...</span></span>
|
||||||
|
<span style="color: #94a3b8;">—</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 8px; padding: 10px 0; border-bottom: 1px solid #f1f5f9;">
|
||||||
|
<span>retro_sprint42.webm</span>
|
||||||
|
<span style="color: #8b5cf6;">💬 Lensa</span>
|
||||||
|
<span>00:45:10</span>
|
||||||
|
<span><span style="background: #dbeafe; color: #1e40af; padding: 2px 8px; border-radius: 10px; font-size: 11px;">Протокол...</span></span>
|
||||||
|
<span style="color: #94a3b8;">—</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" style="margin-top: 20px;">
|
||||||
|
<h3>Страницы интерфейса</h3>
|
||||||
|
<div style="display: flex; gap: 12px; flex-wrap: wrap; font-size: 13px;">
|
||||||
|
<div style="background: #f1f5f9; padding: 12px; border-radius: 8px; flex: 1; min-width: 200px;">
|
||||||
|
<strong>Записи</strong> — список, загрузка, статус обработки, фильтры по источнику/дате
|
||||||
|
</div>
|
||||||
|
<div style="background: #f1f5f9; padding: 12px; border-radius: 8px; flex: 1; min-width: 200px;">
|
||||||
|
<strong>Протоколы</strong> — просмотр, редактирование, экспорт в DOCX/PDF/MD, перегенерация с другим шаблоном
|
||||||
|
</div>
|
||||||
|
<div style="background: #f1f5f9; padding: 12px; border-radius: 8px; flex: 1; min-width: 200px;">
|
||||||
|
<strong>Шаблоны</strong> — управление промптами, создание кастомных шаблонов, предпросмотр
|
||||||
|
</div>
|
||||||
|
<div style="background: #f1f5f9; padding: 12px; border-radius: 8px; flex: 1; min-width: 200px;">
|
||||||
|
<strong>Настройки</strong> — LLM провайдер/модель, retention period, очистка данных, API ключи, профиль
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"reason":"idle timeout","timestamp":1775226043406}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{"type":"server-started","port":56999,"host":"127.0.0.1","url_host":"localhost","url":"http://localhost:56999","screen_dir":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content","state_dir":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/state"}
|
||||||
|
{"type":"screen-added","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/approaches.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/approaches.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/approaches.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/approaches.html"}
|
||||||
|
{"source":"user-event","type":"click","text":"B\n \n Модульный монолит с очередями (рекомендация)\n Стек: FastAPI + Celery + PostgreSQL + Redis + React/Vue\n Единый деплой, но внутри — изолированные модули: API, транскрибация, генерация протоколов, боты мессенджеров. Общение между модулями — через очереди задач (Celery/Redis). Каждый модуль можно выделить в отдельный сервис позже.\n \n \n ✓ Плюсы\n \n Баланс простоты и масштабируемости\n Модули изолированы — падение воркера не роняет API\n Легко выделить модуль в микросервис при росте\n Один деплой, но чистая архитектура\n \n \n \n ✗ Минусы\n \n Чуть больше начальной настройки чем чистый монолит\n Нужна дисциплина разделения модулей","choice":"b","id":null,"timestamp":1775223177656}
|
||||||
|
{"type":"screen-added","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/architecture.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/architecture.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/architecture.html"}
|
||||||
|
{"type":"screen-added","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/data-model.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/data-model.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/data-model.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/data-model.html"}
|
||||||
|
{"type":"screen-added","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/templates-and-ui.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/templates-and-ui.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/templates-and-ui.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/templates-and-ui.html"}
|
||||||
|
{"type":"screen-added","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/messengers.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/messengers.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/messengers.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/messengers.html"}
|
||||||
|
{"type":"screen-added","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/deployment.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/deployment.html"}
|
||||||
|
{"type":"screen-updated","file":"/Users/romanchesnokov/Library/CloudStorage/OneDrive-Личная/Работа/Внутренние проекты/meeting_recording_analysis/.superpowers/brainstorm/47219-1775222083/content/deployment.html"}
|
||||||
|
{"type":"server-stopped","reason":"idle timeout"}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
47231
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,267 @@
|
|||||||
|
# Meeting Protocol Service — Design Spec
|
||||||
|
|
||||||
|
Сервис транскрибации аудио/видео записей встреч и автоматической генерации протоколов с использованием локальной модели Whisper и внешних LLM.
|
||||||
|
|
||||||
|
## 1. Цели и контекст
|
||||||
|
|
||||||
|
- Автоматизация создания протоколов по записям встреч (внутренних и с клиентами)
|
||||||
|
- Протоколы клиентских встреч — основа для результирующей документации по обследованию процессов
|
||||||
|
- Бесплатная локальная транскрибация (Whisper на GPU)
|
||||||
|
- Генерация протоколов через бесплатные/платные LLM API
|
||||||
|
- Веб-интерфейс + полнофункциональные боты в Telegram и Lensa
|
||||||
|
- Хранение кода и версионирование в Gitea на http://78.153.7.224:3000
|
||||||
|
|
||||||
|
## 2. Архитектура
|
||||||
|
|
||||||
|
### Подход: модульный монолит
|
||||||
|
|
||||||
|
Единый деплой с изолированными модулями, общение между которыми — через очереди задач (Celery/Redis). Каждый модуль можно выделить в отдельный сервис при необходимости.
|
||||||
|
|
||||||
|
### Модули
|
||||||
|
|
||||||
|
| Модуль | Ответственность |
|
||||||
|
|--------|----------------|
|
||||||
|
| **API** | REST endpoints, авторизация (JWT), загрузка файлов, раздача SPA |
|
||||||
|
| **Транскрибация** | Извлечение аудио (FFmpeg), транскрибация (faster-whisper на GPU) |
|
||||||
|
| **Протоколирование** | Вызов LLM, применение шаблонов промптов, экспорт DOCX/PDF/MD |
|
||||||
|
| **Мессенджеры** | Telegram бот (aiogram 3.x), Lensa бот (SDK/webhook), общий MessengerService |
|
||||||
|
|
||||||
|
### Поток обработки записи
|
||||||
|
|
||||||
|
1. Загрузка файла (web / telegram / lensa)
|
||||||
|
2. Извлечение аудио из видео (FFmpeg) — Celery task
|
||||||
|
3. Транскрибация (faster-whisper large-v3, GPU) — Celery task
|
||||||
|
4. Генерация протокола (LLM через LiteLLM) — Celery task
|
||||||
|
5. Сохранение результата, уведомление пользователя
|
||||||
|
6. Экспорт по запросу (DOCX/PDF/MD)
|
||||||
|
|
||||||
|
### Асинхронная обработка
|
||||||
|
|
||||||
|
Все тяжёлые операции (шаги 2-4) выполняются в Celery workers и не блокируют API. Пользователь получает обновления о прогрессе через polling (web) и push-уведомления (мессенджеры).
|
||||||
|
|
||||||
|
## 3. Модель данных
|
||||||
|
|
||||||
|
### User
|
||||||
|
- `id` UUID PK
|
||||||
|
- `username` str unique
|
||||||
|
- `email` str unique
|
||||||
|
- `password_hash` str
|
||||||
|
- `role` enum: admin, user (расширяемо)
|
||||||
|
- `is_active` bool
|
||||||
|
- `created_at` timestamp
|
||||||
|
|
||||||
|
### Recording
|
||||||
|
- `id` UUID PK
|
||||||
|
- `user_id` FK → User
|
||||||
|
- `title` str
|
||||||
|
- `file_path` str
|
||||||
|
- `file_size` bigint
|
||||||
|
- `duration` interval
|
||||||
|
- `format` str (mp4, webm, mp3, wav, ogg)
|
||||||
|
- `source` enum: web, telegram, lensa
|
||||||
|
- `status` enum: uploaded, processing, done, error
|
||||||
|
- `created_at` timestamp
|
||||||
|
|
||||||
|
### Transcription
|
||||||
|
- `id` UUID PK
|
||||||
|
- `recording_id` FK → Recording (1:1)
|
||||||
|
- `text` text
|
||||||
|
- `segments` JSONB (массив сегментов с таймкодами)
|
||||||
|
- `language` str
|
||||||
|
- `whisper_model` str
|
||||||
|
- `processing_time` interval
|
||||||
|
- `created_at` timestamp
|
||||||
|
|
||||||
|
### Protocol
|
||||||
|
- `id` UUID PK
|
||||||
|
- `transcription_id` FK → Transcription
|
||||||
|
- `template_id` FK → PromptTemplate
|
||||||
|
- `content` JSONB (структурированный по разделам)
|
||||||
|
- `raw_text` text
|
||||||
|
- `llm_model` str
|
||||||
|
- `status` enum: generating, done, error
|
||||||
|
- `created_at` timestamp
|
||||||
|
- `updated_at` timestamp
|
||||||
|
|
||||||
|
### PromptTemplate
|
||||||
|
- `id` UUID PK
|
||||||
|
- `name` str
|
||||||
|
- `description` str
|
||||||
|
- `type` enum: client_survey, client_intro, internal, custom
|
||||||
|
- `system_prompt` text
|
||||||
|
- `user_prompt` text
|
||||||
|
- `output_schema` JSONB (описание ожидаемых разделов)
|
||||||
|
- `is_default` bool
|
||||||
|
- `created_at` timestamp
|
||||||
|
|
||||||
|
### ExportFile
|
||||||
|
- `id` UUID PK
|
||||||
|
- `protocol_id` FK → Protocol
|
||||||
|
- `format` enum: docx, pdf, md
|
||||||
|
- `file_path` str
|
||||||
|
- `file_size` bigint
|
||||||
|
- `created_at` timestamp
|
||||||
|
|
||||||
|
### Связи
|
||||||
|
|
||||||
|
```
|
||||||
|
User 1→N Recording 1→1 Transcription 1→N Protocol 1→N ExportFile
|
||||||
|
PromptTemplate 1→N Protocol
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Предустановленные шаблоны протоколов
|
||||||
|
|
||||||
|
### 4.1 Обследование процессов клиента
|
||||||
|
|
||||||
|
Разделы:
|
||||||
|
1. Дата, участники, тема встречи
|
||||||
|
2. Описание обследуемого процесса (задачи бизнеса, подпроцесс)
|
||||||
|
3. Текущее состояние (as-is)
|
||||||
|
4. Выявленные проблемы / узкие места
|
||||||
|
5. Договорённости и решения
|
||||||
|
6. Открытые вопросы (о которых не договорились)
|
||||||
|
7. Задачи с ответственными и сроками
|
||||||
|
8. Следующие шаги
|
||||||
|
|
||||||
|
### 4.2 Вводная встреча-знакомство с клиентом
|
||||||
|
|
||||||
|
Разделы:
|
||||||
|
1. Дата, участники, тема встречи
|
||||||
|
2. Верхнеуровневые цели клиента
|
||||||
|
3. Параметры будущего проекта
|
||||||
|
4. Бюджетные ограничения
|
||||||
|
5. Ограничения по срокам
|
||||||
|
6. Лица, принимающие решения (ЛПР)
|
||||||
|
7. Бенефициары
|
||||||
|
8. Лица, влияющие на принятие решения
|
||||||
|
9. Договорённости и решения
|
||||||
|
10. Открытые вопросы
|
||||||
|
11. Следующие шаги
|
||||||
|
|
||||||
|
### 4.3 Внутренняя рабочая встреча
|
||||||
|
|
||||||
|
Разделы:
|
||||||
|
1. Дата, участники, тема
|
||||||
|
2. Обсуждённые вопросы
|
||||||
|
3. Выявленные проблемы
|
||||||
|
4. Принятые решения
|
||||||
|
5. Открытые вопросы
|
||||||
|
6. Задачи с ответственными и сроками
|
||||||
|
7. Следующие шаги
|
||||||
|
|
||||||
|
### 4.4 Кастомный шаблон
|
||||||
|
|
||||||
|
Пользователь может создать свой шаблон с произвольными разделами и промптом через веб-интерфейс или бот.
|
||||||
|
|
||||||
|
## 5. Веб-интерфейс
|
||||||
|
|
||||||
|
### Страницы
|
||||||
|
|
||||||
|
| Страница | Функционал |
|
||||||
|
|----------|-----------|
|
||||||
|
| **Записи** | Список записей с фильтрами по источнику/дате, загрузка файлов, статус обработки |
|
||||||
|
| **Протоколы** | Просмотр, редактирование, экспорт (DOCX/PDF/MD), перегенерация с другим шаблоном |
|
||||||
|
| **Шаблоны** | Управление промптами, создание кастомных шаблонов, предпросмотр |
|
||||||
|
| **Настройки** | LLM провайдер/модель, API-ключи, retention period, очистка данных, профиль |
|
||||||
|
|
||||||
|
### Навигация
|
||||||
|
|
||||||
|
Шапка: логотип, разделы (Записи, Протоколы, Шаблоны, Настройки), индикатор занятого дискового пространства ("Занято: N ГБ"), профиль пользователя.
|
||||||
|
|
||||||
|
### Стек фронтенда
|
||||||
|
|
||||||
|
- React + TypeScript
|
||||||
|
- Vite (сборка)
|
||||||
|
- Tailwind CSS
|
||||||
|
- React Query (работа с API)
|
||||||
|
- React Router
|
||||||
|
|
||||||
|
## 6. Интеграция с мессенджерами
|
||||||
|
|
||||||
|
### Сценарий работы
|
||||||
|
|
||||||
|
1. Пользователь отправляет файл в бот
|
||||||
|
2. Бот предлагает выбрать тип протокола (inline-кнопки)
|
||||||
|
3. Бот показывает прогресс обработки
|
||||||
|
4. Бот отправляет готовый протокол + кнопки: экспорт (DOCX/PDF/MD), перегенерация, открыть в вебе
|
||||||
|
|
||||||
|
### Команды бота
|
||||||
|
|
||||||
|
**Основные:** `/start` (авторизация), `/upload` (или просто отправить файл), `/list` (записи), `/protocols` (протоколы)
|
||||||
|
|
||||||
|
**Работа с протоколами:** `/view [id]`, `/export [id] [формат]`, `/regenerate [id]`, `/templates`
|
||||||
|
|
||||||
|
**Настройки:** `/settings` (шаблон по умолчанию), `/help`, `/logout`
|
||||||
|
|
||||||
|
### Технические детали
|
||||||
|
|
||||||
|
- **Telegram** — aiogram 3.x, webhook mode через FastAPI, inline-кнопки
|
||||||
|
- **Lensa** — SDK/webhook интеграция с аналогичным интерфейсом
|
||||||
|
- **MessengerService** — общий слой абстракции, единая логика для обоих мессенджеров
|
||||||
|
- **Лимит файлов** — Telegram Bot API ограничивает 50 МБ; для больших файлов — ссылка на веб-загрузку
|
||||||
|
- **Авторизация** — привязка аккаунта мессенджера к учётной записи через `/start` (логин/пароль)
|
||||||
|
|
||||||
|
## 7. Авторизация
|
||||||
|
|
||||||
|
- Базовая: логин/пароль, JWT-токены
|
||||||
|
- Роли: admin, user (расширяемо в будущем)
|
||||||
|
- Все авторизованные пользователи видят все протоколы
|
||||||
|
- Привязка аккаунтов мессенджеров к учётной записи
|
||||||
|
- Подготовлена структура для расширения ролевой модели (поле role — enum, легко расширить)
|
||||||
|
|
||||||
|
## 8. Управление хранилищем
|
||||||
|
|
||||||
|
- **Retention policies** — настраиваемый срок хранения для записей, транскрипций и экспортов (по умолчанию: 90 дней)
|
||||||
|
- **Ручная очистка** — админ может удалить старые данные из настроек (записи + связанные файлы)
|
||||||
|
- **Автоочистка** — Celery beat задача по расписанию удаляет данные старше retention period
|
||||||
|
- **Индикатор** — в шапке навигации отображается занятое место ("Занято: N ГБ")
|
||||||
|
- **Стратегия хранения** — SSD для активных данных (ОС, Docker, БД), HDD для архива (старые записи)
|
||||||
|
|
||||||
|
## 9. Деплой
|
||||||
|
|
||||||
|
### Сервер
|
||||||
|
|
||||||
|
- **Адрес:** 78.153.7.224
|
||||||
|
- **ОС:** Windows (Docker Desktop установлен, PostgreSQL и другие сервисы уже развёрнуты)
|
||||||
|
- **CPU:** Intel i9-10900 (10 ядер, 2.8 GHz)
|
||||||
|
- **RAM:** 32 GB
|
||||||
|
- **GPU:** NVIDIA RTX 3070 Ti (8 GB VRAM)
|
||||||
|
- **Хранилище:** 1 TB SSD + 1 TB HDD
|
||||||
|
|
||||||
|
### Docker Compose — контейнеры
|
||||||
|
|
||||||
|
| Контейнер | Назначение |
|
||||||
|
|-----------|-----------|
|
||||||
|
| `app` | FastAPI + Uvicorn, API + раздача SPA, port 8000 |
|
||||||
|
| `worker` | Celery worker с GPU доступом (Whisper + LLM вызовы) |
|
||||||
|
| `beat` | Celery beat — планировщик (автоочистка, scheduled tasks) |
|
||||||
|
| `redis` | Redis 7 — брокер задач + кэш |
|
||||||
|
| `db` | PostgreSQL 16 |
|
||||||
|
| `nginx` | Reverse proxy, static files, port 80/443 |
|
||||||
|
|
||||||
|
### Распределение ресурсов
|
||||||
|
|
||||||
|
- **GPU (8 GB VRAM)** — faster-whisper large-v3 (~3 GB модель, остальное — буфер)
|
||||||
|
- **RAM** — ~4 GB PostgreSQL, ~2 GB Redis, ~4 GB FastAPI + workers, ~8 GB Whisper worker, остальное — ОС
|
||||||
|
- **CPU** — 10 ядер достаточно для параллельной работы API + воркеров
|
||||||
|
|
||||||
|
### Портативность
|
||||||
|
|
||||||
|
Архитектура на Docker Compose полностью переносима: `docker-compose.yml` + `.env` → `docker compose up -d` на любом сервере. При отсутствии GPU на целевом сервере — переключение faster-whisper на CPU-режим через переменную окружения.
|
||||||
|
|
||||||
|
### CI/CD
|
||||||
|
|
||||||
|
- Код — Gitea на http://78.153.7.224:3000
|
||||||
|
- Деплой — `docker compose up -d --build` (ручной или через Gitea webhook)
|
||||||
|
- Миграции — `alembic upgrade head` при старте контейнера `app`
|
||||||
|
|
||||||
|
## 10. Технологический стек — сводка
|
||||||
|
|
||||||
|
| Слой | Технологии |
|
||||||
|
|------|-----------|
|
||||||
|
| Backend | Python 3.11+, FastAPI, Uvicorn, Celery, Redis, SQLAlchemy, Alembic, Pydantic v2 |
|
||||||
|
| AI/ML | faster-whisper large-v3, CUDA 12 + cuDNN, FFmpeg, LiteLLM |
|
||||||
|
| Frontend | React, TypeScript, Vite, Tailwind CSS, React Query, React Router |
|
||||||
|
| Мессенджеры | aiogram 3.x (Telegram), Lensa SDK/webhook |
|
||||||
|
| Экспорт | python-docx (DOCX), WeasyPrint (PDF), Jinja2 (шаблоны) |
|
||||||
|
| Инфра | Docker, Docker Compose, NVIDIA Container Toolkit, Nginx, Gitea, Alembic |
|
||||||
Binary file not shown.
Reference in New Issue
Block a user