Урок курса
Pipecat: модульный пайплайн из процессоров
Voice AI Agents PROЗачем голосовому агенту фреймворк
В прошлых уроках вы собирали голосового агента из отдельных деталей. Сначала — нижний слой: распознавание речи, синтез, определение пауз, момент конца реплики, перехват чужой речи и бюджет задержки. Затем — слой модели: промпт, инструменты, память. Каждый кусок вы умеете подключить сам по себе. Остаётся вопрос, который в чате не возникает, а в звонке решает всё: кто склеивает эти куски в реальном времени, пока человек говорит.
В текстовом чате склейка тривиальна. Пришло сообщение — вызвали модель — отдали ответ. В звонке всё иначе: звук идёт сплошным потоком, обе стороны могут заговорить одновременно, и каждая лишняя сотня миллисекунд слышна. Поэтому между деталями появляется отдельный слой — тот, что управляет разговором во времени.
Что приходилось держать руками
Если собирать агента из голых компонентов самостоятельно, на вас ложится вся работа по координации потока. Перечислим её честно, потому что именно это фреймворк потом и заберёт.
Событийный цикл. Звук с микрофона приходит маленькими кадрами, без пауз. Кто-то должен непрерывно гонять их через определение голоса в STT, накапливать распознанный текст и решать, что делать дальше. Это не разовый вызов функции, а бесконечный цикл, который крутится всё время разговора.
Переход хода (turn-taking). Человек умолк на секунду — он закончил мысль или просто вдохнул? Ответить рано — перебьёте собеседника, ответить поздно — разговор тормозит. Нужен детектор конца реплики, который ловит этот момент по паузе и по самому смыслу фразы.
Перебивания (barge-in). Агент говорит, и тут вступает человек. Правильное поведение — мгновенно замолчать и начать слушать. Значит, надо параллельно с синтезом речи следить за входящим звуком и уметь оборвать собственный вывод на полуслове.
Стриминг STT → LLM → TTS. Ждать, пока модель допишет ответ целиком, а потом отдавать его в синтез — слишком медленно для разговора. Текст из модели надо отдавать в синтез по частям, как только он появляется, чтобы агент начинал говорить, ещё не закончив думать. Стыковка трёх потоков — отдельная инженерная задача.
Транспорт. Звук между человеком и сервером надо доставить с минимальной задержкой и устойчивостью к потерям. Это WebRTC или WebSocket-канал, переподключения, синхронизация — слой, который к логике агента отношения не имеет, но без которого ничего не работает.
Один раз это можно написать на коленке для демо. На проде такой цикл превращается в источник трудноуловимых сбоев: где-то агент не успел замолчать, где-то ответил в паузу между словами, где-то задержка выросла под нагрузкой. Сопровождать это руками дорого.
Где здесь фреймворк
В начале курса мы раскладывали способы собрать голосового агента на спектр от полного контроля до готового решения: кастомный стек (всё своими руками), фреймворк (готовый слой оркестрации, но код ваш) и no-code платформы (собираешь мышкой). Pipecat — это середина: фреймворк-оркестратор. Он берёт на себя ровно тот слой координации, что перечислен выше, и оставляет вам выбор компонентов и логику агента.
То есть вы по-прежнему сами решаете, какой STT, какую модель и какой синтез подключить и что агент должен делать. Но событийный цикл, переход хода, перебивания, стриминг и транспорт за вас держит фреймворк. Это и есть смысл слова «оркестратор»: он дирижирует деталями, не подменяя их.
Философия Pipecat: пайплайн из процессоров
Pipecat снимает с разработчика ручную сшивку событийного цикла, перехвата хода и стриминга, но делает это в духе конструктора: агент собирается из мелких одинаковых деталей, а фреймворк задаёт правила, по которым они стыкуются. Из этой идеи вытекает всё его устройство.
Frame — единица данных
Через агента постоянно течёт разнородная информация: куски входного звука, распознанный текст, ответ модели, синтезированная речь, служебные сигналы вроде «пользователь начал говорить» или «реплика закончилась». В Pipecat каждая такая порция — это Frame, типизированный объект. AudioRawFrame несёт аудио, TextFrame — текст, TranscriptionFrame — результат распознавания, и так далее. Frame не перемешиваются в один общий поток байтов: по типу всегда понятно, что именно пришло.
FrameProcessor — кирпич
FrameProcessor — базовый класс для всех обработчиков. Процессор получает Frame, делает с ним что-то одно и передаёт результат дальше по цепочке. Распознавание речи — это процессор, который принимает аудио и отдаёт текст. Модель — процессор, который принимает запрос и отдаёт ответ в виде текста. Синтез — процессор, который принимает текст и отдаёт звук. Каждый занят своим делом и ничего не знает о соседях: он работает с входными Frame и порождает выходные.
Из этого вытекает главное свойство Pipecat — на любом участке цепочки можно вставить свой процессор. Нужно перехватывать реплики и писать их в лог, подменять текст перед синтезом или добавить фильтр нецензурной лексики — это просто ещё один FrameProcessor между двумя соседними. Плоская модель из одинаковых кирпичей делает такие вставки естественными.
Pipeline и Runner — сборка и запуск
Процессоры выстраиваются в Pipeline — список, по которому фреймы идут слева направо. Сам список ничего не выполняет: это описание маршрута. Чтобы пайплайн заработал, его оборачивают в PipelineTask (одна сессия со своими параметрами и метриками) и отдают PipelineRunner — он запускает задачу, держит её жизненный цикл и корректно завершает по сигналу остановки.
Три уровня легко перепутать:
Pipeline— что за чем идёт,PipelineTask— конкретный запуск этой схемы,PipelineRunner— кто этим запуском управляет.
Транспорт отделён от логики
Собственного медиасервера у Pipecat нет, и транспорт звука не выделен в отдельную подсистему. Это просто крайние процессоры пайплайна: transport.input() в начале и transport.output() в конце. Между ними — логика, которая про транспорт ничего не знает.
Поэтому канал связи меняется без правки логики. Daily-транспорт даёт WebRTC, есть WebSocket-транспорт для телефонии и серверных интеграций. Заменили крайние процессоры — пайплайн поехал по другому каналу, а STT, модель и синтез между ними остались прежними. Pipecat не привязывает к одному медиасерверу: по какому каналу идёт звук, разработчик решает сам.
Минимальный пайплайн: код
Соберём рабочего агента из тех самых кирпичей. Кода немного — почти всё место занимает не сборка, а создание сервисов с ключами.
Старт проекта
Самый быстрый путь — готовый шаблон через CLI: поставить инструмент командой pip install pipecat-ai-cli и сгенерировать каркас командой pipecat init quickstart. Тогда минимальный агент и переменные окружения уже готовы.


На Windows
pipecat initпадает с ошибкой'charmap' codec can't encode character '→'. Причина — в шаблоне есть символ стрелки→(из названия архитектуры «STT → LLM → TTS»), а Python по умолчанию пишет файлы в кодировкеcp1252, которая этот символ не знает. Проект при этом создаётся пустым. Лечится включением UTF-8-режима Python: в текущей сессии cmd —set PYTHONUTF8=1, навсегда —setx PYTHONUTF8 1(применяется только к новым окнам терминала, текущее нужно перезапустить). После этого удалите пустой каталог и запуститеpipecat init quickstartзаново.
Если проект собирать с нуля руками, ставится сам пакет, а провайдеры подключаются как extras в квадратных скобках — по умолчанию ядро идёт без них, чтобы не тянуть лишнего:
pip install "pipecat-ai[daily,deepgram,openai,cartesia,silero]"
Здесь daily — транспорт, deepgram — распознавание, openai — модель, cartesia — синтез, silero — определение голоса (VAD). Каталог сервисов широкий: десятки вариантов STT, моделей и TTS подключаются той же строкой, меняется только имя extra.
extra
dailyпод Windows не ставится — пакетdaily-pythonвыпускается только для Linux и macOS, колеса под Windows на PyPI нет. Команда выше упадёт с длинным перебором версий и финальной ошибкойResolutionImpossible; реальную причину видно в последних строках вывода:no matching distributions available for your environment: daily-python. Для локальной разработки на Windows уберитеdailyиз списка (pip install "pipecat-ai[deepgram,openai,cartesia,silero]") — для теста с микрофоном и колонками транспорт Daily не нужен. Если Daily обязателен, запускайте проект под Linux через WSL2 или Docker.
Ключи провайдеров
Схема с ключами уже знакома по прошлым урокам: каждый сервис берёт свой API-ключ из .env рядом с проектом, а сам файл — в .gitignore. Здесь ключи нужны под транспорт, распознавание, модель и синтез:
# .env
DEEPGRAM_API_KEY=your-deepgram-key
OPENAI_API_KEY=sk-your-openai-key
CARTESIA_API_KEY=your-cartesia-key
DAILY_ROOM_URL=https://your-domain.daily.co/your-room
DAILY_TOKEN=your-daily-token
Сборка пайплайна
Сначала создаём транспорт и три сервиса, потом выстраиваем их в Pipeline. Порядок процессоров в списке — это и есть маршрут Frame: вход, определение голоса, распознавание, модель, синтез, выход. Определение голоса (VAD) вынесено в отдельный процессор VADProcessor перед STT — по его сигналам «началась/закончилась речь» распознавание нарезает аудио на реплики, поэтому порядок (VAD → STT) обязателен.
import os
from dotenv import load_dotenv
from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.pipeline.runner import PipelineRunner
from pipecat.transports.services.daily import DailyTransport, DailyParams
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair
from pipecat.processors.audio.vad_processor import VADProcessor
from pipecat.services.deepgram.stt import DeepgramSTTService
from pipecat.services.openai.llm import OpenAILLMService
from pipecat.services.cartesia.tts import CartesiaTTSService
load_dotenv() # подхватываем ключи из .env в окружение
transport = DailyTransport(
room_url=os.getenv("DAILY_ROOM_URL"),
token=os.getenv("DAILY_TOKEN"),
bot_name="Bot",
params=DailyParams(
audio_in_enabled=True,
audio_out_enabled=True,
),
)
stt = DeepgramSTTService(api_key=os.getenv("DEEPGRAM_API_KEY"))
llm = OpenAILLMService(
api_key=os.getenv("OPENAI_API_KEY"),
settings=OpenAILLMService.Settings(model="gpt-5.5"),
)
tts = CartesiaTTSService(
api_key=os.getenv("CARTESIA_API_KEY"),
settings=CartesiaTTSService.Settings(voice="VOICE_ID"),
)
# Системный промпт лежит в контексте LLM, а не внутри сервиса модели
context = LLMContext(messages=[
{"role": "system", "content": "Ты администратор клиники. Отвечай коротко и по делу."}
])
# Универсальная пара агрегаторов копит историю диалога
aggregator = LLMContextAggregatorPair(context)
pipeline = Pipeline([
transport.input(),
VADProcessor(vad_analyzer=SileroVADAnalyzer()), # сегментация речи перед STT
stt,
aggregator.user(),
llm,
tts,
transport.output(),
aggregator.assistant(),
])
Системный промпт агента (тот самый голосовой промпт администратора клиники, который собирали в модуле LLM) задаётся через контекст модели, а распознанная реплика идёт по пайплайну как Frame. Логика та же, что в LangChain-цепочке: реплика клиента превращается в текст, текст — в ответ модели, ответ — в речь.
Обратите внимание на пару агрегаторов вокруг
llm. Промпт и история диалога хранятся не внутри модели, а в отдельном объекте контекста LLM (LLMContext); чтобы реплики накапливались в этой истории, контекст оборачивают в универсальную пару агрегаторовLLMContextAggregatorPair, и её ставят в пайплайн доllm(aggregator.user()— добавляет реплику пользователя) и после (aggregator.assistant()— добавляет ответ модели).
Запуск
Готовый Pipeline сам не работает — его оборачивают в PipelineTask и передают PipelineRunner. Запуск асинхронный: runner.run() — корутина, поэтому её вызывают через await внутри async-функции, а саму функцию стартуют через asyncio.run():
import asyncio
async def main():
task = PipelineTask(pipeline, params=PipelineParams(enable_metrics=True))
runner = PipelineRunner()
await runner.run(task)
if __name__ == "__main__":
asyncio.run(main())
PipelineTask — это одна сессия. Её параметры передают не по одному, а собранными в объект PipelineParams (например, enable_metrics=True для сбора метрик задержки). PipelineRunner запускает задачу, держит её до конца разговора и аккуратно завершает по сигналу остановки. Дальше работает событийный цикл, перехват хода и стриминг — это берёт на себя фреймворк.
Какие сервисы использовать
В примере собран один конкретный набор: Deepgram распознаёт речь, OpenAI отвечает, Cartesia озвучивает. Это не единственный вариант — каждый из трёх кирпичей меняется независимо, той же строкой extras. Под распознавание в каталоге есть deepgram, assemblyai, gladia; под модель — openai, anthropic, google, groq, mistral; под синтез — cartesia, elevenlabs, rime, kokoro. Выбирают по задаче: задержка, поддержка нужного языка и цена.
Русских сервисов в каталоге Pipecat по умолчанию нет — ни SpeechKit и SaluteSpeech для распознавания и синтеза, ни YandexGPT и GigaChat для модели. Их встраивают обёрткой — через совместимый эндпоинт или собственный класс сервиса; как это делается, разобрано в уроке «Pipecat: обёртки для российского стека».
Конкретные строковые идентификаторы моделей и голосов провайдеры периодически меняют — сверьтесь с актуальной документацией провайдера.
Несколько агентов на общей шине
Один пайплайн — один агент. Когда задача требует нескольких агентов, которые переговариваются между собой (например, оператор передаёт звонок профильному специалисту), в Pipecat 1.3 есть модуль pipecat.workers: воркеры на общей шине обмениваются типизированными сообщениями и распределяют работу между собой. Под капотом этой модели в 1.3 базовым классом стал PipelineWorker, а знакомый по прошлым шагам PipelineTask — его частный случай для одиночного пайплайна, поэтому код из предыдущих шагов работает без изменений. Это отдельная большая тема — здесь достаточно знать, что такая возможность встроена, а одиночный пайплайн при этом продолжает работать как раньше.
Где запускать агента
Готового агента нужно где-то держать. У Pipecat два пути.
Pipecat Cloud — managed-хостинг от Daily (авторов фреймворка). Агент разворачивается их инструментами, инфраструктуру и масштабирование берёт на себя платформа. Оплата — поминутно за активного агента, ориентир порядка 0,01–0,03 долл. за минуту в зависимости от тира мощности; зарезервированный инстанс стоит примерно в двадцать раз дешевле активного. Платформа вышла в общий доступ в начале 2026 года.
Точные цены Pipecat Cloud провайдер периодически пересматривает — перед расчётом бюджета сверьтесь с актуальным прайсом.
Self-host — поскольку Pipecat и его deploy-инструменты open-source, агента можно развернуть где угодно: Fly.io, Google Cloud Run, собственные серверы. Платишь только за инфраструктуру, но настраиваешь и масштабируешь сам.
Локальный запуск без затрат
Чтобы погонять пайплайн и не платить за облачные сервисы, каждый кирпич можно заменить локальным аналогом. Транспорт Daily меняем на локальное аудио (микрофон и колонки), распознавание — на Whisper прямо на машине, модель — на LM Studio (он поднимает у себя OpenAI-совместимый сервер), синтез — на локальный Kokoro. Всё это ставится теми же extras, только без облачных провайдеров:
pip install "pipecat-ai[local,whisper,openai,silero,kokoro]"
Здесь local — локальный аудио-транспорт (ставит pyaudio), whisper — распознавание через faster-whisper, openai — тот же клиент OpenAI, которым мы достучимся до LM Studio, silero — VAD, kokoro — локальный синтез. Extra daily здесь не нужен — и это удобно, ведь под Windows он всё равно не ставится.
LM Studio вместо облачной модели
В LM Studio загружаем модель (например, google/gemma-4-e4b, или какой-то другой из множества доступных вариантов) и на вкладке Local Server жмём Start Server — по умолчанию он слушает http://localhost:1234/v1. В коде используем тот же OpenAILLMService, но указываем ему base_url на локальный сервер; api_key может быть любой строкой, LM Studio его не проверяет.
import asyncio
from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.transports.local.audio import LocalAudioTransport, LocalAudioTransportParams
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair
from pipecat.processors.audio.vad_processor import VADProcessor
from pipecat.services.whisper.stt import WhisperSTTService, Model
from pipecat.services.openai.llm import OpenAILLMService
from pipecat.services.kokoro.tts import KokoroTTSService
from pipecat.processors.logger import FrameLogger
from pipecat.transcriptions.language import Language
async def main():
# Локальный транспорт: микрофон + колонки (VAD вынесен в отдельный процессор)
transport = LocalAudioTransport(
LocalAudioTransportParams(
audio_in_enabled=True,
audio_out_enabled=True,
)
)
stt = WhisperSTTService( # локальный Whisper
settings=WhisperSTTService.Settings(
model=Model.BASE.value,
language=Language.EN, # распознаём английскую речь
no_speech_prob=0.6, # меньше отсекаем как "не речь"
)
)
llm = OpenAILLMService(
api_key="lm-studio", # любая строка
base_url="http://localhost:1234/v1", # сервер LM Studio
settings=OpenAILLMService.Settings(model="google/gemma-4-e4b"),
)
tts = KokoroTTSService( # локальный синтез
settings=KokoroTTSService.Settings(
voice="af_heart", # женский голос (US English)
language=Language.EN,
)
)
context = LLMContext(messages=[
{"role": "system", "content": "You are a helpful voice assistant. Keep replies short."}
])
aggregator = LLMContextAggregatorPair(context)
pipeline = Pipeline([
transport.input(),
VADProcessor(vad_analyzer=SileroVADAnalyzer()), # VAD -> сегментация речи для STT
stt,
FrameLogger("STT"), # видно, что распознал Whisper
aggregator.user(),
llm,
FrameLogger("LLM"), # видно, что ответила модель
tts,
transport.output(),
aggregator.assistant(),
])
task = PipelineTask(pipeline, params=PipelineParams(enable_metrics=True))
await PipelineRunner().run(task)
if __name__ == "__main__":
asyncio.run(main())
Определение голоса вынесено в отдельный процессор VADProcessor перед STT — именно по его сигналам «началась/закончилась речь» Whisper нарезает аудио на реплики, так что порядок (VAD → STT) обязателен. Два FrameLogger — чисто для наглядности: они печатают в консоль Frame, проходящие после распознавания и после модели, чтобы видеть весь путь реплики.
Строку модели (
model="google/gemma-4-e4b") подставьте свою — она должна точно совпадать с идентификатором модели, загруженной в LM Studio, иначе на первом же ответе будет ошибка 404. Голос Kokoro (voice="af_heart") тоже обязателен: без явного голоса сервис падает сTypeError: 'NoneType' object is not subscriptable. Доступные голоса — женскиеaf_*и мужскиеam_*(US English),bf_*/bm_*(British).
Что увидите в консоли
При первом запуске сборка не отвечает сразу — локальные сервисы докачивают свои модели. По порядку в логах видно, как поднимается каждый кирпич:
ᓚᘏᗢ Pipecat 0.0.108 ... ᓚᘏᗢ # баннер фреймворка Loading Silero VAD model... / Loaded Silero VAD # загрузился VAD Loading Whisper model... / Loaded Whisper model # веса распознавания (качаются один раз) Downloading ...kokoro-v1.0.onnx ... / Downloaded # модель синтеза + файл голосов Linking ... -> ... -> ... # процессоры сшиваются в цепочку PipelineTask#0: ... pipeline is now ready. # всё готово, агент слушает микрофон
Скачивание разовое: Whisper кладёт веса в кэш Hugging Face (BASE — от ~75 МБ), Kokoro — .onnx-модель (~300 МБ) и файл голосов в ~/.cache/kokoro-onnx. При следующих запусках этих строк уже не будет, и старт пройдёт за пару секунд. Строка pipeline is now ready — сигнал, что можно говорить.

Когда вы произносите фразу, в консоли разворачивается весь маршрут реплики:
User started speaking / User stopped speaking # VAD поймал границы речи
Transcription: [ Hello ] # Whisper распознал текст
> STT: TranscriptionFrame ... # наш FrameLogger: текст пошёл в LLM
OpenAILLMService ... Generating chat from ... # запрос ушёл в LM Studio
> LLM: ...TextFrame... # наш FrameLogger: пришёл ответ модели
KokoroTTSService ... Generating TTS [Hi!] # синтез ответа в речь
Между этапами мелькают метрики (с enable_metrics=True): processing time — сколько считал сервис, TTFB (time to first byte) — задержка до первого результата. На CPU без видеокарты задержка LLM в пару-тройку секунд — норма. Если строки Transcription: [...] нет — значит Whisper вернул пустой текст (не тот язык, тихий микрофон), и до модели реплика просто не дошла.
Что с русским языком
С распознаванием всё хорошо: Whisper русский понимает уверенно — достаточно указать ему язык (language=Language.RU) и при желании взять модель посерьёзнее (Model.SMALL или Model.MEDIUM вместо BASE). А вот с синтезом загвоздка: Kokoro русский не озвучивает. В его таблице языков всего несколько локалей — английский (US/GB), испанский, французский, итальянский, португальский, хинди, японский и китайский. Русского там нет, и подставить его параметром не выйдет.
Готового русского TTS в каталоге Pipecat «из коробки» тоже нет (как и других сервисов российского стека). Хорошие локальные движки с русскими голосами существуют — например Silero TTS (тот же Silero, что мы уже используем для VAD; лёгкий, считает на CPU) или Piper. Но чтобы подключить любой из них к пайплайну, нужна обёртка — небольшой собственный класс-наследник TTSService с методом run_tts(), который отдаёт аудио кадрами TTSAudioRawFrame (ровно так же, как это делает разобранный Kokoro). Как написать такую обёртку и получить полноценного русскоязычного агента, разобрано в уроке «Pipecat: обёртки для российского стека».
Поэтому практичный порядок такой: сначала прогнать пайплайн целиком на Kokoro по-английски (как в коде выше) — так меньше всего движущихся частей и проще убедиться, что сборка живая. А уже потом, с пониманием, как устроен TTSService, заменить синтез на русский через такую обёртку.
Kokoro под Windows для фонемизации может попросить установленный
espeak-ng(winget install eSpeak-NG) — если при синтезе появятся ошибки про фонемы. Всё считается на CPU, без видеокарты: для теста годится, но задержку видно по метрикам.
Ускорение на GPU
Те самые пара-тройка секунд задержки LLM из метрик выше — это плата за расчёт на CPU. Если в машине есть видеокарта, почти всю задержку можно срезать, переложив счёт на неё. Но выигрыш будет полным, только если модель целиком помещается в видеопамять — с этого и начинается подбор.
Прикидка простая: модель должна влезть в объём VRAM с запасом примерно 1–2 ГБ под контекст и служебные данные. У карты на 8 ГБ это модели вроде 7–8B в квантизации Q4 (около 4–5 ГБ весов), на 12–16 ГБ помещаются варианты покрупнее. В карточке модели в LM Studio размер файла виден сразу — на него и ориентируйтесь. Если модель в VRAM не влезает, часть слоёв всё равно уедет на CPU и затормозит весь ответ; тогда берут модель полегче или более сжатую квантизацию.
Когда модель подобрана, при её загрузке выкручиваем ползунок GPU Offload — он задаёт, сколько слоёв считать на видеокарте. По умолчанию он не всегда на максимуме, поэтому сдвиньте его до конца (все слои), а в настройках рантайма выберите GPU-бэкенд под свою карту: CUDA для NVIDIA, Vulkan или ROCm для AMD, Metal на Mac. При полной загрузке в VRAM скорость генерации вырастает в несколько раз, и задержка LLM падает с секунд до долей секунды.
Что бэкенд действительно подхватился, видно двумя способами: в логах LM Studio (Help → Show Logs) появляется строка вида GPU Backend: CUDA, а во время ответа модели команда nvidia-smi показывает скачок загрузки GPU.
Распознавание тоже умеет считать на видеокарте: faster-whisper под капотом WhisperSTTService поддерживает CUDA. Включается это не в Settings, а аргументами самого сервиса — device и compute_type:
stt = WhisperSTTService(
device="cuda", # счёт на видеокарте вместо CPU
compute_type="float16", # формат под GPU (на CPU оставляют "int8")
settings=WhisperSTTService.Settings(
model=Model.BASE.value,
language=Language.EN,
no_speech_prob=0.6,
),
)
Для этого нужна карта NVIDIA с установленными библиотеками CUDA и cuDNN; без них сервис не стартует на cuda, и тогда оставляют device="cpu". На практике для Whisper выигрыш заметнее на моделях покрупнее (SMALL, MEDIUM) — лёгкая BASE и на CPU отрабатывает быстро.
Синтез Kokoro трогать не стоит: модель лёгкая и на CPU отвечает почти мгновенно, GPU здесь ощутимого выигрыша не даёт. Так что главный рычаг — GPU Offload в LM Studio, а перенос Whisper на видеокарту имеет смысл, только когда взяли модель распознавания посерьёзнее.
Задача 1
Что в Pipecat называют Frame?
Задача 2
Как в Pipecat устроен транспорт звука?
Задача 3
Сопоставьте сущность Pipecat с её ролью.
Сопоставьте элементы
Задача 4
Расставьте компоненты Pipecat в порядке прохождения Frame через минимальный пайплайн — от входа к выходу.
Расположите элементы в правильном порядке
- 1.transport.output()
- 2.CartesiaTTSService
- 3.OpenAILLMService
- 4.DeepgramSTTService
- 5.transport.input()
Задача 5
Что верно про хостинг агента на Pipecat? Выберите все подходящие варианты.
Задача 6
Как в локальном пайплайне обращаются к модели, запущенной в LM Studio?
Задача 7
Почему в локальном пайплайне VADProcessor ставят перед STT?
Задача 8
Что верно про русский язык при локальном запуске пайплайна?
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
