顯示 PChome 單位價候選資訊
All checks were successful
CD Pipeline / deploy (push) Successful in 1m2s

This commit is contained in:
OoO
2026-05-20 00:11:29 +08:00
parent 89c2bc96e4
commit 36c177762f
5 changed files with 12 additions and 5 deletions

View File

@@ -4,7 +4,7 @@
================================================================================
【已完成】
- V10.293 補核心 MOMO/PChome 比價第三層語意:同核心商品但買送、套組、件數不同且只有單一基礎規格時標記 `unit_comparable`,只寫入 `competitor_match_attempts`商品看板顯示「需單位價比較」與單位價換算;多容量/多品項套組仍保持不可比較,避免把不同販售組合直接寫進正式總價差。
- V10.295 補核心 MOMO/PChome 比價第三層語意:同核心商品但買送、套組、件數不同且只有單一基礎規格時標記 `unit_comparable`,只寫入 `competitor_match_attempts`商品看板顯示「需單位價比較」、候選商品、候選 PChome 價格與單位價換算證據;多容量/多品項套組仍保持不可比較,避免把不同販售組合直接寫進正式總價差。
- V10.289 重排 Elephant Alpha L3 HITL `ea_escalation` Telegram 告警:改成專業 incident brief 格式分成決策狀態、背景摘要、風險摘要、TOP 待審 SKU 與建議處置;價格行動會拆出 MOMO/PChome 價格、價差、人工處置與 PChome ID避免長 bullet 難讀。
- V10.284 關閉 Code Review Hermes LLM scan 預設路徑Step 2 改 deterministic fast static scan不再讓部署後先卡三段 Ollama timeout若需要 LLM scan 可用 `CODE_REVIEW_HERMES_LLM_SCAN_ENABLED=true` 顯式開啟,仍只走本地矩陣、不走 Gemini。
- V10.283 將 Code Review Hermes scan 收斂為 fast compact prompt預設 2 檔 × 900 字、輸出 384 tokens仍走 GCP-A → GCP-B → 111 本地矩陣,避免部署後 code_review_hermes 先卡三段 timeout。

View File

@@ -320,7 +320,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
# ==========================================
# 系統版本與路徑
# ==========================================
SYSTEM_VERSION = "V10.294"
SYSTEM_VERSION = "V10.295"
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
public_url = PUBLIC_URL # 用於模板顯示

View File

@@ -1,8 +1,8 @@
# MOMO PRO — AI 競價情報模組 Single Source of Truth
> **最後更新**: 2026-05-19 (台北時間)
> **最後更新**: 2026-05-20 (台北時間)
> **狀態**: 🟢 四 AI Agent 自動化閉環已落地LLM 路由紅線升級為 Ollama-first 三主機級聯Gemini 僅備援 / 鎖定場景
> **適用版本**: V10.293
> **適用版本**: V10.295
---
@@ -345,7 +345,7 @@ LEFT JOIN competitor_prices cp
- `services/competitor_identity_revalidator.py` 可對既有 `competitor_prices` legacy row 離線重跑 `identity_v2`:只有新版 matcher 分數 `>= 0.76` 且無 hard veto 才補 `identity_v2` / `legacy_revalidated` tags預設不刷新 `expires_at`,避免過期價格進入決策。
- `CompetitorPriceFeeder.run_expired_identity_refresh()` 會優先刷新已通過 `identity_v2` 但 TTL 過期的 PChome row直接用既有 `competitor_product_id` 批次呼叫 PChome 商品 API再用新版 matcher 重新驗證名稱/規格/價格 sanity通過後寫回 `competitor_prices``competitor_price_history`。這條路徑提升新鮮價格覆蓋率,但不降低 match threshold也不讓過期價格直接進入決策。
- `marketplace_product_matcher.py` 的擴充只能走「正向證據 + 反向 veto」品牌一致、商品線/型號訊號強、價格合理且無 hard veto 時才允許 `strong_product_line_match` 加分;補充瓶/補充包/refill 與一般正裝不互相配對,分享組/加量組/明星組等組合包不得誤配單品。
- 套組/買送/件數不同但品牌、核心商品線與單一基礎規格一致時matcher 必須回傳 `comparison_mode='unit_comparable'``unit_comparable` reasonFeeder 只能寫入 `competitor_match_attempts.attempt_status='unit_comparable'``refresh_unit_comparable`,不得寫入 `competitor_prices`。Dashboard 與 `competitor_intel_repository` 必須用 `build_unit_price_comparison()` 產生每 ml / 每 g / 每入單位價證據,讓 PPT / AI 報表可說明「需單位價比較」而不是把總價當同款價差。若任一側含多個不同容量/重量規格,視為多品項套組,不可進 `unit_comparable`
- 套組/買送/件數不同但品牌、核心商品線與單一基礎規格一致時matcher 必須回傳 `comparison_mode='unit_comparable'``unit_comparable` reasonFeeder 只能寫入 `competitor_match_attempts.attempt_status='unit_comparable'``refresh_unit_comparable`,不得寫入 `competitor_prices`。Dashboard 與 `competitor_intel_repository` 必須用 `build_unit_price_comparison()` 產生每 ml / 每 g / 每入單位價證據,讓 PPT / AI 報表可說明「需單位價比較」而不是把總價當同款價差。商品看板在正式配對尚未成立時,仍必須顯示最佳候選 PChome 商品名稱、候選價與「候選價,需單位換算」說明,讓人工覆核可直接看見下一步;若任一側含多個不同容量/重量規格,視為多品項套組,不可進 `unit_comparable`
- PChome feeder 的外部 request timeout 由 `PCHOME_FEEDER_TIMEOUT` 控制,預設 12 秒;排程不得因單一 PChome 搜尋 API timeout 被拖到數分鐘。
- 商品看板的 PChome 狀態必須把 matcher 診斷原因翻成可行動語意:品牌衝突、規格衝突、補充包差異、組合差異、商品線不符等,不可只顯示籠統「待比對」或「身份否決」。
- Dashboard 必須把「待比對」拆成可診斷狀態:`價格過期待刷新``舊版配對待重驗``低分配對待審``身份否決``需單位價比較``找不到同款``抓取異常``尚未搜尋`。不可再用單一「待比對」掩蓋資料品質原因。

View File

@@ -361,6 +361,8 @@
</div>
{% if competitor and competitor.product_name %}
<div class="dashboard-product-id momo-mono" title="{{ competitor.product_name }}">PChome{{ competitor.product_name }}</div>
{% elif item.pchome_match_attempt and item.pchome_match_attempt.best_competitor_product_name %}
<div class="dashboard-product-id momo-mono" title="{{ item.pchome_match_attempt.best_competitor_product_name }}">候選:{{ item.pchome_match_attempt.best_competitor_product_name }}</div>
{% endif %}
{% if item.ai_pick %}
<div class="dashboard-product-id momo-mono" title="{{ item.ai_pick.reason }}">
@@ -389,6 +391,9 @@
{% if competitor.match_score %}
<div class="dashboard-price-sub">match {{ (competitor.match_score * 100) | round(0) | int }}%</div>
{% endif %}
{% elif item.pchome_match_attempt and item.pchome_match_attempt.best_competitor_price and match_status.label == '需單位價比較' %}
<div class="dashboard-pchome-price">${{ item.pchome_match_attempt.best_competitor_price | int | number_format }}</div>
<div class="dashboard-price-sub">候選價,需單位換算</div>
{% else %}
<span class="dashboard-muted">{{ match_status.label | default('待比對') }}</span>
{% if match_status.detail %}

View File

@@ -333,6 +333,8 @@ def test_dashboard_v2_shows_pchome_competitor_pricing_and_links():
assert "dashboard-competition-badge" in dashboard
assert "decision.summary" in dashboard
assert "PChome {{ match_status.label" in dashboard
assert "候選:{{ item.pchome_match_attempt.best_competitor_product_name }}" in dashboard
assert "候選價,需單位換算" in dashboard
assert "_load_pchome_match_attempt_map" in route_source
assert "低信心待審" in route_source
assert "規格衝突待審" in route_source