From d609d3803eeeeece22692e9b2627c4400f846fbf Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Mon, 27 Apr 2026 06:23:09 +0800 Subject: [PATCH] feat: implement scan terminal service with caching and background refresh logic --- tests/test_web_observability.py | 33 +++++++++++++++++++++++++++++++++ web/scan_terminal_service.py | 4 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/test_web_observability.py b/tests/test_web_observability.py index b3aa4d2f..6e951b4a 100644 --- a/tests/test_web_observability.py +++ b/tests/test_web_observability.py @@ -100,6 +100,39 @@ def test_metrics_endpoint_returns_prometheus_payload(): assert 'polyweather_http_requests_total' in response.text +def test_city_ai_fallback_reasoning_says_ai_read_is_normal(): + payload = scan_terminal_service._build_city_ai_fallback( + { + "city_display_name": "Tokyo", + "temp_symbol": "°C", + "deb": {"prediction": 17.8}, + "model_cluster": { + "sources": [ + {"value": 17.0}, + {"value": 17.8}, + {"value": 20.6}, + ] + }, + "observation_anchor": { + "is_airport_metar": True, + "station_code": "RJTT", + }, + "airport_current": { + "station_code": "RJTT", + "temp": 16.0, + "report_time": "21:30Z", + "raw_metar": "RJTT 262130Z AUTO 00000KT 9999 FEW030 16/10 Q1015", + }, + }, + locale="zh-CN", + reason="preview", + ) + + assert "AI 机场报文解读正常" in payload["reasoning_zh"] + assert "后补" not in payload["reasoning_zh"] + assert "AI 增强可作为后续补充" not in payload["reasoning_zh"] + + def test_cities_endpoint_uses_denver_display_name_for_aurora_market(): response = client.get("/api/cities") assert response.status_code == 200 diff --git a/web/scan_terminal_service.py b/web/scan_terminal_service.py index 73c65414..d5c1057c 100644 --- a/web/scan_terminal_service.py +++ b/web/scan_terminal_service.py @@ -653,12 +653,12 @@ def _build_city_ai_fallback( reasoning_zh = str(partial_ai.get("reasoning_zh") or "").strip() or ( f"AI {bulletin_zh}解读已用于校准日内节奏;DEB 与多模型集合继续约束最高温中枢,后续{source_name_zh}用于确认是否需要上调或下修。" if partial_ai - else f"DEB、多模型集合和最新{source_name_zh}已足够给出当前方向判断;AI 增强可作为后续补充,不阻塞本轮读数。" + else f"AI {bulletin_zh}解读正常;当前结合 DEB、多模型集合和最新{source_name_zh},共同支撑本轮最高温中枢判断。" ) reasoning_en = str(partial_ai.get("reasoning_en") or "").strip() or ( f"The AI {bulletin_en} read is already used to calibrate the intraday pace; DEB and the model cluster still constrain the high-temperature center, while later {source_name_en} updates confirm whether to revise it." if partial_ai - else f"DEB, the model cluster and latest {source_name_en} are enough for the current directional read; AI enhancement can be added later without blocking this card." + else f"The AI {bulletin_en} read is available; DEB, the model cluster and latest {source_name_en} jointly support the current daily-high center." ) risks_zh = [f"后续{source_name_zh}若明显偏离模型路径,需及时修正最高温中枢。"] risks_en = [f"If later {source_name_en} updates diverge from the model path, revise the daily-high center promptly."]