tkadkghdlf commited on
Commit
2ac8680
ยท
verified ยท
1 Parent(s): 8b846cd

Sync from GitHub via hub-sync

Browse files
api/ai-service/app/api/v1/endpoints/route_generation.py CHANGED
@@ -499,8 +499,8 @@ def generate_routes(payload: RouteGenerateRequest) -> dict[str, Any]:
499
  raise
500
  except Exception as exc:
501
  raise HTTPException(
502
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
503
- detail=f"OSM-CLIP execution failed: {exc}",
504
  ) from exc
505
 
506
  if not isinstance(result, dict):
 
499
  raise
500
  except Exception as exc:
501
  raise HTTPException(
502
+ status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
503
+ detail="๊ฒฝ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด ์ฃผ์„ธ์š”.",
504
  ) from exc
505
 
506
  if not isinstance(result, dict):
router/ai/scripts/clip_osm_region_test.py CHANGED
@@ -7,7 +7,7 @@ import random
7
  import threading
8
  import time
9
  from pathlib import Path
10
- from typing import Any
11
 
12
  import torch
13
  import cv2
@@ -143,6 +143,7 @@ LABEL_PROMPTS = {
143
  }
144
 
145
  _CACHE_LOCK = threading.Lock()
 
146
  _MODEL_CACHE: dict[str, tuple[CLIPModel, CLIPProcessor]] = {}
147
  _IMAGE_PROTO_CACHE: dict[tuple[str, str, str, tuple[str, ...]], torch.Tensor] = {}
148
  _TEXT_PROTO_CACHE: dict[tuple[str, str, str, tuple[str, ...]], torch.Tensor] = {}
@@ -155,6 +156,35 @@ _GRAPH_CACHE: dict[tuple[Any, ...], tuple[float, nx.MultiDiGraph, str]] = {}
155
  GRAPH_CACHE_TTL_SECONDS = 30 * 60
156
  GRAPH_CACHE_MAX_ENTRIES = 12
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
  def _normalize_place_for_cache(place: str) -> str:
160
  return " ".join(place.strip().lower().split())
@@ -218,11 +248,13 @@ def _build_or_get_walk_graph(
218
  if cached is not None:
219
  return cached
220
 
221
- graph = ox.graph_from_point(
222
- (center_lat, center_lon),
223
- dist=dist_m,
224
- network_type="walk",
225
- simplify=True,
 
 
226
  )
227
  location_name = f"{center_lat:.6f},{center_lon:.6f}"
228
  _set_cached_graph(cache_key, graph, location_name)
@@ -279,16 +311,24 @@ def _build_or_get_walk_graph(
279
  geocode_errors.append(f"{query}: {exc}")
280
 
281
  if lat_lon is not None:
282
- graph = ox.graph_from_point(
283
- lat_lon,
284
- dist=dist_m,
285
- network_type="walk",
286
- simplify=True,
 
 
287
  )
288
  location_name = place
289
  else:
290
  try:
291
- graph = ox.graph_from_place(place, network_type="walk", simplify=True)
 
 
 
 
 
 
292
  location_name = place
293
  except Exception as exc:
294
  detail = " | ".join(geocode_errors + [f"graph_from_place: {exc}"])
 
7
  import threading
8
  import time
9
  from pathlib import Path
10
+ from typing import Any, Callable
11
 
12
  import torch
13
  import cv2
 
143
  }
144
 
145
  _CACHE_LOCK = threading.Lock()
146
+ _OVERPASS_SETTINGS_LOCK = threading.Lock()
147
  _MODEL_CACHE: dict[str, tuple[CLIPModel, CLIPProcessor]] = {}
148
  _IMAGE_PROTO_CACHE: dict[tuple[str, str, str, tuple[str, ...]], torch.Tensor] = {}
149
  _TEXT_PROTO_CACHE: dict[tuple[str, str, str, tuple[str, ...]], torch.Tensor] = {}
 
156
  GRAPH_CACHE_TTL_SECONDS = 30 * 60
157
  GRAPH_CACHE_MAX_ENTRIES = 12
158
 
159
+ # Public Overpass instances occasionally reject requests from a deployment
160
+ # network. OSMnx appends `/interpreter`, so these are API base URLs.
161
+ OVERPASS_API_BASE_URLS = (
162
+ "https://overpass-api.de/api",
163
+ "https://overpass.private.coffee/api",
164
+ )
165
+
166
+
167
+ def _load_walk_graph_with_overpass_fallback(
168
+ loader: Callable[[], nx.MultiDiGraph],
169
+ ) -> nx.MultiDiGraph:
170
+ """Load an OSM graph with a deterministic secondary Overpass endpoint."""
171
+ errors: list[str] = []
172
+ # osmnx.settings is process-global, therefore changing the endpoint must
173
+ # not overlap another request handled by the AI service.
174
+ with _OVERPASS_SETTINGS_LOCK:
175
+ original_url = ox.settings.overpass_url
176
+ try:
177
+ for base_url in OVERPASS_API_BASE_URLS:
178
+ try:
179
+ ox.settings.overpass_url = base_url
180
+ return loader()
181
+ except Exception as exc:
182
+ errors.append(f"{base_url}: {exc}")
183
+ finally:
184
+ ox.settings.overpass_url = original_url
185
+
186
+ raise RuntimeError("All Overpass endpoints failed. " + " | ".join(errors))
187
+
188
 
189
  def _normalize_place_for_cache(place: str) -> str:
190
  return " ".join(place.strip().lower().split())
 
248
  if cached is not None:
249
  return cached
250
 
251
+ graph = _load_walk_graph_with_overpass_fallback(
252
+ lambda: ox.graph_from_point(
253
+ (center_lat, center_lon),
254
+ dist=dist_m,
255
+ network_type="walk",
256
+ simplify=True,
257
+ )
258
  )
259
  location_name = f"{center_lat:.6f},{center_lon:.6f}"
260
  _set_cached_graph(cache_key, graph, location_name)
 
311
  geocode_errors.append(f"{query}: {exc}")
312
 
313
  if lat_lon is not None:
314
+ graph = _load_walk_graph_with_overpass_fallback(
315
+ lambda: ox.graph_from_point(
316
+ lat_lon,
317
+ dist=dist_m,
318
+ network_type="walk",
319
+ simplify=True,
320
+ )
321
  )
322
  location_name = place
323
  else:
324
  try:
325
+ graph = _load_walk_graph_with_overpass_fallback(
326
+ lambda: ox.graph_from_place(
327
+ place,
328
+ network_type="walk",
329
+ simplify=True,
330
+ )
331
+ )
332
  location_name = place
333
  except Exception as exc:
334
  detail = " | ".join(geocode_errors + [f"graph_from_place: {exc}"])