diff --git a/bots/models.py b/bots/models.py index 19bc2786d..8b8ad343a 100644 --- a/bots/models.py +++ b/bots/models.py @@ -764,6 +764,21 @@ def get_web_widget_config(self, target="#gooey-embed") -> dict: ) return config + def translate(self, text: str) -> str: + from daras_ai_v2.asr import run_google_translate, should_translate_lang + + if text and should_translate_lang(self.user_language): + active_run = self.get_active_saved_run() + return run_google_translate( + [text], + self.user_language, + glossary_url=( + active_run.state.get("output_glossary") if active_run else None + ), + )[0] + else: + return text + class BotIntegrationAnalysisRun(models.Model): bot_integration = models.ForeignKey( diff --git a/daras_ai_v2/bots.py b/daras_ai_v2/bots.py index 6096b9808..3f146dbe9 100644 --- a/daras_ai_v2/bots.py +++ b/daras_ai_v2/bots.py @@ -84,7 +84,7 @@ class BotInterface: page_cls: typing.Type[BasePage] | None query_params: dict - language: str + language: str | None billing_account_uid: str show_feedback_buttons: bool = False streaming_enabled: bool = False @@ -140,37 +140,44 @@ def nice_filename(self, mime_type: str) -> str: return f"{self.platform.name}_{self.input_type}_from_{self.user_id}_to_{self.bot_id}{ext}" def _unpack_bot_integration(self): - bi = self.convo.bot_integration - if bi.published_run: - self.page_cls = Workflow(bi.published_run.workflow).page_cls + self.bi = self.convo.bot_integration + if self.bi.published_run: + self.page_cls = Workflow(self.bi.published_run.workflow).page_cls self.query_params = self.page_cls.clean_query_params( - example_id=bi.published_run.published_run_id, + example_id=self.bi.published_run.published_run_id, run_id="", uid="", ) - saved_run = bi.published_run.saved_run + saved_run = self.bi.published_run.saved_run self.input_glossary = saved_run.state.get("input_glossary_document") self.output_glossary = saved_run.state.get("output_glossary_document") self.language = saved_run.state.get("user_language") - elif bi.saved_run: - self.page_cls = Workflow(bi.saved_run.workflow).page_cls + elif self.bi.saved_run: + self.page_cls = Workflow(self.bi.saved_run.workflow).page_cls self.query_params = self.page_cls.clean_query_params( - example_id=bi.saved_run.example_id, - run_id=bi.saved_run.run_id, - uid=bi.saved_run.uid, + example_id=self.bi.saved_run.example_id, + run_id=self.bi.saved_run.run_id, + uid=self.bi.saved_run.uid, ) - self.input_glossary = bi.saved_run.state.get("input_glossary_document") - self.output_glossary = bi.saved_run.state.get("output_glossary_document") - self.language = bi.saved_run.state.get("user_language") + self.input_glossary = self.bi.saved_run.state.get("input_glossary_document") + self.output_glossary = self.bi.saved_run.state.get( + "output_glossary_document" + ) + self.language = self.bi.saved_run.state.get("user_language") else: self.page_cls = None self.query_params = {} - self.billing_account_uid = bi.billing_account_uid - if should_translate_lang(bi.user_language): - self.language = bi.user_language - self.show_feedback_buttons = bi.show_feedback_buttons - self.streaming_enabled = bi.streaming_enabled + self.billing_account_uid = self.bi.billing_account_uid + if should_translate_lang(self.bi.user_language): + self.language = self.bi.user_language + else: + self.language = None + self.show_feedback_buttons = self.bi.show_feedback_buttons + self.streaming_enabled = self.bi.streaming_enabled + + def translate(self, text: str | None) -> str: + return self.bi.translate(text or "") def _echo(bot, input_text): @@ -199,8 +206,17 @@ def _mock_api_output(input_text): } -@db_middleware def msg_handler(bot: BotInterface): + try: + _msg_handler(bot) + except Exception: + bot.send_msg( + text=bot.translate("Sorry, an error occurred. Please try again later."), + ) + + +@db_middleware +def _msg_handler(bot: BotInterface): recieved_time: datetime = timezone.now() if not bot.page_cls: bot.send_msg(text=PAGE_NOT_CONNECTED_ERROR) diff --git a/daras_ai_v2/twilio_bot.py b/daras_ai_v2/twilio_bot.py index de22c2b50..d3b9b7776 100644 --- a/daras_ai_v2/twilio_bot.py +++ b/daras_ai_v2/twilio_bot.py @@ -2,7 +2,6 @@ from daras_ai_v2.bots import BotInterface, ReplyButton from phonenumber_field.phonenumber import PhoneNumber -from daras_ai_v2.asr import run_google_translate, should_translate_lang from uuid import uuid4 @@ -20,7 +19,6 @@ def __init__(self, *, sid: str, convo: Conversation, text: str, bi: BotIntegrati self.user_id = convo.twilio_phone_number.as_e164 self._unpack_bot_integration() - self.bi = bi def get_input_text(self) -> str | None: return self._text @@ -41,10 +39,8 @@ def send_msg( assert buttons is None, "Interactive mode is not implemented yet" assert update_msg_id is None, "Twilio does not support un-sms-ing things" - if text and should_translate and should_translate_lang(self.language): - text = run_google_translate( - [text], self.language, glossary_url=self.output_glossary - )[0] + if should_translate: + text = self.translate(text) return send_sms_message( self.convo, @@ -95,7 +91,6 @@ def __init__( self._audio = audio self._unpack_bot_integration() - self.bi = bi def get_input_text(self) -> str | None: return self._text @@ -127,10 +122,8 @@ def send_msg( else: audio = None - if text and should_translate and should_translate_lang(self.language): - text = run_google_translate( - [text], self.language, glossary_url=self.output_glossary - )[0] + if should_translate: + text = self.translate(text) twilio_voice_call_respond( text=text, diff --git a/routers/twilio_api.py b/routers/twilio_api.py index 013c4924f..93c7661c1 100644 --- a/routers/twilio_api.py +++ b/routers/twilio_api.py @@ -5,7 +5,6 @@ from app_users.models import AppUser from bots.models import Conversation, BotIntegration, SavedRun, PublishedRun, Platform from phonenumber_field.phonenumber import PhoneNumber -from daras_ai_v2.asr import run_google_translate, should_translate_lang from daras_ai_v2 import settings from furl import furl @@ -17,19 +16,6 @@ router = APIRouter() -def translate(text: str, bi: BotIntegration) -> str: - if text and should_translate_lang(bi.user_language): - return run_google_translate( - [text], - bi.user_language, - glossary_url=bi.get_active_saved_run().state.get( - "output_glossary_document" - ), - )[0] - else: - return text - - def say(resp: VoiceResponse, text: str, bi: BotIntegration): """Say the given text using the bot integration's voice. If the bot integration is set to use Gooey TTS, use that instead.""" @@ -82,9 +68,8 @@ def twilio_voice_call( text = bi.twilio_initial_text.strip() audio_url = bi.twilio_initial_audio_url.strip() if not text and not audio_url: - text = translate( + text = bi.translate( f"Welcome to {bi.name}! Please ask your question and press 0 if the end of your question isn't detected.", - bi, ) if bi.twilio_use_missed_call: @@ -142,20 +127,11 @@ def twilio_voice_call_asked( bi=bi, ) - def msg_handler_with_error_handling(bot: TwilioVoice): - """Handle the user's question and catch any errors to make sure they don't get stuck in the queue until it times out.""" - try: - msg_handler(bot) - except Exception: - bot.send_msg( - text=translate("Sorry, an error occurred. Please try again later.", bi), - ) - - background_tasks.add_task(msg_handler_with_error_handling, bot) + background_tasks.add_task(msg_handler, bot) # send back waiting audio resp = VoiceResponse() - say(resp, translate("I heard ", bi) + text, bi) + say(resp, bot.translate("I heard ") + text, bi) resp.enqueue( name=queue_name, @@ -200,16 +176,7 @@ def twilio_voice_call_asked_audio( bi=bi, ) - def msg_handler_with_error_handling(bot: TwilioVoice): - """Handle the user's question and catch any errors to make sure they don't get stuck in the queue until it times out.""" - try: - msg_handler(bot) - except Exception: - bot.send_msg( - text=translate("Sorry, an error occurred. Please try again later.", bi), - ) - - background_tasks.add_task(msg_handler_with_error_handling, bot) + background_tasks.add_task(msg_handler, bot) # send back waiting audio resp = VoiceResponse() @@ -339,9 +306,8 @@ def twilio_voice_call_response(bi_id: int, text: str, audio_url: str): # if the user doesn't say anything, we'll ask them to call back in a quieter environment say( resp, - translate( - "Sorry, I didn't get that. Please call again in a more quiet environment.", - bi, + bi.translate( + "Sorry, I didn't get that. Please call again in a more quiet environment." ), bi, ) @@ -409,7 +375,7 @@ def twilio_sms( if bi.twilio_waiting_text.strip(): resp.message(bi.twilio_waiting_text) else: - resp.message(translate("Please wait while we process your request.", bi)) + resp.message(bot.translate("Please wait while we process your request.")) return Response(str(resp), headers={"Content-Type": "text/xml"}) @@ -474,7 +440,9 @@ def create_voice_call(convo: Conversation, text: str | None, audio_url: str | No return call -def send_sms_message(convo: Conversation, text: str, media_url: str | None = None): +def send_sms_message( + convo: Conversation, text: str | None, media_url: str | None = None +): """Send an SMS message to the given conversation.""" assert ( @@ -486,7 +454,7 @@ def send_sms_message(convo: Conversation, text: str, media_url: str | None = Non client = Client(account_sid, auth_token) message = client.messages.create( - body=text, + body=text or "", media_url=media_url, from_=convo.bot_integration.twilio_phone_number.as_e164, to=convo.twilio_phone_number.as_e164,