Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for location-based interactions in whatsapp #606

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions daras_ai_v2/bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ def get_input_documents(self) -> list[str] | None:
def get_interactive_msg_info(self) -> ButtonPressed:
raise NotImplementedError("This bot does not support interactive messages.")

def get_location_info(self) -> dict:
raise NotImplementedError("This bot does not support location messages.")

def on_run_created(self, sr: "SavedRun"):
pass

Expand Down Expand Up @@ -295,7 +298,7 @@ def msg_handler(bot: BotInterface):
try:
_msg_handler(bot)
except Exception as e:
# send error msg as repsonse
# send error msg as response
bot.send_msg(text=ERROR_MSG.format(e))
raise

Expand Down Expand Up @@ -341,6 +344,12 @@ def _msg_handler(bot: BotInterface):
if not input_audio:
bot.send_msg(text=DEFAULT_RESPONSE)
return
case "location":
input_location = bot.get_location_info()
if not input_location:
bot.send_msg(text=DEFAULT_RESPONSE)
return
input_text = _handle_location_msg(input_text, input_location)
case "text":
if not input_text:
bot.send_msg(text=DEFAULT_RESPONSE)
Expand Down Expand Up @@ -385,7 +394,7 @@ def _handle_feedback_msg(bot: BotInterface, input_text):
run_google_translate([input_text], "en", glossary_url=bot.input_glossary)
)
last_feedback.save()
# send back a confimation msg
# send back a confirmation msg
bot.show_feedback_buttons = False # don't show feedback for this confirmation
bot_name = str(bot.bi.name)
# reset convo state
Expand Down Expand Up @@ -683,6 +692,20 @@ def _handle_interactive_msg(bot: BotInterface):
return False


def _handle_location_msg(input_text, input_location: dict[str, float]) -> str:
from geopy.geocoders import Nominatim

if not input_location:
return input_text

geolocator = Nominatim(user_agent="my_geopy_app")
Copy link
Member

@devxpy devxpy Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we dont pay for this api - it will likely rate limit us. we should look into google - or maybe just pass the coordinates directly to the llm - in general gpt4o does a good job of geolocation itself!

location = geolocator.reverse(
str(input_location["latitude"]) + "," + str(input_location["longitude"])
)
input_text += "My present location is" + location.raw["address"].__str__()
return input_text


class ButtonIds:
action_skip = "ACTION_SKIP"
feedback_thumbs_up = "FEEDBACK_THUMBS_UP"
Expand Down
73 changes: 52 additions & 21 deletions daras_ai_v2/facebook_bots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
from furl import furl

from bots.models import BotIntegration, Platform, Conversation
from components_doc import buttons_group
from daras_ai.image_input import upload_file_from_bytes, get_mimetype_from_response
from daras_ai_v2 import settings
from daras_ai_v2.asr import (
audio_bytes_to_wav,
)
from daras_ai_v2.bots import BotInterface, ReplyButton, ButtonPressed
from daras_ai_v2.csv_lines import csv_decode_row
from daras_ai_v2.exceptions import raise_for_status
from daras_ai_v2.text_splitter import text_splitter

Expand Down Expand Up @@ -96,6 +98,13 @@ def get_interactive_msg_info(self) -> ButtonPressed:
context_msg_id=self.input_message["context"]["id"],
)

def get_location_info(self) -> dict | None:
try:
location_info = self.input_message["location"]
except KeyError:
return None
return location_info

def _send_msg(
self,
*,
Expand Down Expand Up @@ -266,27 +275,49 @@ def retrieve_wa_media_by_id(

def _build_msg_buttons(buttons: list[ReplyButton], msg: dict) -> list[dict]:
ret = []
for i in range(0, len(buttons), 3):
ret.append(
{
"type": "interactive",
"interactive": {
"type": "button",
**msg,
"action": {
"buttons": [
{
"type": "reply",
"reply": {"id": button["id"], "title": button["title"]},
}
for button in buttons[i : i + 3]
],
},
},
}
)
# dont repeat text in subsequent messages
msg = {"body": {"text": "\u200b"}}
button_grp = []
for i in range(0, len(buttons)):
_, button_type, *_ = csv_decode_row(buttons[i]["id"])
match button_type:
case "send_location":
ret.append(
{
"type": "interactive",
"interactive": {
"type": "location_request_message",
"body": {"text": buttons[i]["title"]},
"action": {"name": "send_location"},
},
}
)
case "input_prompt":
button_grp.append(buttons[i])
if button_grp and (len(button_grp) == 3 or i == len(buttons) - 1):
ret.append(
{
"type": "interactive",
"interactive": {
"type": "button",
**msg,
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": button["id"],
"title": button["title"],
},
}
for button in button_grp
],
},
},
}
)
button_grp = []
# dont repeat text in subsequent messages
msg = {"body": {"text": "\u200b"}}

return ret


Expand Down
57 changes: 56 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ python-pptx = "^1.0.2"
azure-identity = "^1.19.0"
azure-keyvault-secrets = "^4.9.0"
xlrd = "^2.0.1"
geopy = "^2.4.1"

[tool.poetry.group.dev.dependencies]
watchdog = "^2.1.9"
Expand Down
Loading