Relax V4 scan timeout and trim output
This commit is contained in:
+3
-2
@@ -133,10 +133,11 @@ POLYWEATHER_SCAN_AI_ENABLED=false
|
|||||||
POLYWEATHER_DEEPSEEK_API_KEY=
|
POLYWEATHER_DEEPSEEK_API_KEY=
|
||||||
POLYWEATHER_DEEPSEEK_BASE_URL=https://api.deepseek.com
|
POLYWEATHER_DEEPSEEK_BASE_URL=https://api.deepseek.com
|
||||||
POLYWEATHER_SCAN_AI_MODEL=deepseek-v4-flash
|
POLYWEATHER_SCAN_AI_MODEL=deepseek-v4-flash
|
||||||
POLYWEATHER_SCAN_AI_TIMEOUT_SEC=12
|
POLYWEATHER_SCAN_AI_TIMEOUT_SEC=40
|
||||||
POLYWEATHER_SCAN_AI_CACHE_TTL_SEC=600
|
POLYWEATHER_SCAN_AI_CACHE_TTL_SEC=600
|
||||||
POLYWEATHER_SCAN_AI_MAX_ROWS=40
|
POLYWEATHER_SCAN_AI_MAX_ROWS=40
|
||||||
POLYWEATHER_SCAN_AI_PROXY_TIMEOUT_MS=18000
|
POLYWEATHER_SCAN_AI_MAX_TOKENS=1600
|
||||||
|
POLYWEATHER_SCAN_AI_PROXY_TIMEOUT_MS=45000
|
||||||
POLYWEATHER_PREWARM_CITIES=ankara,istanbul,shanghai,beijing,shenzhen,guangzhou,wuhan,chengdu,chongqing,hong kong,taipei,singapore,tokyo,seoul,busan,london,paris,madrid
|
POLYWEATHER_PREWARM_CITIES=ankara,istanbul,shanghai,beijing,shenzhen,guangzhou,wuhan,chengdu,chongqing,hong kong,taipei,singapore,tokyo,seoul,busan,london,paris,madrid
|
||||||
|
|
||||||
# Weekly reward / leaderboard
|
# Weekly reward / leaderboard
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ import {
|
|||||||
} from "@/lib/backend-auth";
|
} from "@/lib/backend-auth";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
const SCAN_AI_PROXY_TIMEOUT_MS = Number(
|
const SCAN_AI_PROXY_TIMEOUT_MS = Math.max(
|
||||||
process.env.POLYWEATHER_SCAN_AI_PROXY_TIMEOUT_MS || "18000",
|
35_000,
|
||||||
|
Number(process.env.POLYWEATHER_SCAN_AI_PROXY_TIMEOUT_MS || "45000") || 45_000,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
export const maxDuration = 20;
|
export const maxDuration = 60;
|
||||||
|
|
||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
if (!API_BASE) {
|
if (!API_BASE) {
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ SCAN_AI_ENABLED = str(
|
|||||||
os.getenv("POLYWEATHER_SCAN_AI_ENABLED") or "false"
|
os.getenv("POLYWEATHER_SCAN_AI_ENABLED") or "false"
|
||||||
).strip().lower() in {"1", "true", "yes", "on"}
|
).strip().lower() in {"1", "true", "yes", "on"}
|
||||||
SCAN_AI_TIMEOUT_SEC = max(
|
SCAN_AI_TIMEOUT_SEC = max(
|
||||||
3,
|
30,
|
||||||
int(os.getenv("POLYWEATHER_SCAN_AI_TIMEOUT_SEC", "12")),
|
int(os.getenv("POLYWEATHER_SCAN_AI_TIMEOUT_SEC", "40")),
|
||||||
)
|
)
|
||||||
SCAN_AI_CACHE_TTL_SEC = max(
|
SCAN_AI_CACHE_TTL_SEC = max(
|
||||||
30,
|
30,
|
||||||
@@ -50,6 +50,10 @@ SCAN_AI_MAX_ROWS = max(
|
|||||||
1,
|
1,
|
||||||
int(os.getenv("POLYWEATHER_SCAN_AI_MAX_ROWS", "40")),
|
int(os.getenv("POLYWEATHER_SCAN_AI_MAX_ROWS", "40")),
|
||||||
)
|
)
|
||||||
|
SCAN_AI_MAX_TOKENS = max(
|
||||||
|
600,
|
||||||
|
int(os.getenv("POLYWEATHER_SCAN_AI_MAX_TOKENS", "1600")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _safe_float(value: Any) -> Optional[float]:
|
def _safe_float(value: Any) -> Optional[float]:
|
||||||
@@ -490,11 +494,19 @@ def _call_deepseek_scan_ai(ai_input: Dict[str, Any]) -> Dict[str, Any]:
|
|||||||
"city_theses items need city, thesis_zh, thesis_en, model_cluster_note, confidence, "
|
"city_theses items need city, thesis_zh, thesis_en, model_cluster_note, confidence, "
|
||||||
"recommended_row_ids, vetoed_row_ids. recommendations items need row_id, rank, decision, "
|
"recommended_row_ids, vetoed_row_ids. recommendations items need row_id, rank, decision, "
|
||||||
"confidence, reason_zh, reason_en, model_cluster_note. vetoed/downgraded items need row_id, "
|
"confidence, reason_zh, reason_en, model_cluster_note. vetoed/downgraded items need row_id, "
|
||||||
"reason_zh/reason_en. watchlist items are optional and need row_id plus reason."
|
"reason_zh/reason_en. watchlist items are optional and need row_id plus reason. "
|
||||||
|
"Keep every thesis and reason concise: one sentence only, no markdown, no repeated data tables."
|
||||||
),
|
),
|
||||||
"snapshot": model_snapshot,
|
"snapshot": model_snapshot,
|
||||||
}
|
}
|
||||||
with httpx.Client(timeout=float(SCAN_AI_TIMEOUT_SEC)) as client:
|
timeout = httpx.Timeout(
|
||||||
|
timeout=float(SCAN_AI_TIMEOUT_SEC),
|
||||||
|
connect=min(8.0, float(SCAN_AI_TIMEOUT_SEC)),
|
||||||
|
read=float(SCAN_AI_TIMEOUT_SEC),
|
||||||
|
write=10.0,
|
||||||
|
pool=5.0,
|
||||||
|
)
|
||||||
|
with httpx.Client(timeout=timeout) as client:
|
||||||
response = client.post(
|
response = client.post(
|
||||||
f"{SCAN_AI_BASE_URL}/chat/completions",
|
f"{SCAN_AI_BASE_URL}/chat/completions",
|
||||||
headers={
|
headers={
|
||||||
@@ -504,7 +516,7 @@ def _call_deepseek_scan_ai(ai_input: Dict[str, Any]) -> Dict[str, Any]:
|
|||||||
json={
|
json={
|
||||||
"model": SCAN_AI_MODEL,
|
"model": SCAN_AI_MODEL,
|
||||||
"temperature": 0.1,
|
"temperature": 0.1,
|
||||||
"max_tokens": 2200,
|
"max_tokens": SCAN_AI_MAX_TOKENS,
|
||||||
"response_format": {"type": "json_object"},
|
"response_format": {"type": "json_object"},
|
||||||
"messages": [
|
"messages": [
|
||||||
{"role": "system", "content": system_prompt},
|
{"role": "system", "content": system_prompt},
|
||||||
@@ -1182,6 +1194,21 @@ def build_scan_terminal_ai_payload(
|
|||||||
duration_ms=duration_ms,
|
duration_ms=duration_ms,
|
||||||
input_rows=len(payload.get("rows") or []),
|
input_rows=len(payload.get("rows") or []),
|
||||||
)
|
)
|
||||||
|
except httpx.TimeoutException as exc:
|
||||||
|
duration_ms = int((time.time() - ai_started_at) * 1000)
|
||||||
|
reason = f"V4 provider timed out after {SCAN_AI_TIMEOUT_SEC}s"
|
||||||
|
logger.warning(
|
||||||
|
"scan terminal AI review timeout snapshot={} duration_ms={} error={}",
|
||||||
|
current_snapshot_id,
|
||||||
|
duration_ms,
|
||||||
|
exc,
|
||||||
|
)
|
||||||
|
return _build_scan_ai_unavailable_payload(
|
||||||
|
payload,
|
||||||
|
status="timeout",
|
||||||
|
reason=reason,
|
||||||
|
duration_ms=duration_ms,
|
||||||
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
duration_ms = int((time.time() - ai_started_at) * 1000)
|
duration_ms = int((time.time() - ai_started_at) * 1000)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
|||||||
Reference in New Issue
Block a user