From 4d9b7cdd611b6a8c9bf0cf9cd9de94b1d52edca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Thu, 1 Aug 2024 18:08:57 -0700 Subject: [PATCH] DailyRESTHelper now receives an aiohttp client session --- .../deployment/flyio-example/bot_runner.py | 28 +++- examples/dialin-chatbot/bot_runner.py | 29 +++- examples/foundational/01-say-one-thing.py | 3 +- examples/foundational/02-llm-say-one-thing.py | 3 +- examples/foundational/03-still-frame.py | 3 +- .../foundational/04-utterance-and-speech.py | 3 +- .../foundational/05-sync-speech-and-image.py | 3 +- .../foundational/06-listen-and-respond.py | 3 +- examples/foundational/06a-image-sync.py | 3 +- examples/foundational/07-interruptible.py | 4 +- .../07a-interruptible-anthropic.py | 3 +- .../07b-interruptible-langchain.py | 3 +- .../07c-interruptible-deepgram.py | 3 +- .../07d-interruptible-cartesia.py | 95 +++++------ .../foundational/07e-interruptible-playht.py | 95 +++++------ .../foundational/07f-interruptible-azure.py | 107 ++++++------ .../07g-interruptible-openai-tts.py | 92 ++++++----- .../07h-interruptible-openpipe.py | 4 +- .../foundational/07i-interruptible-xtts.py | 4 +- .../foundational/07j-interruptible-gladia.py | 4 +- examples/foundational/08-bots-arguing.py | 4 +- examples/foundational/09-mirror.py | 38 +++-- examples/foundational/09a-local-mirror.py | 52 +++--- examples/foundational/10-wake-phrase.py | 4 +- examples/foundational/11-sound-effects.py | 4 +- examples/foundational/12-describe-video.py | 4 +- .../12a-describe-video-gemini-flash.py | 4 +- .../foundational/12b-describe-video-gpt-4o.py | 4 +- .../12c-describe-video-anthropic.py | 4 +- .../foundational/13-whisper-transcription.py | 20 ++- .../13b-deepgram-transcription.py | 20 ++- examples/foundational/14-function-calling.py | 4 +- examples/foundational/15-switch-voices.py | 156 +++++++++--------- examples/foundational/15a-switch-languages.py | 4 +- .../16-gpu-container-local-bot.py | 5 +- examples/foundational/17-detect-user-idle.py | 4 +- examples/foundational/runner.py | 8 +- examples/moondream-chatbot/bot.py | 3 +- examples/moondream-chatbot/runner.py | 9 +- examples/moondream-chatbot/server.py | 27 ++- examples/patient-intake/bot.py | 3 +- examples/patient-intake/runner.py | 8 +- examples/patient-intake/server.py | 27 ++- examples/simple-chatbot/bot.py | 3 +- examples/simple-chatbot/runner.py | 9 +- examples/simple-chatbot/server.py | 27 ++- .../storytelling-chatbot/src/bot_runner.py | 27 ++- examples/translation-chatbot/bot.py | 84 +++++----- examples/translation-chatbot/runner.py | 10 +- examples/translation-chatbot/server.py | 27 ++- .../transports/services/helpers/daily_rest.py | 68 ++++---- 51 files changed, 647 insertions(+), 516 deletions(-) diff --git a/examples/deployment/flyio-example/bot_runner.py b/examples/deployment/flyio-example/bot_runner.py index d20dd26c4..2c2ee43cc 100644 --- a/examples/deployment/flyio-example/bot_runner.py +++ b/examples/deployment/flyio-example/bot_runner.py @@ -9,6 +9,8 @@ import argparse import subprocess import os +from contextlib import asynccontextmanager + from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse @@ -39,14 +41,23 @@ FLY_HEADERS = { 'Content-Type': 'application/json' } -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) +daily_helpers = {} # ----------------- API ----------------- # -app = FastAPI() +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -127,7 +138,7 @@ async def start_bot(request: Request) -> JSONResponse: properties=DailyRoomProperties() ) try: - room: DailyRoomObject = await daily_rest_helper.create_room(params=params) + room: DailyRoomObject = await daily_helpers["rest"].create_room(params=params) except Exception as e: raise HTTPException( status_code=500, @@ -135,13 +146,13 @@ async def start_bot(request: Request) -> JSONResponse: else: # Check passed room URL exists, we should assume that it already has a sip set up try: - room: DailyRoomObject = await daily_rest_helper.get_room_from_url(room_url) + room: DailyRoomObject = await daily_helpers["rest"].get_room_from_url(room_url) except Exception: raise HTTPException( status_code=500, detail=f"Room not found: {room_url}") # Give the agent a token to join the session - token = await daily_rest_helper.get_token(room.url, MAX_SESSION_TIME) + token = await daily_helpers["rest"].get_token(room.url, MAX_SESSION_TIME) if not room or not token: raise HTTPException( @@ -168,7 +179,7 @@ async def start_bot(request: Request) -> JSONResponse: status_code=500, detail=f"Failed to spawn VM: {e}") # Grab a token for the user to join with - user_token = await daily_rest_helper.get_token(room.url, MAX_SESSION_TIME) + user_token = await daily_helpers["rest"].get_token(room.url, MAX_SESSION_TIME) return JSONResponse({ "room_url": room.url, @@ -200,6 +211,5 @@ if __name__ == "__main__": port=config.port, reload=config.reload ) - except KeyboardInterrupt: print("Pipecat runner shutting down...") diff --git a/examples/dialin-chatbot/bot_runner.py b/examples/dialin-chatbot/bot_runner.py index bf2038170..3b6e12eec 100644 --- a/examples/dialin-chatbot/bot_runner.py +++ b/examples/dialin-chatbot/bot_runner.py @@ -7,10 +7,14 @@ provisioning a room and starting a Pipecat bot in response. Refer to README for more information. """ + +import aiohttp import os import argparse import subprocess +from contextlib import asynccontextmanager + from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, PlainTextResponse @@ -33,14 +37,23 @@ MAX_SESSION_TIME = 5 * 60 # 5 minutes REQUIRED_ENV_VARS = ['OPENAI_API_KEY', 'DAILY_API_KEY', 'ELEVENLABS_API_KEY', 'ELEVENLABS_VOICE_ID'] -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) - +daily_helpers = {} # ----------------- API ----------------- # -app = FastAPI() + +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -76,13 +89,13 @@ async def _create_daily_room(room_url, callId, callDomain=None, vendor="daily"): ) print(f"Creating new room...") - room: DailyRoomObject = await daily_rest_helper.create_room(params=params) + room: DailyRoomObject = await daily_helpers["rest"].create_room(params=params) else: # Check passed room URL exist (we assume that it already has a sip set up!) try: print(f"Joining existing room: {room_url}") - room: DailyRoomObject = await daily_rest_helper.get_room_from_url(room_url) + room: DailyRoomObject = await daily_helpers["rest"].get_room_from_url(room_url) except Exception: raise HTTPException( status_code=500, detail=f"Room not found: {room_url}") @@ -90,7 +103,7 @@ async def _create_daily_room(room_url, callId, callDomain=None, vendor="daily"): print(f"Daily room: {room.url} {room.config.sip_endpoint}") # Give the agent a token to join the session - token = await daily_rest_helper.get_token(room.url, MAX_SESSION_TIME) + token = await daily_helpers["rest"].get_token(room.url, MAX_SESSION_TIME) if not room or not token: raise HTTPException( diff --git a/examples/foundational/01-say-one-thing.py b/examples/foundational/01-say-one-thing.py index 2cf339fa1..f7330e1c1 100644 --- a/examples/foundational/01-say-one-thing.py +++ b/examples/foundational/01-say-one-thing.py @@ -28,8 +28,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, _) = await configure() async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) + transport = DailyTransport( room_url, None, "Say One Thing", DailyParams(audio_out_enabled=True)) diff --git a/examples/foundational/02-llm-say-one-thing.py b/examples/foundational/02-llm-say-one-thing.py index 9e1b60c19..14086ad2e 100644 --- a/examples/foundational/02-llm-say-one-thing.py +++ b/examples/foundational/02-llm-say-one-thing.py @@ -29,8 +29,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, _) = await configure() async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) + transport = DailyTransport( room_url, None, diff --git a/examples/foundational/03-still-frame.py b/examples/foundational/03-still-frame.py index 852e5777c..1ad36dfcc 100644 --- a/examples/foundational/03-still-frame.py +++ b/examples/foundational/03-still-frame.py @@ -28,8 +28,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, _) = await configure() async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) + transport = DailyTransport( room_url, None, diff --git a/examples/foundational/04-utterance-and-speech.py b/examples/foundational/04-utterance-and-speech.py index b57bb196b..30ce4ef19 100644 --- a/examples/foundational/04-utterance-and-speech.py +++ b/examples/foundational/04-utterance-and-speech.py @@ -31,8 +31,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, _) = await configure() async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) + transport = DailyTransport(room_url, None, "Static And Dynamic Speech") meeting = TransportServiceOutput(transport, mic_enabled=True) diff --git a/examples/foundational/05-sync-speech-and-image.py b/examples/foundational/05-sync-speech-and-image.py index 9f449f469..1eb05b96b 100644 --- a/examples/foundational/05-sync-speech-and-image.py +++ b/examples/foundational/05-sync-speech-and-image.py @@ -74,8 +74,9 @@ class MonthPrepender(FrameProcessor): async def main(): - (room_url, _) = await configure() async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) + transport = DailyTransport( room_url, None, diff --git a/examples/foundational/06-listen-and-respond.py b/examples/foundational/06-listen-and-respond.py index e9fae6c0b..af325cda1 100644 --- a/examples/foundational/06-listen-and-respond.py +++ b/examples/foundational/06-listen-and-respond.py @@ -35,8 +35,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/06a-image-sync.py b/examples/foundational/06a-image-sync.py index db97d84c8..fb1824ed8 100644 --- a/examples/foundational/06a-image-sync.py +++ b/examples/foundational/06a-image-sync.py @@ -60,8 +60,9 @@ class ImageSyncAggregator(FrameProcessor): async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07-interruptible.py b/examples/foundational/07-interruptible.py index 7960ee031..05c0ccd5a 100644 --- a/examples/foundational/07-interruptible.py +++ b/examples/foundational/07-interruptible.py @@ -32,9 +32,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07a-interruptible-anthropic.py b/examples/foundational/07a-interruptible-anthropic.py index dfe915194..6156b3a48 100644 --- a/examples/foundational/07a-interruptible-anthropic.py +++ b/examples/foundational/07a-interruptible-anthropic.py @@ -32,8 +32,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07b-interruptible-langchain.py b/examples/foundational/07b-interruptible-langchain.py index 21617d916..6e691f62c 100644 --- a/examples/foundational/07b-interruptible-langchain.py +++ b/examples/foundational/07b-interruptible-langchain.py @@ -48,8 +48,9 @@ def get_session_history(session_id: str) -> BaseChatMessageHistory: async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07c-interruptible-deepgram.py b/examples/foundational/07c-interruptible-deepgram.py index b8be29859..dad6834ec 100644 --- a/examples/foundational/07c-interruptible-deepgram.py +++ b/examples/foundational/07c-interruptible-deepgram.py @@ -32,8 +32,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07d-interruptible-cartesia.py b/examples/foundational/07d-interruptible-cartesia.py index e0a71ff8b..6b8bbcc5f 100644 --- a/examples/foundational/07d-interruptible-cartesia.py +++ b/examples/foundational/07d-interruptible-cartesia.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -32,62 +33,64 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - transport = DailyTransport( - room_url, - token, - "Respond bot", - DailyParams( - audio_out_sample_rate=44100, - audio_out_enabled=True, - transcription_enabled=True, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + + transport = DailyTransport( + room_url, + token, + "Respond bot", + DailyParams( + audio_out_sample_rate=44100, + audio_out_enabled=True, + transcription_enabled=True, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer() + ) ) - ) - tts = CartesiaTTSService( - api_key=os.getenv("CARTESIA_API_KEY"), - voice_id="a0e99841-438c-4a64-b679-ae501e7d6091", # Barbershop Man - sample_rate=44100, - ) + tts = CartesiaTTSService( + api_key=os.getenv("CARTESIA_API_KEY"), + voice_id="a0e99841-438c-4a64-b679-ae501e7d6091", # Barbershop Man + sample_rate=44100, + ) - 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 = [ + { + "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.", + }, + ] - tma_in = LLMUserResponseAggregator(messages) - tma_out = LLMAssistantResponseAggregator(messages) + tma_in = LLMUserResponseAggregator(messages) + tma_out = LLMAssistantResponseAggregator(messages) - pipeline = Pipeline([ - transport.input(), # Transport user input - tma_in, # User responses - llm, # LLM - tts, # TTS - tma_out, # Goes before the transport because cartesia has word-level timestamps! - transport.output(), # Transport bot output - ]) + pipeline = Pipeline([ + transport.input(), # Transport user input + tma_in, # User responses + llm, # LLM + tts, # TTS + tma_out, # Goes before the transport because cartesia has word-level timestamps! + transport.output(), # Transport bot output + ]) - task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True, enable_metrics=True)) + task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True, enable_metrics=True)) - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_transcription(participant["id"]) - # Kick off the conversation. - messages.append( - {"role": "system", "content": "Please introduce yourself to the user."}) - await task.queue_frames([LLMMessagesFrame(messages)]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + messages.append( + {"role": "system", "content": "Please introduce yourself to the user."}) + await task.queue_frames([LLMMessagesFrame(messages)]) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/07e-interruptible-playht.py b/examples/foundational/07e-interruptible-playht.py index 5d5317dbd..1ad61dc5e 100644 --- a/examples/foundational/07e-interruptible-playht.py +++ b/examples/foundational/07e-interruptible-playht.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -31,62 +32,64 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - transport = DailyTransport( - room_url, - token, - "Respond bot", - DailyParams( - audio_out_enabled=True, - audio_out_sample_rate=16000, - transcription_enabled=True, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + + transport = DailyTransport( + room_url, + token, + "Respond bot", + DailyParams( + audio_out_enabled=True, + audio_out_sample_rate=16000, + transcription_enabled=True, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer() + ) ) - ) - tts = PlayHTTTSService( - user_id=os.getenv("PLAYHT_USER_ID"), - api_key=os.getenv("PLAYHT_API_KEY"), - voice_url="s3://voice-cloning-zero-shot/801a663f-efd0-4254-98d0-5c175514c3e8/jennifer/manifest.json", - ) + tts = PlayHTTTSService( + user_id=os.getenv("PLAYHT_USER_ID"), + api_key=os.getenv("PLAYHT_API_KEY"), + voice_url="s3://voice-cloning-zero-shot/801a663f-efd0-4254-98d0-5c175514c3e8/jennifer/manifest.json", + ) - 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 = [ + { + "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.", + }, + ] - tma_in = LLMUserResponseAggregator(messages) - tma_out = LLMAssistantResponseAggregator(messages) + tma_in = LLMUserResponseAggregator(messages) + tma_out = LLMAssistantResponseAggregator(messages) - pipeline = Pipeline([ - transport.input(), # Transport user input - tma_in, # User responses - llm, # LLM - tts, # TTS - transport.output(), # Transport bot output - tma_out # Assistant spoken responses - ]) + pipeline = Pipeline([ + transport.input(), # Transport user input + tma_in, # User responses + llm, # LLM + tts, # TTS + transport.output(), # Transport bot output + tma_out # Assistant spoken responses + ]) - task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) + task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_transcription(participant["id"]) - # Kick off the conversation. - messages.append( - {"role": "system", "content": "Please introduce yourself to the user."}) - await task.queue_frames([LLMMessagesFrame(messages)]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + messages.append( + {"role": "system", "content": "Please introduce yourself to the user."}) + await task.queue_frames([LLMMessagesFrame(messages)]) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/07f-interruptible-azure.py b/examples/foundational/07f-interruptible-azure.py index fd163d465..50f67f94c 100644 --- a/examples/foundational/07f-interruptible-azure.py +++ b/examples/foundational/07f-interruptible-azure.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -31,69 +32,71 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - transport = DailyTransport( - room_url, - token, - "Respond bot", - DailyParams( - audio_out_enabled=True, - audio_out_sample_rate=16000, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer(), - vad_audio_passthrough=True, + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + + transport = DailyTransport( + room_url, + token, + "Respond bot", + DailyParams( + audio_out_enabled=True, + audio_out_sample_rate=16000, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer(), + vad_audio_passthrough=True, + ) ) - ) - stt = AzureSTTService( - api_key=os.getenv("AZURE_SPEECH_API_KEY"), - region=os.getenv("AZURE_SPEECH_REGION"), - ) + stt = AzureSTTService( + api_key=os.getenv("AZURE_SPEECH_API_KEY"), + region=os.getenv("AZURE_SPEECH_REGION"), + ) - tts = AzureTTSService( - api_key=os.getenv("AZURE_SPEECH_API_KEY"), - region=os.getenv("AZURE_SPEECH_REGION"), - ) + tts = AzureTTSService( + api_key=os.getenv("AZURE_SPEECH_API_KEY"), + region=os.getenv("AZURE_SPEECH_REGION"), + ) - llm = AzureLLMService( - api_key=os.getenv("AZURE_CHATGPT_API_KEY"), - endpoint=os.getenv("AZURE_CHATGPT_ENDPOINT"), - model=os.getenv("AZURE_CHATGPT_MODEL"), - ) + llm = AzureLLMService( + api_key=os.getenv("AZURE_CHATGPT_API_KEY"), + endpoint=os.getenv("AZURE_CHATGPT_ENDPOINT"), + model=os.getenv("AZURE_CHATGPT_MODEL"), + ) - 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 = [ + { + "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.", + }, + ] - tma_in = LLMUserResponseAggregator(messages) - tma_out = LLMAssistantResponseAggregator(messages) + tma_in = LLMUserResponseAggregator(messages) + tma_out = LLMAssistantResponseAggregator(messages) - pipeline = Pipeline([ - transport.input(), # Transport user input - stt, # STT - tma_in, # User responses - llm, # LLM - tts, # TTS - transport.output(), # Transport bot output - tma_out # Assistant spoken responses - ]) + pipeline = Pipeline([ + transport.input(), # Transport user input + stt, # STT + tma_in, # User responses + llm, # LLM + tts, # TTS + transport.output(), # Transport bot output + tma_out # Assistant spoken responses + ]) - task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) + task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_transcription(participant["id"]) - # Kick off the conversation. - messages.append( - {"role": "system", "content": "Please introduce yourself to the user."}) - await task.queue_frames([LLMMessagesFrame(messages)]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + messages.append( + {"role": "system", "content": "Please introduce yourself to the user."}) + await task.queue_frames([LLMMessagesFrame(messages)]) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/07g-interruptible-openai-tts.py b/examples/foundational/07g-interruptible-openai-tts.py index 539f508c8..2b27f7c0b 100644 --- a/examples/foundational/07g-interruptible-openai-tts.py +++ b/examples/foundational/07g-interruptible-openai-tts.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -31,62 +32,63 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) - transport = DailyTransport( - room_url, - token, - "Respond bot", - DailyParams( - audio_out_enabled=True, - audio_out_sample_rate=24000, - transcription_enabled=True, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer() + transport = DailyTransport( + room_url, + token, + "Respond bot", + DailyParams( + audio_out_enabled=True, + audio_out_sample_rate=24000, + transcription_enabled=True, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer() + ) ) - ) - tts = OpenAITTSService( - api_key=os.getenv("OPENAI_API_KEY"), - voice="alloy" - ) + tts = OpenAITTSService( + api_key=os.getenv("OPENAI_API_KEY"), + voice="alloy" + ) - 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 = [ + { + "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.", + }, + ] - tma_in = LLMUserResponseAggregator(messages) - tma_out = LLMAssistantResponseAggregator(messages) + tma_in = LLMUserResponseAggregator(messages) + tma_out = LLMAssistantResponseAggregator(messages) - pipeline = Pipeline([ - transport.input(), # Transport user input - tma_in, # User responses - llm, # LLM - tts, # TTS - transport.output(), # Transport bot output - tma_out # Assistant spoken responses - ]) + pipeline = Pipeline([ + transport.input(), # Transport user input + tma_in, # User responses + llm, # LLM + tts, # TTS + transport.output(), # Transport bot output + tma_out # Assistant spoken responses + ]) - task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) + task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_transcription(participant["id"]) - # Kick off the conversation. - messages.append( - {"role": "system", "content": "Please introduce yourself to the user."}) - await task.queue_frames([LLMMessagesFrame(messages)]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + messages.append( + {"role": "system", "content": "Please introduce yourself to the user."}) + await task.queue_frames([LLMMessagesFrame(messages)]) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/07h-interruptible-openpipe.py b/examples/foundational/07h-interruptible-openpipe.py index 6b4ef564d..e48f0517f 100644 --- a/examples/foundational/07h-interruptible-openpipe.py +++ b/examples/foundational/07h-interruptible-openpipe.py @@ -35,9 +35,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07i-interruptible-xtts.py b/examples/foundational/07i-interruptible-xtts.py index d08e3fb68..e892651e0 100644 --- a/examples/foundational/07i-interruptible-xtts.py +++ b/examples/foundational/07i-interruptible-xtts.py @@ -33,9 +33,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/07j-interruptible-gladia.py b/examples/foundational/07j-interruptible-gladia.py index 43021b20c..23025dcfd 100644 --- a/examples/foundational/07j-interruptible-gladia.py +++ b/examples/foundational/07j-interruptible-gladia.py @@ -34,9 +34,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/08-bots-arguing.py b/examples/foundational/08-bots-arguing.py index 7cda5e36f..0186f2c8e 100644 --- a/examples/foundational/08-bots-arguing.py +++ b/examples/foundational/08-bots-arguing.py @@ -23,9 +23,9 @@ logger.setLevel(logging.DEBUG) async def main(): - (room_url, _) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) + transport = DailyTransport( room_url, None, diff --git a/examples/foundational/09-mirror.py b/examples/foundational/09-mirror.py index 2b875b571..8f5f1073b 100644 --- a/examples/foundational/09-mirror.py +++ b/examples/foundational/09-mirror.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import sys @@ -24,31 +25,32 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) - transport = DailyTransport( - room_url, token, "Test", - DailyParams( - audio_in_enabled=True, - audio_out_enabled=True, - camera_out_enabled=True, - camera_out_is_live=True, - camera_out_width=1280, - camera_out_height=720 + transport = DailyTransport( + room_url, token, "Test", + DailyParams( + audio_in_enabled=True, + audio_out_enabled=True, + camera_out_enabled=True, + camera_out_is_live=True, + camera_out_width=1280, + camera_out_height=720 + ) ) - ) - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_video(participant["id"]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_video(participant["id"]) - pipeline = Pipeline([transport.input(), transport.output()]) + pipeline = Pipeline([transport.input(), transport.output()]) - runner = PipelineRunner() + runner = PipelineRunner() - task = PipelineTask(pipeline) + task = PipelineTask(pipeline) - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/09a-local-mirror.py b/examples/foundational/09a-local-mirror.py index 8ae05f380..d657a3631 100644 --- a/examples/foundational/09a-local-mirror.py +++ b/examples/foundational/09a-local-mirror.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import sys @@ -28,39 +29,42 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) - tk_root = tk.Tk() - tk_root.title("Local Mirror") + tk_root = tk.Tk() + tk_root.title("Local Mirror") - daily_transport = DailyTransport(room_url, token, "Test", DailyParams(audio_in_enabled=True)) + daily_transport = DailyTransport( + room_url, token, "Test", DailyParams( + audio_in_enabled=True)) - tk_transport = TkLocalTransport( - tk_root, - TransportParams( - audio_out_enabled=True, - camera_out_enabled=True, - camera_out_is_live=True, - camera_out_width=1280, - camera_out_height=720)) + tk_transport = TkLocalTransport( + tk_root, + TransportParams( + audio_out_enabled=True, + camera_out_enabled=True, + camera_out_is_live=True, + camera_out_width=1280, + camera_out_height=720)) - @daily_transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_video(participant["id"]) + @daily_transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_video(participant["id"]) - pipeline = Pipeline([daily_transport.input(), tk_transport.output()]) + pipeline = Pipeline([daily_transport.input(), tk_transport.output()]) - task = PipelineTask(pipeline) + task = PipelineTask(pipeline) - async def run_tk(): - while not task.has_finished(): - tk_root.update() - tk_root.update_idletasks() - await asyncio.sleep(0.1) + async def run_tk(): + while not task.has_finished(): + tk_root.update() + tk_root.update_idletasks() + await asyncio.sleep(0.1) - runner = PipelineRunner() + runner = PipelineRunner() - await asyncio.gather(runner.run(task), run_tk()) + await asyncio.gather(runner.run(task), run_tk()) if __name__ == "__main__": diff --git a/examples/foundational/10-wake-phrase.py b/examples/foundational/10-wake-phrase.py index c191c48f1..6002d8f09 100644 --- a/examples/foundational/10-wake-phrase.py +++ b/examples/foundational/10-wake-phrase.py @@ -32,9 +32,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/11-sound-effects.py b/examples/foundational/11-sound-effects.py index 7dff1f10a..00fb0c9be 100644 --- a/examples/foundational/11-sound-effects.py +++ b/examples/foundational/11-sound-effects.py @@ -84,9 +84,9 @@ class InboundSoundEffectWrapper(FrameProcessor): async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/12-describe-video.py b/examples/foundational/12-describe-video.py index 7e8d17ce7..f574aa50f 100644 --- a/examples/foundational/12-describe-video.py +++ b/examples/foundational/12-describe-video.py @@ -50,9 +50,9 @@ class UserImageRequester(FrameProcessor): async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/12a-describe-video-gemini-flash.py b/examples/foundational/12a-describe-video-gemini-flash.py index 9d3cef8d8..d399e0814 100644 --- a/examples/foundational/12a-describe-video-gemini-flash.py +++ b/examples/foundational/12a-describe-video-gemini-flash.py @@ -50,9 +50,9 @@ class UserImageRequester(FrameProcessor): async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/12b-describe-video-gpt-4o.py b/examples/foundational/12b-describe-video-gpt-4o.py index 1fe884ca9..dc5bb4846 100644 --- a/examples/foundational/12b-describe-video-gpt-4o.py +++ b/examples/foundational/12b-describe-video-gpt-4o.py @@ -50,9 +50,9 @@ class UserImageRequester(FrameProcessor): async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/12c-describe-video-anthropic.py b/examples/foundational/12c-describe-video-anthropic.py index d7a07b7c9..052ffa5d4 100644 --- a/examples/foundational/12c-describe-video-anthropic.py +++ b/examples/foundational/12c-describe-video-anthropic.py @@ -50,9 +50,9 @@ class UserImageRequester(FrameProcessor): async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/13-whisper-transcription.py b/examples/foundational/13-whisper-transcription.py index 7dfe4792a..bb24a80bb 100644 --- a/examples/foundational/13-whisper-transcription.py +++ b/examples/foundational/13-whisper-transcription.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import sys @@ -36,22 +37,23 @@ class TranscriptionLogger(FrameProcessor): async def main(): - (room_url, _) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) - transport = DailyTransport(room_url, None, "Transcription bot", - DailyParams(audio_in_enabled=True)) + transport = DailyTransport(room_url, None, "Transcription bot", + DailyParams(audio_in_enabled=True)) - stt = WhisperSTTService() + stt = WhisperSTTService() - tl = TranscriptionLogger() + tl = TranscriptionLogger() - pipeline = Pipeline([transport.input(), stt, tl]) + pipeline = Pipeline([transport.input(), stt, tl]) - task = PipelineTask(pipeline) + task = PipelineTask(pipeline) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/13b-deepgram-transcription.py b/examples/foundational/13b-deepgram-transcription.py index 7df20df3d..c5961109b 100644 --- a/examples/foundational/13b-deepgram-transcription.py +++ b/examples/foundational/13b-deepgram-transcription.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -37,22 +38,23 @@ class TranscriptionLogger(FrameProcessor): async def main(): - (room_url, _) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, _) = await configure(session) - transport = DailyTransport(room_url, None, "Transcription bot", - DailyParams(audio_in_enabled=True)) + transport = DailyTransport(room_url, None, "Transcription bot", + DailyParams(audio_in_enabled=True)) - stt = DeepgramSTTService(api_key=os.getenv("DEEPGRAM_API_KEY")) + stt = DeepgramSTTService(api_key=os.getenv("DEEPGRAM_API_KEY")) - tl = TranscriptionLogger() + tl = TranscriptionLogger() - pipeline = Pipeline([transport.input(), stt, tl]) + pipeline = Pipeline([transport.input(), stt, tl]) - task = PipelineTask(pipeline) + task = PipelineTask(pipeline) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/14-function-calling.py b/examples/foundational/14-function-calling.py index c5b883106..ea6d57b78 100644 --- a/examples/foundational/14-function-calling.py +++ b/examples/foundational/14-function-calling.py @@ -45,9 +45,9 @@ async def fetch_weather_from_api(llm, args): async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/15-switch-voices.py b/examples/foundational/15-switch-voices.py index f1e83536b..2b762513e 100644 --- a/examples/foundational/15-switch-voices.py +++ b/examples/foundational/15-switch-voices.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -58,96 +59,97 @@ async def barbershop_man_filter(frame) -> bool: async def main(): - (room_url, token) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) - transport = DailyTransport( - room_url, - token, - "Pipecat", - DailyParams( - audio_out_enabled=True, - transcription_enabled=True, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer() + transport = DailyTransport( + room_url, + token, + "Pipecat", + DailyParams( + audio_out_enabled=True, + transcription_enabled=True, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer() + ) ) - ) - news_lady = CartesiaTTSService( - api_key=os.getenv("CARTESIA_API_KEY"), - voice_id="bf991597-6c13-47e4-8411-91ec2de5c466", # Newslady - ) + news_lady = CartesiaTTSService( + api_key=os.getenv("CARTESIA_API_KEY"), + voice_id="bf991597-6c13-47e4-8411-91ec2de5c466", # Newslady + ) - british_lady = CartesiaTTSService( - api_key=os.getenv("CARTESIA_API_KEY"), - voice_id="79a125e8-cd45-4c13-8a67-188112f4dd22", # British Lady - ) + british_lady = CartesiaTTSService( + api_key=os.getenv("CARTESIA_API_KEY"), + voice_id="79a125e8-cd45-4c13-8a67-188112f4dd22", # British Lady + ) - barbershop_man = CartesiaTTSService( - api_key=os.getenv("CARTESIA_API_KEY"), - voice_id="a0e99841-438c-4a64-b679-ae501e7d6091", # Barbershop Man - ) + barbershop_man = CartesiaTTSService( + api_key=os.getenv("CARTESIA_API_KEY"), + voice_id="a0e99841-438c-4a64-b679-ae501e7d6091", # Barbershop Man + ) - llm = OpenAILLMService( - api_key=os.getenv("OPENAI_API_KEY"), - model="gpt-4o") - llm.register_function("switch_voice", switch_voice) + llm = OpenAILLMService( + api_key=os.getenv("OPENAI_API_KEY"), + model="gpt-4o") + llm.register_function("switch_voice", switch_voice) - tools = [ - ChatCompletionToolParam( - type="function", - function={ - "name": "switch_voice", - "description": "Switch your voice only when the user asks you to", - "parameters": { - "type": "object", - "properties": { - "voice": { - "type": "string", - "description": "The voice the user wants you to use", + tools = [ + ChatCompletionToolParam( + type="function", + function={ + "name": "switch_voice", + "description": "Switch your voice only when the user asks you to", + "parameters": { + "type": "object", + "properties": { + "voice": { + "type": "string", + "description": "The voice the user wants you to use", + }, }, + "required": ["voice"], }, - "required": ["voice"], - }, - })] - messages = [ - { - "role": "system", - "content": "You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities. Respond to what the user said in a creative and helpful way. Your output should not include non-alphanumeric characters. You can do the following voices: 'News Lady', 'British Lady' and 'Barbershop Man'.", - }, - ] - - context = OpenAILLMContext(messages, tools) - tma_in = LLMUserContextAggregator(context) - tma_out = LLMAssistantContextAggregator(context) - - pipeline = Pipeline([ - transport.input(), # Transport user input - tma_in, # User responses - llm, # LLM - ParallelPipeline( # TTS (one of the following vocies) - [FunctionFilter(news_lady_filter), news_lady], # News Lady voice - [FunctionFilter(british_lady_filter), british_lady], # British Lady voice - [FunctionFilter(barbershop_man_filter), barbershop_man], # Barbershop Man voice - ), - transport.output(), # Transport bot output - tma_out # Assistant spoken responses - ]) - - task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) - - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_transcription(participant["id"]) - # Kick off the conversation. - messages.append( + })] + messages = [ { "role": "system", - "content": f"Please introduce yourself to the user and let them know the voices you can do. Your initial responses should be as if you were a {current_voice}."}) - await task.queue_frames([LLMMessagesFrame(messages)]) + "content": "You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities. Respond to what the user said in a creative and helpful way. Your output should not include non-alphanumeric characters. You can do the following voices: 'News Lady', 'British Lady' and 'Barbershop Man'.", + }, + ] - runner = PipelineRunner() + context = OpenAILLMContext(messages, tools) + tma_in = LLMUserContextAggregator(context) + tma_out = LLMAssistantContextAggregator(context) - await runner.run(task) + pipeline = Pipeline([ + transport.input(), # Transport user input + tma_in, # User responses + llm, # LLM + ParallelPipeline( # TTS (one of the following vocies) + [FunctionFilter(news_lady_filter), news_lady], # News Lady voice + [FunctionFilter(british_lady_filter), british_lady], # British Lady voice + [FunctionFilter(barbershop_man_filter), barbershop_man], # Barbershop Man voice + ), + transport.output(), # Transport bot output + tma_out # Assistant spoken responses + ]) + + task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True)) + + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + messages.append( + { + "role": "system", + "content": f"Please introduce yourself to the user and let them know the voices you can do. Your initial responses should be as if you were a {current_voice}."}) + await task.queue_frames([LLMMessagesFrame(messages)]) + + runner = PipelineRunner() + + await runner.run(task) if __name__ == "__main__": diff --git a/examples/foundational/15a-switch-languages.py b/examples/foundational/15a-switch-languages.py index fe8ee8302..f2501613f 100644 --- a/examples/foundational/15a-switch-languages.py +++ b/examples/foundational/15a-switch-languages.py @@ -56,9 +56,9 @@ async def spanish_filter(frame) -> bool: async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/16-gpu-container-local-bot.py b/examples/foundational/16-gpu-container-local-bot.py index 58ebadbfb..7c0af45f7 100644 --- a/examples/foundational/16-gpu-container-local-bot.py +++ b/examples/foundational/16-gpu-container-local-bot.py @@ -8,7 +8,6 @@ import asyncio import aiohttp import os import sys -import json from pipecat.frames.frames import LLMMessagesFrame from pipecat.pipeline.pipeline import Pipeline @@ -33,9 +32,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/17-detect-user-idle.py b/examples/foundational/17-detect-user-idle.py index cb0600b63..80bdbb32e 100644 --- a/examples/foundational/17-detect-user-idle.py +++ b/examples/foundational/17-detect-user-idle.py @@ -34,9 +34,9 @@ logger.add(sys.stderr, level="DEBUG") async def main(): - (room_url, token) = await configure() - async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/foundational/runner.py b/examples/foundational/runner.py index 5e3225f72..7242c4f27 100644 --- a/examples/foundational/runner.py +++ b/examples/foundational/runner.py @@ -4,13 +4,14 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import argparse import os from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper -async def configure(): +async def configure(aiohttp_session: aiohttp.ClientSession): parser = argparse.ArgumentParser(description="Daily AI SDK Bot Sample") parser.add_argument( "-u", @@ -38,7 +39,10 @@ async def configure(): if not key: raise Exception("No Daily API key specified. use the -k/--apikey option from the command line, or set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers.") - daily_rest_helper = DailyRESTHelper(key, os.getenv("DAILY_API_URL", "https://api.daily.co/v1")) + 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) # Create a meeting token for the given room with an expiration 1 hour in # the future. diff --git a/examples/moondream-chatbot/bot.py b/examples/moondream-chatbot/bot.py index 60ebc11e1..e29ce43e7 100644 --- a/examples/moondream-chatbot/bot.py +++ b/examples/moondream-chatbot/bot.py @@ -135,8 +135,9 @@ class ImageFilterProcessor(FrameProcessor): async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/moondream-chatbot/runner.py b/examples/moondream-chatbot/runner.py index 5e3225f72..7507d28d6 100644 --- a/examples/moondream-chatbot/runner.py +++ b/examples/moondream-chatbot/runner.py @@ -4,13 +4,14 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import argparse import os from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper -async def configure(): +async def configure(aiohttp_session: aiohttp.ClientSession): parser = argparse.ArgumentParser(description="Daily AI SDK Bot Sample") parser.add_argument( "-u", @@ -38,7 +39,11 @@ async def configure(): if not key: raise Exception("No Daily API key specified. use the -k/--apikey option from the command line, or set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers.") - daily_rest_helper = DailyRESTHelper(key, os.getenv("DAILY_API_URL", "https://api.daily.co/v1")) + 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 + ) # Create a meeting token for the given room with an expiration 1 hour in # the future. diff --git a/examples/moondream-chatbot/server.py b/examples/moondream-chatbot/server.py index 1941ca3d0..d758e67f9 100644 --- a/examples/moondream-chatbot/server.py +++ b/examples/moondream-chatbot/server.py @@ -4,10 +4,12 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import os import argparse import subprocess -import atexit + +from contextlib import asynccontextmanager from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware @@ -20,9 +22,7 @@ MAX_BOTS_PER_ROOM = 1 # Bot sub-process dict for status reporting and concurrency control bot_procs = {} -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) +daily_helpers = {} def cleanup(): @@ -33,10 +33,19 @@ def cleanup(): proc.wait() -atexit.register(cleanup) +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + cleanup() - -app = FastAPI() +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -50,7 +59,7 @@ app.add_middleware( @app.get("/start") async def start_agent(request: Request): print(f"!!! Creating room") - room = await daily_rest_helper.create_room(DailyRoomParams()) + room = await daily_helpers["rest"].create_room(DailyRoomParams()) print(f"!!! Room URL: {room.url}") # Ensure the room property is present if not room.url: @@ -66,7 +75,7 @@ async def start_agent(request: Request): status_code=500, detail=f"Max bot limited reach for room: {room.url}") # Get the token for the room - token = await daily_rest_helper.get_token(room.url) + token = await daily_helpers["rest"].get_token(room.url) if not token: raise HTTPException( diff --git a/examples/patient-intake/bot.py b/examples/patient-intake/bot.py index 62b627d2e..0826921db 100644 --- a/examples/patient-intake/bot.py +++ b/examples/patient-intake/bot.py @@ -258,8 +258,9 @@ class IntakeProcessor: async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/patient-intake/runner.py b/examples/patient-intake/runner.py index 5e3225f72..7242c4f27 100644 --- a/examples/patient-intake/runner.py +++ b/examples/patient-intake/runner.py @@ -4,13 +4,14 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import argparse import os from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper -async def configure(): +async def configure(aiohttp_session: aiohttp.ClientSession): parser = argparse.ArgumentParser(description="Daily AI SDK Bot Sample") parser.add_argument( "-u", @@ -38,7 +39,10 @@ async def configure(): if not key: raise Exception("No Daily API key specified. use the -k/--apikey option from the command line, or set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers.") - daily_rest_helper = DailyRESTHelper(key, os.getenv("DAILY_API_URL", "https://api.daily.co/v1")) + 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) # Create a meeting token for the given room with an expiration 1 hour in # the future. diff --git a/examples/patient-intake/server.py b/examples/patient-intake/server.py index 5b0279730..639587894 100644 --- a/examples/patient-intake/server.py +++ b/examples/patient-intake/server.py @@ -4,10 +4,12 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import os import argparse import subprocess -import atexit + +from contextlib import asynccontextmanager from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware @@ -20,9 +22,7 @@ MAX_BOTS_PER_ROOM = 1 # Bot sub-process dict for status reporting and concurrency control bot_procs = {} -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) +daily_helpers = {} def cleanup(): @@ -33,10 +33,19 @@ def cleanup(): proc.wait() -atexit.register(cleanup) +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + cleanup() - -app = FastAPI() +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -50,7 +59,7 @@ app.add_middleware( @app.get("/start") async def start_agent(request: Request): print(f"!!! Creating room") - room = await daily_rest_helper.create_room(DailyRoomParams()) + room = await daily_helpers["rest"].create_room(DailyRoomParams()) print(f"!!! Room URL: {room.url}") # Ensure the room property is present if not room.url: @@ -66,7 +75,7 @@ async def start_agent(request: Request): status_code=500, detail=f"Max bot limited reach for room: {room.url}") # Get the token for the room - token = await daily_rest_helper.get_token(room.url) + token = await daily_helpers["rest"].get_token(room.url) if not token: raise HTTPException( diff --git a/examples/simple-chatbot/bot.py b/examples/simple-chatbot/bot.py index bf54ce4fd..bb4381eba 100644 --- a/examples/simple-chatbot/bot.py +++ b/examples/simple-chatbot/bot.py @@ -84,8 +84,9 @@ class TalkingAnimation(FrameProcessor): async def main(): - (room_url, token) = await configure() async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + transport = DailyTransport( room_url, token, diff --git a/examples/simple-chatbot/runner.py b/examples/simple-chatbot/runner.py index 5e3225f72..7507d28d6 100644 --- a/examples/simple-chatbot/runner.py +++ b/examples/simple-chatbot/runner.py @@ -4,13 +4,14 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import argparse import os from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper -async def configure(): +async def configure(aiohttp_session: aiohttp.ClientSession): parser = argparse.ArgumentParser(description="Daily AI SDK Bot Sample") parser.add_argument( "-u", @@ -38,7 +39,11 @@ async def configure(): if not key: raise Exception("No Daily API key specified. use the -k/--apikey option from the command line, or set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers.") - daily_rest_helper = DailyRESTHelper(key, os.getenv("DAILY_API_URL", "https://api.daily.co/v1")) + 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 + ) # Create a meeting token for the given room with an expiration 1 hour in # the future. diff --git a/examples/simple-chatbot/server.py b/examples/simple-chatbot/server.py index b06a67e07..d54452d10 100644 --- a/examples/simple-chatbot/server.py +++ b/examples/simple-chatbot/server.py @@ -4,10 +4,12 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import os import argparse import subprocess -import atexit + +from contextlib import asynccontextmanager from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware @@ -20,9 +22,7 @@ MAX_BOTS_PER_ROOM = 1 # Bot sub-process dict for status reporting and concurrency control bot_procs = {} -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) +daily_helpers = {} def cleanup(): @@ -33,10 +33,19 @@ def cleanup(): proc.wait() -atexit.register(cleanup) +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + cleanup() - -app = FastAPI() +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -50,7 +59,7 @@ app.add_middleware( @app.get("/start") async def start_agent(request: Request): print(f"!!! Creating room") - room = await daily_rest_helper.create_room(DailyRoomParams()) + room = await daily_helpers["rest"].create_room(DailyRoomParams()) print(f"!!! Room URL: {room.url}") # Ensure the room property is present if not room.url: @@ -66,7 +75,7 @@ async def start_agent(request: Request): status_code=500, detail=f"Max bot limited reach for room: {room.url}") # Get the token for the room - token = await daily_rest_helper.get_token(room.url) + token = await daily_helpers["rest"].get_token(room.url) if not token: raise HTTPException( diff --git a/examples/storytelling-chatbot/src/bot_runner.py b/examples/storytelling-chatbot/src/bot_runner.py index aa3de8774..97e933c25 100644 --- a/examples/storytelling-chatbot/src/bot_runner.py +++ b/examples/storytelling-chatbot/src/bot_runner.py @@ -12,6 +12,8 @@ import os from pathlib import Path from typing import Optional +from contextlib import asynccontextmanager + from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles @@ -28,12 +30,21 @@ load_dotenv(override=True) MAX_SESSION_TIME = 5 * 60 # 5 minutes -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) +daily_helpers = {} -app = FastAPI() +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -78,7 +89,7 @@ async def start_bot(request: Request) -> JSONResponse: properties=DailyRoomProperties() ) try: - room: DailyRoomObject = await daily_rest_helper.create_room(params=params) + room: DailyRoomObject = await daily_helpers["rest"].create_room(params=params) except Exception as e: raise HTTPException( status_code=500, @@ -86,13 +97,13 @@ async def start_bot(request: Request) -> JSONResponse: else: # Check passed room URL exists, we should assume that it already has a sip set up try: - room: DailyRoomObject = await daily_rest_helper.get_room_from_url(room_url) + room: DailyRoomObject = await daily_helpers["rest"].get_room_from_url(room_url) except Exception: raise HTTPException( status_code=500, detail=f"Room not found: {room_url}") # Give the agent a token to join the session - token = await daily_rest_helper.get_token(room.url, MAX_SESSION_TIME) + token = await daily_helpers["rest"].get_token(room.url, MAX_SESSION_TIME) if not room or not token: raise HTTPException( @@ -117,7 +128,7 @@ async def start_bot(request: Request) -> JSONResponse: status_code=500, detail=f"Failed to start subprocess: {e}") # Grab a token for the user to join with - user_token = await daily_rest_helper.get_token(room.url, MAX_SESSION_TIME) + user_token = await daily_helpers["rest"].get_token(room.url, MAX_SESSION_TIME) return JSONResponse({ "room_url": room.url, diff --git a/examples/translation-chatbot/bot.py b/examples/translation-chatbot/bot.py index 8ab4223a0..1dbe802b9 100644 --- a/examples/translation-chatbot/bot.py +++ b/examples/translation-chatbot/bot.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import asyncio import os import sys @@ -89,57 +90,58 @@ class TranslationSubtitles(FrameProcessor): async def main(): - (room_url, token) = await configure() + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) - transport = DailyTransport( - room_url, - token, - "Translator", - DailyParams( - audio_out_enabled=True, - transcription_enabled=True, - transcription_settings=DailyTranscriptionSettings(extra={ - "interim_results": False - }) + transport = DailyTransport( + room_url, + token, + "Translator", + DailyParams( + audio_out_enabled=True, + transcription_enabled=True, + transcription_settings=DailyTranscriptionSettings(extra={ + "interim_results": False + }) + ) ) - ) - tts = AzureTTSService( - api_key=os.getenv("AZURE_SPEECH_API_KEY"), - region=os.getenv("AZURE_SPEECH_REGION"), - voice="es-ES-AlvaroNeural", - ) + tts = AzureTTSService( + api_key=os.getenv("AZURE_SPEECH_API_KEY"), + region=os.getenv("AZURE_SPEECH_REGION"), + voice="es-ES-AlvaroNeural", + ) - llm = OpenAILLMService( - api_key=os.getenv("OPENAI_API_KEY"), - model="gpt-4o" - ) + llm = OpenAILLMService( + api_key=os.getenv("OPENAI_API_KEY"), + model="gpt-4o" + ) - sa = SentenceAggregator() - tp = TranslationProcessor("Spanish") - lfra = LLMFullResponseAggregator() - ts = TranslationSubtitles("spanish") + sa = SentenceAggregator() + tp = TranslationProcessor("Spanish") + lfra = LLMFullResponseAggregator() + ts = TranslationSubtitles("spanish") - pipeline = Pipeline([ - transport.input(), - sa, - tp, - llm, - lfra, - ts, - tts, - transport.output() - ]) + pipeline = Pipeline([ + transport.input(), + sa, + tp, + llm, + lfra, + ts, + tts, + transport.output() + ]) - task = PipelineTask(pipeline) + task = PipelineTask(pipeline) - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - transport.capture_participant_transcription(participant["id"]) + @transport.event_handler("on_first_participant_joined") + async def on_first_participant_joined(transport, participant): + transport.capture_participant_transcription(participant["id"]) - runner = PipelineRunner() + runner = PipelineRunner() - await runner.run(task) + await runner.run(task) if __name__ == "__main__": diff --git a/examples/translation-chatbot/runner.py b/examples/translation-chatbot/runner.py index 5e3225f72..5f0e41795 100644 --- a/examples/translation-chatbot/runner.py +++ b/examples/translation-chatbot/runner.py @@ -7,10 +7,12 @@ import argparse import os +import aiohttp + from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper -async def configure(): +async def configure(aiohttp_session: aiohttp.ClientSession): parser = argparse.ArgumentParser(description="Daily AI SDK Bot Sample") parser.add_argument( "-u", @@ -38,7 +40,11 @@ async def configure(): if not key: raise Exception("No Daily API key specified. use the -k/--apikey option from the command line, or set DAILY_API_KEY in your environment to specify a Daily API key, available from https://dashboard.daily.co/developers.") - daily_rest_helper = DailyRESTHelper(key, os.getenv("DAILY_API_URL", "https://api.daily.co/v1")) + 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 + ) # Create a meeting token for the given room with an expiration 1 hour in # the future. diff --git a/examples/translation-chatbot/server.py b/examples/translation-chatbot/server.py index b06a67e07..d54452d10 100644 --- a/examples/translation-chatbot/server.py +++ b/examples/translation-chatbot/server.py @@ -4,10 +4,12 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import aiohttp import os import argparse import subprocess -import atexit + +from contextlib import asynccontextmanager from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware @@ -20,9 +22,7 @@ MAX_BOTS_PER_ROOM = 1 # Bot sub-process dict for status reporting and concurrency control bot_procs = {} -daily_rest_helper = DailyRESTHelper( - os.getenv("DAILY_API_KEY", ""), - os.getenv("DAILY_API_URL", 'https://api.daily.co/v1')) +daily_helpers = {} def cleanup(): @@ -33,10 +33,19 @@ def cleanup(): proc.wait() -atexit.register(cleanup) +@asynccontextmanager +async def lifespan(app: FastAPI): + aiohttp_session = aiohttp.ClientSession() + daily_helpers["rest"] = DailyRESTHelper( + daily_api_key=os.getenv("DAILY_API_KEY", ""), + daily_api_url=os.getenv("DAILY_API_URL", 'https://api.daily.co/v1'), + aiohttp_session=aiohttp_session + ) + yield + await aiohttp_session.close() + cleanup() - -app = FastAPI() +app = FastAPI(lifespan=lifespan) app.add_middleware( CORSMiddleware, @@ -50,7 +59,7 @@ app.add_middleware( @app.get("/start") async def start_agent(request: Request): print(f"!!! Creating room") - room = await daily_rest_helper.create_room(DailyRoomParams()) + room = await daily_helpers["rest"].create_room(DailyRoomParams()) print(f"!!! Room URL: {room.url}") # Ensure the room property is present if not room.url: @@ -66,7 +75,7 @@ async def start_agent(request: Request): status_code=500, detail=f"Max bot limited reach for room: {room.url}") # Get the token for the room - token = await daily_rest_helper.get_token(room.url) + token = await daily_helpers["rest"].get_token(room.url) if not token: raise HTTPException( diff --git a/src/pipecat/transports/services/helpers/daily_rest.py b/src/pipecat/transports/services/helpers/daily_rest.py index 34af4b1b0..f5f6717bc 100644 --- a/src/pipecat/transports/services/helpers/daily_rest.py +++ b/src/pipecat/transports/services/helpers/daily_rest.py @@ -62,24 +62,26 @@ class DailyRoomObject(BaseModel): class DailyRESTHelper: def __init__(self, + *, daily_api_key: str, - daily_api_url: str = "https://api.daily.co/v1"): + daily_api_url: str = "https://api.daily.co/v1", + aiohttp_session: aiohttp.ClientSession): self.daily_api_key = daily_api_key self.daily_api_url = daily_api_url + self.aiohttp_session = aiohttp_session def _get_name_from_url(self, room_url: str) -> str: return urlparse(room_url).path[1:] async def create_room(self, params: DailyRoomParams) -> DailyRoomObject: - async with aiohttp.ClientSession() as session: - headers = {"Authorization": f"Bearer {self.daily_api_key}"} - json = {**params.model_dump(exclude_none=True)} - async with session.post(f"{self.daily_api_url}/rooms", headers=headers, json=json) as r: - if r.status != 200: - text = await r.text() - raise Exception(f"Unable to create room: {text}") + headers = {"Authorization": f"Bearer {self.daily_api_key}"} + json = {**params.model_dump(exclude_none=True)} + async with self.aiohttp_session.post(f"{self.daily_api_url}/rooms", headers=headers, json=json) as r: + if r.status != 200: + text = await r.text() + raise Exception(f"Unable to create room: {text}") - data = await r.json() + data = await r.json() try: room = DailyRoomObject(**data) @@ -89,17 +91,17 @@ class DailyRESTHelper: return room async def _get_room_from_name(self, room_name: str) -> DailyRoomObject: - async with aiohttp.ClientSession() as session: - headers = {"Authorization": f"Bearer {self.daily_api_key}"} - async with session.get(f"{self.daily_api_url}/rooms/{room_name}", headers=headers) as r: - if r.status != 200: - raise Exception(f"Room not found: {room_name}") + headers = {"Authorization": f"Bearer {self.daily_api_key}"} + async with self.aiohttp_session.get(f"{self.daily_api_url}/rooms/{room_name}", headers=headers) as r: + if r.status != 200: + raise Exception(f"Room not found: {room_name}") - data = await r.json() - try: - room = DailyRoomObject(**data) - except ValidationError as e: - raise Exception(f"Invalid response: {e}") + data = await r.json() + + try: + room = DailyRoomObject(**data) + except ValidationError as e: + raise Exception(f"Invalid response: {e}") return room @@ -120,21 +122,19 @@ class DailyRESTHelper: room_name = self._get_name_from_url(room_url) - async with aiohttp.ClientSession() as session: - headers = {"Authorization": f"Bearer {self.daily_api_key}"} - json = { - "properties": { - "room_name": room_name, - "is_owner": owner, - "exp": expiration - } + headers = {"Authorization": f"Bearer {self.daily_api_key}"} + json = { + "properties": { + "room_name": room_name, + "is_owner": owner, + "exp": expiration } - async with session.post(f"{self.daily_api_url}/meeting-tokens", headers=headers, json=json) as r: - if r.status != 200: - text = await r.text() - raise Exception(f"Failed to create meeting token: {r.status} {text}") + } + async with self.aiohttp_session.post(f"{self.daily_api_url}/meeting-tokens", headers=headers, json=json) as r: + if r.status != 200: + text = await r.text() + raise Exception(f"Failed to create meeting token: {r.status} {text}") - data = await r.json() - token: str = data["token"] + data = await r.json() - return token + return data["token"]