Spaces:
Running
Running
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.
|
| 503 |
-
detail=
|
| 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 =
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
| 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 =
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
|
|
|
|
|
|
| 287 |
)
|
| 288 |
location_name = place
|
| 289 |
else:
|
| 290 |
try:
|
| 291 |
-
graph =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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}"])
|