diff --git a/bot.py b/bot.py index 908949c..1be4bfe 100644 --- a/bot.py +++ b/bot.py @@ -15,7 +15,6 @@ import os import re import time -from datetime import datetime, timedelta from loguru import logger @@ -113,9 +112,9 @@ HANGUP_DELAY_SECS = float(os.environ.get("HANGUP_DELAY_SECS", "4.0")) SYSTEM_PROMPT = ( f"You are {AGENT_NAME}, a warm, friendly receptionist for Advanced Vision Care, an " "optometry practice with eight offices in South Florida. You are on a real phone call, so " - "talk like a helpful human being: natural, relaxed, and genuinely conversational — usually " - "just one short sentence at a time. Speak in English. Say numbers, dates, and times as " - "words a person would say.\n\n" + "talk like a helpful human being: natural, relaxed, and genuinely conversational. Keep every " + "reply to ONE short sentence — two at the very most, never a paragraph. Speak in English. Say " + "numbers, dates, and times as words a person would say.\n\n" "Your job is to answer callers' questions and to take appointment requests. For a " "booking, gather these SIX things naturally as the conversation flows — don't " "interrogate, and never ask for something the caller already told you:\n" @@ -128,7 +127,7 @@ SYSTEM_PROMPT = ( " 4. The reason for the visit.\n" " 5. Their insurance — ask what insurance they have and simply note it (see the insurance " "rule below).\n" - " 6. The day and time they prefer (validate the date — see the date rule below).\n" + " 6. The day and time they prefer (take it in their own words — see the date rule below).\n" "When you have the details, repeat them back in one warm sentence to confirm, and let them " "know a staff member will call to finalize the time.\n\n" "Stay truthful and within your limits:\n" @@ -142,14 +141,13 @@ SYSTEM_PROMPT = ( "Do NOT promise, confirm, or deny coverage or any treatment based on their insurance, even " "if the plan is one we list. Always say our staff will verify their coverage when they call " "back. Just capture the plan name.\n" - "- DATES — always validate against the calendar provided below. Work out the real date the " - "caller means and check it. If the weekday and the date they say do not match, or the date " - "does not exist, gently correct them and offer the right one, then confirm before booking. " - "For example, if they say 'Monday the fifth' but the Monday next month is the sixth, say: " - "'Next month, Monday lands on the sixth — would you like to schedule that date?' Never accept " - "an impossible or mismatched date silently.\n" - "- You cannot see a calendar of openings, so never say a time slot is open or available — " - "take the day/time as a request that staff will confirm.\n" + "- DATES — just take down the day and time the caller asks for in their OWN words (e.g. " + "'next Monday', 'the fifth'). Do NOT work out, state, or correct the calendar date, and NEVER " + "argue about what today's date is. Tell them staff will confirm the exact date and time on the " + "callback.\n" + "- You CANNOT see appointment availability or a schedule of openings. Never say a slot is " + "open or available, never offer to 'check availability', and never say you will book or have " + "booked anything. Always frame the day/time as a request staff will confirm on callback.\n" "- Hours are not published — say they vary by office and staff will confirm; never give " "specific hours.\n" "- You don't give medical advice and can't transfer calls. If the caller mentions an eye " @@ -161,25 +159,6 @@ SYSTEM_PROMPT = ( ) -def _date_context(now: datetime | None = None) -> str: - """Calendar grounding injected per call so the local model can resolve and VALIDATE - the dates a caller mentions (e.g. catch 'Monday the 5th' when the Monday is the 6th). - Recomputed each call because the server is long-running.""" - now = now or datetime.now() - today = now.date() - # 45 days covers 'next month' references for any call date. - lines = [] - for i in range(45): - d = today + timedelta(days=i) - tag = " <- TODAY" if i == 0 else (" <- tomorrow" if i == 1 else "") - lines.append(f" {d.strftime('%A, %B %d, %Y').replace(' 0', ' ')}{tag}") - return ( - "CALENDAR — authoritative, use for EVERY date the caller mentions:\n" - f"Today is {today.strftime('%A, %B %d, %Y').replace(' 0', ' ')}.\n" - "Upcoming dates:\n" + "\n".join(lines) + "\n" - ) - - def _build_tools() -> ToolsSchema: # Only the booking action is a tool. Practice facts already live in the system prompt, # so no get_practice_info tool (avoids needless calls/latency). callback_number is NOT @@ -385,8 +364,7 @@ async def run_agent(transport, caller_number=None, call_sid=None, do_capture=Tru ))) heartbeat = AudioHeartbeat() - # Per-call system message = static prompt + today's calendar + the caller-ID number to - # confirm. Built here (not at import) so the date is current on a long-running server. + # Per-call system message = static prompt + the caller-ID number to confirm. if caller_number: caller_line = ( f"\n\nCALLER ID: the caller's number on file is {caller_number}. Read it back and " @@ -397,7 +375,7 @@ async def run_agent(transport, caller_number=None, call_sid=None, do_capture=Tru "\n\nCALLER ID: no number is available — ask the caller for the best phone number " "to reach them." ) - system_content = SYSTEM_PROMPT + "\n\n" + _date_context() + caller_line + system_content = SYSTEM_PROMPT + caller_line context_kwargs = {"messages": [{"role": "system", "content": system_content}]} if ENABLE_TOOLS: context_kwargs["tools"] = _build_tools()