diff --git a/examples/foundational/07u-interruptible-openrouter.py b/examples/foundational/07u-interruptible-openrouter.py deleted file mode 100644 index 9aee79e16..000000000 --- a/examples/foundational/07u-interruptible-openrouter.py +++ /dev/null @@ -1,96 +0,0 @@ -import asyncio -import os -import sys - -import aiohttp -from dotenv import load_dotenv -from loguru import logger -from runner import configure - -from pipecat.frames.frames import LLMMessagesFrame -from pipecat.pipeline.pipeline import Pipeline -from pipecat.pipeline.runner import PipelineRunner -from pipecat.pipeline.task import PipelineTask, PipelineParams -from pipecat.services.azure import AzureTTSService -from pipecat.services.openrouter import OpenRouterLLMService -from pipecat.services.openai import OpenAILLMContext -from pipecat.transports.services.daily import DailyParams, DailyTransport -from pipecat.audio.vad.silero import SileroVADAnalyzer - -load_dotenv(override=True) - -logger.remove(0) -logger.add(sys.stderr, level="DEBUG") - - -async def main(): - async with aiohttp.ClientSession() as session: - (room_url, token) = await configure(session) - - transport = DailyTransport( - room_url, - token, - "Chatbot", - DailyParams( - audio_out_enabled=True, - transcription_enabled=True, - vad_enabled=True, - vad_analyzer=SileroVADAnalyzer(), - vad_audio_passthrough=True, - ), - ) - - tts = AzureTTSService( - api_key=os.getenv("AZURE_API_KEY"), - region="eastus", - voice="en-US-JennyNeural", - params=AzureTTSService.InputParams( - language="en-US", - rate="1.1", - style="chat", - ), - ) - - llm = OpenRouterLLMService( - api_key=os.getenv("OPENROUTER_API_KEY"), model="microsoft/phi-4" - ) - 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, helpful, and brief way.", - } - ] - context = OpenAILLMContext(messages=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, - PipelineParams(allow_interruptions=True), - ) - - @transport.event_handler("on_first_participant_joined") - async def on_first_participant_joined(transport, participant): - await transport.capture_participant_transcription(participant["id"]) - messages.append( - {"role": "system", "content": "Please introduce yourself to the user."} - ) - await task.queue_frames([LLMMessagesFrame(messages)]) - - runner = PipelineRunner() - - await runner.run(task) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/examples/foundational/14l-function-calling-openrouter.py b/examples/foundational/14l-function-calling-openrouter.py new file mode 100644 index 000000000..0c885e0ae --- /dev/null +++ b/examples/foundational/14l-function-calling-openrouter.py @@ -0,0 +1,111 @@ +import asyncio +import os +import sys + +import aiohttp +from dotenv import load_dotenv +from loguru import logger +from runner import configure + +from pipecat.audio.vad.silero import SileroVADAnalyzer +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.openrouter import OpenRouterLLMService +from pipecat.services.azure import AzureTTSService +from pipecat.transports.services.daily import DailyParams, DailyTransport + +load_dotenv(override=True) + +logger.remove(0) +logger.add(sys.stderr, level="DEBUG") + + +async def get_weather(function_name, tool_call_id, arguments, llm, context, result_callback): + location = arguments["location"] + await result_callback(f"The weather in {location} is currently 72 degrees and sunny.") + + +async def main(): + async with aiohttp.ClientSession() as session: + (room_url, token) = await configure(session) + + transport = DailyTransport( + room_url, + token, + "Respond bot", + DailyParams( + audio_out_enabled=True, + transcription_enabled=True, + vad_enabled=True, + vad_analyzer=SileroVADAnalyzer(), + ), + ) + + tts = AzureTTSService( + api_key=os.getenv("AZURE_API_KEY"), + region="eastus", + voice="en-US-JennyNeural", + params=AzureTTSService.InputParams(language="en-US", rate="1.1", style="cheerful"), + ) + + llm = OpenRouterLLMService( + api_key=os.getenv("OPENROUTER_API_KEY"), model="openai/chatgpt-4o-latest" + ) + llm.register_function("get_weather", get_weather) + + tools = [ + { + "name": "get_weather", + "description": "Get the current weather in a given location", + "input_schema": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + } + }, + "required": ["location"], + }, + } + ] + + messages = [ + { + "role": "system", + "content": "You are a helpful assistant and whenever you asked about weather trigger get_weather function.", + }, + {"role": "user", "content": "Say 'hello' to start the conversation."}, + ] + + context = OpenAILLMContext(messages, tools) + context_aggregator = llm.create_context_aggregator(context) + + pipeline = Pipeline( + [ + transport.input(), # Transport user input + context_aggregator.user(), # User spoken responses + llm, # LLM + tts, # TTS + transport.output(), # Transport bot output + context_aggregator.assistant(), # Assistant spoken responses and tool context + ] + ) + + 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): + await transport.capture_participant_transcription(participant["id"]) + # Kick off the conversation. + await task.queue_frames([context_aggregator.user().get_context_frame()]) + + runner = PipelineRunner() + + await runner.run(task) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/pyproject.toml b/pyproject.toml index f0809b305..f1bfd2a28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,7 @@ soundfile = [ "soundfile~=0.12.1" ] together = [ "openai~=1.59.0" ] websocket = [ "websockets~=13.1", "fastapi~=0.115.0" ] whisper = [ "faster-whisper~=1.1.0" ] +openrouter = [ "openai~=1.59.0" ] [tool.setuptools.packages.find] # All the following settings are optional: diff --git a/src/pipecat/services/openrouter.py b/src/pipecat/services/openrouter.py index 62552f83a..5b06dda33 100644 --- a/src/pipecat/services/openrouter.py +++ b/src/pipecat/services/openrouter.py @@ -17,7 +17,7 @@ try: except ModuleNotFoundError as e: logger.error(f"Exception: {e}") logger.error( - "In order to use OpenRouter, you need to `pip install pipecat-ai[openai]`. Also, set `OPENROUTER_API_KEY` environment variable." + "In order to use OpenRouter, you need to `pip install pipecat-ai[openrouter]`. Also, set `OPENROUTER_API_KEY` environment variable." ) raise Exception(f"Missing module: {e}")