diff --git a/bots/migrations/0080_botintegration_twilio_fresh_conversation_per_call_and_more.py b/bots/migrations/0080_botintegration_twilio_fresh_conversation_per_call_and_more.py new file mode 100644 index 000000000..355c68877 --- /dev/null +++ b/bots/migrations/0080_botintegration_twilio_fresh_conversation_per_call_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.7 on 2024-08-09 19:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bots', '0079_remove_botintegration_twilio_asr_language_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='botintegration', + name='twilio_fresh_conversation_per_call', + field=models.BooleanField(default=False, help_text='If set, the bot will start a new conversation for each call'), + ), + migrations.AddField( + model_name='conversation', + name='twilio_call_sid', + field=models.TextField(blank=True, default='', help_text='Twilio call sid (only used if each call is a new conversation)'), + ), + ] diff --git a/bots/models.py b/bots/models.py index 0407569d5..760def3a0 100644 --- a/bots/models.py +++ b/bots/models.py @@ -694,6 +694,10 @@ class BotIntegration(models.Model): blank=True, help_text="The audio url to play to the user while waiting for a response if using voice", ) + twilio_fresh_conversation_per_call = models.BooleanField( + default=False, + help_text="If set, the bot will start a new conversation for each call", + ) streaming_enabled = models.BooleanField( default=False, @@ -1064,6 +1068,11 @@ class Conversation(models.Model): default="", help_text="User's Twilio phone number (mandatory)", ) + twilio_call_sid = models.TextField( + blank=True, + default="", + help_text="Twilio call sid (only used if each call is a new conversation)", + ) web_user_id = models.CharField( max_length=512, diff --git a/daras_ai_v2/bot_integration_widgets.py b/daras_ai_v2/bot_integration_widgets.py index 4958f389d..b91c14bba 100644 --- a/daras_ai_v2/bot_integration_widgets.py +++ b/daras_ai_v2/bot_integration_widgets.py @@ -126,7 +126,7 @@ def render_workflow_url_input(key: str, del_key: str | None, d: dict): def twilio_specific_settings(bi: BotIntegration): - SETTINGS_FIELDS = ["twilio_use_missed_call", "twilio_initial_text", "twilio_initial_audio_url", "twilio_waiting_text", "twilio_waiting_audio_url"] # fmt:skip + SETTINGS_FIELDS = ["twilio_use_missed_call", "twilio_initial_text", "twilio_initial_audio_url", "twilio_waiting_text", "twilio_waiting_audio_url", "twilio_fresh_conversation_per_call"] # fmt:skip if gui.session_state.get(f"_bi_reset_{bi.id}"): for field in SETTINGS_FIELDS: gui.session_state[f"_bi_{field}_{bi.id}"] = BotIntegration._meta.get_field( @@ -166,6 +166,11 @@ def twilio_specific_settings(bi: BotIntegration): gui.caption( "When enabled, immediately hangs up incoming calls and calls back the user so they don't incur charges (depending on their carrier/plan)." ) + bi.twilio_fresh_conversation_per_call = gui.checkbox( + "🔄 Fresh Conversation History for Each Call", + value=bi.twilio_fresh_conversation_per_call, + key=f"_bi_twilio_fresh_conversation_per_call_{bi.id}", + ) def slack_specific_settings(bi: BotIntegration, default_name: str): diff --git a/daras_ai_v2/twilio_bot.py b/daras_ai_v2/twilio_bot.py index 8d4dd8606..4529952ec 100644 --- a/daras_ai_v2/twilio_bot.py +++ b/daras_ai_v2/twilio_bot.py @@ -95,6 +95,8 @@ def from_data(cls, data: dict): account_sid = data["AccountSid"][0] if account_sid == settings.TWILIO_ACCOUNT_SID: account_sid = "" + call_sid = data["CallSid"][0] + caller_number = data["Caller"][0] user_number, bot_number = data["From"][0], data["To"][0] try: # cases where user is calling the bot @@ -108,14 +110,25 @@ def from_data(cls, data: dict): twilio_account_sid=account_sid, twilio_phone_number=bot_number ) - convo = Conversation.objects.get_or_create( - bot_integration=bi, twilio_phone_number=user_number - )[0] + will_be_missed = caller_number == user_number and bi.twilio_use_missed_call + if will_be_missed: + # for call_sids that we will reject and re-call, the convo is not used, so we don't want to create a new one + convo = None + if bi.twilio_fresh_conversation_per_call and not will_be_missed: + convo = Conversation.objects.get_or_create( + bot_integration=bi, + twilio_phone_number=user_number, + twilio_call_sid=call_sid, + )[0] + else: + convo = Conversation.objects.get_or_create( + bot_integration=bi, twilio_phone_number=user_number + )[0] return cls( convo, text=data.get("SpeechResult", [None])[0], audio_url=data.get("RecordingUrl", [None])[0], - call_sid=data["CallSid"][0], + call_sid=call_sid, ) def __init__(