延長競價摘要快取並在更新後失效
This commit is contained in:
@@ -320,7 +320,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
|
||||
# ==========================================
|
||||
# 系統版本與路徑
|
||||
# ==========================================
|
||||
SYSTEM_VERSION = "V10.277"
|
||||
SYSTEM_VERSION = "V10.278"
|
||||
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
|
||||
public_url = PUBLIC_URL # 用於模板顯示
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **最後更新**: 2026-05-19 (台北時間)
|
||||
> **狀態**: 🟢 四 AI Agent 自動化閉環已落地;LLM 路由紅線升級為 Ollama-first 三主機級聯,Gemini 僅備援 / 鎖定場景
|
||||
> **適用版本**: V10.277
|
||||
> **適用版本**: V10.278
|
||||
|
||||
---
|
||||
|
||||
@@ -52,7 +52,7 @@ SQL漏斗(~300筆)
|
||||
- 配對來源仍以 PChome crawler 真實搜尋結果為準;無競品資料時不生成挑品。
|
||||
- 比對覆蓋率補強入口:`POST /api/ai/pchome-match/backfill`,優先補抓仍無有效 PChome 配對的高價 ACTIVE 商品,完成後自動重算 AI 挑品清單。
|
||||
- 排程閉環:`run_pchome_match_backfill_task` 每日 10:30 執行,補抓 PChome 待比對商品、寫入歷史價格,再重算 `strategy='product_pick'` 清單。
|
||||
- PChome / MOMO 競價摘要出口 `services/competitor_intel_repository.py` 使用 5 分鐘共享快取(`COMPETITOR_INTEL_CACHE_TTL_SECONDS` 可調),避免 `/growth_analysis`、`/daily_sales`、PPT/AI 報表每次請求重跑昂貴覆蓋率與價差趨勢查詢;快取只包摘要輸出,不改 matcher 的高信心門檻與 identity_v2 準確性規則。
|
||||
- PChome / MOMO 競價摘要出口 `services/competitor_intel_repository.py` 使用 30 分鐘共享快取(`COMPETITOR_INTEL_CACHE_TTL_SECONDS` 可調),避免 `/growth_analysis`、`/daily_sales`、PPT/AI 報表每次請求重跑昂貴覆蓋率與價差趨勢查詢;`run_competitor_price_feeder_task` 與 PChome backfill 完成後會主動清除快取。快取只包摘要輸出,不改 matcher 的高信心門檻與 identity_v2 準確性規則。
|
||||
- 商品看板第一屏:`/` 的 V2 看板直接以 `products`、`price_records`、`competitor_prices`、`ai_price_recommendations` 顯示比對覆蓋率、PChome 優勢、MOMO 威脅、AI 挑品與待比對優先清單;`filter=ai_picks` 可查看 50 品 AI 挑品列表,並在列表上方顯示平均信心、平均價差、最大價差與估算總價差空間,列表列內顯示 AI 排名與建議理由,且可透過 `/api/export/excel/ai-picks` 匯出 50 品 Excel 操作清單。商品看板深度快取同時寫入 `data/dashboard_full_cache.pkl`,供多個 Gunicorn worker 共用,避免部署後各 worker 重複重建 7,000+ 商品統計造成開頁變慢;所有資料異動與 AI 挑品重算都透過 `clear_dashboard_cache()` 同步清除記憶體與共享快取,手動重算 API 會立即預熱商品看板快取,避免第一位使用者承擔重建成本。
|
||||
|
||||
| 角色 | 模型 | 主機 | 成本 | 每日限額 |
|
||||
|
||||
@@ -1719,6 +1719,7 @@ def api_pchome_match_backfill():
|
||||
from config import DATABASE_PATH
|
||||
from sqlalchemy import create_engine
|
||||
from services.ai_product_pick_agent import generate_product_pick_list
|
||||
from services.competitor_intel_repository import clear_competitor_intel_cache
|
||||
from services.competitor_price_feeder import CompetitorPriceFeeder
|
||||
|
||||
engine = create_engine(DATABASE_PATH)
|
||||
@@ -1726,6 +1727,7 @@ def api_pchome_match_backfill():
|
||||
pick_result = generate_product_pick_list(engine, limit=50)
|
||||
from services.cache_manager import clear_dashboard_cache
|
||||
clear_dashboard_cache()
|
||||
clear_competitor_intel_cache()
|
||||
logger.info(
|
||||
"[PChomeBackfill] done total=%s matched=%s no=%s low=%s errors=%s history=%s duration=%ss pick_written=%s",
|
||||
result.total_skus,
|
||||
|
||||
@@ -2131,6 +2131,7 @@ def run_competitor_price_feeder_task():
|
||||
try:
|
||||
from config import DATABASE_PATH
|
||||
from sqlalchemy import create_engine
|
||||
from services.competitor_intel_repository import clear_competitor_intel_cache
|
||||
from services.competitor_price_feeder import CompetitorPriceFeeder
|
||||
|
||||
now_str = datetime.now(TAIPEI_TZ).strftime('%Y-%m-%d %H:%M')
|
||||
@@ -2159,6 +2160,7 @@ def run_competitor_price_feeder_task():
|
||||
f"errors={result.errors} "
|
||||
f"耗時={result.duration_sec}s"
|
||||
)
|
||||
clear_competitor_intel_cache()
|
||||
_save_stats('competitor_price_feeder', stats)
|
||||
|
||||
except Exception as e:
|
||||
@@ -2191,6 +2193,7 @@ def run_pchome_match_backfill_task():
|
||||
from sqlalchemy import create_engine
|
||||
from services.ai_product_pick_agent import generate_product_pick_list
|
||||
from services.cache_manager import clear_dashboard_cache
|
||||
from services.competitor_intel_repository import clear_competitor_intel_cache
|
||||
from services.competitor_price_feeder import CompetitorPriceFeeder
|
||||
|
||||
now_str = datetime.now(TAIPEI_TZ).strftime('%Y-%m-%d %H:%M')
|
||||
@@ -2200,6 +2203,7 @@ def run_pchome_match_backfill_task():
|
||||
feeder_result = CompetitorPriceFeeder(engine=engine).run_unmatched_priority(limit=120)
|
||||
pick_result = generate_product_pick_list(engine, limit=50)
|
||||
clear_dashboard_cache()
|
||||
clear_competitor_intel_cache()
|
||||
|
||||
stats = {
|
||||
"total_skus": feeder_result.total_skus,
|
||||
|
||||
@@ -22,7 +22,7 @@ from sqlalchemy import inspect, text
|
||||
|
||||
|
||||
PCHOME_MATCH_SCORE_FLOOR = 0.76
|
||||
COMPETITOR_INTEL_CACHE_TTL_SECONDS = int(os.getenv("COMPETITOR_INTEL_CACHE_TTL_SECONDS", "300"))
|
||||
COMPETITOR_INTEL_CACHE_TTL_SECONDS = int(os.getenv("COMPETITOR_INTEL_CACHE_TTL_SECONDS", "1800"))
|
||||
_BASE_DIR = Path(__file__).resolve().parents[1]
|
||||
_CACHE_FILE = _BASE_DIR / "data" / "competitor_intel_cache.pkl"
|
||||
_CACHE_LOCK = Lock()
|
||||
|
||||
Reference in New Issue
Block a user