### Run Voice Agent Service Locally Source: https://context7.com/bentoml/bentovoiceagent/llms.txt Commands to install dependencies and start the BentoML server with required environment variables for XTTS and LLM endpoints. ```bash apt-get install ffmpeg pip install -U -r requirements.txt XTTS_SERVICE_URL=https://xtts-streaming.example.bentoml.ai \ OPENAI_SERVICE_URL=https://llama-3-1.example.bentoml.ai/v1 \ bentoml serve ``` -------------------------------- ### Deploying to BentoCloud Source: https://context7.com/bentoml/bentovoiceagent/llms.txt Guide for deploying the voice agent to BentoCloud for production use. ```APIDOC ## Deploying to BentoCloud ### Description Deploy the voice agent to BentoCloud for production use with automatic scaling and management. ### Steps 1. **Login to BentoCloud:** ```bash bentoml cloud login ``` 2. **Deploy with environment variables:** ```bash bentoml deploy . --env XTTS_SERVICE_URL=https://xtts-streaming.example.bentoml.ai --env OPENAI_SERVICE_URL=https://llama-3-1.example.bentoml.ai/v1 ``` 3. **Configure Twilio:** - Go to Twilio Console > Phone Numbers > Your Number. - Set Voice Configuration webhook URL to: `https://your-deployment.bentoml.ai/voice/start_call` - Set HTTP method to POST. ``` -------------------------------- ### Twilio Webhook to Start Call Endpoint Source: https://context7.com/bentoml/bentovoiceagent/llms.txt An HTTP POST endpoint that acts as the Twilio webhook to initiate calls. It generates TwiML XML to instruct Twilio to establish a WebSocket stream connection for bidirectional audio. Requires os and HTMLResponse. ```python @app.post("/start_call") async def start_call(self): service_url = os.environ.get("BENTOCLOUD_DEPLOYMENT_URL") or "" assert(service_url) if service_url.startswith("http"): from urllib.parse import urlparse service_url = urlparse(service_url).netloc tmpl = """ """ return HTMLResponse(content=tmpl.format(service_url=service_url), media_type="application/xml") # Configure this endpoint as Twilio webhook: # URL: https://your-deployment.bentoml.ai/voice/start_call # Method: POST ``` -------------------------------- ### Running the Service Locally Source: https://context7.com/bentoml/bentovoiceagent/llms.txt Instructions for setting up and running the voice agent service on a local machine. ```APIDOC ## Running the Service Locally ### Description Start the voice agent service with environment variables pointing to deployed LLM and XTTS endpoints. ### Steps 1. **Install system dependencies:** ```bash apt-get install ffmpeg ``` 2. **Install Python dependencies:** ```bash pip install -U -r requirements.txt ``` 3. **Start the server with model endpoints:** ```bash XTTS_SERVICE_URL=https://xtts-streaming.example.bentoml.ai \ OPENAI_SERVICE_URL=https://llama-3-1.example.bentoml.ai/v1 \ bentoml serve ``` ### Server Exposes - **POST /voice/start_call** - Twilio webhook for call initiation. - **WS /voice/ws** - WebSocket for real-time audio streaming. ``` -------------------------------- ### Configure Voice Bot Pipeline with Pipecat Source: https://context7.com/bentoml/bentovoiceagent/llms.txt This snippet demonstrates how to initialize a voice pipeline using Pipecat. It configures a WebSocket transport for Twilio, integrates OpenAI-compatible LLM services, and sets up the audio processing flow. ```python from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineParams, PipelineTask from pipecat.services.openai import OpenAILLMService, OpenAILLMContext from pipecat.transports.network.fastapi_websocket import FastAPIWebsocketTransport, FastAPIWebsocketParams from pipecat.vad.silero import SileroVADAnalyzer from pipecat.serializers.twilio import TwilioFrameSerializer async def run_bot(websocket_client, stream_sid, whisper_model): transport = FastAPIWebsocketTransport( websocket=websocket_client, params=FastAPIWebsocketParams( audio_out_enabled=True, add_wav_header=False, vad_enabled=True, vad_analyzer=SileroVADAnalyzer(), vad_audio_passthrough=True, serializer=TwilioFrameSerializer(stream_sid), ), ) llm = OpenAILLMService( base_url=os.getenv("OPENAI_SERVICE_URL"), api_key="n/a", model="meta-llama/Meta-Llama-3.1-8B-Instruct", ) stt = BentoWhisperSTTService(model=whisper_model) tts = SimpleXTTSService( base_url=os.getenv("XTTS_SERVICE_URL"), language="en", aiohttp_session=aiohttp.ClientSession(), ) messages = [ { "role": "system", "content": "You are a helpful LLM assistant in an audio call. Your name is Jane. " "Your goal is to demonstrate your capabilities in a succinct way. " "Your output will be converted to audio so don't include special characters.", }, ] context = OpenAILLMContext(messages) context_aggregator = llm.create_context_aggregator(context) pipeline = Pipeline([ transport.input(), stt, context_aggregator.user(), llm, tts, transport.output(), context_aggregator.assistant(), ]) task = PipelineTask(pipeline, params=PipelineParams(allow_interruptions=True)) runner = PipelineRunner(handle_sigint=False) await runner.run(task) ``` -------------------------------- ### Define and Register OpenAI-Compatible Tool for LLM Function Calling (Python) Source: https://context7.com/bentoml/bentovoiceagent/llms.txt This snippet demonstrates how to define a tool using `ChatCompletionToolParam` for OpenAI-compatible function calling. It includes the tool's schema, parameters, and how to register an execution function with the LLM. This enables the voice agent to call custom functions based on LLM instructions. ```python from openai.types.chat import ChatCompletionToolParam tools = [ ChatCompletionToolParam( type="function", function={ "name": "get_deployment_count", "description": "Get the deployment count in a region of a specific status.", "parameters": { "type": "object", "properties": { "region": { "type": "string", "enum": ["north america", "europe", "asia"], "description": "The region where the deployments are located.", }, "status": { "type": "string", "enum": ["running", "scaled to zero", "terminated"], "description": "The status of the deployment.", }, }, "required": ["region", "status"], }, }, ), ] async def exec_function(function_name, tool_call_id, args, llm, context, result_callback): logger.debug(f"Executing function: {function_name}") await result_callback({"deployment_count": 10}) llm.register_function("get_deployment_count", exec_function, start_callback=start_function) context = OpenAILLMContext(messages, tools) ``` -------------------------------- ### POST /start_call Source: https://context7.com/bentoml/bentovoiceagent/llms.txt HTTP POST endpoint that serves as the Twilio webhook to initiate calls. Returns TwiML XML that instructs Twilio to establish a WebSocket stream connection for bidirectional audio. ```APIDOC ## POST /start_call ### Description HTTP POST endpoint that serves as the Twilio webhook to initiate calls. Returns TwiML XML that instructs Twilio to establish a WebSocket stream connection for bidirectional audio. ### Method POST ### Endpoint /start_call ### Parameters N/A ### Request Example N/A ### Response #### Success Response (200) - **TwiML XML** - XML document instructing Twilio to connect to the WebSocket stream. #### Response Example ```xml ``` **Note**: Configure this endpoint as a Twilio webhook with URL: `https://your-deployment.bentoml.ai/voice/start_call` and Method: `POST`. ``` -------------------------------- ### Deploy Voice Agent to BentoCloud Source: https://context7.com/bentoml/bentovoiceagent/llms.txt Deployment workflow for pushing the voice agent to BentoCloud, including authentication and environment variable configuration. ```bash bentoml cloud login bentoml deploy . \ --env XTTS_SERVICE_URL=https://xtts-streaming.example.bentoml.ai \ --env OPENAI_SERVICE_URL=https://llama-3-1.example.bentoml.ai/v1 ``` -------------------------------- ### Initialize TwilioBot BentoML Service with Whisper Model Source: https://context7.com/bentoml/bentovoiceagent/llms.txt Initializes the main service class for handling Twilio calls. It sets up the Whisper model for speech-to-text and mounts FastAPI endpoints for call handling and WebSocket communication. Requires PyTorch and faster_whisper. ```python import bentoml from fastapi import FastAPI, WebSocket from faster_whisper import WhisperModel app = FastAPI() @bentoml.service( traffic={"timeout": 30}, resources={ "gpu": 1, "gpu_type": "nvidia-tesla-t4", }, ) @bentoml.mount_asgi_app(app, path="/voice") class TwilioBot: def __init__(self): import torch self.batch_size = 16 self.device = "cuda" if torch.cuda.is_available() else "cpu" compute_type = "float16" if torch.cuda.is_available() else "int8" self.whisper_model = WhisperModel("large-v3", self.device, compute_type=compute_type) ``` -------------------------------- ### Implement SimpleXTTSService for Audio Streaming Source: https://context7.com/bentoml/bentovoiceagent/llms.txt A custom Pipecat service that streams audio from an XTTS endpoint. It handles audio resampling from 24kHz to 16kHz to ensure compatibility with Twilio's audio requirements. ```python from pipecat.frames.frames import TTSAudioRawFrame, TTSStartedFrame, TTSStoppedFrame, ErrorFrame from pipecat.services.ai_services import TTSService import aiohttp import numpy as np import resampy class SimpleXTTSService(TTSService): def __init__(self, *, language: str, base_url: str, aiohttp_session: aiohttp.ClientSession, **kwargs): super().__init__(**kwargs) self._language = language self._base_url = base_url self._aiohttp_session = aiohttp_session async def run_tts(self, text: str): url = self._base_url + "/tts/stream" payload = { "text": text.replace('.', '').replace('*', ''), "language": self._language, "add_wav_header": False, "stream_chunk_size": 20, } await self.start_ttfb_metrics() async with self._aiohttp_session.post(url, json=payload) as r: if r.status != 200: error_text = await r.text() yield ErrorFrame(f"Error getting audio (status: {r.status}, error: {error_text})") return yield TTSStartedFrame() buffer = bytearray() async for chunk in r.content.iter_chunked(1024): if len(chunk) > 0: await self.stop_ttfb_metrics() buffer.extend(chunk) while len(buffer) >= 48000: process_data = buffer[:48000] buffer = buffer[48000:] audio_np = np.frombuffer(process_data, dtype=np.int16) resampled_audio = resampy.resample(audio_np, 24000, 16000) resampled_audio_bytes = resampled_audio.astype(np.int16).tobytes() yield TTSAudioRawFrame(resampled_audio_bytes, 16000, 1) if len(buffer) > 0: audio_np = np.frombuffer(buffer, dtype=np.int16) resampled_audio = resampy.resample(audio_np, 24000, 16000) yield TTSAudioRawFrame(resampled_audio.astype(np.int16).tobytes(), 16000, 1) yield TTSStoppedFrame() ``` -------------------------------- ### SimpleXTTSService Definition Source: https://context7.com/bentoml/bentovoiceagent/llms.txt Defines the SimpleXTTSService class, which handles text-to-speech using a remote XTTS endpoint and resamples audio for compatibility. ```APIDOC ## Class SimpleXTTSService ### Description Custom text-to-speech service that streams audio from a remote XTTS endpoint. Handles audio resampling from 24kHz to 16kHz for Twilio compatibility. ### Methods #### `__init__` Initializes the SimpleXTTSService with language, base URL, and an aiohttp session. #### `run_tts` Generates speech audio from text using XTTS streaming API. ### Parameters #### `__init__` Parameters - **language** (str) - Required - The language for text-to-speech. - **base_url** (str) - Required - The base URL of the XTTS endpoint. - **aiohttp_session** (aiohttp.ClientSession) - Required - An active aiohttp client session. ### Request Example (run_tts) ```json { "text": "Hello, this is a test.", "language": "en", "add_wav_header": false, "stream_chunk_size": 20 } ``` ### Response Example (run_tts) - **TTSStartedFrame** - Indicates the start of TTS streaming. - **TTSAudioRawFrame** - Contains raw audio data chunks. - **TTSStoppedFrame** - Indicates the end of TTS streaming. - **ErrorFrame** - Indicates an error during the TTS process. ``` -------------------------------- ### Implement Custom BentoWhisperSTTService Source: https://context7.com/bentoml/bentovoiceagent/llms.txt This class extends SegmentedSTTService to provide speech-to-text capabilities using the faster-whisper model. It handles audio buffer conversion from PCM to float32 and filters segments based on speech probability. ```python from pipecat.frames.frames import TranscriptionFrame, ErrorFrame from pipecat.services.ai_services import SegmentedSTTService from faster_whisper import WhisperModel import numpy as np import asyncio class BentoWhisperSTTService(SegmentedSTTService): def __init__(self, *, model: WhisperModel, no_speech_prob: float = 0.4, **kwargs): super().__init__(**kwargs) self._no_speech_prob = no_speech_prob self._model = model async def run_stt(self, audio: bytes): if not self._model: yield ErrorFrame("Whisper model not available") return await self.start_processing_metrics() await self.start_ttfb_metrics() audio_float = np.frombuffer(audio, dtype=np.int16).astype(np.float32) / 32768.0 segments, _ = await asyncio.to_thread(self._model.transcribe, audio_float) text = "" for segment in segments: if segment.no_speech_prob < self._no_speech_prob: text += f"{segment.text} " await self.stop_ttfb_metrics() await self.stop_processing_metrics() if text: yield TranscriptionFrame(text, "", time_now_iso8601()) ``` -------------------------------- ### WebSocket /ws Source: https://context7.com/bentoml/bentovoiceagent/llms.txt WebSocket endpoint that handles real-time bidirectional audio streaming with Twilio. Accepts the connection, extracts the stream session ID, and launches the voice bot pipeline. ```APIDOC ## WebSocket /ws ### Description WebSocket endpoint that handles real-time bidirectional audio streaming with Twilio. Accepts the connection, extracts the stream session ID, and launches the voice bot pipeline. ### Method WebSocket ### Endpoint /ws ### Parameters N/A ### Request Example N/A ### Response N/A (Handles streaming data) ```python @app.websocket("/ws") async def websocket_endpoint(self, websocket: WebSocket): from bot import run_bot await websocket.accept() start_data = websocket.iter_text() await start_data.__anext__() call_data = json.loads(await start_data.__anext__()) stream_sid = call_data["start"]["streamSid"] print("WebSocket connection accepted") await run_bot(websocket, stream_sid, whisper_model=self.whisper_model) ``` ``` -------------------------------- ### WebSocket Voice Endpoint for Audio Streaming Source: https://context7.com/bentoml/bentovoiceagent/llms.txt A WebSocket endpoint that manages real-time bidirectional audio streaming with Twilio. It accepts connections, extracts stream session IDs, and initiates the voice bot pipeline. Requires json and the run_bot function. ```python @app.websocket("/ws") async def websocket_endpoint(self, websocket: WebSocket): from bot import run_bot await websocket.accept() start_data = websocket.iter_text() await start_data.__anext__() call_data = json.loads(await start_data.__anext__()) stream_sid = call_data["start"]["streamSid"] print("WebSocket connection accepted") await run_bot(websocket, stream_sid, whisper_model=self.whisper_model) ``` -------------------------------- ### TwilioBot BentoML Service Source: https://context7.com/bentoml/bentovoiceagent/llms.txt The main service class that handles incoming Twilio calls and manages the voice pipeline. It initializes the Whisper model for speech-to-text and mounts FastAPI endpoints for call handling and WebSocket communication. ```APIDOC ## TwilioBot BentoML Service ### Description The main service class that handles incoming Twilio calls and manages the voice pipeline. It initializes the Whisper model for speech-to-text and mounts FastAPI endpoints for call handling and WebSocket communication. ### Method N/A (Service Definition) ### Endpoint N/A (Service Definition) ### Parameters N/A ### Request Example N/A ### Response N/A ```python import bentoml from fastapi import FastAPI, WebSocket from faster_whisper import WhisperModel app = FastAPI() @bentoml.service( traffic={"timeout": 30}, resources={ "gpu": 1, "gpu_type": "nvidia-tesla-t4", }, ) @bentoml.mount_asgi_app(app, path="/voice") class TwilioBot: def __init__(self): import torch self.batch_size = 16 self.device = "cuda" if torch.cuda.is_available() else "cpu" compute_type = "float16" if torch.cuda.is_available() else "int8" self.whisper_model = WhisperModel("large-v3", self.device, compute_type=compute_type) ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.