Используйте ThunderPhone из Pipecat
Запускайте голосового агента ThunderPhone как сервис преобразования речи в речь внутри конвейера Pipecat, используя собственные транспорт и телефонию.
Pipecat — это фреймворк с открытым исходным кодом для создания голосовых агентов из компонуемых сервисов. ThunderPhone подключается как речевой LLM-сервис: Pipecat отправляет аудио звонящего, ThunderPhone возвращает голос агента, расшифровки и вызовы функций, а транспорт Pipecat (Daily, LiveKit, Twilio, WebRTC, локальный микрофон) передаёт аудио. Распознавание речи, языковая модель, голос, управление очередностью реплик, 47 языков и инструменты — всё работает на ThunderPhone.
Звонки, совершённые таким способом, отображаются в истории звонков и тарифицируются по поминутному тарифу вашего продукта, как любой другой звонок в реальном времени. Подписка и номер телефона ThunderPhone не требуются.
Установка
pip install pipecat-thunderphone
export THUNDERPHONE_API_KEY=sk_live_... # a secret API keyПакет оборачивает сервис OpenAI Realtime из Pipecat, поскольку
Realtime WebSocket ThunderPhone использует тот же протокол. Требуется
pipecat-ai версии 1.8 или новее.
Запуск сохранённого агента
Всё, что делает агент (промпт, голос, движок, языки, инструменты, приветствие, проверки тишины), настраивается в ThunderPhone. Конвейер только передаёт аудио.
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.worker import PipelineParams, PipelineWorker
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair
from pipecat_thunderphone import ThunderPhoneRealtimeLLMService
llm = ThunderPhoneRealtimeLLMService(agent_id=12)
context = LLMContext()
aggregators = LLMContextAggregatorPair(context)
pipeline = Pipeline([
transport.input(),
aggregators.user(),
llm,
aggregators.assistant(),
transport.output(),
])
worker = PipelineWorker(pipeline, params=PipelineParams(allow_interruptions=True))Сохранённый агент начинает звонок по собственному сценарию, поэтому сервис не
запрашивает у Pipecat начальный ответ. Передайте greet_on_connect=True, если
хотите получить его в любом случае.
Настройка сеанса в коде
Без agent_id инструкции и инструменты берутся из контекста Pipecat,
так же, как для OpenAI. product выбирает движок, а voice — голос
ThunderPhone.
from pipecat.adapters.schemas.function_schema import FunctionSchema
from pipecat.adapters.schemas.tools_schema import ToolsSchema
from pipecat.services.llm_service import FunctionCallParams
llm = ThunderPhoneRealtimeLLMService(product="bolt", voice="olivia", language="es")
async def check_availability(params: FunctionCallParams):
slots = await calendar.free_slots(params.arguments["date"])
await params.result_callback({"slots": slots})
llm.register_function("check_availability", check_availability)
context = LLMContext(
messages=[{"role": "system", "content": "You are Acme Dental's receptionist."}],
tools=ToolsSchema(standard_tools=[
FunctionSchema(
name="check_availability",
description="Free appointment slots on a date",
properties={"date": {"type": "string"}},
required=["date"],
)
]),
)Встроенные сеансы управляются клиентом: агент говорит первым, поскольку Pipecat запрашивает ответ при поступлении контекста, и молчит во время пауз, пока вы не добавите сообщение или не запросите другой ответ.
Параметры
| Аргумент | Значение |
|---|---|
api_key | Секретный ключ (sk_live_...). По умолчанию используется THUNDERPHONE_API_KEY. |
agent_id | Запуск сохранённого агента. Взаимоисключающий с product и voice. |
product | Движок для встроенных сессий: spark, bolt или storm. |
voice | Имя голоса ThunderPhone для встроенных сессий. |
language | Подсказка основного языка для встроенных сессий, например es. |
from_number, to_number | Номера для записи в вызове, когда пайплайн подключён к телефонной линии. |
live_transcripts | Передавать фрагменты расшифровки звонящего в середине реплики (оплачивается дополнительно). |
greet_on_connect | Запросить первый ответ сразу после готовности сессии. |
end_task_on_call_ended | Отправить EndWorkerFrame, когда ThunderPhone завершает вызов (по умолчанию включено). |
События
ThunderPhone добавляет события платформы поверх протокола реального времени. Сервис передаёт их обработчикам:
@llm.event_handler("on_call_ended")
async def on_call_ended(service, event):
print("call ended:", event["reason"], "call id:", service.call_id)service.call_id устанавливается, когда сессия становится активной. Используйте его с
GET /v1/calls/{call_id}, чтобы получить запись,
расшифровку и оценку после вызова.
Ограничения
- Определение очередности реплик выполняется на стороне сервера и всегда включено; реплики,
управляемые Pipecat (
turn_detection=False), не поддерживаются. - Функции, зарегистрированные в сервисе, работают только для встроенных сессий. Сохранённый агент выполняет собственные инструменты в ThunderPhone.
- Аудио передаётся в формате 16-битного моно PCM с частотой 24 кГц в обоих направлениях.
- Видеокадры игнорируются.