Spaces:
Sleeping
Sleeping
Upload 21 files
Browse files
app.py
CHANGED
|
@@ -86,11 +86,22 @@ MATCHING_RESULT_CACHE_LOCK = threading.Lock()
|
|
| 86 |
MATCHING_RESULT_CACHE_MAX = int(os.getenv("MATCHING_RESULT_CACHE_MAX", "500"))
|
| 87 |
MATCHING_RESULT_CACHE_TTL_SECONDS = int(os.getenv("MATCHING_RESULT_CACHE_TTL_SECONDS", "86400"))
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
def _matching_cache_storage_key(key: str) -> str:
|
| 91 |
return f"matching:{key}"
|
| 92 |
|
| 93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
def _normalize_cache_category(value: Any) -> str:
|
| 95 |
category = _norm(value)
|
| 96 |
if category in {"topwear", "bottomwear", "others"}:
|
|
@@ -3186,8 +3197,24 @@ def scraper_recommend(payload: dict[str, Any] = Body(default_factory=dict)) -> d
|
|
| 3186 |
if isinstance(max_products, int) and max_products < 1:
|
| 3187 |
raise HTTPException(status_code=400, detail="max_products must be at least 1")
|
| 3188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3189 |
try:
|
| 3190 |
-
|
| 3191 |
occasion=occasion,
|
| 3192 |
gender=gender,
|
| 3193 |
preferences=preferences,
|
|
@@ -3196,8 +3223,12 @@ def scraper_recommend(payload: dict[str, Any] = Body(default_factory=dict)) -> d
|
|
| 3196 |
filters=filters,
|
| 3197 |
max_products=max_products,
|
| 3198 |
store=store,
|
| 3199 |
-
strict_kimi=
|
| 3200 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3201 |
except NvidiaGatewayError as exc:
|
| 3202 |
raise HTTPException(status_code=502, detail=str(exc)) from exc
|
| 3203 |
except NvidiaPayloadError as exc:
|
|
|
|
| 86 |
MATCHING_RESULT_CACHE_MAX = int(os.getenv("MATCHING_RESULT_CACHE_MAX", "500"))
|
| 87 |
MATCHING_RESULT_CACHE_TTL_SECONDS = int(os.getenv("MATCHING_RESULT_CACHE_TTL_SECONDS", "86400"))
|
| 88 |
|
| 89 |
+
SCRAPER_QUERY_CACHE: dict[str, tuple[dict[str, Any], float]] = {}
|
| 90 |
+
SCRAPER_QUERY_CACHE_LOCK = threading.Lock()
|
| 91 |
+
SCRAPER_QUERY_CACHE_TTL_SECONDS = int(os.getenv("SCRAPER_QUERY_CACHE_TTL_SECONDS", "1296000")) # 15 days
|
| 92 |
+
|
| 93 |
|
| 94 |
def _matching_cache_storage_key(key: str) -> str:
|
| 95 |
return f"matching:{key}"
|
| 96 |
|
| 97 |
|
| 98 |
+
def _scraper_cache_key(user_prompt: str, store: str, gender: str, target_category: str) -> str:
|
| 99 |
+
"""Create deterministic cache key for scraper queries"""
|
| 100 |
+
import hashlib
|
| 101 |
+
key_str = f"{user_prompt.lower().strip()}|{store}|{gender}|{target_category}"
|
| 102 |
+
return hashlib.md5(key_str.encode()).hexdigest()
|
| 103 |
+
|
| 104 |
+
|
| 105 |
def _normalize_cache_category(value: Any) -> str:
|
| 106 |
category = _norm(value)
|
| 107 |
if category in {"topwear", "bottomwear", "others"}:
|
|
|
|
| 3197 |
if isinstance(max_products, int) and max_products < 1:
|
| 3198 |
raise HTTPException(status_code=400, detail="max_products must be at least 1")
|
| 3199 |
|
| 3200 |
+
# Check cache first for faster repeat queries
|
| 3201 |
+
cache_key = _scraper_cache_key(user_prompt, store, gender, target_category)
|
| 3202 |
+
with SCRAPER_QUERY_CACHE_LOCK:
|
| 3203 |
+
if cache_key in SCRAPER_QUERY_CACHE:
|
| 3204 |
+
cached_result, cached_timestamp = SCRAPER_QUERY_CACHE[cache_key]
|
| 3205 |
+
if time.time() - cached_timestamp < SCRAPER_QUERY_CACHE_TTL_SECONDS:
|
| 3206 |
+
print(f"[CACHE HIT] Returning cached scraper results for: {user_prompt[:50]}...")
|
| 3207 |
+
return cached_result
|
| 3208 |
+
# Clean up expired cache entries
|
| 3209 |
+
expired_keys = [
|
| 3210 |
+
k for k, (_, ts) in SCRAPER_QUERY_CACHE.items()
|
| 3211 |
+
if time.time() - ts >= SCRAPER_QUERY_CACHE_TTL_SECONDS
|
| 3212 |
+
]
|
| 3213 |
+
for k in expired_keys:
|
| 3214 |
+
del SCRAPER_QUERY_CACHE[k]
|
| 3215 |
+
|
| 3216 |
try:
|
| 3217 |
+
result = _generate_scraper_plan_with_kimi(
|
| 3218 |
occasion=occasion,
|
| 3219 |
gender=gender,
|
| 3220 |
preferences=preferences,
|
|
|
|
| 3223 |
filters=filters,
|
| 3224 |
max_products=max_products,
|
| 3225 |
store=store,
|
| 3226 |
+
strict_kimi=False,
|
| 3227 |
)
|
| 3228 |
+
# Cache the result
|
| 3229 |
+
with SCRAPER_QUERY_CACHE_LOCK:
|
| 3230 |
+
SCRAPER_QUERY_CACHE[cache_key] = (result, time.time())
|
| 3231 |
+
return result
|
| 3232 |
except NvidiaGatewayError as exc:
|
| 3233 |
raise HTTPException(status_code=502, detail=str(exc)) from exc
|
| 3234 |
except NvidiaPayloadError as exc:
|