mashrur950 commited on
Commit
18f4b6b
Β·
1 Parent(s): a7365ce

Add reverse geocoding functionality and enhance driver details retrieval with location information

Browse files
chat/geocoding.py CHANGED
@@ -126,6 +126,105 @@ class GeocodingService:
126
  "confidence": "low (mock - default)"
127
  }
128
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  def get_status(self) -> str:
130
  """Get geocoding service status"""
131
  if self.use_mock:
 
126
  "confidence": "low (mock - default)"
127
  }
128
 
129
+ def reverse_geocode(self, lat: float, lng: float) -> Dict:
130
+ """
131
+ Reverse geocode coordinates to address
132
+
133
+ Args:
134
+ lat: Latitude
135
+ lng: Longitude
136
+
137
+ Returns:
138
+ Dict with keys: address, city, state, country, formatted_address
139
+ """
140
+ if self.use_mock:
141
+ return self._reverse_geocode_mock(lat, lng)
142
+ else:
143
+ try:
144
+ return self._reverse_geocode_google(lat, lng)
145
+ except Exception as e:
146
+ logger.error(f"Google Maps reverse geocoding failed: {e}, falling back to mock")
147
+ return self._reverse_geocode_mock(lat, lng)
148
+
149
+ def _reverse_geocode_google(self, lat: float, lng: float) -> Dict:
150
+ """Real Google Maps API reverse geocoding"""
151
+ try:
152
+ # Call Google Maps Reverse Geocoding API
153
+ result = self.gmaps_client.reverse_geocode((lat, lng))
154
+
155
+ if not result:
156
+ logger.warning(f"Google Maps API found no results for: ({lat}, {lng})")
157
+ return self._reverse_geocode_mock(lat, lng)
158
+
159
+ # Get first result
160
+ first_result = result[0]
161
+
162
+ # Extract address components
163
+ address_components = first_result.get('address_components', [])
164
+ city = ""
165
+ state = ""
166
+ country = ""
167
+
168
+ for component in address_components:
169
+ types = component.get('types', [])
170
+ if 'locality' in types:
171
+ city = component.get('long_name', '')
172
+ elif 'administrative_area_level_1' in types:
173
+ state = component.get('short_name', '')
174
+ elif 'country' in types:
175
+ country = component.get('long_name', '')
176
+
177
+ return {
178
+ "address": first_result.get('formatted_address', f"{lat}, {lng}"),
179
+ "city": city,
180
+ "state": state,
181
+ "country": country,
182
+ "formatted_address": first_result.get('formatted_address', f"{lat}, {lng}"),
183
+ "confidence": "high (Google Maps API)"
184
+ }
185
+
186
+ except Exception as e:
187
+ logger.error(f"Google Maps reverse geocoding error: {e}")
188
+ raise
189
+
190
+ def _reverse_geocode_mock(self, lat: float, lng: float) -> Dict:
191
+ """
192
+ Mock reverse geocoding
193
+ Tries to match coordinates to known cities
194
+ """
195
+ # Find closest city
196
+ min_distance = float('inf')
197
+ closest_city = "Unknown Location"
198
+
199
+ for city, coords in CITY_COORDINATES.items():
200
+ # Simple distance calculation
201
+ distance = ((lat - coords[0]) ** 2 + (lng - coords[1]) ** 2) ** 0.5
202
+ if distance < min_distance:
203
+ min_distance = distance
204
+ closest_city = city
205
+
206
+ # If very close to a known city (within ~0.1 degrees, roughly 11km)
207
+ if min_distance < 0.1:
208
+ logger.info(f"Mock reverse geocoding: Matched to {closest_city}")
209
+ return {
210
+ "address": f"Near {closest_city.title()}",
211
+ "city": closest_city.title(),
212
+ "state": "CA" if "san francisco" in closest_city or "la" in closest_city else "",
213
+ "country": "USA",
214
+ "formatted_address": f"Near {closest_city.title()}, USA",
215
+ "confidence": f"medium (mock - near {closest_city})"
216
+ }
217
+ else:
218
+ logger.info(f"Mock reverse geocoding: Unknown location at ({lat}, {lng})")
219
+ return {
220
+ "address": f"{lat}, {lng}",
221
+ "city": "",
222
+ "state": "",
223
+ "country": "",
224
+ "formatted_address": f"Coordinates: {lat}, {lng}",
225
+ "confidence": "low (mock - no match)"
226
+ }
227
+
228
  def get_status(self) -> str:
229
  """Get geocoding service status"""
230
  if self.use_mock:
chat/providers/gemini_provider.py CHANGED
@@ -104,7 +104,7 @@ You: [geocode_address] β†’ "OK geocoded, now creating..." ❌ WRONG!
104
  **Driver Querying (INTERACTIVE):**
105
  - count_drivers: Count drivers with optional filters
106
  - fetch_drivers: Fetch N drivers with pagination and filters
107
- - get_driver_details: Get complete info about specific driver by ID
108
  - search_drivers: Search by name/email/phone/plate/driver ID
109
  - get_available_drivers: Get all active/offline drivers ready for dispatch
110
 
@@ -501,7 +501,7 @@ You: [get_driver_details with driver_id=DRV-20251114163800] β†’ [Display complet
501
  ),
502
  genai.protos.FunctionDeclaration(
503
  name="get_driver_details",
504
- description="Get complete details of a specific driver by driver ID. Use when user asks 'tell me about driver X' or wants detailed information about a specific driver.",
505
  parameters=genai.protos.Schema(
506
  type=genai.protos.Type.OBJECT,
507
  properties={
 
104
  **Driver Querying (INTERACTIVE):**
105
  - count_drivers: Count drivers with optional filters
106
  - fetch_drivers: Fetch N drivers with pagination and filters
107
+ - get_driver_details: Get complete info about specific driver by ID (includes current location with latitude, longitude, and human-readable address)
108
  - search_drivers: Search by name/email/phone/plate/driver ID
109
  - get_available_drivers: Get all active/offline drivers ready for dispatch
110
 
 
501
  ),
502
  genai.protos.FunctionDeclaration(
503
  name="get_driver_details",
504
+ description="Get complete details of a specific driver by driver ID, including current location (latitude, longitude, and human-readable address), contact info, vehicle details, status, and skills. Use when user asks about a driver's location, coordinates, position, or any other driver information.",
505
  parameters=genai.protos.Schema(
506
  type=genai.protos.Type.OBJECT,
507
  properties={
chat/tools.py CHANGED
@@ -336,7 +336,7 @@ TOOLS_SCHEMA = [
336
  },
337
  {
338
  "name": "get_driver_details",
339
- "description": "Get complete details of a specific driver by driver ID. Use when user asks 'tell me about driver X' or wants detailed information about a specific driver.",
340
  "input_schema": {
341
  "type": "object",
342
  "properties": {
@@ -1866,6 +1866,22 @@ def handle_get_driver_details(tool_input: dict) -> dict:
1866
  except:
1867
  skills = []
1868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1869
  driver = {
1870
  "driver_id": row['driver_id'],
1871
  "name": row['name'],
@@ -1876,6 +1892,7 @@ def handle_get_driver_details(tool_input: dict) -> dict:
1876
  "location": {
1877
  "latitude": float(row['current_lat']) if row['current_lat'] else None,
1878
  "longitude": float(row['current_lng']) if row['current_lng'] else None,
 
1879
  "last_update": str(row['last_location_update']) if row['last_location_update'] else None
1880
  },
1881
  "status": row['status'],
 
336
  },
337
  {
338
  "name": "get_driver_details",
339
+ "description": "Get complete details of a specific driver by driver ID, including current location (latitude, longitude, and human-readable address), contact info, vehicle details, status, and skills. Use when user asks about a driver's location, coordinates, position, or any other driver information.",
340
  "input_schema": {
341
  "type": "object",
342
  "properties": {
 
1866
  except:
1867
  skills = []
1868
 
1869
+ # Reverse geocode location to get address
1870
+ location_address = None
1871
+ if row['current_lat'] and row['current_lng']:
1872
+ try:
1873
+ from chat.geocoding import GeocodingService
1874
+ geocoding_service = GeocodingService()
1875
+ reverse_result = geocoding_service.reverse_geocode(
1876
+ float(row['current_lat']),
1877
+ float(row['current_lng'])
1878
+ )
1879
+ location_address = reverse_result.get('formatted_address', None)
1880
+ logger.info(f"Reverse geocoded driver location: {location_address}")
1881
+ except Exception as e:
1882
+ logger.warning(f"Failed to reverse geocode driver location: {e}")
1883
+ location_address = None
1884
+
1885
  driver = {
1886
  "driver_id": row['driver_id'],
1887
  "name": row['name'],
 
1892
  "location": {
1893
  "latitude": float(row['current_lat']) if row['current_lat'] else None,
1894
  "longitude": float(row['current_lng']) if row['current_lng'] else None,
1895
+ "address": location_address,
1896
  "last_update": str(row['last_location_update']) if row['last_location_update'] else None
1897
  },
1898
  "status": row['status'],