From d4b1e1ab41941f10ec0cfc4d624bf7d7e5fe4d26 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Tue, 23 Sep 2025 12:14:10 -0400 Subject: [PATCH] Update more examples to use universal `LLMContext`. Specifically, update examples we didn't update before because they weren't using `ToolsSchema` for their tool definitions, which is a requirement for using `LLMContext`. NOTE: oops! Turns out some of these files had *already* been updated to use universal `LLMContext` even though they weren't yet using `ToolsSchema`. This commit should fix those examples. --- examples/foundational/15-switch-voices.py | 33 ++++++------- examples/foundational/15a-switch-languages.py | 32 +++++-------- examples/foundational/33-gemini-rag.py | 48 ++++++++----------- .../foundational/36-user-email-gathering.py | 43 ++++++++--------- 4 files changed, 67 insertions(+), 89 deletions(-) diff --git a/examples/foundational/15-switch-voices.py b/examples/foundational/15-switch-voices.py index bd544462e..afa51289c 100644 --- a/examples/foundational/15-switch-voices.py +++ b/examples/foundational/15-switch-voices.py @@ -9,8 +9,9 @@ import os from dotenv import load_dotenv from loguru import logger -from openai.types.chat import ChatCompletionToolParam +from pipecat.adapters.schemas.function_schema import FunctionSchema +from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 from pipecat.audio.vad.silero import SileroVADAnalyzer @@ -121,25 +122,19 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY")) llm.register_function("switch_voice", tts.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", - }, - }, - "required": ["voice"], - }, + switch_voice_function = FunctionSchema( + name="switch_voice", + description="Switch your voice only when the user asks you to", + properties={ + "voice": { + "type": "string", + "description": "The voice the user wants you to use", }, - ) - ] + }, + required=["voice"], + ) + tools = ToolsSchema(standard_tools=[switch_voice_function]) + messages = [ { "role": "system", diff --git a/examples/foundational/15a-switch-languages.py b/examples/foundational/15a-switch-languages.py index f5e92af4f..7e70b0f2d 100644 --- a/examples/foundational/15a-switch-languages.py +++ b/examples/foundational/15a-switch-languages.py @@ -10,8 +10,9 @@ import os from deepgram import LiveOptions from dotenv import load_dotenv from loguru import logger -from openai.types.chat import ChatCompletionToolParam +from pipecat.adapters.schemas.function_schema import FunctionSchema +from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 from pipecat.audio.vad.silero import SileroVADAnalyzer @@ -112,25 +113,18 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY")) llm.register_function("switch_language", tts.switch_language) - tools = [ - ChatCompletionToolParam( - type="function", - function={ - "name": "switch_language", - "description": "Switch to another language when the user asks you to", - "parameters": { - "type": "object", - "properties": { - "language": { - "type": "string", - "description": "The language the user wants you to speak", - }, - }, - "required": ["language"], - }, + switch_language_function = FunctionSchema( + name="switch_language", + description="Switch to another language when the user asks you to", + properties={ + "language": { + "type": "string", + "description": "The language the user wants you to speak", }, - ) - ] + }, + required=["language"], + ) + tools = ToolsSchema(standard_tools=[switch_language_function]) messages = [ { "role": "system", diff --git a/examples/foundational/33-gemini-rag.py b/examples/foundational/33-gemini-rag.py index b9293ae23..e2e88e390 100644 --- a/examples/foundational/33-gemini-rag.py +++ b/examples/foundational/33-gemini-rag.py @@ -55,6 +55,8 @@ from dotenv import load_dotenv from google import genai from loguru import logger +from pipecat.adapters.schemas.function_schema import FunctionSchema +from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 from pipecat.audio.vad.silero import SileroVADAnalyzer @@ -63,7 +65,8 @@ from pipecat.frames.frames import LLMRunFrame 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.processors.aggregators.llm_context import LLMContext +from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport from pipecat.services.cartesia.tts import CartesiaTTSService @@ -121,11 +124,7 @@ async def query_knowledge_base(params: FunctionCallParams): # for our case, the first two messages are the instructions and the user message # so we remove them. - conversation_turns = params.context.messages[2:] - # convert to standard messages - messages = [] - for turn in conversation_turns: - messages.extend(params.context.to_standard_messages(turn)) + conversation_turns = params.context.get_messages()[2:] def _is_tool_call(turn): if turn.get("role", None) == "tool": @@ -135,7 +134,7 @@ async def query_knowledge_base(params: FunctionCallParams): return False # filter out tool calls - messages = [turn for turn in messages if not _is_tool_call(turn)] + messages = [turn for turn in conversation_turns if not _is_tool_call(turn)] # use the last 3 turns as the conversation history/context messages = messages[-3:] messages_json = json.dumps(messages, ensure_ascii=False, indent=2) @@ -199,25 +198,20 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): api_key=os.getenv("GOOGLE_API_KEY"), ) llm.register_function("query_knowledge_base", query_knowledge_base) - tools = [ - { - "function_declarations": [ - { - "name": "query_knowledge_base", - "description": "Query the knowledge base for the answer to the question.", - "parameters": { - "type": "object", - "properties": { - "question": { - "type": "string", - "description": "The question to query the knowledge base with.", - }, - }, - }, - }, - ], + + query_function = FunctionSchema( + name="query_knowledge_base", + description="Query the knowledge base for the answer to the question.", + properties={ + "question": { + "type": "string", + "description": "The question to query the knowledge base with.", + }, }, - ] + required=["question"], + ) + tools = ToolsSchema(standard_tools=[query_function]) + system_prompt = """\ You are a helpful assistant who converses with a user and answers questions. @@ -230,8 +224,8 @@ Your response will be turned into speech so use only simple words and punctuatio {"role": "user", "content": "Greet the user."}, ] - context = OpenAILLMContext(messages, tools) - context_aggregator = llm.create_context_aggregator(context) + context = LLMContext(messages, tools) + context_aggregator = LLMContextAggregatorPair(context) pipeline = Pipeline( [ diff --git a/examples/foundational/36-user-email-gathering.py b/examples/foundational/36-user-email-gathering.py index cc0c9f29f..4cf20b750 100644 --- a/examples/foundational/36-user-email-gathering.py +++ b/examples/foundational/36-user-email-gathering.py @@ -9,8 +9,9 @@ import os from dotenv import load_dotenv from loguru import logger -from openai.types.chat import ChatCompletionToolParam +from pipecat.adapters.schemas.function_schema import FunctionSchema +from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 from pipecat.audio.vad.silero import SileroVADAnalyzer @@ -19,14 +20,14 @@ from pipecat.frames.frames import LLMRunFrame 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.processors.aggregators.llm_context import LLMContext +from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport from pipecat.services.cartesia.tts import CartesiaTTSService from pipecat.services.deepgram.stt import DeepgramSTTService from pipecat.services.llm_service import FunctionCallParams from pipecat.services.openai.llm import OpenAILLMService -from pipecat.services.rime.tts import RimeHttpTTSService from pipecat.transports.base_transport import BaseTransport, TransportParams from pipecat.transports.daily.transport import DailyParams from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams @@ -90,26 +91,20 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): # sent to the same callback with an additional function_name parameter. llm.register_function("store_user_emails", store_user_emails) - tools = [ - ChatCompletionToolParam( - type="function", - function={ - "name": "store_user_emails", - "description": "Store user emails when confirmed", - "parameters": { - "type": "object", - "properties": { - "emails": { - "type": "array", - "description": "The list of user emails", - "items": {"type": "string"}, - }, - }, - "required": ["emails"], - }, + store_emails_function = FunctionSchema( + name="store_user_emails", + description="Store user emails when confirmed", + properties={ + "emails": { + "type": "array", + "description": "The list of user emails", + "items": {"type": "string"}, }, - ) - ] + }, + required=["emails"], + ) + tools = ToolsSchema(standard_tools=[store_emails_function]) + messages = [ { "role": "system", @@ -120,8 +115,8 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): }, ] - context = OpenAILLMContext(messages, tools) - context_aggregator = llm.create_context_aggregator(context) + context = LLMContext(messages, tools) + context_aggregator = LLMContextAggregatorPair(context) pipeline = Pipeline( [