Update Pipecat Flows foundational examples
This commit is contained in:
396
examples/foundational/25c-flow-travel-planner.py
Normal file
396
examples/foundational/25c-flow-travel-planner.py
Normal file
@@ -0,0 +1,396 @@
|
||||
#
|
||||
# Copyright (c) 2024, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
import aiohttp
|
||||
from dotenv import load_dotenv
|
||||
from loguru import logger
|
||||
from pipecat_flows import FlowManager
|
||||
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.deepgram import DeepgramSTTService, DeepgramTTSService
|
||||
from pipecat.services.openai import OpenAILLMService
|
||||
from pipecat.transports.services.daily import DailyParams, DailyTransport
|
||||
|
||||
load_dotenv(override=True)
|
||||
|
||||
logger.remove(0)
|
||||
logger.add(sys.stderr, level="DEBUG")
|
||||
|
||||
# Flow Configuration - Travel Planner
|
||||
#
|
||||
# This configuration defines a vacation planning system with the following states:
|
||||
#
|
||||
# 1. start
|
||||
# - Initial state where user chooses between beach or mountain vacation
|
||||
# - Functions: choose_beach, choose_mountain
|
||||
# - Pre-action: Welcome message
|
||||
# - Transitions to: choose_beach or choose_mountain
|
||||
#
|
||||
# 2. choose_beach/choose_mountain
|
||||
# - Handles destination selection for chosen vacation type
|
||||
# - Functions:
|
||||
# * select_destination (terminal function with location-specific options)
|
||||
# * get_dates (transitions to date selection)
|
||||
# - Pre-action: Destination-specific welcome message
|
||||
#
|
||||
# 3. get_dates
|
||||
# - Handles travel date selection
|
||||
# - Functions:
|
||||
# * record_dates (terminal function, can be modified)
|
||||
# * get_activities (transitions to activity selection)
|
||||
#
|
||||
# 4. get_activities
|
||||
# - Handles activity preference selection
|
||||
# - Functions:
|
||||
# * record_activities (terminal function, array-based selection)
|
||||
# * verify_itinerary (transitions to verification)
|
||||
#
|
||||
# 5. verify_itinerary
|
||||
# - Reviews complete vacation plan
|
||||
# - Functions:
|
||||
# * revise_plan (loops back to get_dates)
|
||||
# * confirm_booking (transitions to confirmation)
|
||||
#
|
||||
# 6. confirm_booking
|
||||
# - Handles final confirmation and tips
|
||||
# - Functions: end
|
||||
# - Pre-action: Confirmation message
|
||||
#
|
||||
# 7. end
|
||||
# - Final state that closes the conversation
|
||||
# - No functions available
|
||||
# - Post-action: Ends conversation
|
||||
|
||||
flow_config = {
|
||||
"initial_node": "start",
|
||||
"nodes": {
|
||||
"start": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "For this step, ask if they're interested in planning a beach vacation or a mountain retreat, and wait for them to choose. Start with an enthusiastic greeting and be conversational; you're helping them plan their dream vacation.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "choose_beach",
|
||||
"description": "User wants to plan a beach vacation",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "choose_mountain",
|
||||
"description": "User wants to plan a mountain retreat",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
],
|
||||
"pre_actions": [
|
||||
{
|
||||
"type": "tts_say",
|
||||
"text": "Welcome to Dream Vacations! I'll help you plan your perfect getaway.",
|
||||
}
|
||||
],
|
||||
},
|
||||
"choose_beach": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are handling beach vacation planning. Use the available functions:\n - Use select_destination when the user chooses their preferred beach location\n - Use get_dates once they've selected a destination\n\nAvailable beach destinations are: 'Maui', 'Cancun', or 'Maldives'. After they choose, confirm their selection and proceed to dates. Be enthusiastic and paint a picture of each destination.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "select_destination",
|
||||
"description": "Record the selected beach destination",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"destination": {
|
||||
"type": "string",
|
||||
"enum": ["Maui", "Cancun", "Maldives"],
|
||||
"description": "Selected beach destination",
|
||||
}
|
||||
},
|
||||
"required": ["destination"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_dates",
|
||||
"description": "Proceed to date selection",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
],
|
||||
"pre_actions": [
|
||||
{"type": "tts_say", "text": "Let's find your perfect beach paradise..."}
|
||||
],
|
||||
},
|
||||
"choose_mountain": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are handling mountain retreat planning. Use the available functions:\n - Use select_destination when the user chooses their preferred mountain location\n - Use get_dates once they've selected a destination\n\nAvailable mountain destinations are: 'Swiss Alps', 'Rocky Mountains', or 'Himalayas'. After they choose, confirm their selection and proceed to dates. Be enthusiastic and paint a picture of each destination.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "select_destination",
|
||||
"description": "Record the selected mountain destination",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"destination": {
|
||||
"type": "string",
|
||||
"enum": ["Swiss Alps", "Rocky Mountains", "Himalayas"],
|
||||
"description": "Selected mountain destination",
|
||||
}
|
||||
},
|
||||
"required": ["destination"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_dates",
|
||||
"description": "Proceed to date selection",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
],
|
||||
"pre_actions": [
|
||||
{"type": "tts_say", "text": "Let's find your perfect mountain getaway..."}
|
||||
],
|
||||
},
|
||||
"get_dates": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Handle travel date selection. Use the available functions:\n - Use record_dates when the user specifies their travel dates (can be used multiple times if they change their mind)\n - Use get_activities once dates are confirmed\n\nAsk for their preferred travel dates within the next 6 months. After recording dates, confirm the selection and proceed to activities.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "record_dates",
|
||||
"description": "Record the selected travel dates",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"check_in": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Check-in date (YYYY-MM-DD)",
|
||||
},
|
||||
"check_out": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Check-out date (YYYY-MM-DD)",
|
||||
},
|
||||
},
|
||||
"required": ["check_in", "check_out"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_activities",
|
||||
"description": "Proceed to activity selection",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
"get_activities": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Handle activity preferences. Use the available functions:\n - Use record_activities to save their activity preferences\n - Use verify_itinerary once activities are selected\n\nFor beach destinations, suggest: snorkeling, surfing, sunset cruise\nFor mountain destinations, suggest: hiking, skiing, mountain biking\n\nAfter they choose, confirm their selections and proceed to verification.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "record_activities",
|
||||
"description": "Record selected activities",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"activities": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"minItems": 1,
|
||||
"maxItems": 3,
|
||||
"description": "Selected activities",
|
||||
}
|
||||
},
|
||||
"required": ["activities"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "verify_itinerary",
|
||||
"description": "Proceed to itinerary verification",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
"verify_itinerary": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Review the complete itinerary with the user. Summarize their destination, dates, and chosen activities. Use the available functions:\n - Use get_dates if they want to make changes\n - Use confirm_booking if they're happy with everything\n\nBe thorough in reviewing all details and ask for their confirmation.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_dates",
|
||||
"description": "Return to date selection to revise the plan",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "confirm_booking",
|
||||
"description": "Confirm the booking and proceed to end",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
"confirm_booking": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "The booking is confirmed. Share some relevant tips about their chosen destination, thank them warmly, and use end to complete the conversation.",
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "end",
|
||||
"description": "End the conversation",
|
||||
"parameters": {"type": "object", "properties": {}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"pre_actions": [
|
||||
{"type": "tts_say", "text": "Fantastic! Your dream vacation is confirmed!"}
|
||||
],
|
||||
},
|
||||
"end": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Wish them a wonderful trip and end the conversation.",
|
||||
}
|
||||
],
|
||||
"functions": [],
|
||||
"post_actions": [{"type": "end_conversation"}],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def main():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
(room_url, _) = await configure(session)
|
||||
|
||||
transport = DailyTransport(
|
||||
room_url,
|
||||
None,
|
||||
"Respond bot",
|
||||
DailyParams(
|
||||
audio_out_enabled=True,
|
||||
vad_enabled=True,
|
||||
vad_analyzer=SileroVADAnalyzer(),
|
||||
vad_audio_passthrough=True,
|
||||
),
|
||||
)
|
||||
|
||||
stt = DeepgramSTTService(api_key=os.getenv("DEEPGRAM_API_KEY"))
|
||||
tts = DeepgramTTSService(api_key=os.getenv("DEEPGRAM_API_KEY"), voice="aura-helios-en")
|
||||
llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o")
|
||||
|
||||
# Get initial tools from the first node
|
||||
initial_tools = flow_config["nodes"]["start"]["functions"]
|
||||
|
||||
# Create initial context
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a travel planning assistant. You must ALWAYS use one of the available functions to progress the conversation. This is a phone conversations and your responses will be converted to audio. Avoid outputting special characters and emojis.",
|
||||
}
|
||||
]
|
||||
|
||||
context = OpenAILLMContext(messages, initial_tools)
|
||||
context_aggregator = llm.create_context_aggregator(context)
|
||||
|
||||
pipeline = Pipeline(
|
||||
[
|
||||
transport.input(), # Transport user input
|
||||
stt, # STT
|
||||
context_aggregator.user(), # User responses
|
||||
llm, # LLM
|
||||
tts, # TTS
|
||||
transport.output(), # Transport bot output
|
||||
context_aggregator.assistant(), # Assistant spoken responses
|
||||
]
|
||||
)
|
||||
|
||||
task = PipelineTask(pipeline, PipelineParams(allow_interruptions=True))
|
||||
|
||||
# Initialize flow manager
|
||||
flow_manager = FlowManager(flow_config, task, tts)
|
||||
|
||||
# Register functions with LLM service
|
||||
await flow_manager.register_functions(llm)
|
||||
|
||||
@transport.event_handler("on_first_participant_joined")
|
||||
async def on_first_participant_joined(transport, participant):
|
||||
await transport.capture_participant_transcription(participant["id"])
|
||||
# Initialize the flow processor
|
||||
await flow_manager.initialize(messages)
|
||||
# Kick off the conversation using the context aggregator
|
||||
await task.queue_frames([context_aggregator.user().get_context_frame()])
|
||||
|
||||
runner = PipelineRunner()
|
||||
await runner.run(task)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user