This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Архитектура
Страница описывает внутреннюю структуру GigaAM-Multilingual ASR Server: как взаимодействуют модули FastAPI, конвейер инференса на базе ONNX Runtime и система обнаружения речи (Silero VAD), а также показывает, как эти компоненты связаны между собой.
Общие сведения
Приложение реализовано как единый модуль src/gigam_asr/server.py, который выполняет роль HTTP-сервера, оркестратора загрузки моделей и диспетчера запросов. Такой подход минимизирует количество зависимостей и упрощает развёртывание в контейнере — весь жизненный цикл приложения управляется одним процессом.
Ключевые архитектурные решения:
- Отсутствие PyTorch/Transformers. Инференс выполняется исключительно через
onnx-asrи ONNX Runtime, что снижает размер образа и убирает зависимость от тяжёлых библиотек глубокого обучения. - Мульти-модельность. Несколько моделей (large и small) загружаются одновременно и выбираются клиентом полем
modelв каждом запросе. - Асинхронная обработка блокирующих вызовов. Вычисления инференса выносятся в отдельные потоки через
asyncio.to_thread, чтобы не блокировать событийный цикл FastAPI. - Разделение ответственности за аудио. Декодирование произвольных форматов (mp3, m4a, ogg, flac, wav) выполняется внешним
ffmpeg, нормализация до mono 16 кГц float32 — NumPy, распознавание — ONNX Runtime.
Компоненты системы
FastAPI-слой
Сервер построен на FastAPI с использованием контекстного менеджера жизненного цикла (lifespan). При старте приложения происходит однократная загрузка всех моделей из списка, заданного переменной окружения MODELS. После завершения загрузки состояние сохраняется в глобальном словаре _state, доступном всем обработчикам.
Реализованы следующие конечные точки:
| Метод | Путь | Назначение |
|---|---|---|
POST |
/v1/audio/transcriptions |
Основной эндпоинт транскрипции, совместимый с OpenAI API |
GET |
/v1/models |
Список загруженных моделей |
GET |
/health |
Проверка работоспособности и статус моделей |
Авторизация реализуется через Bearer-токены: при наличии переменной API_KEYS каждый запрос проверяется функцией _auth(). CORS-политика настраивается через CORS_ORIGINS и поддерживает preflight-запросы OPTIONS для совместимости с прокси-сервисами вроде LiteLLM.
Подробнее о параметрах запросов и формате ответов см. Справочник API.
Конвейер инференса (ONNX Runtime)
Ядро распознавания опирается на библиотеку onnx-asr версии 0.12, которая предоставляет адаптеры для работы с ONNX-моделями Conformer CTC. Архитектура конвейера следующая:
-
Загрузка моделей. Для каждой модели из
MODELSсоздаётся экземплярAsrAdapterизonnx_asr.adapters. Модели размещаются в отдельных подкаталогах{MODEL_DIR}/<имя>/, что позволяет резолверуonnx-asrкорректно находить файлы через glob-паттернmultilingual*_ctc. -
Выбор провайдера вычислений. Функция
_providers()определяет список execution providers ONNX Runtime в зависимости от значенияGIGAAm_CUDA:autoили1→CUDAExecutionProvider+CPUExecutionProvider0→ толькоCPUExecutionProvider
-
Распознавание. Функция
_recognize()вызываетmodel.recognize(wav, sample_rate=16000)в отдельном потоке. В зависимости от режима (короткая запись или long-form с VAD) возвращаемая структура различается:- Короткий режим: объект с полями
text,tokens,timestamps(метки времени на уровне символов). - Long-form (VAD): итератор сегментов
TimestampedSegmentResult, где метки времени относительны началу каждого сегмента и требуют сдвига наseg.start.
- Короткий режим: объект с полями
-
Формирование результата. Сырой вывод нормализуется в унифицированную структуру
{"text", "segments", "words"}. Группировка символьных меток времени в слова выполняется функцией_chars_to_words(), которая агрегирует последовательности токенов до пробелов.
Настройки производительности (квантизация, размер чанков, максимальная длительность) описаны в разделе Конфигурация. Анализ скорости обработки приведён в Производительность.
Silero VAD (Voice Activity Detection)
Для обработки длинных аудиозаписей (до 1 часа) используется модель Silero VAD в ONNX-формате. Она подключается к адаптеру onnx-asr при условии, что CHUNK_SECONDS > 0.
Роль VAD в системе:
- Сегментация речи. Длинное аудио разбивается на фрагменты, содержащие активную речь, что исключает распознавание тишины и снижает нагрузку на GPU/CPU.
- Ограничение размера входного буфера. Каждый сегмент обрабатывается независимо, что предотвращает переполнение памяти при работе с многочасовыми записями.
- Сохранение временных меток. Результаты VAD включают абсолютные границы сегментов (
start,end), которые используются для корректного позиционирования слов в итоговой транскрипции.
Модель VAD скачивается скриптом scripts/download_models.py из репозитория Hugging Face istupakov/silero-vad-onnx и размещается в {VAD_DIR}/silero_vad.onnx.
Обработка аудио
Входной поток аудио проходит несколько этапов преобразования перед подачей на модель:
- Декодирование. Функция
_to_pcm16()вызывает внешний процессffmpeg(илиimageio-ffmpeg) для конвертации любого поддерживаемого формата в моно-PCM 16 кГц. Путь к бинарнику может быть переопределён переменнойFFMPEG_BIN. - Преобразование типов. Байтовый поток PCM декодируется в массив NumPy типа
float32черезnp.frombuffer. - Проверка длительности. Если длительность превышает
MAX_DURATION, запрос отклоняется с ошибкой.
Такой подход позволяет принимать mp3, m4a, ogg, flac, wav и другие форматы без дополнительных Python-зависимостей для декодирования.
Схема взаимодействия компонентов
sequenceDiagram
participant Client as Клиент
participant API as FastAPI
participant FFmpeg as ffmpeg
participant ONNX as ONNX Runtime
participant VAD as Silero VAD
Client->>API: POST /v1/audio/transcriptions
API->>API: Проверка авторизации
API->>FFmpeg: Декодирование аудио в PCM 16kHz
FFmpeg-->>API: Mono float32 numpy array
API->>API: Выбор модели по полю model
alt Long-form mode enabled
API->>VAD: Сегментация речи
VAD-->>API: Список сегментов с границами
loop Для каждого сегмента
API->>ONNX: Распознавание сегмента
ONNX-->>API: Текст и метки времени
end
else Short-form mode
API->>ONNX: Распознавание всего аудио
ONNX-->>API: Текст и метки времени
end
API->>API: Нормализация результата
API-->>Client: JSON ответ с text segments words
Структура проекта
├── src/gigam_asr/
│ ├── __init__.py # Пустой маркер пакета
│ └── server.py # Весь сервер: API, загрузка моделей, инференс
├── scripts/
│ └── download_models.py # Скачивание ONNX-моделей и VAD из Hugging Face
├── tests/
│ ├── test_models.py # Тесты выбора моделей и CORS
│ └── test_words.py # Тесты группировки символов в слова
├── Dockerfile # Сборка образа на базе nvidia/cuda
├── docker-compose.yml # Локальное развёртывание с GPU
├── requirements.txt # Зависимости рантайма
└── pyproject.toml # Метаданные пакета и настройки инструментов
Связь с другими разделами
- Обзор проекта — общее описание возможностей и преимуществ сервиса.
- Установка и запуск — пошаговые инструкции по развёртыванию через Docker Compose или ручной сборке.
- Справочник API — детальное описание параметров запросов, форматов ответов и кодов ошибок.
- Конфигурация — полный перечень переменных окружения и их влияние на поведение системы.
- Производительность — бенчмарки RTF на GPU и CPU, рекомендации по выбору размера модели.
- Тестирование — описание набора юнит-тестов и покрытие критических путей.
- CI/CD и автоматизация — конвейеры сборки, линтинга и публикации образов.
Пример использования в коде
Типовой сценарий работы клиента с сервером:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:43000/v1", api_key="none")
# Транскрипция с метками времени на уровне слов
result = client.audio.transcriptions.create(
model="gigaam-multilingual-large-ctc",
file=open("interview.mp3", "rb"),
response_format="verbose_json",
timestamp_granularities=["word"],
)
print(result.text)
for word in result.words:
print(f"{word['word']} [{word['start']:.2f}s – {word['end']:.2f}s]")
Под капотом этот запрос проходит путь: парсинг multipart → декодирование ffmpeg → выбор модели из _state → (опционально) сегментация VAD → инференс ONNX Runtime в отдельном потоке → нормализация меток времени → формирование JSON-ответа.