Merge pull request #1343 from pipecat-ai/mb/pipecat-cloud-example
Add a Pipecat Cloud deployment example
This commit is contained in:
@@ -114,6 +114,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Fixed an issue in `RimeTTSService` where the last line of text sent didn't
|
- Fixed an issue in `RimeTTSService` where the last line of text sent didn't
|
||||||
result in an audio output being generated.
|
result in an audio output being generated.
|
||||||
|
|
||||||
|
### Other
|
||||||
|
|
||||||
|
- Added a Pipecat Cloud deployment example to the `examples` directory.
|
||||||
|
|
||||||
## [0.0.58] - 2025-02-26
|
## [0.0.58] - 2025-02-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
94
examples/deployment/pipecat-cloud-example/.gitignore
vendored
Normal file
94
examples/deployment/pipecat-cloud-example/.gitignore
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.egg-info/
|
||||||
|
*.egg
|
||||||
|
.installed.cfg
|
||||||
|
.eggs/
|
||||||
|
downloads/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# Virtual Environments
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
.env
|
||||||
|
.venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# Testing and Coverage
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
htmlcov/
|
||||||
|
.pytest_cache/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Logs and Databases
|
||||||
|
*.log
|
||||||
|
*.db
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
pip-log.txt
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
desktop.ini
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Build and Documentation
|
||||||
|
docs/_build/
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
.pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Other
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
*.sage.py
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
.pyre/
|
||||||
|
.pytype/
|
||||||
|
cython_debug/
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# Pipecat cloud
|
||||||
|
.pcc-deploy.toml
|
||||||
7
examples/deployment/pipecat-cloud-example/Dockerfile
Normal file
7
examples/deployment/pipecat-cloud-example/Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FROM dailyco/pipecat-base:latest
|
||||||
|
|
||||||
|
COPY ./requirements.txt requirements.txt
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
||||||
|
|
||||||
|
COPY ./bot.py bot.py
|
||||||
196
examples/deployment/pipecat-cloud-example/README.md
Normal file
196
examples/deployment/pipecat-cloud-example/README.md
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
# Pipecat Cloud Starter Project
|
||||||
|
|
||||||
|
[](https://docs.pipecat.daily.co) [](https://discord.gg/dailyco)
|
||||||
|
|
||||||
|
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+
|
||||||
|
- Linux, MacOS, or Windows Subsystem for Linux (WSL)
|
||||||
|
- [Docker](https://www.docker.com) and a Docker repository (e.g., [Docker Hub](https://hub.docker.com))
|
||||||
|
- A Docker Hub account (or other container registry account)
|
||||||
|
- [Pipecat Cloud](https://pipecat.daily.co) account
|
||||||
|
|
||||||
|
> **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`.
|
||||||
|
|
||||||
|
## Get Started
|
||||||
|
|
||||||
|
### 1. Get the starter project
|
||||||
|
|
||||||
|
Clone the starter project from GitHub:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/daily-co/pipecat-cloud-starter
|
||||||
|
cd pipecat-cloud-starter
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Set up your 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 the Pipecat Cloud CLI
|
||||||
|
pip install pipecatcloud
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Authenticate with Pipecat Cloud
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pcc auth login
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Acquire required API keys
|
||||||
|
|
||||||
|
This starter requires the following API keys:
|
||||||
|
|
||||||
|
- **OpenAI API Key**: Get from [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
|
||||||
|
- **Cartesia API Key**: Get from [play.cartesia.ai/keys](https://play.cartesia.ai/keys)
|
||||||
|
- **Daily API Key**: Automatically provided through your Pipecat Cloud account
|
||||||
|
|
||||||
|
### 5. Configure to run locally (optional)
|
||||||
|
|
||||||
|
You can test your agent locally before deploying to Pipecat Cloud:
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy & Run
|
||||||
|
|
||||||
|
### 1. Build and push your Docker image
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build the image (targeting ARM architecture for cloud deployment)
|
||||||
|
docker build --platform=linux/arm64 -t my-first-agent:latest .
|
||||||
|
|
||||||
|
# Tag with your Docker username and version
|
||||||
|
docker tag my-first-agent:latest your-username/my-first-agent:0.1
|
||||||
|
|
||||||
|
# Push to Docker Hub
|
||||||
|
docker push your-username/my-first-agent:0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Create a secret set for your API keys
|
||||||
|
|
||||||
|
The starter project requires API keys for OpenAI and Cartesia:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy the example env file
|
||||||
|
cp env.example .env
|
||||||
|
|
||||||
|
# Edit .env to add your API keys:
|
||||||
|
# CARTESIA_API_KEY=your_cartesia_key
|
||||||
|
# OPENAI_API_KEY=your_openai_key
|
||||||
|
|
||||||
|
# Create a secret set from your .env file
|
||||||
|
pcc secrets set my-first-agent-secrets --file .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can create secrets directly via CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pcc secrets set my-first-agent-secrets \
|
||||||
|
CARTESIA_API_KEY=your_cartesia_key \
|
||||||
|
OPENAI_API_KEY=your_openai_key
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Deploy to Pipecat Cloud
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
>
|
||||||
|
> ```toml
|
||||||
|
> agent_name = "my-first-agent"
|
||||||
|
> image = "your-username/my-first-agent:0.1"
|
||||||
|
> secret_set = "my-first-agent-secrets"
|
||||||
|
>
|
||||||
|
> [scaling]
|
||||||
|
> min_instances = 0
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> Then simply run `pcc deploy` without additional arguments.
|
||||||
|
|
||||||
|
> **Note**: If your repository is private, you'll need to add credentials:
|
||||||
|
>
|
||||||
|
> ```bash
|
||||||
|
> # Create pull secret (you’ll be prompted for credentials)
|
||||||
|
> pcc secrets image-pull-secret pull-secret https://index.docker.io/v1/
|
||||||
|
>
|
||||||
|
> # Deploy with credentials
|
||||||
|
> pcc deploy my-first-agent your-username/my-first-agent:0.1 --credentials pull-secret
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### 4. Check deployment and scaling (optional)
|
||||||
|
|
||||||
|
By default, your agent will use "scale-to-zero" configuration, which means it may have a cold start of around 10 seconds when first used. By default, idle instances are maintained for 5 minutes before being terminated when using scale-to-zero.
|
||||||
|
|
||||||
|
For more responsive testing, you can scale your deployment to keep a minimum of one instance warm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ensure at least one warm instance is always available
|
||||||
|
pcc deploy my-first-agent your-username/my-first-agent:0.1 --min-instances 1
|
||||||
|
|
||||||
|
# Check the status of your deployment
|
||||||
|
pcc agent status my-first-agent
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, idle instances are maintained for 5 minutes before being terminated when using scale-to-zero.
|
||||||
|
|
||||||
|
### 5. Create an API key
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a public API key for accessing your agent
|
||||||
|
pcc organizations keys create
|
||||||
|
|
||||||
|
# Set it as the default key to use with your agent
|
||||||
|
pcc organizations keys use
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Start your agent
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start a session with your agent in a Daily room
|
||||||
|
pcc agent start my-first-agent --use-daily
|
||||||
|
```
|
||||||
|
|
||||||
|
This will return a URL, which you can use to connect to your running agent.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
For more details on Pipecat Cloud and its capabilities:
|
||||||
|
|
||||||
|
- [Pipecat Cloud Documentation](https://docs.pipecat.daily.co)
|
||||||
|
- [Pipecat Project Documentation](https://docs.pipecat.ai)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Join our [Discord community](https://discord.gg/dailyco) for help and discussions.
|
||||||
161
examples/deployment/pipecat-cloud-example/bot.py
Normal file
161
examples/deployment/pipecat-cloud-example/bot.py
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2025, Daily
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD 2-Clause License
|
||||||
|
#
|
||||||
|
|
||||||
|
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
|
||||||
|
from pipecat.pipeline.pipeline import Pipeline
|
||||||
|
from pipecat.pipeline.runner import PipelineRunner
|
||||||
|
from pipecat.pipeline.task import PipelineParams, PipelineTask
|
||||||
|
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
|
||||||
|
from pipecat.services.cartesia import CartesiaTTSService
|
||||||
|
from pipecat.services.openai import OpenAILLMService
|
||||||
|
from pipecat.transports.services.daily import DailyParams, DailyTransport
|
||||||
|
|
||||||
|
# Check if we're in local development mode
|
||||||
|
LOCAL_RUN = os.getenv("LOCAL_RUN")
|
||||||
|
if LOCAL_RUN:
|
||||||
|
import asyncio
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
try:
|
||||||
|
from local_runner import configure
|
||||||
|
except ImportError:
|
||||||
|
logger.error("Could not import local_runner module. Local development mode may not work.")
|
||||||
|
|
||||||
|
# Load environment variables
|
||||||
|
load_dotenv(override=True)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
logger.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(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
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.",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
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": "Please start with 'Hello World' and introduce yourself to the user.",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await task.queue_frames([LLMMessagesFrame(messages)])
|
||||||
|
|
||||||
|
@transport.event_handler("on_participant_left")
|
||||||
|
async def on_participant_left(transport, participant, reason):
|
||||||
|
logger.info("Participant left: {}", participant)
|
||||||
|
await task.cancel()
|
||||||
|
|
||||||
|
runner = PipelineRunner()
|
||||||
|
|
||||||
|
await runner.run(task)
|
||||||
|
|
||||||
|
|
||||||
|
async def bot(args: DailySessionArguments):
|
||||||
|
"""Main bot entry point compatible with the FastAPI route handler.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
logger.info(f"Bot process initialized {args.room_url} {args.token}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
await main(args.room_url, args.token)
|
||||||
|
logger.info("Bot process completed")
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Error in bot process: {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# Local development functions
|
||||||
|
async def local_main():
|
||||||
|
"""Function for local development testing."""
|
||||||
|
try:
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
(room_url, token) = await configure(session)
|
||||||
|
logger.warning("_")
|
||||||
|
logger.warning("_")
|
||||||
|
logger.warning(f"Talk to your voice agent here: {room_url}")
|
||||||
|
logger.warning("_")
|
||||||
|
logger.warning("_")
|
||||||
|
webbrowser.open(room_url)
|
||||||
|
await main(room_url, token)
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Error in local development mode: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
# Local development entry point
|
||||||
|
if LOCAL_RUN and __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
asyncio.run(local_main())
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Failed to run in local mode: {e}")
|
||||||
2
examples/deployment/pipecat-cloud-example/env.example
Normal file
2
examples/deployment/pipecat-cloud-example/env.example
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
CARTESIA_API_KEY=
|
||||||
|
OPENAI_API_KEY=
|
||||||
46
examples/deployment/pipecat-cloud-example/local_runner.py
Normal file
46
examples/deployment/pipecat-cloud-example/local_runner.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024–2025, Daily
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD 2-Clause License
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
|
from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper, DailyRoomParams
|
||||||
|
|
||||||
|
|
||||||
|
async def configure(aiohttp_session: aiohttp.ClientSession):
|
||||||
|
(url, token) = await configure_with_args(aiohttp_session)
|
||||||
|
return (url, token)
|
||||||
|
|
||||||
|
|
||||||
|
async def configure_with_args(aiohttp_session: aiohttp.ClientSession = None):
|
||||||
|
key = os.getenv("DAILY_API_KEY")
|
||||||
|
if not key:
|
||||||
|
raise Exception(
|
||||||
|
"No Daily API key specified. set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers."
|
||||||
|
)
|
||||||
|
|
||||||
|
daily_rest_helper = DailyRESTHelper(
|
||||||
|
daily_api_key=key,
|
||||||
|
daily_api_url=os.getenv("DAILY_API_URL", "https://api.daily.co/v1"),
|
||||||
|
aiohttp_session=aiohttp_session,
|
||||||
|
)
|
||||||
|
|
||||||
|
room = await daily_rest_helper.create_room(
|
||||||
|
DailyRoomParams(properties={"enable_prejoin_ui": False})
|
||||||
|
)
|
||||||
|
if not room.url:
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to create room")
|
||||||
|
|
||||||
|
url = room.url
|
||||||
|
|
||||||
|
# Create a meeting token for the given room with an expiration 1 hour in
|
||||||
|
# the future.
|
||||||
|
expiry_time: float = 60 * 60
|
||||||
|
|
||||||
|
token = await daily_rest_helper.get_token(url, expiry_time)
|
||||||
|
|
||||||
|
return (url, token)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
agent_name = "my-first-agent"
|
||||||
|
image = "your-username/my-first-agent:0.1"
|
||||||
|
secret_set = "my-first-agent-secrets"
|
||||||
|
|
||||||
|
[scaling]
|
||||||
|
min_instances = 0
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
pipecatcloud
|
||||||
|
pipecat-ai[cartesia,daily,openai,silero]>=0.0.58
|
||||||
|
python-dotenv~=1.0.1
|
||||||
Reference in New Issue
Block a user