From d3cd1a6c597104685dad56d2d807fea07e799201 Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Fri, 14 Mar 2025 20:37:55 -0400 Subject: [PATCH] Update with latest starter --- .../pipecat-cloud-example/README.md | 55 ++++--- .../deployment/pipecat-cloud-example/bot.py | 144 +++++++++--------- .../pipecat-cloud-example/requirements.txt | 3 +- 3 files changed, 101 insertions(+), 101 deletions(-) diff --git a/examples/deployment/pipecat-cloud-example/README.md b/examples/deployment/pipecat-cloud-example/README.md index 1950a0f94..7d5e4bd6f 100644 --- a/examples/deployment/pipecat-cloud-example/README.md +++ b/examples/deployment/pipecat-cloud-example/README.md @@ -4,6 +4,8 @@ A template voice agent for [Pipecat Cloud](https://www.daily.co/products/pipecat-cloud/) that demonstrates building and deploying a conversational AI agent. +> **For a detailed step-by-step guide, see our [Quickstart Documentation](https://docs.pipecat.daily.co/quickstart).** + ## Prerequisites - Python 3.10+ @@ -14,25 +16,9 @@ A template voice agent for [Pipecat Cloud](https://www.daily.co/products/pipecat > **Note**: If you haven't installed Docker yet, follow the official installation guides for your platform ([Linux](https://docs.docker.com/engine/install/), [Mac](https://docs.docker.com/desktop/setup/install/mac-install/), [Windows](https://docs.docker.com/desktop/setup/install/windows-install/)). For Docker Hub, [create a free account](https://hub.docker.com/signup) and log in via terminal with `docker login`. -## Getting Started +## Get Started -### 1. Set up Python environment - -We recommend using a virtual environment to manage your Python dependencies. - -```bash -# Create a virtual environment -python -m venv venv - -# Activate it -source venv/bin/activate # On Windows: venv\Scripts\activate - -# Install dependencies -pip install -r requirements.txt -pip install pipecatcloud -``` - -### 2. Get the starter project +### 1. Get the starter project Clone the starter project from GitHub: @@ -41,11 +27,19 @@ git clone https://github.com/daily-co/pipecat-cloud-starter cd pipecat-cloud-starter ``` -or use the Pipecat Cloud CLI to initialize a new project: +### 2. Set up your Python environment + +We recommend using a virtual environment to manage your Python dependencies. ```bash -mkdir pipecat-cloud-starter && cd pipecat-cloud-starter -pcc init +# Create a virtual environment +python -m venv .venv + +# Activate it +source .venv/bin/activate # On Windows: .venv\Scripts\activate + +# Install the Pipecat Cloud CLI +pip install pipecatcloud ``` ### 3. Authenticate with Pipecat Cloud @@ -66,13 +60,24 @@ This starter requires the following API keys: You can test your agent locally before deploying to Pipecat Cloud: -- `DAILY_API_KEY` value can be found at [https://pipecat.daily.co](https://pipecat.daily.co) Under the `Settings` menu of your agent, in the `Daily` tab. - ```bash # Set environment variables with your API keys export CARTESIA_API_KEY="your_cartesia_key" export DAILY_API_KEY="your_daily_key" export OPENAI_API_KEY="your_openai_key" +``` + +> Your `DAILY_API_KEY` can be found at [https://pipecat.daily.co](https://pipecat.daily.co) under the `Settings` in the `Daily (WebRTC)` tab. + +First install requirements: + +```bash +pip install -r requirements.txt +``` + +Then, launch the bot.py script locally: + +```bash LOCAL_RUN=1 python bot.py ``` @@ -118,7 +123,7 @@ pcc secrets set my-first-agent-secrets \ ### 3. Deploy to Pipecat Cloud ```bash -pcc deploy my-first-agent your-username/my-first-agent:0.1 +pcc deploy my-first-agent your-username/my-first-agent:0.1 --secrets my-first-agent-secrets ``` > **Note (Optional)**: For a more maintainable approach, you can use the included `pcc-deploy.toml` file: @@ -137,7 +142,7 @@ pcc deploy my-first-agent your-username/my-first-agent:0.1 > **Note**: If your repository is private, you'll need to add credentials: > > ```bash -> # Create pull secret (you'll be prompted for credentials) +> # Create pull secret (you’ll be prompted for credentials) > pcc secrets image-pull-secret pull-secret https://index.docker.io/v1/ > > # Deploy with credentials diff --git a/examples/deployment/pipecat-cloud-example/bot.py b/examples/deployment/pipecat-cloud-example/bot.py index fdb3eb712..89d4973b7 100644 --- a/examples/deployment/pipecat-cloud-example/bot.py +++ b/examples/deployment/pipecat-cloud-example/bot.py @@ -9,6 +9,7 @@ import os import aiohttp from dotenv import load_dotenv from loguru import logger +from pipecatcloud.agent import DailySessionArguments from pipecat.audio.vad.silero import SileroVADAnalyzer from pipecat.frames.frames import LLMMessagesFrame @@ -35,110 +36,103 @@ if LOCAL_RUN: load_dotenv(override=True) -async def main(room_url: str, token: str, session_logger=None): +async def main(room_url: str, token: str): """Main pipeline setup and execution function. Args: room_url: The Daily room URL token: The Daily room token - session_logger: Optional logger instance """ - log = session_logger or logger + logger.debug("Starting bot in room: {}", room_url) - log.debug("Starting bot in room: {}", room_url) + transport = DailyTransport( + room_url, + token, + "bot", + DailyParams( + audio_out_enabled=True, + transcription_enabled=True, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer(), + ), + ) - async with aiohttp.ClientSession() as session: - transport = DailyTransport( - room_url, - token, - "bot", - DailyParams( - audio_out_enabled=True, - transcription_enabled=True, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer(), - ), - ) + tts = CartesiaTTSService( + api_key=os.getenv("CARTESIA_API_KEY"), voice_id="79a125e8-cd45-4c13-8a67-188112f4dd22" + ) - tts = CartesiaTTSService( - api_key=os.getenv("CARTESIA_API_KEY"), voice_id="79a125e8-cd45-4c13-8a67-188112f4dd22" - ) + llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o") - llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o") + messages = [ + { + "role": "system", + "content": "You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities in a succinct way. Your output will be converted to audio so don't include special characters in your answers. Respond to what the user said in a creative and helpful way.", + }, + ] - messages = [ + context = OpenAILLMContext(messages) + context_aggregator = llm.create_context_aggregator(context) + + pipeline = Pipeline( + [ + transport.input(), + context_aggregator.user(), + llm, + tts, + transport.output(), + context_aggregator.assistant(), + ] + ) + + task = PipelineTask( + pipeline, + params=PipelineParams( + allow_interruptions=True, + enable_metrics=True, + enable_usage_metrics=True, + report_only_initial_ttfb=True, + ), + ) + + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + logger.info("First participant joined: {}", participant["id"]) + await transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + messages.append( { "role": "system", - "content": "You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities in a succinct way. Your output will be converted to audio so don't include special characters in your answers. Respond to what the user said in a creative and helpful way.", - }, - ] - - context = OpenAILLMContext(messages) - context_aggregator = llm.create_context_aggregator(context) - - pipeline = Pipeline( - [ - transport.input(), - context_aggregator.user(), - llm, - tts, - transport.output(), - context_aggregator.assistant(), - ] + "content": "Please start with 'Hello World' and introduce yourself to the user.", + } ) + await task.queue_frames([LLMMessagesFrame(messages)]) - task = PipelineTask( - pipeline, - params=PipelineParams( - allow_interruptions=True, - enable_metrics=True, - enable_usage_metrics=True, - report_only_initial_ttfb=True, - ), - ) + @transport.event_handler("on_participant_left") + async def on_participant_left(transport, participant, reason): + logger.info("Participant left: {}", participant) + await task.cancel() - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - log.info("First participant joined: {}", participant["id"]) - await transport.capture_participant_transcription(participant["id"]) - # Kick off the conversation. - messages.append( - { - "role": "system", - "content": "Please start with 'Hello World' and introduce yourself to the user.", - } - ) - await task.queue_frames([LLMMessagesFrame(messages)]) + runner = PipelineRunner() - @transport.event_handler("on_participant_left") - async def on_participant_left(transport, participant, reason): - log.info("Participant left: {}", participant) - await task.cancel() - - runner = PipelineRunner() - - await runner.run(task) + await runner.run(task) -async def bot(config, room_url: str, token: str, session_id=None, session_logger=None): +async def bot(args: DailySessionArguments): """Main bot entry point compatible with the FastAPI route handler. Args: - config: The configuration object from the request body room_url: The Daily room URL token: The Daily room token + body: The configuration object from the request body session_id: The session ID for logging - session_logger: The session-specific logger """ - log = session_logger or logger - log.info(f"Bot process initialized {room_url} {token}") - log.info(f"Bot config {config}") + logger.info(f"Bot process initialized {args.room_url} {args.token}") try: - await main(room_url, token, session_logger) - log.info("Bot process completed") + await main(args.room_url, args.token) + logger.info("Bot process completed") except Exception as e: - log.exception(f"Error in bot process: {str(e)}") + logger.exception(f"Error in bot process: {str(e)}") raise diff --git a/examples/deployment/pipecat-cloud-example/requirements.txt b/examples/deployment/pipecat-cloud-example/requirements.txt index f5abaf91f..2e9fd4e9d 100644 --- a/examples/deployment/pipecat-cloud-example/requirements.txt +++ b/examples/deployment/pipecat-cloud-example/requirements.txt @@ -1,2 +1,3 @@ +pipecatcloud pipecat-ai[cartesia,daily,openai,silero]>=0.0.58 -python-dotenv~=1.0.1 \ No newline at end of file +python-dotenv~=1.0.1