Skip to content

Commit

Permalink
Fixed up state management and filter logic
Browse files Browse the repository at this point in the history
  • Loading branch information
DominicStewart committed Feb 2, 2025
1 parent c19c36c commit 6b671f6
Showing 1 changed file with 28 additions and 15 deletions.
43 changes: 28 additions & 15 deletions examples/phone-chatbot/bot_daily.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,17 @@ def __init__(self):
self.summary_finished = False
self.operator_connected = False

async def process_frame(self, frame: Frame, direction: FrameDirection):
await super().process_frame(frame, direction)
def set_operator_connected(self, connected: bool):
self.operator_connected = connected
if not connected:
self.summary_finished = False

async def process_frame(self, frame: Frame, direction: FrameDirection):
if self.operator_connected and isinstance(frame, BotStoppedSpeakingFrame):
logger.debug("Summary finished, bot will stop speaking")
self.summary_finished = True
else:
await self.push_frame(frame, direction)

await self.push_frame(frame, direction)


async def main(
Expand Down Expand Up @@ -187,20 +191,18 @@ async def dial_operator(
summary_finished = SummaryFinished()

async def llm_on_filter() -> bool:
if not dial_operator_state.operator_connected:
return True

async def llm_off_filter() -> bool:
if summary_finished.summary_finished:
return True
should_speak = (
not dial_operator_state.operator_connected or not summary_finished.summary_finished
)
logger.debug(f"LLM filter check - should bot speak? {should_speak}")
return should_speak

pipeline = Pipeline(
[
transport.input(),
context_aggregator.user(),
ParallelPipeline(
[FunctionFilter(llm_on_filter), llm, tts],
[FunctionFilter(llm_off_filter)],
),
summary_finished,
transport.output(),
Expand All @@ -221,37 +223,48 @@ async def on_joined(transport, data):
await transport.start_dialout({"phoneNumber": dialout_number})

# Register operator-related handlers regardless of initial dialout state
# Register operator-related handlers
@transport.event_handler("on_dialout_answered")
async def on_dialout_answered(transport, data):
nonlocal operator_session_id
if dial_operator_state.dialed_operator and not dial_operator_state.operator_connected:
logger.debug(f"Operator answered: {data}")
dial_operator_state.set_operator_connected()
operator_session_id = data["sessionId"]
# Add the operator context message

# Add the summary request to context
messages.append(
{
"role": "system",
"content": "Summarise the conversation so far. Keep the summary brief.",
}
)

# Update states after queuing the summary request
dial_operator_state.set_operator_connected()
summary_finished.set_operator_connected(True)

# Queue the context frame to trigger summary
await task.queue_frames([context_aggregator.user().get_context_frame()])
## Now I want to prevent the bot from speaking
## and let the operator take over
else:
logger.debug(f"Customer answered: {data}")

@transport.event_handler("on_dialout_stopped")
async def on_dialout_stopped(transport, data):
if operator_session_id and data["sessionId"] == operator_session_id:
logger.debug("Operator left the call")

# Reset states
dial_operator_state.operator_connected = False
summary_finished.set_operator_connected(False)

# Add message about operator leaving
messages.append(
{
"role": "system",
"content": "Inform the user that the operator has left the call. Ask if they would like to end the call or if they need further assistance.",
}
)

await task.queue_frames([context_aggregator.user().get_context_frame()])

if detect_voicemail:
Expand Down

0 comments on commit 6b671f6

Please sign in to comment.