Deadmon commited on
Commit
50cee30
·
verified ·
1 Parent(s): f5c6733

Update simple_dialout.py

Browse files
Files changed (1) hide show
  1. simple_dialout.py +27 -117
simple_dialout.py CHANGED
@@ -7,53 +7,31 @@ import argparse
7
  import asyncio
8
  import os
9
  import sys
10
-
11
- from call_connection_manager import CallConfigManager
12
- from dotenv import load_dotenv
13
  from loguru import logger
14
 
15
- from pipecat.adapters.schemas.function_schema import FunctionSchema
16
- from pipecat.adapters.schemas.tools_schema import ToolsSchema
17
  from pipecat.audio.vad.silero import SileroVADAnalyzer
18
- from pipecat.frames.frames import EndTaskFrame
19
  from pipecat.pipeline.pipeline import Pipeline
20
  from pipecat.pipeline.runner import PipelineRunner
21
  from pipecat.pipeline.task import PipelineParams, PipelineTask
22
  from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
23
- from pipecat.processors.frame_processor import FrameDirection
24
  from pipecat.services.cartesia.tts import CartesiaTTSService
25
- from pipecat.services.llm_service import FunctionCallParams
26
  from pipecat.services.openai.llm import OpenAILLMService
27
  from pipecat.transports.services.daily import DailyParams, DailyTransport
28
 
29
- load_dotenv(override=True)
30
-
31
  logger.remove(0)
32
  logger.add(sys.stderr, level="DEBUG")
33
 
34
- daily_api_key = os.getenv("DAILY_API_KEY", "")
35
- daily_api_url = os.getenv("DAILY_API_URL", "https://api.daily.co/v1")
36
-
37
-
38
- async def main(
39
- room_url: str,
40
- token: str,
41
- body: dict,
42
- ):
43
- # ------------ CONFIGURATION AND SETUP ------------
44
-
45
- # Create a config manager using the provided body
46
  call_config_manager = CallConfigManager.from_json_string(body) if body else CallConfigManager()
47
-
48
- # Get important configuration values
49
  dialout_settings = call_config_manager.get_dialout_settings()
50
  test_mode = call_config_manager.is_test_mode()
51
 
52
  # ------------ TRANSPORT SETUP ------------
53
-
54
  transport_params = DailyParams(
55
- api_url=daily_api_url,
56
- api_key=daily_api_key,
57
  audio_in_enabled=True,
58
  audio_out_enabled=True,
59
  video_out_enabled=False,
@@ -61,124 +39,56 @@ async def main(
61
  transcription_enabled=True,
62
  )
63
 
64
- # Initialize transport with Daily
65
- transport = DailyTransport(
66
- room_url,
67
- token,
68
- "Simple Dial-out Bot",
69
- transport_params,
70
- )
71
-
72
- # Initialize TTS
73
  tts = CartesiaTTSService(
74
- api_key=os.getenv("CARTESIA_API_KEY", ""),
75
- voice_id="b7d50908-b17c-442d-ad8d-810c63997ed9", # Use Helpful Woman voice by default
76
- )
77
-
78
- # ------------ FUNCTION DEFINITIONS ------------
79
-
80
- async def terminate_call(params: FunctionCallParams):
81
- """Function the bot can call to terminate the call upon completion of a voicemail message."""
82
- await params.llm.queue_frame(EndTaskFrame(), FrameDirection.UPSTREAM)
83
-
84
- # Define function schemas for tools
85
- terminate_call_function = FunctionSchema(
86
- name="terminate_call",
87
- description="Call this function to terminate the call.",
88
- properties={},
89
- required=[],
90
  )
91
-
92
- # Create tools schema
93
- tools = ToolsSchema(standard_tools=[terminate_call_function])
94
 
95
  # ------------ LLM AND CONTEXT SETUP ------------
96
-
97
- # Set up the system instruction for the LLM
98
- system_instruction = """You are Chatbot, a friendly, helpful robot. 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, but keep your responses brief. Start by introducing yourself. If the user ends the conversation, **IMMEDIATELY** call the `terminate_call` function. """
99
-
100
- # Initialize LLM
101
- llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"))
102
-
103
- # Register functions with the LLM
104
- llm.register_function("terminate_call", terminate_call)
105
-
106
- # Create system message and initialize messages list
107
  messages = [call_config_manager.create_system_message(system_instruction)]
108
-
109
- # Initialize LLM context and aggregator
110
- context = OpenAILLMContext(messages, tools)
111
  context_aggregator = llm.create_context_aggregator(context)
112
 
113
  # ------------ PIPELINE SETUP ------------
 
 
 
 
 
 
 
 
114
 
115
- # Build pipeline
116
- pipeline = Pipeline(
117
- [
118
- transport.input(), # Transport user input
119
- context_aggregator.user(), # User responses
120
- llm, # LLM
121
- tts, # TTS
122
- transport.output(), # Transport bot output
123
- context_aggregator.assistant(), # Assistant spoken responses
124
- ]
125
- )
126
-
127
- # Create pipeline task
128
  task = PipelineTask(pipeline, params=PipelineParams(allow_interruptions=True))
129
 
130
- # ------------ EVENT HANDLERS ------------
131
-
132
- @transport.event_handler("on_joined")
133
- async def on_joined(transport, data):
134
- # Start dialout if needed
135
- if not test_mode and dialout_settings:
136
- logger.debug("Dialout settings detected; starting dialout")
137
- await call_config_manager.start_dialout(transport, dialout_settings)
138
-
139
- @transport.event_handler("on_dialout_connected")
140
- async def on_dialout_connected(transport, data):
141
- logger.debug(f"Dial-out connected: {data}")
142
-
143
- @transport.event_handler("on_dialout_answered")
144
- async def on_dialout_answered(transport, data):
145
- logger.debug(f"Dial-out answered: {data}")
146
- # Automatically start capturing transcription for the participant
147
- await transport.capture_participant_transcription(data["sessionId"])
148
- # The bot will wait to hear the user before the bot speaks
149
-
150
  @transport.event_handler("on_first_participant_joined")
151
  async def on_first_participant_joined(transport, participant):
152
- if test_mode:
153
- logger.debug(f"First participant joined: {participant['id']}")
154
- await transport.capture_participant_transcription(participant["id"])
155
- # The bot will wait to hear the user before the bot speaks
156
 
157
  @transport.event_handler("on_participant_left")
158
  async def on_participant_left(transport, participant, reason):
159
  logger.debug(f"Participant left: {participant}, reason: {reason}")
160
  await task.cancel()
161
 
162
- # ------------ RUN PIPELINE ------------
163
-
164
- if test_mode:
165
- logger.debug("Running in test mode (can be tested in Daily Prebuilt)")
166
 
 
167
  runner = PipelineRunner()
168
  await runner.run(task)
169
 
170
-
171
  if __name__ == "__main__":
172
- parser = argparse.ArgumentParser(description="Simple Dial-out Bot")
173
  parser.add_argument("-u", "--url", type=str, help="Room URL")
174
  parser.add_argument("-t", "--token", type=str, help="Room Token")
175
  parser.add_argument("-b", "--body", type=str, help="JSON configuration string")
176
-
177
  args = parser.parse_args()
178
-
179
- # Log the arguments for debugging
180
  logger.info(f"Room URL: {args.url}")
181
  logger.info(f"Token: {args.token}")
182
  logger.info(f"Body provided: {bool(args.body)}")
183
-
184
- asyncio.run(main(args.url, args.token, args.body))
 
7
  import asyncio
8
  import os
9
  import sys
 
 
 
10
  from loguru import logger
11
 
12
+ from call_connection_manager import CallConfigManager
 
13
  from pipecat.audio.vad.silero import SileroVADAnalyzer
14
+ from pipecat.frames.frames import EndTaskFrame, LLMMessagesFrame
15
  from pipecat.pipeline.pipeline import Pipeline
16
  from pipecat.pipeline.runner import PipelineRunner
17
  from pipecat.pipeline.task import PipelineParams, PipelineTask
18
  from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
 
19
  from pipecat.services.cartesia.tts import CartesiaTTSService
 
20
  from pipecat.services.openai.llm import OpenAILLMService
21
  from pipecat.transports.services.daily import DailyParams, DailyTransport
22
 
 
 
23
  logger.remove(0)
24
  logger.add(sys.stderr, level="DEBUG")
25
 
26
+ async def main(room_url: str, token: str, body: dict):
 
 
 
 
 
 
 
 
 
 
 
27
  call_config_manager = CallConfigManager.from_json_string(body) if body else CallConfigManager()
 
 
28
  dialout_settings = call_config_manager.get_dialout_settings()
29
  test_mode = call_config_manager.is_test_mode()
30
 
31
  # ------------ TRANSPORT SETUP ------------
 
32
  transport_params = DailyParams(
33
+ api_url=os.environ.get("DAILY_API_URL", "https://api.daily.co/v1"),
34
+ api_key=os.environ.get("HF_DAILY_API_KEY", ""),
35
  audio_in_enabled=True,
36
  audio_out_enabled=True,
37
  video_out_enabled=False,
 
39
  transcription_enabled=True,
40
  )
41
 
42
+ transport = DailyTransport(room_url, token, "Simple Dialout Bot", transport_params)
 
 
 
 
 
 
 
 
43
  tts = CartesiaTTSService(
44
+ api_key=os.environ.get("HF_CARTESIA_API_KEY", ""),
45
+ voice_id="b7d50908-b17c-442d-ad8d-810c63997ed9",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  )
47
+ llm = OpenAILLMService(api_key=os.environ.get("HF_OPENAI_API_KEY"))
 
 
48
 
49
  # ------------ LLM AND CONTEXT SETUP ------------
50
+ system_instruction = """You are a friendly, helpful robot. Greet the user and ask how you can assist them."""
 
 
 
 
 
 
 
 
 
 
51
  messages = [call_config_manager.create_system_message(system_instruction)]
52
+ context = OpenAILLMContext(messages)
 
 
53
  context_aggregator = llm.create_context_aggregator(context)
54
 
55
  # ------------ PIPELINE SETUP ------------
56
+ pipeline = Pipeline([
57
+ transport.input(),
58
+ context_aggregator.user(),
59
+ llm,
60
+ tts,
61
+ transport.output(),
62
+ context_aggregator.assistant(),
63
+ ])
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  task = PipelineTask(pipeline, params=PipelineParams(allow_interruptions=True))
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  @transport.event_handler("on_first_participant_joined")
68
  async def on_first_participant_joined(transport, participant):
69
+ await transport.capture_participant_transcription(participant["id"])
70
+ await task.queue_frames([context_aggregator.user().get_context_frame()])
 
 
71
 
72
  @transport.event_handler("on_participant_left")
73
  async def on_participant_left(transport, participant, reason):
74
  logger.debug(f"Participant left: {participant}, reason: {reason}")
75
  await task.cancel()
76
 
77
+ # ------------ DIALOUT ------------
78
+ if not test_mode:
79
+ await call_config_manager.start_dialout(transport, dialout_settings)
 
80
 
81
+ # ------------ RUN PIPELINE ------------
82
  runner = PipelineRunner()
83
  await runner.run(task)
84
 
 
85
  if __name__ == "__main__":
86
+ parser = argparse.ArgumentParser(description="Pipecat Simple Dialout Bot")
87
  parser.add_argument("-u", "--url", type=str, help="Room URL")
88
  parser.add_argument("-t", "--token", type=str, help="Room Token")
89
  parser.add_argument("-b", "--body", type=str, help="JSON configuration string")
 
90
  args = parser.parse_args()
 
 
91
  logger.info(f"Room URL: {args.url}")
92
  logger.info(f"Token: {args.token}")
93
  logger.info(f"Body provided: {bool(args.body)}")
94
+ asyncio.run(main(args.url, args.token, args.body))