2026-09-28 21:14:38 +00:00
|
|
|
|
FROM python:3.11-slim AS base
|
каркас: домен, генерация типов фронта, стенд и карточки задач
Контракт в коде: КИО по нормативу, 43 события WS по шести союзам направлений,
таймеры ГОСТ, таксономия E1–E6, шесть компетенций радара. make types гоняет
их через JSON Schema в generated.ts, тест ловит забытую регенерацию.
Стенд: docker compose postgres + backend, health отвечает, база досягаема
из контейнера бэкенда. Makefile не врёт — нереализованные цели падают
и называют карточку, которая их закроет.
frontend/.npmrc: под WSL2 npm install зависает на дефолтных 15 сокетах.
2026-09-15 19:35:03 +03:00
|
|
|
|
|
|
|
|
|
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
|
|
|
|
|
|
|
|
|
|
WORKDIR /app
|
lct-06: голосовой контур VAD → STT → звонящий → TTS, с перебиванием
Контур замкнут без LLM: звонящий отвечает заготовками через слот-автомат.
Живой диалог через WebSocket прошёл 5 раз подряд без сбоев: первая
реплика после снятия трубки — 87–154 мс, ход — 1.2–1.4 с, перебивание —
88–90 мс. На LLM до цели 1.5 с остаётся 100–300 мс.
Задача ответа живёт, пока у курсанта доигрывает звук: перебивание —
это отмена одной задачи, и tts.end приходит, когда звонящий
действительно замолчал.
Что нашлось при сборке:
- Silero молча выбрасывает цифры: «улица Ленина, дом… квартира…» без
номеров. Числа и сокращения разворачиваются в слова до синтеза.
- onnxruntime брал все 16 ядер и вытеснял синтез, первый вызов был
холодным: распознавание 576 мс вместо ~210. Прогрев на старте и по
4 потока на модель.
- Весь адрес одним предложением — ~455 мс синтеза до первого звука.
Длинное предложение режется по запятым, номер от улицы не отрывается:
~250 мс.
- Первая реплика «Алло! Помогите!» запускалась мимо задачи ответа и не
перебивалась вовсе.
Отдельно: сломал make dev — num2words попал в pyproject, а Dockerfile
ставил зависимости ручным списком, и бэкенд в контейнере упал на
импорте. Образ теперь ставит зависимости из pyproject.toml.
Голоса в контейнере нет: под WSL модели работают нативно, make back.
2026-09-17 15:04:17 +03:00
|
|
|
|
ENV PYTHONUNBUFFERED=1
|
каркас: домен, генерация типов фронта, стенд и карточки задач
Контракт в коде: КИО по нормативу, 43 события WS по шести союзам направлений,
таймеры ГОСТ, таксономия E1–E6, шесть компетенций радара. make types гоняет
их через JSON Schema в generated.ts, тест ловит забытую регенерацию.
Стенд: docker compose postgres + backend, health отвечает, база досягаема
из контейнера бэкенда. Makefile не врёт — нереализованные цели падают
и называют карточку, которая их закроет.
frontend/.npmrc: под WSL2 npm install зависает на дефолтных 15 сокетах.
2026-09-15 19:35:03 +03:00
|
|
|
|
|
2026-09-21 17:40:54 +03:00
|
|
|
|
# Экспорт PDF требует локальный TTF с кириллицей; базовый slim-образ его не
|
|
|
|
|
|
# гарантирует. Шрифт запекается в образ при подготовке офлайн-комплекта.
|
2026-09-24 01:10:49 +03:00
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends fonts-dejavu-core postgresql-client \
|
2026-09-21 17:40:54 +03:00
|
|
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
|
|
|
lct-06: голосовой контур VAD → STT → звонящий → TTS, с перебиванием
Контур замкнут без LLM: звонящий отвечает заготовками через слот-автомат.
Живой диалог через WebSocket прошёл 5 раз подряд без сбоев: первая
реплика после снятия трубки — 87–154 мс, ход — 1.2–1.4 с, перебивание —
88–90 мс. На LLM до цели 1.5 с остаётся 100–300 мс.
Задача ответа живёт, пока у курсанта доигрывает звук: перебивание —
это отмена одной задачи, и tts.end приходит, когда звонящий
действительно замолчал.
Что нашлось при сборке:
- Silero молча выбрасывает цифры: «улица Ленина, дом… квартира…» без
номеров. Числа и сокращения разворачиваются в слова до синтеза.
- onnxruntime брал все 16 ядер и вытеснял синтез, первый вызов был
холодным: распознавание 576 мс вместо ~210. Прогрев на старте и по
4 потока на модель.
- Весь адрес одним предложением — ~455 мс синтеза до первого звука.
Длинное предложение режется по запятым, номер от улицы не отрывается:
~250 мс.
- Первая реплика «Алло! Помогите!» запускалась мимо задачи ответа и не
перебивалась вовсе.
Отдельно: сломал make dev — num2words попал в pyproject, а Dockerfile
ставил зависимости ручным списком, и бэкенд в контейнере упал на
импорте. Образ теперь ставит зависимости из pyproject.toml.
Голоса в контейнере нет: под WSL модели работают нативно, make back.
2026-09-17 15:04:17 +03:00
|
|
|
|
# Зависимости — из pyproject.toml, а не отдельным списком: ручной список разошёлся
|
|
|
|
|
|
# с проектом, и бэкенд в контейнере упал на первом же новом пакете (num2words).
|
2026-09-28 21:14:38 +00:00
|
|
|
|
# Голосовой контур (группа voice: torch, onnx-asr) в стадию base не входит —
|
|
|
|
|
|
# его вместе с весами добавляет стадия voice ниже.
|
каркас: домен, генерация типов фронта, стенд и карточки задач
Контракт в коде: КИО по нормативу, 43 события WS по шести союзам направлений,
таймеры ГОСТ, таксономия E1–E6, шесть компетенций радара. make types гоняет
их через JSON Schema в generated.ts, тест ловит забытую регенерацию.
Стенд: docker compose postgres + backend, health отвечает, база досягаема
из контейнера бэкенда. Makefile не врёт — нереализованные цели падают
и называют карточку, которая их закроет.
frontend/.npmrc: под WSL2 npm install зависает на дефолтных 15 сокетах.
2026-09-15 19:35:03 +03:00
|
|
|
|
COPY pyproject.toml ./
|
lct-06: голосовой контур VAD → STT → звонящий → TTS, с перебиванием
Контур замкнут без LLM: звонящий отвечает заготовками через слот-автомат.
Живой диалог через WebSocket прошёл 5 раз подряд без сбоев: первая
реплика после снятия трубки — 87–154 мс, ход — 1.2–1.4 с, перебивание —
88–90 мс. На LLM до цели 1.5 с остаётся 100–300 мс.
Задача ответа живёт, пока у курсанта доигрывает звук: перебивание —
это отмена одной задачи, и tts.end приходит, когда звонящий
действительно замолчал.
Что нашлось при сборке:
- Silero молча выбрасывает цифры: «улица Ленина, дом… квартира…» без
номеров. Числа и сокращения разворачиваются в слова до синтеза.
- onnxruntime брал все 16 ядер и вытеснял синтез, первый вызов был
холодным: распознавание 576 мс вместо ~210. Прогрев на старте и по
4 потока на модель.
- Весь адрес одним предложением — ~455 мс синтеза до первого звука.
Длинное предложение режется по запятым, номер от улицы не отрывается:
~250 мс.
- Первая реплика «Алло! Помогите!» запускалась мимо задачи ответа и не
перебивалась вовсе.
Отдельно: сломал make dev — num2words попал в pyproject, а Dockerfile
ставил зависимости ручным списком, и бэкенд в контейнере упал на
импорте. Образ теперь ставит зависимости из pyproject.toml.
Голоса в контейнере нет: под WSL модели работают нативно, make back.
2026-09-17 15:04:17 +03:00
|
|
|
|
RUN uv pip install --system -r pyproject.toml
|
каркас: домен, генерация типов фронта, стенд и карточки задач
Контракт в коде: КИО по нормативу, 43 события WS по шести союзам направлений,
таймеры ГОСТ, таксономия E1–E6, шесть компетенций радара. make types гоняет
их через JSON Schema в generated.ts, тест ловит забытую регенерацию.
Стенд: docker compose postgres + backend, health отвечает, база досягаема
из контейнера бэкенда. Makefile не врёт — нереализованные цели падают
и называют карточку, которая их закроет.
frontend/.npmrc: под WSL2 npm install зависает на дефолтных 15 сокетах.
2026-09-15 19:35:03 +03:00
|
|
|
|
|
|
|
|
|
|
COPY . .
|
|
|
|
|
|
EXPOSE 8000
|
|
|
|
|
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
2026-09-28 21:14:38 +00:00
|
|
|
|
|
|
|
|
|
|
# Прод-образ стенда: голосовой контур, сценарии и веса внутри, bind-mount'ов нет.
|
|
|
|
|
|
# Веса и сценарии приходят именованными контекстами сборки (docker-bake.hcl,
|
|
|
|
|
|
# docker-compose.yml): models=backend/models, scenarios=scenarios,
|
|
|
|
|
|
# licenses=deploy/licenses. В Dockerfile ничего не скачивается — хост Silero
|
|
|
|
|
|
# ненадёжен; нет файла — COPY падает с его именем, `make images` проверяет заранее.
|
|
|
|
|
|
# Whisper в образ не входит: единственный проверенный вживую STT — GigaAM.
|
|
|
|
|
|
FROM base AS voice
|
|
|
|
|
|
# torch только CPU-сборка: обычный PyPI тянет CUDA на гигабайты (pyproject).
|
|
|
|
|
|
RUN uv pip install --system --extra-index-url https://download.pytorch.org/whl/cpu \
|
|
|
|
|
|
'torch>=2.2' 'onnx-asr>=0.6' 'scipy>=1.11'
|
|
|
|
|
|
COPY --from=scenarios . /scenarios
|
|
|
|
|
|
# Из GigaAM — только RNNT int8: CTC-вариант стенд не загружает.
|
|
|
|
|
|
COPY --from=models gigaam-v3-onnx/config.json gigaam-v3-onnx/v3_vocab.txt \
|
|
|
|
|
|
gigaam-v3-onnx/v3_rnnt_encoder.int8.onnx gigaam-v3-onnx/v3_rnnt_decoder.int8.onnx \
|
|
|
|
|
|
gigaam-v3-onnx/v3_rnnt_joint.int8.onnx /app/models/gigaam-v3-onnx/
|
|
|
|
|
|
COPY --from=models silero-vad/silero_vad.onnx /app/models/silero-vad/
|
|
|
|
|
|
COPY --from=models silero-tts/v5_ru.pt /app/models/silero-tts/
|
|
|
|
|
|
COPY --from=models e5-small/config.json e5-small/model_quantized.onnx e5-small/tokenizer.json \
|
|
|
|
|
|
/app/models/e5-small/
|
|
|
|
|
|
COPY --from=licenses . /licenses
|