<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://wiki.era-platform.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AZykov</id>
	<title>Платформа Эра. Документация - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.era-platform.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AZykov"/>
	<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/AZykov"/>
	<updated>2026-11-01T00:28:01Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.11</generator>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2481</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2481"/>
		<updated>2026-09-18T16:05:37Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Установка на Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты). Точная скорость зависит от параметров CPU.&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU, AVX-инструкции&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-ctc-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо выполнить данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Конфигурационный файл nanoasr.yaml =&lt;br /&gt;
&lt;br /&gt;
==== server — HTTP-сервер ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;addr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|Адрес прослушивания. &amp;lt;code&amp;gt;auth.mode: open&amp;lt;/code&amp;gt; разрешён только если это loopback-интерфейс&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;read_header_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;10s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Таймаут чтения заголовков запроса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1073741824&amp;lt;/code&amp;gt;&lt;br /&gt;
|1 ГиБ. Подобрано под &amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;: 4 часа моно 16 кГц WAV ≈ 440 МБ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;shutdown_grace&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько ждать дорабатывающие задачи при остановке&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== auth — доступ ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; вне loopback — отказ при старте&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В режиме &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; нужен хотя бы один, иначе сервер не стартует&lt;br /&gt;
|}&lt;br /&gt;
Поля ключа: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; — имя; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; — сам секрет или &amp;lt;code&amp;gt;sha256:&amp;lt;hex&amp;gt;&amp;lt;/code&amp;gt; (чтобы не хранить открытым); &amp;lt;code&amp;gt;admin: false&amp;lt;/code&amp;gt; — право управлять моделями; &amp;lt;code&amp;gt;rps: 0&amp;lt;/code&amp;gt; — без ограничения скорости; &amp;lt;code&amp;gt;priority: batch&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;interactive&amp;lt;/code&amp;gt; пускает задачи этого ключа вперёд очереди.&lt;br /&gt;
&lt;br /&gt;
==== api / ui ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;api.dialects&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[openai, native]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В поставляемом файле и после &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[openai, native, era]&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; монтируется в корень, поэтому включается осознанно&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Встроенный веб-интерфейс для тестирования.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/ui&amp;lt;/code&amp;gt;&lt;br /&gt;
|Путь освобождён от авторизации, поэтому &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; и пересечение с API запрещены проверкой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== audio — приём и декодирование ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → только WAV/PCM, остальное отклоняется с 415&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;120s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одно декодирование&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4h&amp;lt;/code&amp;gt;&lt;br /&gt;
|Верхняя граница длительности файла; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — без ограничения&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;target_sample_rate&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;16000&amp;lt;/code&amp;gt;&lt;br /&gt;
|Только 16000: все модели VAD и диаризации 16 кГц&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;channel_mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;first&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt; декодирует все каналы целиком; 2 — пара телефонных плеч&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_decoded_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;max_duration × rate × 4 × max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== vad — детектор речи ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;silero-vad-v5&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Порог вероятности речи&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_silence_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;300&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается паузой&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_speech_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;250&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается речью&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_speech_sec&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;20&amp;lt;/code&amp;gt;&lt;br /&gt;
|Без верхней границы монолог станет одним огромным сегментом&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== asr — распознавание ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;models_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/var/lib/nanoasr/models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;default_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;gigaam-v3-ctc-punct-ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|Русская пунктуация и регистр приходят из самой модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_resident_models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(max_model_rss_mb / 1500, 1..6)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_model_rss_mb&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(RAM / 2, 1024..16384)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;inference_slots&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ число CPU (GOMAXPROCS)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;num_threads&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / 2, 1..8)&amp;lt;/code&amp;gt;, на один экземпляр модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;idle_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;15m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Через сколько простоя модель выгружается из пула&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;acquire_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Ожидание свободного слота инференса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сегментов в батче&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_seconds&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;&lt;br /&gt;
|Суммарная длительность батча&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.max&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько дополнительных копий модели под пер-запросные настройки; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — настройки запроса игнорируются с предупреждением&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.allow_hotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== registry — реестр моделей ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;allow_download&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Скачивание весов по запросу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;catalog_url&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → встроенный каталог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mirrors&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|Зеркала для загрузки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;download_concurrency&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|Параллельных загрузок&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;strict_license&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; → отказывать некоммерческим весам&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== jobs — очередь ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;queue_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;100&amp;lt;/code&amp;gt;&lt;br /&gt;
|Мест в очереди&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_concurrent&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / num_threads, 1..8)&amp;lt;/code&amp;gt;; при &amp;lt;code&amp;gt;channel_mode: split&amp;lt;/code&amp;gt; делится на число каналов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_queued_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4294967296&amp;lt;/code&amp;gt;&lt;br /&gt;
|4 ГиБ аудио на диске; не меньше &amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;, превышение → 429 с Retry-After&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_processing_time&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одну задачу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;history_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;720h&amp;lt;/code&amp;gt;&lt;br /&gt;
|30 суток метаданных и транскриптов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_secret&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Подпись &amp;lt;code&amp;gt;X-NanoASR-Signature&amp;lt;/code&amp;gt;; пусто → без подписи и предупреждение в лог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_allow_private&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Разрешает webhook на приватные адреса; само требует loopback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== postproc — постобработка ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Нужно только моделям без пунктуации в словаре&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Модель из каталога вида punctuation&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Числа, даты, время, валюта, телефоны, проценты&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.locale&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;asr.variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.default_score&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Вес, когда клиент не указал свой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== diarization — разделение по говорящим ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;nanoasr init&amp;lt;/code&amp;gt; включает (если не &amp;lt;code&amp;gt;-no-diarize&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;segmentation_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;pyannote-segmentation-3&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;embedding_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;campplus-sv-zh-en&amp;lt;/code&amp;gt;&lt;br /&gt;
|Измерено: 2.9% DER при известном числе говорящих против 40.3% у voxceleb-модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.num_clusters&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; → кластеризовать по порогу. Известное число говорящих сильнее любого порога&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.85&amp;lt;/code&amp;gt;&lt;br /&gt;
|Выше — охотнее объединяет. У sherpa-onnx 0.5, что дробит диалог двоих на 36 «говорящих»&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_on&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.3&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — реплика отбрасывается&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_off&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — соседние реплики склеиваются&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== storage / log ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.db_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|/var/lib/nanoasr/nanoasr.db&lt;br /&gt;
|База задач&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.temp_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;&amp;lt;системный temp&amp;gt;/nanoasr-spool&amp;lt;/code&amp;gt;. Аудио живёт здесь только до завершения задачи, настройки «хранить дольше» нет&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.level&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;warn&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.format&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2480</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2480"/>
		<updated>2026-09-18T16:05:13Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Установка на Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты). Точная скорость зависит от параметров CPU.&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU, AVX-инструкции&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-ctc-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Конфигурационный файл nanoasr.yaml =&lt;br /&gt;
&lt;br /&gt;
==== server — HTTP-сервер ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;addr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|Адрес прослушивания. &amp;lt;code&amp;gt;auth.mode: open&amp;lt;/code&amp;gt; разрешён только если это loopback-интерфейс&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;read_header_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;10s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Таймаут чтения заголовков запроса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1073741824&amp;lt;/code&amp;gt;&lt;br /&gt;
|1 ГиБ. Подобрано под &amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;: 4 часа моно 16 кГц WAV ≈ 440 МБ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;shutdown_grace&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько ждать дорабатывающие задачи при остановке&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== auth — доступ ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; вне loopback — отказ при старте&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В режиме &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; нужен хотя бы один, иначе сервер не стартует&lt;br /&gt;
|}&lt;br /&gt;
Поля ключа: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; — имя; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; — сам секрет или &amp;lt;code&amp;gt;sha256:&amp;lt;hex&amp;gt;&amp;lt;/code&amp;gt; (чтобы не хранить открытым); &amp;lt;code&amp;gt;admin: false&amp;lt;/code&amp;gt; — право управлять моделями; &amp;lt;code&amp;gt;rps: 0&amp;lt;/code&amp;gt; — без ограничения скорости; &amp;lt;code&amp;gt;priority: batch&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;interactive&amp;lt;/code&amp;gt; пускает задачи этого ключа вперёд очереди.&lt;br /&gt;
&lt;br /&gt;
==== api / ui ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;api.dialects&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[openai, native]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В поставляемом файле и после &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[openai, native, era]&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; монтируется в корень, поэтому включается осознанно&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Встроенный веб-интерфейс для тестирования.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/ui&amp;lt;/code&amp;gt;&lt;br /&gt;
|Путь освобождён от авторизации, поэтому &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; и пересечение с API запрещены проверкой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== audio — приём и декодирование ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → только WAV/PCM, остальное отклоняется с 415&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;120s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одно декодирование&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4h&amp;lt;/code&amp;gt;&lt;br /&gt;
|Верхняя граница длительности файла; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — без ограничения&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;target_sample_rate&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;16000&amp;lt;/code&amp;gt;&lt;br /&gt;
|Только 16000: все модели VAD и диаризации 16 кГц&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;channel_mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;first&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt; декодирует все каналы целиком; 2 — пара телефонных плеч&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_decoded_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;max_duration × rate × 4 × max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== vad — детектор речи ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;silero-vad-v5&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Порог вероятности речи&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_silence_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;300&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается паузой&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_speech_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;250&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается речью&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_speech_sec&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;20&amp;lt;/code&amp;gt;&lt;br /&gt;
|Без верхней границы монолог станет одним огромным сегментом&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== asr — распознавание ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;models_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/var/lib/nanoasr/models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;default_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;gigaam-v3-ctc-punct-ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|Русская пунктуация и регистр приходят из самой модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_resident_models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(max_model_rss_mb / 1500, 1..6)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_model_rss_mb&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(RAM / 2, 1024..16384)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;inference_slots&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ число CPU (GOMAXPROCS)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;num_threads&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / 2, 1..8)&amp;lt;/code&amp;gt;, на один экземпляр модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;idle_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;15m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Через сколько простоя модель выгружается из пула&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;acquire_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Ожидание свободного слота инференса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сегментов в батче&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_seconds&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;&lt;br /&gt;
|Суммарная длительность батча&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.max&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько дополнительных копий модели под пер-запросные настройки; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — настройки запроса игнорируются с предупреждением&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.allow_hotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== registry — реестр моделей ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;allow_download&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Скачивание весов по запросу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;catalog_url&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → встроенный каталог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mirrors&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|Зеркала для загрузки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;download_concurrency&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|Параллельных загрузок&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;strict_license&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; → отказывать некоммерческим весам&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== jobs — очередь ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;queue_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;100&amp;lt;/code&amp;gt;&lt;br /&gt;
|Мест в очереди&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_concurrent&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / num_threads, 1..8)&amp;lt;/code&amp;gt;; при &amp;lt;code&amp;gt;channel_mode: split&amp;lt;/code&amp;gt; делится на число каналов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_queued_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4294967296&amp;lt;/code&amp;gt;&lt;br /&gt;
|4 ГиБ аудио на диске; не меньше &amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;, превышение → 429 с Retry-After&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_processing_time&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одну задачу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;history_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;720h&amp;lt;/code&amp;gt;&lt;br /&gt;
|30 суток метаданных и транскриптов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_secret&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Подпись &amp;lt;code&amp;gt;X-NanoASR-Signature&amp;lt;/code&amp;gt;; пусто → без подписи и предупреждение в лог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_allow_private&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Разрешает webhook на приватные адреса; само требует loopback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== postproc — постобработка ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Нужно только моделям без пунктуации в словаре&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Модель из каталога вида punctuation&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Числа, даты, время, валюта, телефоны, проценты&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.locale&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;asr.variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.default_score&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Вес, когда клиент не указал свой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== diarization — разделение по говорящим ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;nanoasr init&amp;lt;/code&amp;gt; включает (если не &amp;lt;code&amp;gt;-no-diarize&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;segmentation_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;pyannote-segmentation-3&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;embedding_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;campplus-sv-zh-en&amp;lt;/code&amp;gt;&lt;br /&gt;
|Измерено: 2.9% DER при известном числе говорящих против 40.3% у voxceleb-модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.num_clusters&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; → кластеризовать по порогу. Известное число говорящих сильнее любого порога&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.85&amp;lt;/code&amp;gt;&lt;br /&gt;
|Выше — охотнее объединяет. У sherpa-onnx 0.5, что дробит диалог двоих на 36 «говорящих»&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_on&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.3&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — реплика отбрасывается&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_off&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — соседние реплики склеиваются&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== storage / log ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.db_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|/var/lib/nanoasr/nanoasr.db&lt;br /&gt;
|База задач&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.temp_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;&amp;lt;системный temp&amp;gt;/nanoasr-spool&amp;lt;/code&amp;gt;. Аудио живёт здесь только до завершения задачи, настройки «хранить дольше» нет&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.level&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;warn&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.format&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2479</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2479"/>
		<updated>2026-09-18T16:04:13Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Общая информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты). Точная скорость зависит от параметров CPU.&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU, AVX-инструкции&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-ctc-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Конфигурационный файл nanoasr.yaml =&lt;br /&gt;
&lt;br /&gt;
==== server — HTTP-сервер ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;addr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|Адрес прослушивания. &amp;lt;code&amp;gt;auth.mode: open&amp;lt;/code&amp;gt; разрешён только если это loopback-интерфейс&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;read_header_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;10s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Таймаут чтения заголовков запроса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1073741824&amp;lt;/code&amp;gt;&lt;br /&gt;
|1 ГиБ. Подобрано под &amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;: 4 часа моно 16 кГц WAV ≈ 440 МБ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;shutdown_grace&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько ждать дорабатывающие задачи при остановке&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== auth — доступ ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; вне loopback — отказ при старте&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В режиме &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; нужен хотя бы один, иначе сервер не стартует&lt;br /&gt;
|}&lt;br /&gt;
Поля ключа: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; — имя; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; — сам секрет или &amp;lt;code&amp;gt;sha256:&amp;lt;hex&amp;gt;&amp;lt;/code&amp;gt; (чтобы не хранить открытым); &amp;lt;code&amp;gt;admin: false&amp;lt;/code&amp;gt; — право управлять моделями; &amp;lt;code&amp;gt;rps: 0&amp;lt;/code&amp;gt; — без ограничения скорости; &amp;lt;code&amp;gt;priority: batch&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;interactive&amp;lt;/code&amp;gt; пускает задачи этого ключа вперёд очереди.&lt;br /&gt;
&lt;br /&gt;
==== api / ui ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;api.dialects&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[openai, native]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В поставляемом файле и после &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[openai, native, era]&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; монтируется в корень, поэтому включается осознанно&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Встроенный веб-интерфейс для тестирования.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/ui&amp;lt;/code&amp;gt;&lt;br /&gt;
|Путь освобождён от авторизации, поэтому &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; и пересечение с API запрещены проверкой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== audio — приём и декодирование ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → только WAV/PCM, остальное отклоняется с 415&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;120s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одно декодирование&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4h&amp;lt;/code&amp;gt;&lt;br /&gt;
|Верхняя граница длительности файла; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — без ограничения&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;target_sample_rate&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;16000&amp;lt;/code&amp;gt;&lt;br /&gt;
|Только 16000: все модели VAD и диаризации 16 кГц&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;channel_mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;first&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt; декодирует все каналы целиком; 2 — пара телефонных плеч&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_decoded_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;max_duration × rate × 4 × max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== vad — детектор речи ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;silero-vad-v5&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Порог вероятности речи&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_silence_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;300&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается паузой&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_speech_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;250&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается речью&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_speech_sec&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;20&amp;lt;/code&amp;gt;&lt;br /&gt;
|Без верхней границы монолог станет одним огромным сегментом&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== asr — распознавание ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;models_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/var/lib/nanoasr/models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;default_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;gigaam-v3-ctc-punct-ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|Русская пунктуация и регистр приходят из самой модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_resident_models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(max_model_rss_mb / 1500, 1..6)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_model_rss_mb&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(RAM / 2, 1024..16384)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;inference_slots&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ число CPU (GOMAXPROCS)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;num_threads&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / 2, 1..8)&amp;lt;/code&amp;gt;, на один экземпляр модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;idle_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;15m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Через сколько простоя модель выгружается из пула&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;acquire_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Ожидание свободного слота инференса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сегментов в батче&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_seconds&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;&lt;br /&gt;
|Суммарная длительность батча&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.max&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько дополнительных копий модели под пер-запросные настройки; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — настройки запроса игнорируются с предупреждением&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.allow_hotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== registry — реестр моделей ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;allow_download&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Скачивание весов по запросу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;catalog_url&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → встроенный каталог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mirrors&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|Зеркала для загрузки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;download_concurrency&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|Параллельных загрузок&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;strict_license&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; → отказывать некоммерческим весам&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== jobs — очередь ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;queue_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;100&amp;lt;/code&amp;gt;&lt;br /&gt;
|Мест в очереди&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_concurrent&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / num_threads, 1..8)&amp;lt;/code&amp;gt;; при &amp;lt;code&amp;gt;channel_mode: split&amp;lt;/code&amp;gt; делится на число каналов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_queued_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4294967296&amp;lt;/code&amp;gt;&lt;br /&gt;
|4 ГиБ аудио на диске; не меньше &amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;, превышение → 429 с Retry-After&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_processing_time&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одну задачу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;history_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;720h&amp;lt;/code&amp;gt;&lt;br /&gt;
|30 суток метаданных и транскриптов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_secret&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Подпись &amp;lt;code&amp;gt;X-NanoASR-Signature&amp;lt;/code&amp;gt;; пусто → без подписи и предупреждение в лог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_allow_private&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Разрешает webhook на приватные адреса; само требует loopback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== postproc — постобработка ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Нужно только моделям без пунктуации в словаре&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Модель из каталога вида punctuation&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Числа, даты, время, валюта, телефоны, проценты&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.locale&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;asr.variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.default_score&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Вес, когда клиент не указал свой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== diarization — разделение по говорящим ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;nanoasr init&amp;lt;/code&amp;gt; включает (если не &amp;lt;code&amp;gt;-no-diarize&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;segmentation_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;pyannote-segmentation-3&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;embedding_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;campplus-sv-zh-en&amp;lt;/code&amp;gt;&lt;br /&gt;
|Измерено: 2.9% DER при известном числе говорящих против 40.3% у voxceleb-модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.num_clusters&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; → кластеризовать по порогу. Известное число говорящих сильнее любого порога&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.85&amp;lt;/code&amp;gt;&lt;br /&gt;
|Выше — охотнее объединяет. У sherpa-onnx 0.5, что дробит диалог двоих на 36 «говорящих»&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_on&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.3&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — реплика отбрасывается&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_off&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — соседние реплики склеиваются&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== storage / log ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.db_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|/var/lib/nanoasr/nanoasr.db&lt;br /&gt;
|База задач&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.temp_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;&amp;lt;системный temp&amp;gt;/nanoasr-spool&amp;lt;/code&amp;gt;. Аудио живёт здесь только до завершения задачи, настройки «хранить дольше» нет&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.level&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;warn&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.format&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2478</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2478"/>
		<updated>2026-09-18T15:55:49Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Системные требования */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты). Точная скорость зависит от параметров CPU.&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU, AVX-инструкции&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-rnnt-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Конфигурационный файл nanoasr.yaml =&lt;br /&gt;
&lt;br /&gt;
==== server — HTTP-сервер ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;addr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|Адрес прослушивания. &amp;lt;code&amp;gt;auth.mode: open&amp;lt;/code&amp;gt; разрешён только если это loopback-интерфейс&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;read_header_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;10s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Таймаут чтения заголовков запроса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1073741824&amp;lt;/code&amp;gt;&lt;br /&gt;
|1 ГиБ. Подобрано под &amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;: 4 часа моно 16 кГц WAV ≈ 440 МБ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;shutdown_grace&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько ждать дорабатывающие задачи при остановке&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== auth — доступ ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; вне loopback — отказ при старте&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В режиме &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; нужен хотя бы один, иначе сервер не стартует&lt;br /&gt;
|}&lt;br /&gt;
Поля ключа: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; — имя; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; — сам секрет или &amp;lt;code&amp;gt;sha256:&amp;lt;hex&amp;gt;&amp;lt;/code&amp;gt; (чтобы не хранить открытым); &amp;lt;code&amp;gt;admin: false&amp;lt;/code&amp;gt; — право управлять моделями; &amp;lt;code&amp;gt;rps: 0&amp;lt;/code&amp;gt; — без ограничения скорости; &amp;lt;code&amp;gt;priority: batch&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;interactive&amp;lt;/code&amp;gt; пускает задачи этого ключа вперёд очереди.&lt;br /&gt;
&lt;br /&gt;
==== api / ui ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;api.dialects&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[openai, native]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В поставляемом файле и после &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[openai, native, era]&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; монтируется в корень, поэтому включается осознанно&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Встроенный веб-интерфейс для тестирования.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/ui&amp;lt;/code&amp;gt;&lt;br /&gt;
|Путь освобождён от авторизации, поэтому &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; и пересечение с API запрещены проверкой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== audio — приём и декодирование ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → только WAV/PCM, остальное отклоняется с 415&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;120s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одно декодирование&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4h&amp;lt;/code&amp;gt;&lt;br /&gt;
|Верхняя граница длительности файла; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — без ограничения&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;target_sample_rate&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;16000&amp;lt;/code&amp;gt;&lt;br /&gt;
|Только 16000: все модели VAD и диаризации 16 кГц&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;channel_mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;first&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt; декодирует все каналы целиком; 2 — пара телефонных плеч&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_decoded_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;max_duration × rate × 4 × max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== vad — детектор речи ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;silero-vad-v5&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Порог вероятности речи&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_silence_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;300&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается паузой&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_speech_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;250&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается речью&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_speech_sec&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;20&amp;lt;/code&amp;gt;&lt;br /&gt;
|Без верхней границы монолог станет одним огромным сегментом&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== asr — распознавание ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;models_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/var/lib/nanoasr/models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;default_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;gigaam-v3-ctc-punct-ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|Русская пунктуация и регистр приходят из самой модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_resident_models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(max_model_rss_mb / 1500, 1..6)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_model_rss_mb&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(RAM / 2, 1024..16384)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;inference_slots&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ число CPU (GOMAXPROCS)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;num_threads&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / 2, 1..8)&amp;lt;/code&amp;gt;, на один экземпляр модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;idle_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;15m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Через сколько простоя модель выгружается из пула&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;acquire_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Ожидание свободного слота инференса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сегментов в батче&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_seconds&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;&lt;br /&gt;
|Суммарная длительность батча&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.max&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько дополнительных копий модели под пер-запросные настройки; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — настройки запроса игнорируются с предупреждением&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.allow_hotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== registry — реестр моделей ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;allow_download&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Скачивание весов по запросу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;catalog_url&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → встроенный каталог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mirrors&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|Зеркала для загрузки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;download_concurrency&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|Параллельных загрузок&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;strict_license&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; → отказывать некоммерческим весам&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== jobs — очередь ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;queue_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;100&amp;lt;/code&amp;gt;&lt;br /&gt;
|Мест в очереди&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_concurrent&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / num_threads, 1..8)&amp;lt;/code&amp;gt;; при &amp;lt;code&amp;gt;channel_mode: split&amp;lt;/code&amp;gt; делится на число каналов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_queued_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4294967296&amp;lt;/code&amp;gt;&lt;br /&gt;
|4 ГиБ аудио на диске; не меньше &amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;, превышение → 429 с Retry-After&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_processing_time&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одну задачу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;history_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;720h&amp;lt;/code&amp;gt;&lt;br /&gt;
|30 суток метаданных и транскриптов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_secret&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Подпись &amp;lt;code&amp;gt;X-NanoASR-Signature&amp;lt;/code&amp;gt;; пусто → без подписи и предупреждение в лог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_allow_private&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Разрешает webhook на приватные адреса; само требует loopback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== postproc — постобработка ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Нужно только моделям без пунктуации в словаре&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Модель из каталога вида punctuation&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Числа, даты, время, валюта, телефоны, проценты&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.locale&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;asr.variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.default_score&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Вес, когда клиент не указал свой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== diarization — разделение по говорящим ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;nanoasr init&amp;lt;/code&amp;gt; включает (если не &amp;lt;code&amp;gt;-no-diarize&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;segmentation_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;pyannote-segmentation-3&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;embedding_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;campplus-sv-zh-en&amp;lt;/code&amp;gt;&lt;br /&gt;
|Измерено: 2.9% DER при известном числе говорящих против 40.3% у voxceleb-модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.num_clusters&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; → кластеризовать по порогу. Известное число говорящих сильнее любого порога&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.85&amp;lt;/code&amp;gt;&lt;br /&gt;
|Выше — охотнее объединяет. У sherpa-onnx 0.5, что дробит диалог двоих на 36 «говорящих»&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_on&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.3&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — реплика отбрасывается&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_off&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — соседние реплики склеиваются&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== storage / log ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.db_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|/var/lib/nanoasr/nanoasr.db&lt;br /&gt;
|База задач&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.temp_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;&amp;lt;системный temp&amp;gt;/nanoasr-spool&amp;lt;/code&amp;gt;. Аудио живёт здесь только до завершения задачи, настройки «хранить дольше» нет&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.level&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;warn&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.format&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=2477</id>
		<title>Заглавная страница</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0&amp;diff=2477"/>
		<updated>2026-09-18T15:52:33Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Навигация по разделам: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Файл:Era wiki logo2.png|безрамки|619x619пкс]]&lt;br /&gt;
&lt;br /&gt;
==== Добро пожаловать на ресурс с документацией по платформе Эра. ====&lt;br /&gt;
На этом сайте вы найдете подробную информацию для работы с системой: техническую и пользовательскую документацию, обучающие материалы, разборы кейсов и часто задаваемых вопросов. Также представлено общее описание платформы и доступных приложений.&lt;br /&gt;
&lt;br /&gt;
Мы стремимся обеспечить максимально комфортное и продуктивное использование платформы. Если у вас возникнут вопросы или потребуется поддержка, пожалуйста, обращайтесь к нашим специалистам и партнерам.&lt;br /&gt;
&lt;br /&gt;
==== Структура: ====&lt;br /&gt;
&#039;&#039;&#039;Концепция и технологии&#039;&#039;&#039; - теоретический раздел необходимый для понимая принципов построения платформы.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Курсы / Быстрый старт&#039;&#039;&#039; - раздел для пошагового изучения платформы от простого к  сложному. Мы рекомендуем использовать собственный экземпляр платформы Эра для прохождения курсов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Практика / Кейсы&#039;&#039;&#039; - раздел для инженеров, уже прошедших курсы. Настройка конкретных кейсов и практические задачи.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Приложения&#039;&#039;&#039; - руководства пользователя для функциональных заказчиков по использованию прикладных приложений. &lt;br /&gt;
&lt;br /&gt;
==== Навигация по разделам: ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;size:18px!important; &amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
![[:Категория:Концепция и технологии|Концепция / технологии]]&lt;br /&gt;
![[:Категория:Администрирование|Администрирование /  DevOps]]&lt;br /&gt;
![[:Категория:Курсы|Курсы / Быстрый старт]]&lt;br /&gt;
![[:Категория:Практика|Практика / Кейсы]]&lt;br /&gt;
![[:Категория:Приложения|Приложения]]&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|[[Обзор возможностей платформы|Возможности]]&lt;br /&gt;
[[Архитектура платформы|Архитектура]]&lt;br /&gt;
&lt;br /&gt;
[[Список микросервисов]]&lt;br /&gt;
&lt;br /&gt;
[[Масштабирование платформы|Масштабирование]]&lt;br /&gt;
&lt;br /&gt;
[[Обеспечение безопасности|Безопасность]]&lt;br /&gt;
&lt;br /&gt;
[[Обеспечение отказоустойчивости|Отказоустойчивость]]&lt;br /&gt;
&lt;br /&gt;
[[Обзор приложений|Пакеты приложений]]&lt;br /&gt;
&lt;br /&gt;
[[Ролевая модель системы]]&lt;br /&gt;
|[[Быстрая установка|&#039;&#039;&#039;Быстрая установка&#039;&#039;&#039;]]&lt;br /&gt;
[[Установка платформы|Руководство по установке]]&lt;br /&gt;
&lt;br /&gt;
[[Лицензирование]]&lt;br /&gt;
&lt;br /&gt;
[[Требования платформы]] &lt;br /&gt;
&lt;br /&gt;
[[Порты используемые системой|Используемые порты]] &lt;br /&gt;
&lt;br /&gt;
[[Сертификаты SSL]]&lt;br /&gt;
&lt;br /&gt;
[[Обновление платформы через апгрейд докер-контейнера|Апгрейд докер-контейнера]]&lt;br /&gt;
&lt;br /&gt;
[[Обеспечение безопасности SIP]]&lt;br /&gt;
&lt;br /&gt;
[[Подключение к Zabbix]]&lt;br /&gt;
&lt;br /&gt;
[[Синхронизация и авторизация с LDAP]]&lt;br /&gt;
|[[:Категория:Курс IP АТС|Курс IP АТС]]&lt;br /&gt;
[[:Категория:Курс контакт-центр|Курс Контакт-центр]]&lt;br /&gt;
&lt;br /&gt;
[[:Категория:Курс Разработка приложений|Курс Разработка приложений]]&lt;br /&gt;
&lt;br /&gt;
[[Сертификация]]&lt;br /&gt;
&lt;br /&gt;
[[Учебная лицензия]]&lt;br /&gt;
|[[Реализация ИИ чат-бота с переводом на оператора|ИИ-чатбот с переводом на оператора]]&lt;br /&gt;
[[Колл-листы в исходящих кампаниях]]&lt;br /&gt;
&lt;br /&gt;
[[Пользовательская настройка статборда|Настройка статбордов]]&lt;br /&gt;
&lt;br /&gt;
[[Настройка Autoprovision на примере Yealink T42G|Настройка Auto Provision]]&lt;br /&gt;
&lt;br /&gt;
[[Подключение Yandex.Cloud]]&lt;br /&gt;
&lt;br /&gt;
[[Создание форм оценки качества]]&lt;br /&gt;
&lt;br /&gt;
[[Подмена номера при исходящем звонке]]&lt;br /&gt;
&lt;br /&gt;
[[Запись разговоров в IVR голосовом меню]]&lt;br /&gt;
&lt;br /&gt;
[[Параметры записи разговоров в MP3]]&lt;br /&gt;
&lt;br /&gt;
[[Сохранение записей разговоров в S3 хранилище|Сохранение разговоров в S3]]&lt;br /&gt;
&lt;br /&gt;
[[Примеры API запросов]]&lt;br /&gt;
&lt;br /&gt;
[[Управление звонками через API]]&lt;br /&gt;
&lt;br /&gt;
[[WebSocket песочница|Websocket-песочница]]&lt;br /&gt;
&lt;br /&gt;
[[Модификация базового отчета]]&lt;br /&gt;
&lt;br /&gt;
|[[Искусственный Интеллект|ИИ]]&lt;br /&gt;
[[Smart]]&lt;br /&gt;
&lt;br /&gt;
[[Установка сервиса распознавания речи NanoASR|NanoASR]]&lt;br /&gt;
&lt;br /&gt;
[[Era Meet|Era Meet (Видеоконференции)]]&lt;br /&gt;
&lt;br /&gt;
[[WFM]]&lt;br /&gt;
&lt;br /&gt;
[[Кабинет]]&lt;br /&gt;
&lt;br /&gt;
[[Отчеты]]&lt;br /&gt;
&lt;br /&gt;
[[Приложение ETL|ETL]]&lt;br /&gt;
&lt;br /&gt;
[[Приложение Тестировщик|Тестировщик]]&lt;br /&gt;
&lt;br /&gt;
[[Рабочее место оператора контакт-центра|Оператор]]&lt;br /&gt;
&lt;br /&gt;
[[Рабочее место супервизора контакт-центра|Супервизор]]&lt;br /&gt;
&lt;br /&gt;
[[Софтфон]]&lt;br /&gt;
&lt;br /&gt;
[[Управление качеством]]&lt;br /&gt;
&lt;br /&gt;
[[Рабочее место оператора]]&lt;br /&gt;
&lt;br /&gt;
[[Управление знаниями]]&lt;br /&gt;
&lt;br /&gt;
[[Управление обучением]]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
__БЕЗ_ОГЛАВЛЕНИЯ__&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2476</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2476"/>
		<updated>2026-09-18T15:50:35Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты).&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-rnnt-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Конфигурационный файл nanoasr.yaml =&lt;br /&gt;
&lt;br /&gt;
==== server — HTTP-сервер ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;addr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|Адрес прослушивания. &amp;lt;code&amp;gt;auth.mode: open&amp;lt;/code&amp;gt; разрешён только если это loopback-интерфейс&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;read_header_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;10s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Таймаут чтения заголовков запроса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1073741824&amp;lt;/code&amp;gt;&lt;br /&gt;
|1 ГиБ. Подобрано под &amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;: 4 часа моно 16 кГц WAV ≈ 440 МБ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;shutdown_grace&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько ждать дорабатывающие задачи при остановке&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== auth — доступ ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; вне loopback — отказ при старте&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В режиме &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; нужен хотя бы один, иначе сервер не стартует&lt;br /&gt;
|}&lt;br /&gt;
Поля ключа: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; — имя; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; — сам секрет или &amp;lt;code&amp;gt;sha256:&amp;lt;hex&amp;gt;&amp;lt;/code&amp;gt; (чтобы не хранить открытым); &amp;lt;code&amp;gt;admin: false&amp;lt;/code&amp;gt; — право управлять моделями; &amp;lt;code&amp;gt;rps: 0&amp;lt;/code&amp;gt; — без ограничения скорости; &amp;lt;code&amp;gt;priority: batch&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;interactive&amp;lt;/code&amp;gt; пускает задачи этого ключа вперёд очереди.&lt;br /&gt;
&lt;br /&gt;
==== api / ui ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;api.dialects&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[openai, native]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В поставляемом файле и после &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[openai, native, era]&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; монтируется в корень, поэтому включается осознанно&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Встроенный веб-интерфейс для тестирования.&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/ui&amp;lt;/code&amp;gt;&lt;br /&gt;
|Путь освобождён от авторизации, поэтому &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; и пересечение с API запрещены проверкой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== audio — приём и декодирование ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → только WAV/PCM, остальное отклоняется с 415&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;120s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одно декодирование&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4h&amp;lt;/code&amp;gt;&lt;br /&gt;
|Верхняя граница длительности файла; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — без ограничения&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;target_sample_rate&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;16000&amp;lt;/code&amp;gt;&lt;br /&gt;
|Только 16000: все модели VAD и диаризации 16 кГц&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;channel_mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;first&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt; декодирует все каналы целиком; 2 — пара телефонных плеч&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_decoded_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;max_duration × rate × 4 × max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== vad — детектор речи ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;silero-vad-v5&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Порог вероятности речи&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_silence_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;300&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается паузой&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_speech_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;250&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается речью&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_speech_sec&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;20&amp;lt;/code&amp;gt;&lt;br /&gt;
|Без верхней границы монолог станет одним огромным сегментом&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== asr — распознавание ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;models_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/var/lib/nanoasr/models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;default_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;gigaam-v3-ctc-punct-ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|Русская пунктуация и регистр приходят из самой модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_resident_models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(max_model_rss_mb / 1500, 1..6)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_model_rss_mb&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(RAM / 2, 1024..16384)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;inference_slots&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ число CPU (GOMAXPROCS)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;num_threads&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / 2, 1..8)&amp;lt;/code&amp;gt;, на один экземпляр модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;idle_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;15m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Через сколько простоя модель выгружается из пула&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;acquire_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Ожидание свободного слота инференса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сегментов в батче&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_seconds&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;&lt;br /&gt;
|Суммарная длительность батча&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.max&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько дополнительных копий модели под пер-запросные настройки; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — настройки запроса игнорируются с предупреждением&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.allow_hotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== registry — реестр моделей ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;allow_download&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Скачивание весов по запросу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;catalog_url&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → встроенный каталог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mirrors&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|Зеркала для загрузки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;download_concurrency&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|Параллельных загрузок&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;strict_license&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; → отказывать некоммерческим весам&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== jobs — очередь ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;queue_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;100&amp;lt;/code&amp;gt;&lt;br /&gt;
|Мест в очереди&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_concurrent&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / num_threads, 1..8)&amp;lt;/code&amp;gt;; при &amp;lt;code&amp;gt;channel_mode: split&amp;lt;/code&amp;gt; делится на число каналов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_queued_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4294967296&amp;lt;/code&amp;gt;&lt;br /&gt;
|4 ГиБ аудио на диске; не меньше &amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;, превышение → 429 с Retry-After&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_processing_time&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одну задачу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;history_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;720h&amp;lt;/code&amp;gt;&lt;br /&gt;
|30 суток метаданных и транскриптов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_secret&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Подпись &amp;lt;code&amp;gt;X-NanoASR-Signature&amp;lt;/code&amp;gt;; пусто → без подписи и предупреждение в лог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_allow_private&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Разрешает webhook на приватные адреса; само требует loopback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== postproc — постобработка ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Нужно только моделям без пунктуации в словаре&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Модель из каталога вида punctuation&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Числа, даты, время, валюта, телефоны, проценты&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.locale&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;asr.variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.default_score&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Вес, когда клиент не указал свой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== diarization — разделение по говорящим ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;nanoasr init&amp;lt;/code&amp;gt; включает (если не &amp;lt;code&amp;gt;-no-diarize&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;segmentation_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;pyannote-segmentation-3&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;embedding_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;campplus-sv-zh-en&amp;lt;/code&amp;gt;&lt;br /&gt;
|Измерено: 2.9% DER при известном числе говорящих против 40.3% у voxceleb-модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.num_clusters&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; → кластеризовать по порогу. Известное число говорящих сильнее любого порога&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.85&amp;lt;/code&amp;gt;&lt;br /&gt;
|Выше — охотнее объединяет. У sherpa-onnx 0.5, что дробит диалог двоих на 36 «говорящих»&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_on&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.3&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — реплика отбрасывается&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_off&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — соседние реплики склеиваются&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== storage / log ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.db_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|/var/lib/nanoasr/nanoasr.db&lt;br /&gt;
|База задач&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.temp_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;&amp;lt;системный temp&amp;gt;/nanoasr-spool&amp;lt;/code&amp;gt;. Аудио живёт здесь только до завершения задачи, настройки «хранить дольше» нет&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.level&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;warn&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.format&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2475</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2475"/>
		<updated>2026-09-18T15:48:54Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Конфигурационный файл nanoasr.yaml */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты).&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-rnnt-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Конфигурационный файл nanoasr.yaml ===&lt;br /&gt;
&lt;br /&gt;
==== server — HTTP-слушатель ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;addr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;&lt;br /&gt;
|Адрес прослушивания. &amp;lt;code&amp;gt;auth.mode: open&amp;lt;/code&amp;gt; разрешён только если это loopback&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;read_header_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;10s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Таймаут чтения заголовков запроса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1073741824&amp;lt;/code&amp;gt;&lt;br /&gt;
|1 ГиБ. Подобрано под &amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;: 4 часа моно 16 кГц WAV ≈ 440 МБ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;shutdown_grace&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько ждать дорабатывающие задачи при остановке&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== auth — доступ ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;open&amp;lt;/code&amp;gt; вне loopback — отказ при старте&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;keys&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В режиме &amp;lt;code&amp;gt;apikey&amp;lt;/code&amp;gt; нужен хотя бы один, иначе сервер не стартует&lt;br /&gt;
|}&lt;br /&gt;
Поля ключа: &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; — имя; &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; — сам секрет или &amp;lt;code&amp;gt;sha256:&amp;lt;hex&amp;gt;&amp;lt;/code&amp;gt; (чтобы не хранить открытым); &amp;lt;code&amp;gt;admin: false&amp;lt;/code&amp;gt; — право управлять моделями; &amp;lt;code&amp;gt;rps: 0&amp;lt;/code&amp;gt; — без ограничения скорости; &amp;lt;code&amp;gt;priority: batch&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;interactive&amp;lt;/code&amp;gt; пускает задачи этого ключа вперёд очереди.&lt;br /&gt;
&lt;br /&gt;
==== api / ui ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;api.dialects&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[openai, native]&amp;lt;/code&amp;gt;&lt;br /&gt;
|В поставляемом файле и после &amp;lt;code&amp;gt;init&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;[openai, native, era]&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;era&amp;lt;/code&amp;gt; монтируется в корень, поэтому включается осознанно&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Встроенный SPA&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ui.path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/ui&amp;lt;/code&amp;gt;&lt;br /&gt;
|Путь освобождён от авторизации, поэтому &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; и пересечение с API запрещены проверкой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== audio — приём и декодирование ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → только WAV/PCM, остальное отклоняется с 415&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ffmpeg_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;120s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одно декодирование&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_duration&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4h&amp;lt;/code&amp;gt;&lt;br /&gt;
|Верхняя граница длительности файла; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — без ограничения&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;target_sample_rate&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;16000&amp;lt;/code&amp;gt;&lt;br /&gt;
|Только 16000: все модели VAD и диаризации 16 кГц&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;channel_mode&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;downmix&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;first&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;split&amp;lt;/code&amp;gt; декодирует все каналы целиком; 2 — пара телефонных плеч&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_decoded_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;max_duration × rate × 4 × max_split_channels&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== vad — детектор речи ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;silero-vad-v5&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Порог вероятности речи&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_silence_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;300&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается паузой&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_speech_ms&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;250&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — не считается речью&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_speech_sec&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;20&amp;lt;/code&amp;gt;&lt;br /&gt;
|Без верхней границы монолог станет одним огромным сегментом&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== asr — распознавание ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;models_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;/var/lib/nanoasr/models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;default_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;gigaam-v3-ctc-punct-ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|Русская пунктуация и регистр приходят из самой модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_resident_models&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(max_model_rss_mb / 1500, 1..6)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_model_rss_mb&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(RAM / 2, 1024..16384)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;inference_slots&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ число CPU (GOMAXPROCS)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;num_threads&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / 2, 1..8)&amp;lt;/code&amp;gt;, на один экземпляр модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;idle_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;15m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Через сколько простоя модель выгружается из пула&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;acquire_timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30s&amp;lt;/code&amp;gt;&lt;br /&gt;
|Ожидание свободного слота инференса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сегментов в батче&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;batch.max_seconds&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt;&lt;br /&gt;
|Суммарная длительность батча&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.max&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|Сколько дополнительных копий модели под пер-запросные настройки; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; — настройки запроса игнорируются с предупреждением&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;variants.allow_hotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== registry — реестр моделей ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;allow_download&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
|Скачивание весов по запросу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;catalog_url&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Пусто → встроенный каталог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;mirrors&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;[]&amp;lt;/code&amp;gt;&lt;br /&gt;
|Зеркала для загрузки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;download_concurrency&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;&lt;br /&gt;
|Параллельных загрузок&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;strict_license&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; → отказывать некоммерческим весам&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== jobs — очередь ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;queue_size&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;100&amp;lt;/code&amp;gt;&lt;br /&gt;
|Мест в очереди&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_concurrent&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;clamp(CPU / num_threads, 1..8)&amp;lt;/code&amp;gt;; при &amp;lt;code&amp;gt;channel_mode: split&amp;lt;/code&amp;gt; делится на число каналов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_queued_bytes&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;4294967296&amp;lt;/code&amp;gt;&lt;br /&gt;
|4 ГиБ аудио на диске; не меньше &amp;lt;code&amp;gt;max_upload_bytes&amp;lt;/code&amp;gt;, превышение → 429 с Retry-After&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;max_processing_time&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;30m&amp;lt;/code&amp;gt;&lt;br /&gt;
|Предел на одну задачу&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;history_ttl&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;720h&amp;lt;/code&amp;gt;&lt;br /&gt;
|30 суток метаданных и транскриптов&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_secret&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Подпись &amp;lt;code&amp;gt;X-NanoASR-Signature&amp;lt;/code&amp;gt;; пусто → без подписи и предупреждение в лог&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;webhook_allow_private&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Разрешает webhook на приватные адреса; само требует loopback&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== postproc — постобработка ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Нужно только моделям без пунктуации в словаре&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;punctuation.model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|Модель из каталога вида punctuation&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Числа, даты, время, валюта, телефоны, проценты&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;itn.locale&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|Требует &amp;lt;code&amp;gt;asr.variants.max &amp;gt; 0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;hotwords.default_score&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;1.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Вес, когда клиент не указал свой&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== diarization — разделение по говорящим ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;enabled&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;nanoasr init&amp;lt;/code&amp;gt; включает (если не &amp;lt;code&amp;gt;-no-diarize&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;segmentation_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;pyannote-segmentation-3&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;embedding_model&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;campplus-sv-zh-en&amp;lt;/code&amp;gt;&lt;br /&gt;
|Измерено: 2.9% DER при известном числе говорящих против 40.3% у voxceleb-модели&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.num_clusters&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; → кластеризовать по порогу. Известное число говорящих сильнее любого порога&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;clustering.threshold&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.85&amp;lt;/code&amp;gt;&lt;br /&gt;
|Выше — охотнее объединяет. У sherpa-onnx 0.5, что дробит диалог двоих на 36 «говорящих»&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_on&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.3&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — реплика отбрасывается&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;min_duration_off&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;0.5&amp;lt;/code&amp;gt;&lt;br /&gt;
|Короче — соседние реплики склеиваются&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== storage / log ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Параметр&lt;br /&gt;
!По умолчанию&lt;br /&gt;
!Комментарий&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.db_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|/var/lib/nanoasr/nanoasr.db&lt;br /&gt;
|База задач&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;storage.temp_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|→ &amp;lt;code&amp;gt;&amp;lt;системный temp&amp;gt;/nanoasr-spool&amp;lt;/code&amp;gt;. Аудио живёт здесь только до завершения задачи, настройки «хранить дольше» нет&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.level&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;info&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;warn&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;log.format&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;&amp;lt;nowiki&amp;gt; | &amp;lt;/nowiki&amp;gt;&amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2474</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2474"/>
		<updated>2026-09-18T15:48:18Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты).&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-rnnt-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Конфигурационный файл nanoasr.yaml ===&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2473</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2473"/>
		<updated>2026-09-18T15:44:02Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Подключение к Платформе Эра */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты).&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-rnnt-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sk-nanoasr-*&#039;&#039;&#039; это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
* &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;br /&gt;
[[Файл:Настройка NanoASR в AI Softphone.png|центр|безрамки|932x932пкс]]&lt;br /&gt;
Настройки -&amp;gt; Расшифровка -&amp;gt; Распознаватели -&amp;gt; Добавить&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Значения настроек для AI Softphone&lt;br /&gt;
!Настройка&lt;br /&gt;
!Значение&lt;br /&gt;
|-&lt;br /&gt;
|Название&lt;br /&gt;
|NanoASR (любое название)&lt;br /&gt;
|-&lt;br /&gt;
|Вид&lt;br /&gt;
|Совместимый с OpenAI (Whisper, OpenAI)&lt;br /&gt;
|-&lt;br /&gt;
|Адрес&lt;br /&gt;
|[http://example.com:8080/v1 http://&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;[NanoASR_host]/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;v1] где &#039;&#039;&#039;[NanoASR_host]&#039;&#039;&#039; = адрес и порт установленного NanoASR&lt;br /&gt;
|-&lt;br /&gt;
|Ключ&lt;br /&gt;
|ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); &lt;br /&gt;
|-&lt;br /&gt;
|Модель&lt;br /&gt;
|По умолчанию gigaam-v3-ctc-punct-ru&lt;br /&gt;
|-&lt;br /&gt;
|Включен&lt;br /&gt;
|Да&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0_NanoASR_%D0%B2_AI_Softphone.png&amp;diff=2472</id>
		<title>Файл:Настройка NanoASR в AI Softphone.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0_NanoASR_%D0%B2_AI_Softphone.png&amp;diff=2472"/>
		<updated>2026-09-18T15:39:42Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Настройка NanoASR в AI Softphone&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2471</id>
		<title>Установка сервиса распознавания речи NanoASR</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%B7%D0%BD%D0%B0%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%80%D0%B5%D1%87%D0%B8_NanoASR&amp;diff=2471"/>
		<updated>2026-09-18T15:27:41Z</updated>

		<summary type="html">&lt;p&gt;AZykov: Новая страница: «= Общая информация = [https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).  Данный проект позволяет запускать передо...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[https://github.com/usunrise88/NanoASR NanoASR - это утилита с открытым исходным кодом], позволяющая запускать модели машинного обучения для распознавания речи (транскрибации) и разделения спикеров (диаризации).&lt;br /&gt;
&lt;br /&gt;
Данный проект позволяет запускать передовые модели для распознавания речи на серверах, не оборудованных графическими ускорителями.&lt;br /&gt;
&lt;br /&gt;
=== Системные требования ===&lt;br /&gt;
Для установки требуется 4гб свободного дискового пространства.&lt;br /&gt;
&lt;br /&gt;
Технически, утилита способна работать на минимальной конфигурации - 1 ядро CPU и 1гб ОЗУ. Единственное требование к CPU - поддержка AVX-инструкций. В таком случае, она сможет обрабатывать 1 параллельный запрос, со скоростью примерно 0.5 от реального времени (1 минуту записи обрабатывать за 2 минуты).&lt;br /&gt;
&lt;br /&gt;
Рекомендуемые параметры сервера:&lt;br /&gt;
&lt;br /&gt;
* 4 ядра CPU&lt;br /&gt;
* 4гб RAM&lt;br /&gt;
* 20гб SSD&lt;br /&gt;
&lt;br /&gt;
В таком режиме, NanoASR может обрабатывать до 4 параллельных запросов со скоростью реального времени (минуту записи за минуту расчетов), либо 2 параллельных запроса со скоростью х2 (минуту записи за 30 секунд расчетов).&lt;br /&gt;
&lt;br /&gt;
= Технические детали =&lt;br /&gt;
Утилита написана на языке Golang и представляет собой единый бинарный файл. В качестве среды исполнения моделей используется библиотека sherpa-onnx.&lt;br /&gt;
&lt;br /&gt;
Утилита поддерживает различные архитектуры моделей, однако &amp;quot;из коробки&amp;quot; загружает следующий набор:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Модели NanoASR&lt;br /&gt;
!Модель&lt;br /&gt;
!Назначение&lt;br /&gt;
|-&lt;br /&gt;
|gigaam-v3-rnnt-punct-ru&lt;br /&gt;
|Распознавание речи&lt;br /&gt;
|-&lt;br /&gt;
|silero-vad-v5&lt;br /&gt;
|Детектор голосовой активности&lt;br /&gt;
|-&lt;br /&gt;
|pyannote-segmentation-3&lt;br /&gt;
|Модель разделения спикеров&lt;br /&gt;
|-&lt;br /&gt;
|campplus-sv-zh-en&lt;br /&gt;
|Модель построения &amp;quot;слепков&amp;quot; голосов (голосовых эмбеддингов)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Установка на Linux =&lt;br /&gt;
[[Файл:Установка NanoASR Linux.png|мини|Результат установки на Linux]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
&lt;br /&gt;
Скрипт автоматически установит утилиту в /opt/nanoasr, зарегистрирует в systemd, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
curl -fsSL https://github.com/usunrise88/NanoASR/releases/latest/download/install.sh | bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
После установки будет отображены данные для подключения, включая токены доступа.&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Установка на Windows =&lt;br /&gt;
[[Файл:Результат установки Windows.png|мини|Результат установки Windows]]&lt;br /&gt;
Доступна быстрая установка с помощью готового скрипта.&lt;br /&gt;
Скрипт автоматически установит утилиту в C:/Program Files/NanoASR, создаст сервис, загрузит веса всех необходимых моделей и установит ffmpeg для работы с mp3.&lt;br /&gt;
&lt;br /&gt;
Для быстрой установки необходимо вызвать данную команду в Powershell:&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
irm https://github.com/usunrise88/NanoASR/releases/latest/download/install.ps1 | iex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Доступны также ручная установка и установка с помощью docker, оба варианта описаны в [https://github.com/usunrise88/NanoASR readme на github].&lt;br /&gt;
&lt;br /&gt;
Если необходимо реализовать доступ к сервису из внешней сети, необходимо настроить на сервере реверс-прокси (например nginx или Caddy) с  TLS к порту 8080.&lt;br /&gt;
&lt;br /&gt;
= Подключение к Платформе Эра =&lt;br /&gt;
Мастер домен -&amp;gt; Приложение &amp;quot;Настройки&amp;quot; -&amp;gt; Домен -&amp;gt; Параметры&lt;br /&gt;
&lt;br /&gt;
Необходимо найти параметр &#039;&#039;&#039;record_asr_options.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Задать значение по следующему шаблону:&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;servers&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;headers&amp;quot;: [&lt;br /&gt;
        &amp;quot;Authorization: Bearer sk-nanoasr-*&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;uri&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task?encode=true&amp;amp;task=transcribe&amp;amp;language=ru&amp;amp;output=json&amp;quot;,&lt;br /&gt;
      &amp;quot;uri_get_task_result&amp;quot;: &amp;quot;http://[NanoASR_host]/asr_task/%TASK_ID%&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;thread_count&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;whisper&amp;quot;,&lt;br /&gt;
  &amp;quot;utc_hours&amp;quot;: [&lt;br /&gt;
    0,&lt;br /&gt;
    0&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Где sk-nanoasr-* это ключ, полученный после установки (либо в yaml конфигурационном файле NanoASR); [NanoASR_host] - адрес и порт установелнного сервиса NanoASR.&lt;br /&gt;
&lt;br /&gt;
= Подключение к AI Softphone =&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A0%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82_%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B8_Windows.png&amp;diff=2470</id>
		<title>Файл:Результат установки Windows.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A0%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82_%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B8_Windows.png&amp;diff=2470"/>
		<updated>2026-09-18T15:24:05Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Результат установки Windows&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_NanoASR_Linux.png&amp;diff=2469</id>
		<title>Файл:Установка NanoASR Linux.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_NanoASR_Linux.png&amp;diff=2469"/>
		<updated>2026-09-18T15:19:22Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Установка NanoASR Linux&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2463</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2463"/>
		<updated>2026-08-10T13:48:43Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 2.3. ASR (T-one на Triton Inference Server) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Модель.&#039;&#039;&#039; Обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре: VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
* &#039;&#039;&#039;Веса.&#039;&#039;&#039; Числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
* &#039;&#039;&#039;Инференс.&#039;&#039;&#039; Использование готовой модели для получения ответа на некий набор входных данных (&amp;quot;прогон&amp;quot; данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
* &#039;&#039;&#039;LLM.&#039;&#039;&#039; Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
* &#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server). Сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
* &#039;&#039;&#039;TensorRT.&#039;&#039;&#039; Библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
* &#039;&#039;&#039;vLLM.&#039;&#039;&#039; Движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
* &#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface). Консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
* &#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений). Память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
* &#039;&#039;&#039;LightTTS.&#039;&#039;&#039; Движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
* &#039;&#039;&#039;Промпт.&#039;&#039;&#039; Инструкция, которой следует большая языковая модель.&lt;br /&gt;
* &#039;&#039;&#039;Токен.&#039;&#039;&#039; В &#039;&#039;контексте LLM&#039;&#039; это единица текста, которой оперирует модель (примерно часть слова / слово / знак). В токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
* &#039;&#039;&#039;Окно контекста.&#039;&#039;&#039; Максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
* &#039;&#039;&#039;Compute.&#039;&#039;&#039; Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их ресурсы ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании и проверке данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://download.era-platform.ru/ai/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени (холодный старт):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
= Этап 4. Запуск контейнера secondchain и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
Ссылка на загрузку контейнера secondchain предоставляется менеджером по запросу.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
docker load -i secondchain.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
Системный промпт задаёт поведение робота, а промпт пост-обработки позволяет после окончания диалога проанализировать его и сохранить в сессии бизнес-результат (удобнее всего, в формате JSON).&lt;br /&gt;
&lt;br /&gt;
При составлении собственного системного важным эффектом является &amp;quot;внимательность&amp;quot; (attention) больших языковых моделей. Они более строго следуют инструкциям, написанным в начале и конце промпта. Поэтому данные области рекомендуется оставлять для строгих ограничений.&lt;br /&gt;
&lt;br /&gt;
Для построения надежных роботов с повторяемой эффективностью, рекомендуется использовать подход с описанием строгих шагов диалога.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2458</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2458"/>
		<updated>2026-07-08T15:20:22Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 4.1. Загрузка образа и запуск контейнера */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Модель.&#039;&#039;&#039; Обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре: VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
* &#039;&#039;&#039;Веса.&#039;&#039;&#039; Числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
* &#039;&#039;&#039;Инференс.&#039;&#039;&#039; Использование готовой модели для получения ответа на некий набор входных данных (&amp;quot;прогон&amp;quot; данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
* &#039;&#039;&#039;LLM.&#039;&#039;&#039; Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
* &#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server). Сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
* &#039;&#039;&#039;TensorRT.&#039;&#039;&#039; Библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
* &#039;&#039;&#039;vLLM.&#039;&#039;&#039; Движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
* &#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface). Консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
* &#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений). Память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
* &#039;&#039;&#039;LightTTS.&#039;&#039;&#039; Движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
* &#039;&#039;&#039;Промпт.&#039;&#039;&#039; Инструкция, которой следует большая языковая модель.&lt;br /&gt;
* &#039;&#039;&#039;Токен.&#039;&#039;&#039; В &#039;&#039;контексте LLM&#039;&#039; это единица текста, которой оперирует модель (примерно часть слова / слово / знак). В токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
* &#039;&#039;&#039;Окно контекста.&#039;&#039;&#039; Максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
* &#039;&#039;&#039;Compute.&#039;&#039;&#039; Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их ресурсы ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании и проверке данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени (холодный старт):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
= Этап 4. Запуск контейнера secondchain и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
Ссылка на загрузку контейнера secondchain предоставляется менеджером по запросу.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
docker load -i secondchain.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
Системный промпт задаёт поведение робота, а промпт пост-обработки позволяет после окончания диалога проанализировать его и сохранить в сессии бизнес-результат (удобнее всего, в формате JSON).&lt;br /&gt;
&lt;br /&gt;
При составлении собственного системного важным эффектом является &amp;quot;внимательность&amp;quot; (attention) больших языковых моделей. Они более строго следуют инструкциям, написанным в начале и конце промпта. Поэтому данные области рекомендуется оставлять для строгих ограничений.&lt;br /&gt;
&lt;br /&gt;
Для построения надежных роботов с повторяемой эффективностью, рекомендуется использовать подход с описанием строгих шагов диалога.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2457</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2457"/>
		<updated>2026-07-07T12:19:35Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Микросервисы робота и их нагрузка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Модель.&#039;&#039;&#039; Обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре: VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
* &#039;&#039;&#039;Веса.&#039;&#039;&#039; Числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
* &#039;&#039;&#039;Инференс.&#039;&#039;&#039; Использование готовой модели для получения ответа на некий набор входных данных (&amp;quot;прогон&amp;quot; данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
* &#039;&#039;&#039;LLM.&#039;&#039;&#039; Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
* &#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server). Сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
* &#039;&#039;&#039;TensorRT.&#039;&#039;&#039; Библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
* &#039;&#039;&#039;vLLM.&#039;&#039;&#039; Движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
* &#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface). Консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
* &#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений). Память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
* &#039;&#039;&#039;LightTTS.&#039;&#039;&#039; Движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
* &#039;&#039;&#039;Промпт.&#039;&#039;&#039; Инструкция, которой следует большая языковая модель.&lt;br /&gt;
* &#039;&#039;&#039;Токен.&#039;&#039;&#039; В &#039;&#039;контексте LLM&#039;&#039; это единица текста, которой оперирует модель (примерно часть слова / слово / знак). В токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
* &#039;&#039;&#039;Окно контекста.&#039;&#039;&#039; Максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
* &#039;&#039;&#039;Compute.&#039;&#039;&#039; Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их ресурсы ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании и проверке данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени (холодный старт):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
Системный промпт задаёт поведение робота, а промпт пост-обработки позволяет после окончания диалога проанализировать его и сохранить в сессии бизнес-результат (удобнее всего, в формате JSON).&lt;br /&gt;
&lt;br /&gt;
При составлении собственного системного важным эффектом является &amp;quot;внимательность&amp;quot; (attention) больших языковых моделей. Они более строго следуют инструкциям, написанным в начале и конце промпта. Поэтому данные области рекомендуется оставлять для строгих ограничений.&lt;br /&gt;
&lt;br /&gt;
Для построения надежных роботов с повторяемой эффективностью, рекомендуется использовать подход с описанием строгих шагов диалога.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2456</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2456"/>
		<updated>2026-07-07T12:19:09Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Общая информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Модель.&#039;&#039;&#039; Обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре: VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
* &#039;&#039;&#039;Веса.&#039;&#039;&#039; Числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
* &#039;&#039;&#039;Инференс.&#039;&#039;&#039; Использование готовой модели для получения ответа на некий набор входных данных (&amp;quot;прогон&amp;quot; данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
* &#039;&#039;&#039;LLM.&#039;&#039;&#039; Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
* &#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server). Сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
* &#039;&#039;&#039;TensorRT.&#039;&#039;&#039; Библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
* &#039;&#039;&#039;vLLM.&#039;&#039;&#039; Движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
* &#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface). Консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
* &#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений). Память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
* &#039;&#039;&#039;LightTTS.&#039;&#039;&#039; Движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
* &#039;&#039;&#039;Промпт.&#039;&#039;&#039; Инструкция, которой следует большая языковая модель.&lt;br /&gt;
* &#039;&#039;&#039;Токен.&#039;&#039;&#039; В &#039;&#039;контексте LLM&#039;&#039; это единица текста, которой оперирует модель (примерно часть слова / слово / знак). В токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
* &#039;&#039;&#039;Окно контекста.&#039;&#039;&#039; Максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
* &#039;&#039;&#039;Compute.&#039;&#039;&#039; Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании и проверке данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени (холодный старт):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
Системный промпт задаёт поведение робота, а промпт пост-обработки позволяет после окончания диалога проанализировать его и сохранить в сессии бизнес-результат (удобнее всего, в формате JSON).&lt;br /&gt;
&lt;br /&gt;
При составлении собственного системного важным эффектом является &amp;quot;внимательность&amp;quot; (attention) больших языковых моделей. Они более строго следуют инструкциям, написанным в начале и конце промпта. Поэтому данные области рекомендуется оставлять для строгих ограничений.&lt;br /&gt;
&lt;br /&gt;
Для построения надежных роботов с повторяемой эффективностью, рекомендуется использовать подход с описанием строгих шагов диалога.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2455</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2455"/>
		<updated>2026-07-07T12:18:08Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Глоссарий */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Модель.&#039;&#039;&#039; Обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре: VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
* &#039;&#039;&#039;Веса.&#039;&#039;&#039; Числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
* &#039;&#039;&#039;Инференс.&#039;&#039;&#039; Использование готовой модели для получения ответа на некий набор входных данных (&amp;quot;прогон&amp;quot; данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
* &#039;&#039;&#039;LLM.&#039;&#039;&#039; Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
* &#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server). Сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
* &#039;&#039;&#039;TensorRT.&#039;&#039;&#039; Библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
* &#039;&#039;&#039;vLLM.&#039;&#039;&#039; Движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
* &#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface). Консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
* &#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений). Память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
* &#039;&#039;&#039;LightTTS.&#039;&#039;&#039; Движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
* &#039;&#039;&#039;Промпт.&#039;&#039;&#039; Инструкция, которой следует большая языковая модель.&lt;br /&gt;
* &#039;&#039;&#039;Токен.&#039;&#039;&#039; В &#039;&#039;контексте LLM&#039;&#039; это единица текста, которой оперирует модель (примерно часть слова / слово / знак). В токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
* &#039;&#039;&#039;Окно контекста.&#039;&#039;&#039; Максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
* &#039;&#039;&#039;Compute.&#039;&#039;&#039; Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании и проверке данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени (холодный старт):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
Системный промпт задаёт поведение робота, а промпт пост-обработки позволяет после окончания диалога проанализировать его и сохранить в сессии бизнес-результат (удобнее всего, в формате JSON).&lt;br /&gt;
&lt;br /&gt;
При составлении собственного системного важным эффектом является &amp;quot;внимательность&amp;quot; (attention) больших языковых моделей. Они более строго следуют инструкциям, написанным в начале и конце промпта. Поэтому данные области рекомендуется оставлять для строгих ограничений.&lt;br /&gt;
&lt;br /&gt;
Для построения надежных роботов с повторяемой эффективностью, рекомендуется использовать подход с описанием строгих шагов диалога.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2454</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2454"/>
		<updated>2026-07-07T12:08:47Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 4.2. Создать робота в приложении ИИ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
Для упрощения работы с настройкой робота, нами был подготовлен набор демо-ресурсов:&lt;br /&gt;
&lt;br /&gt;
[[:Файл:Демо ресурсы для голосового робота.zip]]&lt;br /&gt;
&lt;br /&gt;
Он включает файл голоса, example.env и файлы для импорта в разделы приложения ИИ с готовым настроенным роботом.&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%94%D0%B5%D0%BC%D0%BE_%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B_%D0%B4%D0%BB%D1%8F_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.zip&amp;diff=2453</id>
		<title>Файл:Демо ресурсы для голосового робота.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%94%D0%B5%D0%BC%D0%BE_%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B_%D0%B4%D0%BB%D1%8F_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.zip&amp;diff=2453"/>
		<updated>2026-07-07T12:07:05Z</updated>

		<summary type="html">&lt;p&gt;AZykov: .env файл
Запись голоса
Файлы для импорта голосового робота (Голос, инструменты, робот)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Краткое описание ==&lt;br /&gt;
.env файл&lt;br /&gt;
Запись голоса&lt;br /&gt;
Файлы для импорта голосового робота (Голос, инструменты, робот)&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2452</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2452"/>
		<updated>2026-07-07T12:02:59Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Запуск робота с использованием облачных сервисов инференса */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Популярные подписки на современные модели по типу &amp;quot;Token Plan&amp;quot;, которые предлагают использование с ограничением на количество запросов, а не тарификацию по токенам, зачастую непригодны для использования с роботом. Данные подписки используются в агентских системах, где время отклика не является целевой метрикой, а запросы инференса с таких подписок, как правило обрабатываются облачными сервисами с меньшим приоритетом.&amp;lt;/blockquote&amp;gt;При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (только для серверов с GPU) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
[[Файл:Голос робота в приложении ИИ.png|мини]]&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
[[Файл:Инструменты робота.png|мини]]&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
[[Файл:Пример робота в приложении ИИ.png|мини]]&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
[[Файл:Статус робота.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
[[Файл:Робот в очереди.png|мини]]&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A0%D0%BE%D0%B1%D0%BE%D1%82_%D0%B2_%D0%BE%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D0%B8.png&amp;diff=2451</id>
		<title>Файл:Робот в очереди.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A0%D0%BE%D0%B1%D0%BE%D1%82_%D0%B2_%D0%BE%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D0%B8.png&amp;diff=2451"/>
		<updated>2026-07-07T12:02:51Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Робот в очереди&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A1%D1%82%D0%B0%D1%82%D1%83%D1%81_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2450</id>
		<title>Файл:Статус робота.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%A1%D1%82%D0%B0%D1%82%D1%83%D1%81_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2450"/>
		<updated>2026-07-07T12:02:04Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Статус робота&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0_%D0%B2_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B8_%D0%98%D0%98.png&amp;diff=2449</id>
		<title>Файл:Пример робота в приложении ИИ.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0_%D0%B2_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B8_%D0%98%D0%98.png&amp;diff=2449"/>
		<updated>2026-07-07T12:00:25Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Пример робота в приложении ИИ&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2448</id>
		<title>Файл:Инструменты робота.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2448"/>
		<updated>2026-07-07T11:59:27Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Инструменты робота&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%93%D0%BE%D0%BB%D0%BE%D1%81_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0_%D0%B2_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B8_%D0%98%D0%98.png&amp;diff=2447</id>
		<title>Файл:Голос робота в приложении ИИ.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%93%D0%BE%D0%BB%D0%BE%D1%81_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0_%D0%B2_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B8_%D0%98%D0%98.png&amp;diff=2447"/>
		<updated>2026-07-07T11:58:52Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Голос робота в приложении ИИ&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2446</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2446"/>
		<updated>2026-07-07T11:54:17Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей. При этом остальные модели запускаются локально, на более простой карте.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&lt;br /&gt;
При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2445</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2445"/>
		<updated>2026-07-07T11:53:32Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Запуск сервиса робота с использованием облачных сервисов инференса */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&lt;br /&gt;
При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2444</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2444"/>
		<updated>2026-07-07T11:53:18Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Масштабирование сервиса */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Рекомендуемой конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем 32gb, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
=== Запуск сервиса робота с использованием облачных сервисов инференса ===&lt;br /&gt;
В случае, когда проектные требования позволяют использовать облачную инфраструктуру, нет необходимости полного разворота всех сервисов локально. Можно использовать ресурсы облачных провайдеров и ресурсы, предоставляемые командой платформы.&lt;br /&gt;
&lt;br /&gt;
Сервис поддерживает наиболее популярные API для работы с облачными моделями:&lt;br /&gt;
&lt;br /&gt;
* OpenAI-like формат для LLM. Позволяет подключать к роботу любые из современных передовых языковых моделей.&lt;br /&gt;
* OpenAI-like transcription формат для распознавания речи.&lt;br /&gt;
* LightTTS API формат для генерации речи&lt;br /&gt;
&lt;br /&gt;
Часто, экономически эффективным может быть использование только облачной LLM, так как она требует большого объема VRAM и дорогих ускорителей.&lt;br /&gt;
&lt;br /&gt;
При выборе облачной LLM критичными показателями являются следующие:&lt;br /&gt;
&lt;br /&gt;
* Метрика TTFT (Time To First Token). Время отклика модели до пересылки первых токенов ответа. Должна быть &amp;lt;=300мс, включая сетевые задержки;&lt;br /&gt;
* Поддержка streaming (SSE/chunked) ответов;&lt;br /&gt;
* Возможность отключения режима thinking/reasoning; &lt;br /&gt;
* Скорость генерации ответа &amp;gt;30 токенов/сек.&lt;br /&gt;
&lt;br /&gt;
При использовании всех облачных сервисов инференса, локально разворачивается только главный контейнер - secondchain. Рекомендуемые требования к серверу для такой среды:&lt;br /&gt;
&lt;br /&gt;
4x CPU&lt;br /&gt;
&lt;br /&gt;
8gb RAM&lt;br /&gt;
&lt;br /&gt;
80gb SSD&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2443</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2443"/>
		<updated>2026-07-07T11:39:18Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Приблизительный расчет требуемых мощностей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Минимальной конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
При использовании конфигураций из двух карт с небольшим объемом VRAM (24, 32gb) будет происходить проблема дисбаланса:&lt;br /&gt;
&lt;br /&gt;
Одну из карт будет полностью занимать LLM (22gb базовых весов), а другую карту будут занимать другие модели. При этом в случае 2x24gb VRAM, для LLM будет оставаться крайне мало памяти на активные сессии, что будет являться главным ограничителем. Использовать память или compute соседней карты невозможно без NVLINK, а в потребительских картах он отсутствует.&lt;br /&gt;
&lt;br /&gt;
Таким образом вариант 2x4090/24 может использовать только для ненагруженных систем - демо стендов или сред разработки. Для такой конфигурации возможно заменить вторую карту на более простую, например 4080, так как TTS + ASR не реализуют 24gb vram.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция написана для Unbuntu 24.04.&lt;br /&gt;
&lt;br /&gt;
При написании данной инструкции использовался сервер с RTX PRO 5000 48gb.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2442</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2442"/>
		<updated>2026-07-07T11:31:42Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Приблизительный расчет требуемых мощностей */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
Минимальной конфигурацией является следующая:&lt;br /&gt;
&lt;br /&gt;
CPU 8x&lt;br /&gt;
&lt;br /&gt;
RAM 64gb DDR5&lt;br /&gt;
&lt;br /&gt;
300gb SSD &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Сравнение ускорителей&lt;br /&gt;
!Ускоритель&lt;br /&gt;
!Архитектура&lt;br /&gt;
!VRAM&lt;br /&gt;
!Bandwith&lt;br /&gt;
!Compute (INT8)&lt;br /&gt;
!Приблизительное количество параллельных сессий&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 5000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|48gb&lt;br /&gt;
|1.34TB/s&lt;br /&gt;
|516 TOPS&lt;br /&gt;
|40-50&lt;br /&gt;
|-&lt;br /&gt;
|RTX PRO 6000&lt;br /&gt;
|Blackwell&lt;br /&gt;
|96gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|1000 TOPS&lt;br /&gt;
|50-70&lt;br /&gt;
|-&lt;br /&gt;
|RTX 4090/48&lt;br /&gt;
|Ada&lt;br /&gt;
|48gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|25-30&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 5090&lt;br /&gt;
|Blackwell&lt;br /&gt;
|2x32gb&lt;br /&gt;
|1.79TB/s&lt;br /&gt;
|828 TOPS&lt;br /&gt;
|30-40&lt;br /&gt;
|-&lt;br /&gt;
|2x RTX 4090/24&lt;br /&gt;
|Ada&lt;br /&gt;
|2x24gb&lt;br /&gt;
|1TB/s&lt;br /&gt;
|660 TOPS&lt;br /&gt;
|10-20&lt;br /&gt;
|-&lt;br /&gt;
|A100/40&lt;br /&gt;
|Ampere&lt;br /&gt;
|40gb&lt;br /&gt;
|1.56TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|18-23&lt;br /&gt;
|-&lt;br /&gt;
|A100/80&lt;br /&gt;
|Ampere&lt;br /&gt;
|80gb&lt;br /&gt;
|2TB/s&lt;br /&gt;
|624 TOPS&lt;br /&gt;
|55-75&lt;br /&gt;
|-&lt;br /&gt;
|H100&lt;br /&gt;
|Hopper&lt;br /&gt;
|80gb&lt;br /&gt;
|3.35TB/s&lt;br /&gt;
|990 TOPS&lt;br /&gt;
|70-100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2441</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2441"/>
		<updated>2026-07-07T11:10:40Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Масштабирование сервиса */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы vLLM и LightTTS можно выносить на отдельные сервера. При этом, например, для LightTTS не требуется большой объем VRAM, и он может качественно работать на сравнительно недорогих потребительских ускорителях (4090, 5080). &lt;br /&gt;
&lt;br /&gt;
Отдельно стоит упомянуть вынесение на отдельный сервер ASR. Данный компонент работает в потоковом режиме по протоколу gRPC, и не рекомендуется вынесение его на другие площадки с высокой задержкой. Остальные компоненты (за исключением VAD, который работает на CPU в составе главного сервиса secondchain), не чувствительны к дополнительным задержкам (в рамках разумного, до 50-70мс).&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2440</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2440"/>
		<updated>2026-07-07T10:51:58Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Нюансы подбора GPU */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LLM&#039;&#039;&#039; — Большая языковая модель. Класс моделей text-to-text, обученных на больших объемах мультиязычных и мультидоменных данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Промпт&#039;&#039;&#039; — Инструкция, которой следует большая языковая модель.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Ampere, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры &#039;&#039;&#039;Ampere&#039;&#039;&#039;. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
Из-за логики работы голосового робота, нагрузка на его компоненты в рамках одной сессии достаточно неравномерна. Большинство моделей включаются последовательно после завершения инференса модели на предыдущем шаге:&lt;br /&gt;
&lt;br /&gt;
* VAD (детектирование голосовой активности) - работает всегда (но не вносит существенной нагрузки)&lt;br /&gt;
* ASR (распознавание речи) - запускается при срабатывании триггера VAD (окончание реплики)&lt;br /&gt;
* LLM - запускается после завершения работы ASR&lt;br /&gt;
* TTS - запускается во время / после завершения работы ASR (LLM возвращает текст в потоковом режиме. Текст разбивается на предложения и передается TTS в реальном времени)&lt;br /&gt;
&lt;br /&gt;
Кроме того, архитектурные особенности робота позволяют избегать шага вызова TTS для всех реплик, которые уже были сгенерированы ранее и помещены в кеш. Получается, что если инструкция робота задана таким образом, чтобы его реплики были &amp;quot;статичны&amp;quot; от сессии к сессии, получается экономить значительное количество ресурсов, переиспользуя уже существующие генерации.&lt;br /&gt;
&lt;br /&gt;
Свои оптимизации есть и на стороне инференса LLM:&lt;br /&gt;
&lt;br /&gt;
В команду запуска vLLM по-умолчанию включен режим prefix caching. Данный механизм позволяет кешировать системный промпт и переиспользовать ранее произведенные вычисления для новых запросов. Включение prefix caching позволяет экономить compute для однотипных запросов, а также уменьшить скорость отклика.&lt;br /&gt;
&lt;br /&gt;
Поскольку в рамках голосового робота все запросы (к конкретной конфигурации) используют один системный промпт, это позволяет серьезно экономить.&lt;br /&gt;
&lt;br /&gt;
Данный механизм теряет свою эффективность, к одной LLM будет обращаться большое число роботов с существенно отличающимися системными промптами (50+, точное количество зависит от доступного объема VRAM и настроек vLLM). Также механизм будет мешать, если LLM используется для каких-либо других задач, кроме работы голосового робота.&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
При масштабировании голосового робота существует три подхода:&lt;br /&gt;
&lt;br /&gt;
* Использование дополнительных GPU, либо переход на сервер с более производительным GPU&lt;br /&gt;
* Использование нескольких серверов с GPU для балансировки нагрузки&lt;br /&gt;
* Использование нескольких экземпляров робота (движков)&lt;br /&gt;
&lt;br /&gt;
На текущий момент наиболее удобным вариантом масштабирования является второй. Наиболее нагруженные сервисы&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2439</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2439"/>
		<updated>2026-07-07T10:32:56Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Нюансы подбора GPU */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
При подборе GPU под данный стек объём VRAM не является определяющим критерием. Веса любой из трёх моделей помещаются в память практически любой современной карты (уровня 5090 или выше), тогда как реальными ограничивающими факторами выступают пропускная способность памяти на этапе декодирования LLM и вычислительная нагрузка DiT-декодера в TTS. Соответственно, при выборе оборудования следует ориентироваться в первую очередь на memory bandwidth и на аппаратную поддержку современных типов данных, а не на номинальный объём видеопамяти.&lt;br /&gt;
&lt;br /&gt;
Отдельного внимания заслуживает интерфейс межкарточного взаимодействия. Потребительские карты рассчитаны преимущественно на одиночную эксплуатацию: в актуальных линейках Blackwell и Ada поддержка NVLink отсутствует, и обмен между несколькими GPU на одном сервере осуществляется исключительно через PCIe (Gen4/Gen5). При использовании tensor parallelism это создаёт заметные накладные расходы на межкарточную коммуникацию, что становится ощутимым при высокой конкурентной нагрузке. Дата-центровые решения (H100, H200, а также RTX PRO 6000 в соответствующем сегменте) либо предоставляют NVLink с пропускной способностью в сотни ГБ/с, либо обладают достаточным объёмом памяти для размещения моделей на одной карте, что позволяет полностью исключить tensor parallelism и связанные с ним издержки.&lt;br /&gt;
&lt;br /&gt;
Следует также учитывать высокие темпы развития архитектур GPU. Производительная карта шестилетней давности может уступать современному решению среднего уровня как по вычислительной мощности, так и — что существенно в данном случае — по набору поддерживаемых типов данных. Например, NVIDIA V100 (Volta, 2017), несмотря на наличие NVLink и памяти HBM, не поддерживает аппаратное ускорение FP8 и Int4 на тензорных ядрах. Между тем рассматриваемый стек существенно опирается на эти форматы: Qwen в квантизации GPTQ-Int4 с fp8 KV-cache, T-one в TensorRT, TTS с int8-квантизацией. На оборудовании предыдущих поколений соответствующие операции либо неработоспособны в требуемых форматах, либо выполняются с существенным замедлением за счёт программной эмуляции.&lt;br /&gt;
&lt;br /&gt;
С практической точки зрения приоритеты при выборе оборудования под данный пайплайн выстраиваются следующим образом: в первую очередь — поколение архитектуры (Ada, Hopper, Blackwell — ввиду поддержки FP8 и Int4 на тензорных ядрах), далее — пропускная способность памяти, и лишь затем — объём VRAM, поскольку последний в рамках данной задачи практически всегда достаточен.&lt;br /&gt;
&lt;br /&gt;
Робот тестировался преимущественно на картах поколения Blackwell:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;RTX5090&#039;&#039;&#039; (использовалась другая LLM меньшего размера)&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 5000&#039;&#039;&#039; 48gb&lt;br /&gt;
* &#039;&#039;&#039;RTX PRO 6000&#039;&#039;&#039; 96gb&lt;br /&gt;
&lt;br /&gt;
Однако проводились также тесты на картах архитектуры Ampere. Результат можно считать удовлетворительным, особенно для организации тестовых и демо-сред без постоянной большой нагрузки.&lt;br /&gt;
&lt;br /&gt;
Отдельно хочется сказать про ускорители других производителей (AMD, Intel):&lt;br /&gt;
&lt;br /&gt;
К большому сожалению, большая часть инфраструктурного софта оптимизируется в первую очередь под ускорители NVIDIA. В связи с этим даже более производительные карты AMD &amp;quot;на бумаге&amp;quot;, по факту показывают значительно меньшие скорости при реальных задачах. Некоторые же библиотеки и компоненты (TensorRT, Triton Inference Server и т.д.) вообще являются проприетарными разработками NVIDIA и не поддерживают работу с ускорителями других производителей.&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
пывпаывпыва&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
авыфаывафыв&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2438</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2438"/>
		<updated>2026-07-07T10:22:15Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Микросервисы робота и их нагрузка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
паывпывапва&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
пывпаывпыва&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
авыфаывафыв&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2437</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2437"/>
		<updated>2026-07-07T10:21:19Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Глоссарий */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах. Измеряется в GFLOP/TFLOP (операциях в секунду)&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Микросервисы робота&lt;br /&gt;
!Название&lt;br /&gt;
!Назначение&lt;br /&gt;
!Ключевые ресурсы&lt;br /&gt;
!Минимальное потребление VRAM&lt;br /&gt;
!Дополнительное потребление VRAM из расчета на 1 сессию&lt;br /&gt;
!Условное потребление Compute на 1 сессию&lt;br /&gt;
|-&lt;br /&gt;
|secondchain&lt;br /&gt;
|Инференс модели VAD (CPU), логика робота, голосовой pipeline, работа с сессиями, SIP-клиент&lt;br /&gt;
|CPU, RAM&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
|vLLM (qwen3.5-35b-a3b-INT4)&lt;br /&gt;
Данные указаны с окном контекста 8192 токена.&lt;br /&gt;
|Инференс больших языковых моделей (LLM)&lt;br /&gt;
|VRAM, Compute&lt;br /&gt;
|22gb&lt;br /&gt;
|0.25gb&lt;br /&gt;
|~3 GFLOP/токен&lt;br /&gt;
|-&lt;br /&gt;
|T-one (Triton Inference Server)&lt;br /&gt;
|Инференс T-One speech-to-text&lt;br /&gt;
|Compute&lt;br /&gt;
|600mb&lt;br /&gt;
|10mb&lt;br /&gt;
|~1-3 GFLOP/секунда речи&lt;br /&gt;
|-&lt;br /&gt;
|LightTTS&lt;br /&gt;
|Инференс CosyVoice3 TTS&lt;br /&gt;
|Compute, VRAM&lt;br /&gt;
|8gb&lt;br /&gt;
|0.3gb&lt;br /&gt;
|~120GFLOP/секунда генерируемоей речи&lt;br /&gt;
|}&lt;br /&gt;
При высокой конкуренции за Compute, увеличиваются задержки на каждом из этапов инференса. Самым чувствительным компонентом, при этом, является LightTTS - из-за архитектурных особенностей. TTS требует много вычислительных ресурсов, и большое количество параллельных генераций могут значительно увеличивать задержку. В случае использования нескольких серверов рекомендуется первично выносить на отдельный сервер либо LightTTS, либо vLLM (для высвобождения Compute).&lt;br /&gt;
&lt;br /&gt;
Архитектурно при этом, робот устроен таким образом, чтобы минимизировать инференс LightTTS при возможности (агрессивное кеширование результатов TTS). &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
паывпывапва&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
пывпаывпыва&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
авыфаывафыв&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2436</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2436"/>
		<updated>2026-07-07T09:59:31Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Микросервисы робота и их нагрузка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Compute&#039;&#039;&#039; — Вычислительные ресурсы GPU. Абстрактный ресурс видеоускорителя, аналог CPU Time при обычных расчетах.&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
Робот функционирует на базе 4 микросервисов, каждый из которых может быть вынесен на отдельный сервер, или исполняться на общем сервере. &lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
паывпывапва&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
пывпаывпыва&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
авыфаывафыв&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2435</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2435"/>
		<updated>2026-07-07T09:56:12Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Общая информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
&lt;br /&gt;
= Требования к оборудованию, нагрузка и мастштабирование =&lt;br /&gt;
&lt;br /&gt;
=== Микросервисы робота и их нагрузка ===&lt;br /&gt;
правпыва&lt;br /&gt;
&lt;br /&gt;
=== Нюансы подбора GPU ===&lt;br /&gt;
паывпывапва&lt;br /&gt;
&lt;br /&gt;
=== Анизотропность нагрузки ===&lt;br /&gt;
пывпаывпыва&lt;br /&gt;
&lt;br /&gt;
=== Приблизительный расчет требуемых мощностей ===&lt;br /&gt;
паывпывапыв&lt;br /&gt;
&lt;br /&gt;
=== Масштабирование сервиса ===&lt;br /&gt;
авыфаывафыв&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2434</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2434"/>
		<updated>2026-07-06T23:53:51Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Установка и настройка голосового робота Эра */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Общая информация =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2433</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2433"/>
		<updated>2026-07-06T23:52:22Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 2.6. Итоговая карта портов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 17001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2432</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2432"/>
		<updated>2026-07-06T23:51:08Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Установка и настройка голосового робота Эра (SecondChain) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2431</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2431"/>
		<updated>2026-07-06T23:50:53Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Установка и настройка голосового робота Эра (SecondChain) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
[[Файл:Архитектура голосового робота.png|центр|безрамки|763x763пкс]]&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%90%D1%80%D1%85%D0%B8%D1%82%D0%B5%D0%BA%D1%82%D1%83%D1%80%D0%B0_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2430</id>
		<title>Файл:Архитектура голосового робота.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%90%D1%80%D1%85%D0%B8%D1%82%D0%B5%D0%BA%D1%82%D1%83%D1%80%D0%B0_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2430"/>
		<updated>2026-07-06T23:50:34Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Архитектура голосового робота&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2429</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2429"/>
		<updated>2026-07-06T23:41:08Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 2.5. TTS (LightTTS + CosyVoice3) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights \&lt;br /&gt;
  python -m light_tts.server.api_server \&lt;br /&gt;
    --model_dir /opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
    --data_type float16 \&lt;br /&gt;
    --load_trt True \&lt;br /&gt;
    --host 0.0.0.0&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2428</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2428"/>
		<updated>2026-07-06T23:33:43Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Этап 3. Настройка .env */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
Необходимо переименовать файл example.env в .env и изменить в нём следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&lt;br /&gt;
POSTGRES_HOST=[хост postgresql]&lt;br /&gt;
POSTGRES_PORT=5432&lt;br /&gt;
POSTGRES_USER=[логин postgresql]&lt;br /&gt;
POSTGRES_PASSWORD=[пароль postgresql]&lt;br /&gt;
POSTGRES_DB=[имя БД, если укзаанная БД отсутствует - она будет автоматически создана]&lt;br /&gt;
&lt;br /&gt;
CONCURRENT_SESSIONS=[Жесткое ограничение количества одновременных сессий]&lt;br /&gt;
&lt;br /&gt;
SIP_SERVER=[адрес Эры]&lt;br /&gt;
SIP_PORT=[порт SIP]&lt;br /&gt;
SIP_USERNAME=[Имя учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_PASSWORD=[Пароль учетной записи абонента из пункта 1.4]&lt;br /&gt;
SIP_DOMAIN=[Полное имя домена, например robot.era-platform.ru]&lt;br /&gt;
#Детальные настройки SIP-клиента. В случае необходимости обхода NAT&lt;br /&gt;
SIP_TRANSPORT=udp&lt;br /&gt;
# NAT Traversal&lt;br /&gt;
SIP_STUN_SERVER=stun.l.google.com:19302&lt;br /&gt;
SIP_USE_ICE=false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
LLM_MODE=openai_api&lt;br /&gt;
#В случае использования сервиса инфереса vLLM на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LLM_OPENAI_API_BASE=http://localhost:16080/v1 &lt;br /&gt;
LLM_OPENAI_MODEL=qwen35-35b-a3b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ASR_MODE=triton&lt;br /&gt;
#В случае использования сервиса инфереса tone-triton на другом хосте, необходимо изменить адреса/порты&lt;br /&gt;
ASR_TRITON_URL=http://localhost:17000&lt;br /&gt;
ASR_TRITON_GRPC=localhost:17001&lt;br /&gt;
ASR_TRITON_MODEL=streaming_acoustic&lt;br /&gt;
ASR_TRITON_TIMEOUT=10&lt;br /&gt;
ASR_DECODER_TYPE=beam_search&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TTS_PROVIDER=lighttts&lt;br /&gt;
#В случае использования сервиса инфереса LightTTS на другом хосте, необходимо изменить адрес/порт&lt;br /&gt;
LIGHTTTS_URL=http://localhost:8080/&lt;br /&gt;
LIGHTTTS_SAMPLE_RATE=24000&lt;br /&gt;
LIGHTTTS_STREAMING=false&lt;br /&gt;
LIGHTTTS_CONCURRENCY=4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2427</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2427"/>
		<updated>2026-07-06T23:21:53Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 2.7. Финальная проверка стека */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Файл:Контейнеры сервисов инференса голосового робота.png|центр|безрамки|1067x1067пкс]]&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Базовые параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%9A%D0%BE%D0%BD%D1%82%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D1%8B_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B8%D0%BD%D1%84%D0%B5%D1%80%D0%B5%D0%BD%D1%81%D0%B0_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2426</id>
		<title>Файл:Контейнеры сервисов инференса голосового робота.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%9A%D0%BE%D0%BD%D1%82%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D1%8B_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B8%D0%BD%D1%84%D0%B5%D1%80%D0%B5%D0%BD%D1%81%D0%B0_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.png&amp;diff=2426"/>
		<updated>2026-07-06T23:21:31Z</updated>

		<summary type="html">&lt;p&gt;AZykov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Контейнеры сервисов инференса голосового робота&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2425</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2425"/>
		<updated>2026-07-06T23:17:56Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 2.5. TTS (LightTTS + CosyVoice3) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 10 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — 10 &#039;&#039;&#039;GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После проверки выполняется подключение пайплайна PjSIP → VAD → ASR → LLM → TTS с указанием эндпоинтов в конфигурации: ASR — &amp;lt;code&amp;gt;:8000/:8001&amp;lt;/code&amp;gt;, LLM — &amp;lt;code&amp;gt;:16080&amp;lt;/code&amp;gt;, TTS — &amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Базовые параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2424</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2424"/>
		<updated>2026-07-06T23:17:24Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* 2.5. TTS (LightTTS + CosyVoice3) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 11 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker load -i lightts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:391] ✅ Startup health check passed!&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:395] ✅ Application ready! Server is now accepting requests&lt;br /&gt;
INFO 07-06 23:16:49.963 [server/api_http.py:396] 🌐 Listening at: http://localhost:8080&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — &#039;&#039;&#039;11 GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После проверки выполняется подключение пайплайна PjSIP → VAD → ASR → LLM → TTS с указанием эндпоинтов в конфигурации: ASR — &amp;lt;code&amp;gt;:8000/:8001&amp;lt;/code&amp;gt;, LLM — &amp;lt;code&amp;gt;:16080&amp;lt;/code&amp;gt;, TTS — &amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Базовые параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
	<entry>
		<id>https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2423</id>
		<title>Установка сервисов голосового робота</title>
		<link rel="alternate" type="text/html" href="https://wiki.era-platform.ru/index.php?title=%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2_%D0%B3%D0%BE%D0%BB%D0%BE%D1%81%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0&amp;diff=2423"/>
		<updated>2026-07-06T23:04:11Z</updated>

		<summary type="html">&lt;p&gt;AZykov: /* Установка и настройка голосового робота Эра (SecondChain) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Установка и настройка голосового робота Эра (SecondChain) =&lt;br /&gt;
&lt;br /&gt;
Пошаговая инструкция по развёртыванию голосового робота. Процесс разбит на четыре этапа:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 1. Подготовка|Подготовка]]&#039;&#039;&#039; — Docker, PostgreSQL, настройки в системе телефонии.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 2. Установка сервисов инференса (опционально)|Установка сервисов инференса]]&#039;&#039;&#039; — ASR, LLM, TTS. &#039;&#039;Опционально, только для развёртывания на собственном сервере с GPU.&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 3. Настройка .env|Настройка .env]]&#039;&#039;&#039; — параметры подключения.&lt;br /&gt;
# &#039;&#039;&#039;[[#Этап 4. Запуск контейнера и создание робота|Запуск контейнера и создание робота]]&#039;&#039;&#039; — старт сервиса и конфигурация робота.&lt;br /&gt;
&lt;br /&gt;
= Глоссарий =&lt;br /&gt;
&#039;&#039;&#039;Модель&#039;&#039;&#039; — обученная нейросеть, задающая соответствие между входом и выходом (текст -&amp;gt; текст, звук -&amp;gt; текст и т.д.). Модель определяется архитектурой и набором весов, полученных при обучении. В стеке робота их четыре:VAD (детекция голосовой активности), ASR (распознавание речи), LLM (генерация ответа), TTS (синтез речи).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Веса&#039;&#039;&#039; — числовые параметры модели, полученные при обучении. Именно они хранятся в файлах модели и загружаются в VRAM при старте. «Загрузка весов» в логах vLLM — это чтение этих файлов с диска в память GPU.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инференс&#039;&#039;&#039; — использование готовой модели для получения ответа на новый вход («прогон» данных через веса). В отличие от обучения, веса не меняются. Сервисы инференса в статье — Triton, vLLM, LightTTS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Triton&#039;&#039;&#039; (NVIDIA Triton Inference Server) — сервер инференса от NVIDIA, обслуживающий модели по gRPC и HTTP. В стеке на нём крутится ASR-модель T-one.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TensorRT&#039;&#039;&#039; — библиотека NVIDIA для оптимизации моделей под конкретный GPU: она компилирует модель в специализированный «движок» ради ускорения инференса. Сборка такого движка — разовая операция под железо, поэтому в LightTTS и T-One Triton она выполняется на первой фазе и коммитится в образ.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;vLLM&#039;&#039;&#039; — движок инференса для больших языковых моделей (LLM), оптимизированный на пропускную способность и эффективную работу с памятью. Предоставляет OpenAI-совместимый API.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;nvidia-smi&#039;&#039;&#039; (NVIDIA System Management Interface) — консольная утилита для просмотра состояния GPU: модель карты, версия драйвера, загрузка, потребление VRAM, запущенные процессы. Используется для проверки, что драйвер установлен и GPU виден (в т.ч. изнутри контейнера).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KV-Cache&#039;&#039;&#039; (кэш ключей и значений) — память, где LLM хранит промежуточные представления уже обработанных токенов, чтобы не пересчитывать их при генерации каждого нового токена. Ускоряет генерацию ценой VRAM. В конфиге ограничен параметром &amp;lt;code&amp;gt;--kv-cache-memory&amp;lt;/code&amp;gt; (3 GiB). Растёт с числом сессий и длиной контекста — поэтому его размер критичен на картах с малым запасом VRAM.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LightTTS&#039;&#039;&#039; — движок инференса для TTS-моделей (синтеза речи). В стеке запускает модель CosyVoice3, слушает порт 8080.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Токен&#039;&#039;&#039; —В &#039;&#039;контексте LLM&#039;&#039; — единица текста, которой оперирует модель (примерно часть слова / слово / знак). Именно в токенах измеряются окно контекста и объём генерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Окно контекста&#039;&#039;&#039; — максимальное количество токенов, которое LLM может учитывать за один запрос (вход + генерируемый ответ вместе). Чем больше окно, тем больше VRAM уходит под KV-Cache, поэтому на картах с ограниченным объёмом его сокращают.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Этап 1. Подготовка =&lt;br /&gt;
&lt;br /&gt;
Установка Docker, базы данных и настройка проброса заголовков и абонента в системе телефонии.&lt;br /&gt;
&lt;br /&gt;
== 1.1. Установка Docker ==&lt;br /&gt;
Установка самого Docker:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt install ca-certificates curl&lt;br /&gt;
install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
&lt;br /&gt;
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&lt;br /&gt;
Types: deb&lt;br /&gt;
URIs: https://download.docker.com/linux/ubuntu&lt;br /&gt;
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;)&lt;br /&gt;
Components: stable&lt;br /&gt;
Architectures: $(dpkg --print-architecture)&lt;br /&gt;
Signed-By: /etc/apt/keyrings/docker.asc&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
&lt;br /&gt;
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Установка Nvidia Container Toolkit (только для серверов с GPU):&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# репозиторий&lt;br /&gt;
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \&lt;br /&gt;
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \&lt;br /&gt;
  sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | \&lt;br /&gt;
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
sudo systemctl restart docker&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.2. Создать БД в PostgreSQL ==&lt;br /&gt;
&lt;br /&gt;
Установить или взять существующий инстанс Postgres, создать нового пользователя и базу для робота.&lt;br /&gt;
&lt;br /&gt;
Пример с Docker:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name postgres \&lt;br /&gt;
  --network host \&lt;br /&gt;
  -e POSTGRES_USER=secondchain \&lt;br /&gt;
  -e POSTGRES_PASSWORD=changeme \&lt;br /&gt;
  -e POSTGRES_DB=secondchain \&lt;br /&gt;
  -v pgdata:/var/lib/postgresql/data \&lt;br /&gt;
  postgres:17&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1.3. Настройка проброса заголовка в B2B ==&lt;br /&gt;
[[Файл:Дополнительный заголовок в конфигурации b2b.png|мини]]&lt;br /&gt;
Мастер-домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. В конфигурации, в нодах B2B добавить проброс заголовка &amp;lt;code&amp;gt;X-Robot-Session&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;fwd_headers&amp;quot;: [&amp;quot;X-Robot-Session&amp;quot;],&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Активировать новую конфигурацию.&lt;br /&gt;
&lt;br /&gt;
== 1.4. Создать абонента для робота ==&lt;br /&gt;
[[Файл:Абонент для робота.png|мини|215x215пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать нового абонента, под которым будет регистрироваться робот.&lt;br /&gt;
&lt;br /&gt;
Робот будет использовать данную учетную запись для приема звонков.&lt;br /&gt;
&lt;br /&gt;
== 1.5. Создать канал интеграции для робота ==&lt;br /&gt;
[[Файл:Канал интеграции для робота.png|мини|214x214пкс]]&lt;br /&gt;
Проектный домен → приложение &#039;&#039;&#039;Настройки&#039;&#039;&#039;. Создать новый канал интеграции:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Тип&#039;&#039;&#039; — Подписчик&lt;br /&gt;
* &#039;&#039;&#039;Права&#039;&#039;&#039; — &amp;lt;code&amp;gt;ai_admin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ai_voicebot_admin&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Режим активности&#039;&#039;&#039; — постоянный&lt;br /&gt;
&lt;br /&gt;
== 1.6. Создать движок в приложении ИИ ==&lt;br /&gt;
[[Файл:Движок в приложении ИИ.png|мини]]&lt;br /&gt;
Задать произвольные название и код. В поле &#039;&#039;&#039;Номер телефона&#039;&#039;&#039; указать внутренний номер абонента, созданного на шаге [[#1.4. Создать абонента для робота|1.4]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Количество сессий&#039;&#039;&#039; по умолчанию = 8. Точное число зависит от оборудования, на котором размещаются сервисы робота.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Этап 2. Установка сервисов инференса (опционально) =&lt;br /&gt;
&lt;br /&gt;
Инструкция для &#039;&#039;&#039;Ubuntu Server 24.04&#039;&#039;&#039;. Стек: ASR (T-one/Triton) → LLM (Qwen3.5-35B-A3B на vLLM) → TTS (LightTTS + CosyVoice3).&lt;br /&gt;
&lt;br /&gt;
Целевая машина — сервер с GPU: &#039;&#039;&#039;RTX PRO 5000 (48GB)&#039;&#039;&#039; или &#039;&#039;&#039;RTX PRO 6000 Blackwell (96GB)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== 2.1. Предварительные требования ==&lt;br /&gt;
&lt;br /&gt;
Убедиться, что установлены драйверы NVIDIA, Docker и NVIDIA Container Toolkit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nvidia-smi                          # драйвер и GPU видны&lt;br /&gt;
docker --version                    # Docker установлен&lt;br /&gt;
docker run --rm --gpus all ubuntu nvidia-smi   # GPU проброшен в контейнер&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если последняя команда не отображает GPU, требуется установить NVIDIA Container Toolkit и перезапустить Docker.&lt;br /&gt;
&lt;br /&gt;
=== Бюджет VRAM ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Компонент !! VRAM&lt;br /&gt;
|-&lt;br /&gt;
| ASR (T-one/Triton) || 600–800 MB&lt;br /&gt;
|-&lt;br /&gt;
| LLM (Qwen3.5-35B-A3B) || 24–48 GB (зависит от числа сессий и длины контекста)&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS/CosyVoice3) || 11 GB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Суммарное потребление в пике — ~36–60 GB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 6000 (96GB):&#039;&#039;&#039; объёма достаточно с большим запасом. Допустимо использование максимального числа сессий и длинного контекста.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RTX PRO 5000 (48GB):&#039;&#039;&#039; запас минимальный. Фиксированная сумма ASR (~0.8 GB) и TTS (11 GB) составляет ~12 GB, на LLM остаётся ~36 GB. Это покрывает только нижнюю границу диапазона LLM (24 GB). Требуется ограничение параметров &amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt; во избежание ошибки OOM. Значение &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; (~24 GB на карте 48GB) для данного сценария допустимо при условии, что ASR и TTS инициализированы до старта LLM.&lt;br /&gt;
&lt;br /&gt;
Объем оперативной памяти не может быть меньше, чем VRAM, так как в процессе запуска веса моделей помещаются сначала в оперативную память, и только затем в VRAM.&lt;br /&gt;
&lt;br /&gt;
== 2.2. Порядок запуска ==&lt;br /&gt;
&lt;br /&gt;
Модели независимы. Рекомендуемый порядок развёртывания для упрощения диагностики: &#039;&#039;&#039;ASR → LLM → TTS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Компиляция моделей может занимать больше VRAM, чем запущенный сервис, поэтому в случае дефицита видеопамяти, рекомендуется временно отключать свеже созданные контейнеры, собирать их по одному, после чего запускать по очереди уже в собранном виде.&lt;br /&gt;
&lt;br /&gt;
== 2.3. ASR (T-one на Triton Inference Server) ==&lt;br /&gt;
&lt;br /&gt;
Необходимо скачать и загрузить образ контейнера, создать контейнер и дождаться сборки ML-движка. Первый запуск может проходить долго, 5-15 минут, в зависимости от оборудования. Во время первого запуска система собирает движок модели с оптимизациями под текущий GPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/tone-triton.tar.gz&lt;br /&gt;
docker load &amp;lt; tone-triton.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --name tone-triton --gpus all --restart unless-stopped \&lt;br /&gt;
    -p 17000:8000 -p 17001:8001 -p 17002:8002 \&lt;br /&gt;
    -v tone-engine:/models/streaming_acoustic/1 \&lt;br /&gt;
    tone-triton:dist-trt-b32&lt;br /&gt;
&lt;br /&gt;
docker logs -f tone-triton&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После появления данного сообщения можно считать что движок собран и переходить к следующему шагу установки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
I0706 22:41:02.484518 1 grpc_server.cc:2562] &amp;quot;Started GRPCInferenceService at 0.0.0.0:8001&amp;quot;&lt;br /&gt;
I0706 22:41:02.484664 1 http_server.cc:4832] &amp;quot;Started HTTPService at 0.0.0.0:8000&amp;quot;&lt;br /&gt;
I0706 22:41:02.525792 1 http_server.cc:358] &amp;quot;Started Metrics Service at 0.0.0.0:8002&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после старта Triton слушает gRPC (стандартно 8001) и HTTP (стандартно 8000). Потребление VRAM — &#039;&#039;&#039;600–800 MB&#039;&#039;&#039;. Статус контейнера:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep -i tone&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.4. LLM (Qwen3.5-35B-A3B на vLLM) ==&lt;br /&gt;
&lt;br /&gt;
Установка выполняется из Docker Hub, следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d \&lt;br /&gt;
  --name vllm-qwen35-moe \&lt;br /&gt;
  --gpus all \&lt;br /&gt;
  --ipc=host \&lt;br /&gt;
  -v /path/to/cache:/root/.cache \&lt;br /&gt;
  -p 16080:8000 \&lt;br /&gt;
  vllm/vllm-openai:cu130-nightly \&lt;br /&gt;
  --model Qwen/Qwen3.5-35B-A3B-GPTQ-Int4 \&lt;br /&gt;
  --served-model-name qwen35-35b-a3b \&lt;br /&gt;
  --quantization moe_wna16 \&lt;br /&gt;
  --max-num-seqs 6 \&lt;br /&gt;
  --max-model-len 4096 \&lt;br /&gt;
  --kv-cache-memory 3221225472 \&lt;br /&gt;
  --gpu-memory-utilization 0.50 \&lt;br /&gt;
  --enable-prefix-caching \&lt;br /&gt;
  --host 0.0.0.0 --port 8000 \&lt;br /&gt;
  --reasoning-parser qwen3 \&lt;br /&gt;
  --enable-auto-tool-choice \&lt;br /&gt;
  --tool-call-parser qwen3_coder \&lt;br /&gt;
  --language-model-only&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
docker logs vllm-qwen35-moe -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ключевые параметры:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-model-len 8192&amp;lt;/code&amp;gt; — максимальное окно контекста в токенах.&lt;br /&gt;
* &amp;lt;code&amp;gt;--max-num-seqs 6&amp;lt;/code&amp;gt; — максимум одновременно обрабатываемых запросов.&lt;br /&gt;
* &amp;lt;code&amp;gt;--gpu-memory-utilization 0.50&amp;lt;/code&amp;gt; — 50% VRAM выделено под LLM.&lt;br /&gt;
* &amp;lt;code&amp;gt;--kv-cache-memory 3221225472&amp;lt;/code&amp;gt; — 3 GiB под KV-кэш.&lt;br /&gt;
* &amp;lt;code&amp;gt;/path/to/cache&amp;lt;/code&amp;gt; — директория хост-машины, где будет храниться кеш весов модели (24gb)&lt;br /&gt;
&lt;br /&gt;
Минимальный объём VRAM для запуска — &#039;&#039;&#039;24 GB&#039;&#039;&#039;. Фактическое потребление — &#039;&#039;&#039;24–48 GB&#039;&#039;&#039; в зависимости от числа допустимых сессий (&amp;lt;code&amp;gt;--max-num-seqs&amp;lt;/code&amp;gt;) и длины контекста (&amp;lt;code&amp;gt;--max-model-len&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
После запуска vllm скачает веса модели для запуска (24gb). После завершения запуска и загрузки весов в логах можно наблюдать следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(APIServer pid=1) INFO:     Started server process [1]&lt;br /&gt;
(APIServer pid=1) INFO:     Waiting for application startup.&lt;br /&gt;
(APIServer pid=1) INFO:     Application startup complete.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Как только они появятся, можно переходить к следующему шагу.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Проверка:&#039;&#039;&#039; после загрузки весов проверить OpenAI-совместимый эндпоинт на порту &#039;&#039;&#039;16080.&#039;&#039;&#039; Первый запрос к модели будет занимать достаточно много времени:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker logs -f vllm-qwen35-moe        # ожидать &amp;quot;Application startup complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/models&lt;br /&gt;
&lt;br /&gt;
curl http://localhost:16080/v1/chat/completions \&lt;br /&gt;
  -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  -d &#039;{&lt;br /&gt;
    &amp;quot;model&amp;quot;: &amp;quot;qwen35-35b-a3b&amp;quot;,&lt;br /&gt;
    &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Привет&amp;quot;}],&lt;br /&gt;
    &amp;quot;chat_template_kwargs&amp;quot;: {&amp;quot;enable_thinking&amp;quot;: false}&lt;br /&gt;
  }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.5. TTS (LightTTS + CosyVoice3) ==&lt;br /&gt;
&lt;br /&gt;
По аналогии с T-One, установка выполняется из образа docker-контейнера&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/lightts-weights.tar.gz&lt;br /&gt;
docker load -i lighttts-weights.tar.gz&lt;br /&gt;
&lt;br /&gt;
docker run -d --gpus all -p 8080:8080 --shm-size 4g \&lt;br /&gt;
  --restart unless-stopped --name lighttts \&lt;br /&gt;
  -v lighttts-engines:/opt/models/Fun-CosyVoice3-0.5B \&lt;br /&gt;
  lighttts/light-tts:weights&lt;br /&gt;
&lt;br /&gt;
docker logs -f lighttts&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;После запуска сервис скомпилирует веса, по аналогии с T-One. После завершения подготовки в логах будут следующие строки:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
///////////////////////&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Проверка:&#039;&#039;&#039; TTS слушает порт &#039;&#039;&#039;8080&#039;&#039;&#039;, потребление VRAM — &#039;&#039;&#039;11 GB&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps | grep lighttts&lt;br /&gt;
nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 2.6. Итоговая карта портов ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Сервис !! Контейнер !! Внешний порт&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton HTTP) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8000&lt;br /&gt;
|-&lt;br /&gt;
| ASR (Triton gRPC) || &amp;lt;code&amp;gt;tone-triton&amp;lt;/code&amp;gt; || 8001&lt;br /&gt;
|-&lt;br /&gt;
| LLM (vLLM) || &amp;lt;code&amp;gt;vllm-qwen35-moe&amp;lt;/code&amp;gt; || 16080&lt;br /&gt;
|-&lt;br /&gt;
| TTS (LightTTS) || &amp;lt;code&amp;gt;lighttts&amp;lt;/code&amp;gt; || 8080&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 2.7. Финальная проверка стека ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker ps        # все три контейнера (ASR / vLLM / TTS) в статусе Up&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После проверки выполняется подключение пайплайна PjSIP → VAD → ASR → LLM → TTS с указанием эндпоинтов в конфигурации: ASR — &amp;lt;code&amp;gt;:8000/:8001&amp;lt;/code&amp;gt;, LLM — &amp;lt;code&amp;gt;:16080&amp;lt;/code&amp;gt;, TTS — &amp;lt;code&amp;gt;:8080&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Этап 3. Настройка .env =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Базовые параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
EXTERNAL_TEMPLATES_URL=https://[адрес инстанса эры]/rest/v1/model/ai/robot&lt;br /&gt;
EXTERNAL_TEMPLATES_TOKEN=[локальный токен из шага 1.5]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А также настройки Postgres (из шага [[#1.2. Создать БД в PostgreSQL|1.2]]) и подключения SIP к учётной записи абонента (из шага [[#1.4. Создать абонента для робота|1.4]]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Плейсхолдер под подробное описание .env --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Этап 4. Запуск контейнера и создание робота =&lt;br /&gt;
&lt;br /&gt;
== 4.1. Загрузка образа и запуск контейнера ==&lt;br /&gt;
&lt;br /&gt;
Скопировать на сервер архив с образом контейнера и файл &amp;lt;code&amp;gt;.env&amp;lt;/code&amp;gt; в одну директорию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget https://ai02.era-platform.ru/secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
docker load -i secondchain-1.0.3a-cpu.tar.gz&lt;br /&gt;
mkdir -p ./logs&lt;br /&gt;
docker run -d --name secondchain \&lt;br /&gt;
  --network host \&lt;br /&gt;
  --env-file .env \&lt;br /&gt;
  --restart unless-stopped \&lt;br /&gt;
  -v secondchain-data:/data \&lt;br /&gt;
  -v ./logs:/app/logs \&lt;br /&gt;
  secondchain:1.0.3a-cpu&lt;br /&gt;
&lt;br /&gt;
docker logs secondchain -f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Когда сервис загрузится и проинициализируется, в консоли появится сообщение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Registration: OK (code=200)    [pjsip.account]&lt;br /&gt;
[info     ] SIP client registered successfully [voip.sip]&lt;br /&gt;
[info     ] VoIP health monitor started    [src.api.app]&lt;br /&gt;
[info     ] SecondChain started successfully [src.api.app]&lt;br /&gt;
[info     ] Application startup complete.  [uvicorn.error]&lt;br /&gt;
[info     ] Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2. Создать робота в приложении ИИ ==&lt;br /&gt;
&lt;br /&gt;
=== Загрузить голос ===&lt;br /&gt;
&lt;br /&gt;
Необходим аудиофайл &amp;lt;code&amp;gt;.mp3&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.wav&amp;lt;/code&amp;gt; длительностью ~10 секунд, без лишних шумов и эхо. При загрузке указать точную транскрипцию произнесённого текста (со знаками препинания).&lt;br /&gt;
&lt;br /&gt;
Для быстрого старта можно импортировать демо-голос (импорт + загрузка файла).&lt;br /&gt;
&lt;br /&gt;
=== Создать инструменты ===&lt;br /&gt;
&lt;br /&gt;
Базовые инструменты работы со звонком.&lt;br /&gt;
&lt;br /&gt;
==== drop_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;drop_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Завершение звонка по инициативе робота&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;drop&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== transfer_call ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Параметр !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| Имя || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Код || &amp;lt;code&amp;gt;transfer_call&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| description || Перевод звонка на оператора&lt;br /&gt;
|-&lt;br /&gt;
| toolType || &amp;lt;code&amp;gt;callManagement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| callAction || &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| transferDestination || Короткий номер для перевода звонков (например, номер очереди)&lt;br /&gt;
|-&lt;br /&gt;
| enabled || Да&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Создать робота ===&lt;br /&gt;
&lt;br /&gt;
Импортировать шаблон (&amp;lt;code&amp;gt;Роботы.json&amp;lt;/code&amp;gt;). На вкладке &#039;&#039;&#039;Инструкции&#039;&#039;&#039; изучить рекомендуемый шаблон системного промпта, а также промпта пост-обработки звонка.&lt;br /&gt;
&lt;br /&gt;
== 4.3. Проверить создание пользователя ==&lt;br /&gt;
&lt;br /&gt;
После создания робота должен автоматически создаться пользователь &amp;lt;code&amp;gt;Робот_имяРобота&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== 4.4. Проверить и установить статус пользователя ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Супервизор контакт-центра&#039;&#039;&#039; → раздел &#039;&#039;&#039;Операторы → Текущие статусы&#039;&#039;&#039;. Убрать фильтры, найти пользователя робота и убедиться, что у него установлен статус &#039;&#039;&#039;Готов&#039;&#039;&#039;. При необходимости установить этот статус.&lt;br /&gt;
&lt;br /&gt;
== 4.5. Добавить робота в очередь ==&lt;br /&gt;
&lt;br /&gt;
Приложение &#039;&#039;&#039;Администратор контакт-центра&#039;&#039;&#039; → добавить робота как участника очереди. &#039;&#039;&#039;Тип участника&#039;&#039;&#039; = Робот. В остальном настройки идентичны.&lt;br /&gt;
&lt;br /&gt;
== 4.6. Осуществить звонок ==&lt;br /&gt;
&lt;br /&gt;
Настройка завершена. Можно совершить звонок в очередь и протестировать работу робота.&lt;br /&gt;
&lt;br /&gt;
[[Category:Эра]]&lt;br /&gt;
[[Category:Голосовой робот]]&lt;br /&gt;
[[Category:Развёртывание]]&lt;/div&gt;</summary>
		<author><name>AZykov</name></author>
	</entry>
</feed>