127 lines
4.7 KiB
Python
127 lines
4.7 KiB
Python
from typing import Type, Optional
|
|
from pydantic import BaseModel, Field
|
|
import requests
|
|
import os
|
|
from urllib.parse import urlencode
|
|
from crewai.tools import BaseTool
|
|
from pydantic import BaseModel
|
|
import requests
|
|
import geocoder
|
|
|
|
FSQ_API_BASE = "https://api.foursquare.com/v3"
|
|
FSQ_SERVICE_TOKEN = os.getenv("FOURSQUARE_SERVICE_TOKEN")
|
|
|
|
# Wrapper function to execute the API call
|
|
def submit_request(endpoint, params):
|
|
|
|
headers = {
|
|
"accept": "application/json",
|
|
"Authorization": f"{FSQ_SERVICE_TOKEN}",
|
|
# "X-Places-Api-Version": "2025-02-05"
|
|
}
|
|
encoded_params = urlencode(params)
|
|
url = f"{FSQ_API_BASE}{endpoint}?{encoded_params}"
|
|
print(url)
|
|
try:
|
|
response = requests.get(url, headers=headers)
|
|
print(response)
|
|
if response.status_code == 200:
|
|
return response.json()
|
|
else:
|
|
print('Error:', response.status_code)
|
|
return None
|
|
except requests.exceptions.RequestException as e:
|
|
print('Error:', e)
|
|
return None
|
|
|
|
|
|
class SeachNearRegionSchema(BaseModel):
|
|
query: str
|
|
near: str
|
|
limit: Optional[int] = Field(default=5, description="Maximum number of results to return")
|
|
|
|
class SearchNearRegionTool(BaseTool):
|
|
name: str = 'Search Near a Named Region Tool'
|
|
description: str ="""Search for places near a particular named region.
|
|
Has a geographic region (e.g., New Delhi, India) and looks for specific concepts (e.g., coffee shop, restaurants) in that geographic region"""
|
|
args_schema: Type[BaseModel] = SeachNearRegionSchema
|
|
def _run(self, query: str, near: str, limit: Optional[int] = 5):
|
|
params = {
|
|
"query": query,
|
|
"near": near,
|
|
"limit": limit
|
|
}
|
|
return submit_request("/places/search", params)
|
|
|
|
|
|
class SeachNearPointSchema(BaseModel):
|
|
query: str
|
|
ll: str = Field(description="Comma separated latitude and longitude pair (e.g., 40.74,-74.0)")
|
|
radius: int = Field(default=2000, description="Maximum radius within which to search", limit=100000)
|
|
limit: Optional[int] = Field(default=5, description="Maximum number of results to return")
|
|
|
|
class SearchNearPointTool(BaseTool):
|
|
name: str = 'Search Near a Point Tool'
|
|
description: str ="""Search for places near a particular point.
|
|
Looks for concepts (e.g., coffee shop, Hard Rock Cafe) using comma separated latitude and longitude pair (e.g., 40.74,-74.0) and radius which is defined in metres (e.g., 1000)"""
|
|
args_schema: Type[BaseModel] = SeachNearPointSchema
|
|
|
|
def _run(self, query: str, ll: str, radius: Optional[int] = 2000, limit: Optional[int] = 5):
|
|
params = {
|
|
"query": query,
|
|
"ll": ll,
|
|
"radius": radius,
|
|
"limit": limit
|
|
}
|
|
return submit_request("/places/search", params)
|
|
|
|
|
|
class PlaceSnapSchema(BaseModel):
|
|
ll: str = Field(description="Comma separated latitude and longitude pair (e.g., 40.74,-74.0)")
|
|
|
|
class PlaceSnapTool(BaseTool):
|
|
name: str = "Get the place tool"
|
|
description: str = """Get the most likely place the user is at based on their reported location. Takes in a comma separated latitude and longitude pair as input"""
|
|
args_schema: Type[BaseModel] = PlaceSnapSchema
|
|
|
|
def _run(self, ll: str):
|
|
params = {
|
|
"ll": ll,
|
|
"limit": 1
|
|
}
|
|
return submit_request("/geotagging/candidates", params)
|
|
|
|
|
|
class PlaceDetailsSchema(BaseModel):
|
|
id: str
|
|
|
|
class GetPlaceDetailsTool(BaseTool):
|
|
name: str = "Get details of a place tool"
|
|
description: str = """Get detailed information about a place based on the fsq_id (foursquare id), including:
|
|
description, phone, website, social media, hours, popular hours, rating (out of 10),
|
|
price, menu, top photos, top tips (mini-reviews from users), top tastes, and features
|
|
such as takes reservations."""
|
|
args_schema: Type[BaseModel] = PlaceDetailsSchema
|
|
|
|
def _run(self, id: str):
|
|
params = {
|
|
"fields": "name,description,location,distance,tel,email,website"
|
|
}
|
|
return submit_request(f"/places/{id}", params)
|
|
|
|
class GetUserLocationTool(BaseTool):
|
|
name: str = "Get user location tool"
|
|
description: str = """Get user's location. Returns latitude and longitude, or else reports it could not find location. Tries to guess
|
|
user's location based on ip address. Useful if the user has not provided their own precise location."""
|
|
|
|
def _run(self):
|
|
location = geocoder.ip('me')
|
|
if not location.ok:
|
|
return "I don't know where you are"
|
|
return f"{location.lat},{location.lng}"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
tool = GetUserLocationTool()
|
|
result = tool._run()
|
|
print("Result: ", result) |