Compare commits

...

3 Commits

Author SHA1 Message Date
James Hush
21b13d85ea Update 2025-06-30 14:32:19 +08:00
James Hush
6088848209 Add comment 2025-06-30 12:29:58 +08:00
James Hush
f5d2dbe977 demo: mute while transfering 2025-06-30 12:27:19 +08:00

View File

@@ -14,15 +14,25 @@ from loguru import logger
from pipecat.adapters.schemas.function_schema import FunctionSchema
from pipecat.adapters.schemas.tools_schema import ToolsSchema
from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.frames.frames import EndFrame, LLMMessagesFrame, TTSTextFrame, UserStartedSpeakingFrame
from pipecat.observers.loggers.debug_log_observer import DebugLogObserver, FrameEndpoint
from pipecat.observers.loggers.llm_log_observer import LLMLogObserver
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.filters.stt_mute_filter import STTMuteConfig, STTMuteFilter, STTMuteStrategy
from pipecat.processors.filters.stt_mute_filter import (
STTMuteConfig,
STTMuteFilter,
STTMuteFrame,
STTMuteStrategy,
)
from pipecat.services.deepgram.stt import DeepgramSTTService
from pipecat.services.deepgram.tts import DeepgramTTSService
from pipecat.services.llm_service import FunctionCallParams
from pipecat.services.openai.llm import OpenAILLMService
from pipecat.transports.base_input import BaseInputTransport
from pipecat.transports.base_output import BaseOutputTransport
from pipecat.transports.base_transport import BaseTransport, TransportParams
from pipecat.transports.network.fastapi_websocket import FastAPIWebsocketParams
from pipecat.transports.services.daily import DailyParams
@@ -30,14 +40,6 @@ from pipecat.transports.services.daily import DailyParams
load_dotenv(override=True)
async def fetch_weather_from_api(params: FunctionCallParams):
# Add a delay to test interruption during function calls
logger.info("Weather API call starting...")
await asyncio.sleep(5) # 5-second delay
logger.info("Weather API call completed")
await params.result_callback({"conditions": "nice", "temperature": "75"})
# We store functions so objects (e.g. SileroVADAnalyzer) don't get
# instantiated. The function will be called when the desired transport gets
# selected.
@@ -69,39 +71,59 @@ async def run_example(transport: BaseTransport, _: argparse.Namespace, handle_si
stt_mute_processor = STTMuteFilter(
config=STTMuteConfig(
strategies={
STTMuteStrategy.MUTE_UNTIL_FIRST_BOT_COMPLETE,
STTMuteStrategy.FUNCTION_CALL,
STTMuteStrategy.MUTE_UNTIL_FIRST_BOT_COMPLETE,
}
),
)
tts = DeepgramTTSService(api_key=os.getenv("DEEPGRAM_API_KEY"), voice="aura-helios-en")
llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"))
llm.register_function("get_current_weather", fetch_weather_from_api)
async def transfer_to_human(params: FunctionCallParams):
# Add a delay to test interruption during function calls
weather_function = FunctionSchema(
name="get_current_weather",
description="Get the current weather",
caller_name = params.arguments.get("caller_name", "Unknown")
human_agent_name = params.arguments.get("human_agent_name", "Unknown")
logger.info(f"Transfer starting... {caller_name} wants to transfer to {human_agent_name}")
await task.queue_frame(STTMuteFrame(True))
await asyncio.sleep(
5
) # 5-second delay to simulate a transfer. You could play hold music here too.
messages.clear()
messages.append(
{
"role": "system",
"content": f"You are an agent named {human_agent_name}. Greet {caller_name} and let them know you are taking over the conversation.",
}
)
await params.llm.push_frame(LLMMessagesFrame(messages))
logger.info("Transfer complete, calling result callback")
await params.result_callback({"transfer_successful": True})
llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"))
llm.register_function("transfer_to_human", transfer_to_human)
transfer_function = FunctionSchema(
name="transfer_to_human",
description="Transfer the conversation to a human agent.",
properties={
"location": {
"caller_name": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
"description": "The name of the person who is calling. This will be used to greet them.",
},
"format": {
"human_agent_name": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The temperature unit to use. Infer this from the user's location.",
"description": "The name of the human agent to transfer the conversation to.",
},
},
required=["location", "format"],
required=["caller_name", "human_agent_name"],
)
tools = ToolsSchema(standard_tools=[weather_function])
tools = ToolsSchema(standard_tools=[transfer_function])
messages = [
{
"role": "system",
"content": "You are a helpful assistant who can check the weather. Always check the weather when a location is mentioned. Respond concisely and naturally. Your output will be converted to audio so use only simple words and punctuation.",
"content": "You are a cheerful and helpful assistant named Bob. It is your job to ask the user their name, and the name of the person they want to transfer the conversation to. Start by introducing yourself and asking for the user's name.",
},
]
@@ -127,6 +149,16 @@ async def run_example(transport: BaseTransport, _: argparse.Namespace, handle_si
enable_metrics=True,
enable_usage_metrics=True,
),
observers=[
LLMLogObserver(),
DebugLogObserver(
frame_types={
TTSTextFrame: (BaseOutputTransport, FrameEndpoint.DESTINATION),
UserStartedSpeakingFrame: (BaseInputTransport, FrameEndpoint.SOURCE),
EndFrame: None,
}
),
],
)
@transport.event_handler("on_client_connected")