fixup
|
Before Width: | Height: | Size: 733 KiB After Width: | Height: | Size: 733 KiB |
@@ -1,4 +1,7 @@
|
|||||||
FROM dailyco/pipecat-base:latest
|
FROM dailyco/pipecat-base:latest
|
||||||
|
RUN apt-get update && apt-get install ffmpeg -y
|
||||||
|
|
||||||
|
COPY ./pipecat pipecat
|
||||||
|
|
||||||
COPY ./requirements.txt requirements.txt
|
COPY ./requirements.txt requirements.txt
|
||||||
|
|
||||||
@@ -6,4 +9,4 @@ COPY ./assets assets
|
|||||||
|
|
||||||
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
||||||
|
|
||||||
COPY ./bot.py bot.py
|
COPY ./bot.py bot.py
|
||||||
|
Before Width: | Height: | Size: 759 KiB After Width: | Height: | Size: 759 KiB |
|
Before Width: | Height: | Size: 884 KiB After Width: | Height: | Size: 884 KiB |
|
Before Width: | Height: | Size: 876 KiB After Width: | Height: | Size: 876 KiB |
|
Before Width: | Height: | Size: 881 KiB After Width: | Height: | Size: 881 KiB |
|
Before Width: | Height: | Size: 866 KiB After Width: | Height: | Size: 866 KiB |
|
Before Width: | Height: | Size: 874 KiB After Width: | Height: | Size: 874 KiB |
|
Before Width: | Height: | Size: 882 KiB After Width: | Height: | Size: 882 KiB |
|
Before Width: | Height: | Size: 885 KiB After Width: | Height: | Size: 885 KiB |
|
Before Width: | Height: | Size: 888 KiB After Width: | Height: | Size: 888 KiB |
|
Before Width: | Height: | Size: 890 KiB After Width: | Height: | Size: 890 KiB |
|
Before Width: | Height: | Size: 898 KiB After Width: | Height: | Size: 898 KiB |
|
Before Width: | Height: | Size: 836 KiB After Width: | Height: | Size: 836 KiB |
|
Before Width: | Height: | Size: 903 KiB After Width: | Height: | Size: 903 KiB |
|
Before Width: | Height: | Size: 908 KiB After Width: | Height: | Size: 908 KiB |
|
Before Width: | Height: | Size: 908 KiB After Width: | Height: | Size: 908 KiB |
|
Before Width: | Height: | Size: 905 KiB After Width: | Height: | Size: 905 KiB |
|
Before Width: | Height: | Size: 903 KiB After Width: | Height: | Size: 903 KiB |
|
Before Width: | Height: | Size: 866 KiB After Width: | Height: | Size: 866 KiB |
|
Before Width: | Height: | Size: 849 KiB After Width: | Height: | Size: 849 KiB |
|
Before Width: | Height: | Size: 866 KiB After Width: | Height: | Size: 866 KiB |
|
Before Width: | Height: | Size: 866 KiB After Width: | Height: | Size: 866 KiB |
|
Before Width: | Height: | Size: 864 KiB After Width: | Height: | Size: 864 KiB |
|
Before Width: | Height: | Size: 858 KiB After Width: | Height: | Size: 858 KiB |
|
Before Width: | Height: | Size: 875 KiB After Width: | Height: | Size: 875 KiB |
|
Before Width: | Height: | Size: 881 KiB After Width: | Height: | Size: 881 KiB |
@@ -18,13 +18,15 @@ the conversation flow.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pipecatcloud.agent import DailySessionArguments
|
from pipecatcloud.agent import (
|
||||||
from pipecatcloud.agent import SessionArguments as PCCSessionArguments
|
DailySessionArguments,
|
||||||
|
)
|
||||||
|
|
||||||
from pipecat.adapters.schemas.function_schema import FunctionSchema
|
from pipecat.adapters.schemas.function_schema import FunctionSchema
|
||||||
from pipecat.adapters.schemas.tools_schema import ToolsSchema
|
from pipecat.adapters.schemas.tools_schema import ToolsSchema
|
||||||
@@ -43,17 +45,20 @@ from pipecat.pipeline.task import PipelineParams, PipelineTask
|
|||||||
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
|
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
|
||||||
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
|
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
|
||||||
from pipecat.processors.frameworks.rtvi import RTVIConfig, RTVIObserver, RTVIProcessor
|
from pipecat.processors.frameworks.rtvi import RTVIConfig, RTVIObserver, RTVIProcessor
|
||||||
from pipecat.services.cartesia import CartesiaTTSService
|
from pipecat.services.cartesia.tts import CartesiaTTSService
|
||||||
from pipecat.services.gladia import GladiaSTTService
|
from pipecat.services.gladia.stt import GladiaSTTService
|
||||||
from pipecat.services.openai import OpenAILLMService
|
from pipecat.services.openai.llm import OpenAILLMService
|
||||||
from pipecat.transports.services.daily import DailyParams, DailyTransport
|
from pipecat.transports.services.daily import DailyTransport
|
||||||
from pipecat.transports.services.pipecat_cloud import (
|
from pipecat.transports.services.pipecat_cloud import (
|
||||||
PipecatCloudParams,
|
PipecatCloudParams,
|
||||||
|
PipecatCloudSessionArguments,
|
||||||
PipecatCloudTransport,
|
PipecatCloudTransport,
|
||||||
SessionArguments,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
load_dotenv(override=True)
|
load_dotenv(override=True)
|
||||||
|
logger.add(sys.stderr, level="DEBUG")
|
||||||
|
|
||||||
|
print(f"DailyTransport: {DailyTransport}")
|
||||||
|
|
||||||
# Check if we're in local development mode
|
# Check if we're in local development mode
|
||||||
LOCAL_RUN = os.getenv("LOCAL_RUN")
|
LOCAL_RUN = os.getenv("LOCAL_RUN")
|
||||||
@@ -67,7 +72,7 @@ if LOCAL_RUN:
|
|||||||
logger.error("Could not import local_runner module. Local development mode may not work.")
|
logger.error("Could not import local_runner module. Local development mode may not work.")
|
||||||
|
|
||||||
# Logger for local dev
|
# Logger for local dev
|
||||||
# logger.add(sys.stderr, level="DEBUG")
|
logger.add(sys.stderr, level="DEBUG")
|
||||||
|
|
||||||
sprites = []
|
sprites = []
|
||||||
script_dir = os.path.dirname(__file__)
|
script_dir = os.path.dirname(__file__)
|
||||||
@@ -133,7 +138,7 @@ async def fetch_weather_from_api(function_name, tool_call_id, args, llm, context
|
|||||||
await result_callback({"conditions": "nice", "temperature": "75"})
|
await result_callback({"conditions": "nice", "temperature": "75"})
|
||||||
|
|
||||||
|
|
||||||
async def main(session_args: SessionArguments):
|
async def main(session_args: PipecatCloudSessionArguments):
|
||||||
"""Main bot execution function.
|
"""Main bot execution function.
|
||||||
|
|
||||||
Sets up and runs the bot pipeline including:
|
Sets up and runs the bot pipeline including:
|
||||||
@@ -276,10 +281,16 @@ async def bot(args: DailySessionArguments):
|
|||||||
body: The configuration object from the request body
|
body: The configuration object from the request body
|
||||||
session_id: The session ID for logging
|
session_id: The session ID for logging
|
||||||
"""
|
"""
|
||||||
logger.info(f"Bot process initialized {args.room_url} {args.token}")
|
pcc_args = PipecatCloudSessionArguments(
|
||||||
|
room_url=args.room.url,
|
||||||
|
token=args.token,
|
||||||
|
body=args.body,
|
||||||
|
session_id=args.session_id,
|
||||||
|
)
|
||||||
|
logger.info(f"Bot process initialized {pcc_args.room_url} {pcc_args.token}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await main(args)
|
await main(pcc_args)
|
||||||
logger.info("Bot process completed")
|
logger.info("Bot process completed")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Error in bot process: {str(e)}")
|
logger.exception(f"Error in bot process: {str(e)}")
|
||||||
@@ -293,19 +304,22 @@ async def local_daily():
|
|||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
(room_url, token) = await configure(session)
|
(room_url, token) = await configure(session)
|
||||||
|
args = PipecatCloudSessionArguments(
|
||||||
|
room_url=room_url, token=token, body={}, session_id=None
|
||||||
|
)
|
||||||
logger.warning("_")
|
logger.warning("_")
|
||||||
logger.warning("_")
|
logger.warning("_")
|
||||||
logger.warning(f"Talk to your voice agent here: {room_url}")
|
logger.warning(f"Talk to your voice agent here: {room_url}")
|
||||||
logger.warning("_")
|
logger.warning("_")
|
||||||
logger.warning("_")
|
logger.warning("_")
|
||||||
webbrowser.open(room_url)
|
webbrowser.open(room_url)
|
||||||
await main(room_url, token, config={})
|
await main(args)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Error in local development mode: {e}")
|
logger.exception(f"Error in local development mode: {e}")
|
||||||
|
|
||||||
|
|
||||||
async def local_webrtc(webrtc_connection):
|
async def local_webrtc(webrtc_connection):
|
||||||
await main(SessionArguments(webrtc_connection=webrtc_connection))
|
await main(PipecatCloudSessionArguments(webrtc_connection=webrtc_connection))
|
||||||
|
|
||||||
|
|
||||||
# Local development entry point
|
# Local development entry point
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
VERSION="0.1"
|
VERSION="0.2"
|
||||||
DOCKER_USERNAME="your-docker-hub-username"
|
DOCKER_USERNAME="chadbailey59"
|
||||||
AGENT_NAME="simple-chatbot"
|
AGENT_NAME="pcc-transport-chatbot"
|
||||||
|
|
||||||
# Build the Docker image with the correct context
|
# Build the Docker image with the correct context
|
||||||
echo "Building Docker image..."
|
echo "Building Docker image..."
|
||||||
7
examples/pcc-transport-chatbot/server/pcc-deploy.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
agent_name = "pcc-transport-chatbot"
|
||||||
|
image = "chadbailey59/pcc-transport-chatbot:0.2"
|
||||||
|
secret_set = "pcc-transport-chatbot-secrets"
|
||||||
|
|
||||||
|
[scaling]
|
||||||
|
min_instances = 0
|
||||||
|
max_instances = 2
|
||||||
5
examples/pcc-transport-chatbot/server/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
python-dotenv
|
||||||
|
fastapi[all]
|
||||||
|
uvicorn
|
||||||
|
-e ./pipecat[daily,cartesia,openai,silero,gladia,webrtc]
|
||||||
|
pipecatcloud
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
agent_name = "simple-chatbot"
|
|
||||||
image = "your-docker-hub-username/simple-chatbot:0.1"
|
|
||||||
secret_set = "simple-chatbot-secrets"
|
|
||||||
|
|
||||||
[scaling]
|
|
||||||
min_instances = 0
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
python-dotenv
|
|
||||||
fastapi[all]
|
|
||||||
uvicorn
|
|
||||||
pipecat-ai[daily,cartesia,openai,silero]
|
|
||||||
pipecatcloud
|
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024–2025, Daily
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD 2-Clause License
|
||||||
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import Any, Callable, Optional, Union
|
from typing import Any, Callable, Optional, Union
|
||||||
|
|
||||||
from fastapi import WebSocket
|
from fastapi import WebSocket
|
||||||
from pipecatcloud.agent import DailySessionArguments, WebSocketSessionArguments
|
from pipecatcloud.agent import DailySessionArguments, SessionArguments, WebSocketSessionArguments
|
||||||
from pipecatcloud.agent import SessionArguments as PCCSessionArguments
|
|
||||||
from pydantic import BaseModel, ConfigDict
|
from pydantic import BaseModel, ConfigDict
|
||||||
|
|
||||||
from pipecat.transports.base_transport import BaseTransport, TransportParams
|
from pipecat.transports.base_transport import BaseTransport, TransportParams
|
||||||
@@ -29,7 +34,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class WebRTCSessionArguments(PCCSessionArguments):
|
class WebRTCSessionArguments(SessionArguments):
|
||||||
"""WebRTC based agent session arguments. The arguments are received by the
|
"""WebRTC based agent session arguments. The arguments are received by the
|
||||||
bot() entry point.
|
bot() entry point.
|
||||||
"""
|
"""
|
||||||
@@ -64,8 +69,14 @@ class PipecatCloudParams(TransportParams):
|
|||||||
|
|
||||||
def to_websocket_params(self) -> FastAPIWebsocketParams:
|
def to_websocket_params(self) -> FastAPIWebsocketParams:
|
||||||
"""Convert to FastAPIWebsocketParams."""
|
"""Convert to FastAPIWebsocketParams."""
|
||||||
|
base_params = self.model_dump()
|
||||||
|
# Remove WebSocket-specific fields since we'll add them explicitly
|
||||||
|
websocket_fields = ["add_wav_header", "serializer", "session_timeout"]
|
||||||
|
for field in websocket_fields:
|
||||||
|
base_params.pop(field, None)
|
||||||
|
|
||||||
return FastAPIWebsocketParams(
|
return FastAPIWebsocketParams(
|
||||||
**self.model_dump(),
|
**base_params,
|
||||||
add_wav_header=self.add_wav_header,
|
add_wav_header=self.add_wav_header,
|
||||||
serializer=self.serializer,
|
serializer=self.serializer,
|
||||||
session_timeout=self.session_timeout,
|
session_timeout=self.session_timeout,
|
||||||
@@ -73,8 +84,20 @@ class PipecatCloudParams(TransportParams):
|
|||||||
|
|
||||||
def to_daily_params(self) -> DailyParams:
|
def to_daily_params(self) -> DailyParams:
|
||||||
"""Convert to DailyParams."""
|
"""Convert to DailyParams."""
|
||||||
|
base_params = self.model_dump()
|
||||||
|
# Remove Daily-specific fields since we'll add them explicitly
|
||||||
|
daily_fields = [
|
||||||
|
"api_url",
|
||||||
|
"api_key",
|
||||||
|
"dialin_settings",
|
||||||
|
"transcription_enabled",
|
||||||
|
"transcription_settings",
|
||||||
|
]
|
||||||
|
for field in daily_fields:
|
||||||
|
base_params.pop(field, None)
|
||||||
|
|
||||||
return DailyParams(
|
return DailyParams(
|
||||||
**self.model_dump(),
|
**base_params,
|
||||||
api_url=self.api_url,
|
api_url=self.api_url,
|
||||||
api_key=self.api_key,
|
api_key=self.api_key,
|
||||||
dialin_settings=self.dialin_settings,
|
dialin_settings=self.dialin_settings,
|
||||||
@@ -83,7 +106,7 @@ class PipecatCloudParams(TransportParams):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SessionArguments:
|
class PipecatCloudSessionArguments:
|
||||||
"""Arguments for creating a PipecatCloudTransport session.
|
"""Arguments for creating a PipecatCloudTransport session.
|
||||||
|
|
||||||
This class can be initialized with arguments for any of the supported transport types:
|
This class can be initialized with arguments for any of the supported transport types:
|
||||||
@@ -98,16 +121,20 @@ class SessionArguments:
|
|||||||
websocket: Optional[WebSocket] = None,
|
websocket: Optional[WebSocket] = None,
|
||||||
room_url: Optional[str] = None,
|
room_url: Optional[str] = None,
|
||||||
token: Optional[str] = None,
|
token: Optional[str] = None,
|
||||||
bot_name: Optional[str] = None,
|
|
||||||
webrtc_connection: Optional[SmallWebRTCConnection] = None,
|
webrtc_connection: Optional[SmallWebRTCConnection] = None,
|
||||||
session_id: Optional[str] = None,
|
session_id: Optional[str] = None,
|
||||||
|
body: Optional[dict] = None,
|
||||||
):
|
):
|
||||||
"""Initialize session arguments for any supported transport type."""
|
"""Initialize session arguments for any supported transport type."""
|
||||||
if websocket is not None:
|
if websocket is not None:
|
||||||
self._args = WebSocketSessionArguments(websocket=websocket, session_id=session_id)
|
self._args = WebSocketSessionArguments(websocket=websocket, session_id=session_id)
|
||||||
elif any(x is not None for x in (room_url, token, bot_name)):
|
elif room_url is not None:
|
||||||
self._args = DailySessionArguments(
|
self._args = DailySessionArguments(
|
||||||
room_url=room_url, token=token, bot_name=bot_name, session_id=session_id
|
# TODO-CB: bot_name is missing from DailySessionArguments?
|
||||||
|
room_url=room_url,
|
||||||
|
token=token,
|
||||||
|
session_id=session_id,
|
||||||
|
body=body,
|
||||||
)
|
)
|
||||||
elif webrtc_connection is not None:
|
elif webrtc_connection is not None:
|
||||||
self._args = WebRTCSessionArguments(
|
self._args = WebRTCSessionArguments(
|
||||||
@@ -163,14 +190,13 @@ class PipecatCloudTransport(BaseTransport):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
session_args: SessionArguments,
|
session_args: PipecatCloudSessionArguments,
|
||||||
params: Optional[Union[PipecatCloudParams, TransportParams]] = None,
|
params: Optional[Union[PipecatCloudParams, TransportParams]] = None,
|
||||||
*,
|
*,
|
||||||
input_name: Optional[str] = None,
|
input_name: Optional[str] = None,
|
||||||
output_name: Optional[str] = None,
|
output_name: Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__(input_name=input_name, output_name=output_name)
|
super().__init__(input_name=input_name, output_name=output_name)
|
||||||
logger.debug(f"SessionArguments: {session_args}")
|
|
||||||
|
|
||||||
# Convert TransportParams to PipecatCloudParams if needed
|
# Convert TransportParams to PipecatCloudParams if needed
|
||||||
if isinstance(params, TransportParams):
|
if isinstance(params, TransportParams):
|
||||||
@@ -200,7 +226,8 @@ class PipecatCloudTransport(BaseTransport):
|
|||||||
self._transport = DailyTransport(
|
self._transport = DailyTransport(
|
||||||
args.room_url,
|
args.room_url,
|
||||||
args.token,
|
args.token,
|
||||||
args.bot_name,
|
# TODO-CB: Bot name is missing from DailySessionArguments
|
||||||
|
"Bot",
|
||||||
params=daily_params,
|
params=daily_params,
|
||||||
input_name=input_name,
|
input_name=input_name,
|
||||||
output_name=output_name,
|
output_name=output_name,
|
||||||
|
|||||||