diff --git a/TODO_NEXT_STEPS.txt b/TODO_NEXT_STEPS.txt index ccf3721..588c038 100644 --- a/TODO_NEXT_STEPS.txt +++ b/TODO_NEXT_STEPS.txt @@ -4,6 +4,7 @@ ================================================================================ 【已完成】 + - V10.482 補 exact variant-safe 回收:LUSH 櫻之花身體噴霧 200ml、ARTMIS 金縷梅/蔓越莓私密清潔慕斯 250ml、SO NATURAL FIXX 120ml plain 與 Baan 原味/草莓同 catalog,若雙方同品名、同規格且同明確 variant,移除過度保守的 `variant_selection_review` 並進 `exact / total_price / price_alert_exact`;SO NATURAL 經典款/光澤款/霧面款/夏日款 catalog 對單款 120ml 仍維持人工覆核。Production 已部署 `/health=V10.482`,並只 materialize 5 筆新增 exact-line SKU 到 `rescore_accepted_current`,最新 accepted audit `scanned=94 / gate_pass=94 / still_low=0`。測試:`tests/test_marketplace_product_matcher.py`、`tests/test_competitor_match_attempts_persistence.py`、`tests/test_competitor_match_attempt_rescore_audit.py` 通過。 - V10.481 補 rescore accepted retraction 工具缺口:`--retract-variant-accepted` 不只看舊 row 已存的 `diagnostic_codes`,也會用當前 matcher 重判 latest `rescore_accepted_current`;若新版規則已變成 `variant_selection_review / low_score_current`,會追加退回 `true_low_confidence`,避免舊 accepted queue 殘留不該採用候選。Production 已先保守 materialize 15 筆安全 SKU,再退回 7 筆舊 accepted 變體風險;最終 `rescore_accepted_current=89`,accepted audit `gate_pass=89 / still_low=0`。 - V10.480 依 production accepted-current 風險樣本補安全閘門:rom&nd 零絲絨/果凍唇釉不可被果汁唇釉多款 listing 誤收為同款;Relove 潔淨凝露若一側為傳明酸/淨白活性變體改送 `variant_selection_review`;1990 融燭燈不同設計(歐式可彎 vs 韓風原木底座)改 hard veto。此版先清 accepted queue 風險,再做保守 materialize。 - V10.479 依 production audit 再補二階風險:Cetaphil 修護乳 vs 潔膚露改 hard veto;私密防護慕絲二款可選 vs 單一香型、雪芙蘭滋養霜 vs 單側清爽型改走 `variant_selection_review`,避免仍殘留在 accepted queue。 diff --git a/config.py b/config.py index eba7b94..ee83ca1 100644 --- a/config.py +++ b/config.py @@ -350,7 +350,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.481" +SYSTEM_VERSION = "V10.482" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/memory/current_execution_queue_20260524.md b/docs/memory/current_execution_queue_20260524.md index 2ef64e0..be67c59 100644 --- a/docs/memory/current_execution_queue_20260524.md +++ b/docs/memory/current_execution_queue_20260524.md @@ -33,6 +33,7 @@ - 2026-05-25 19:20 CST 起,`V10.477` 補高分錯配防線:SPF 數值不同直接 veto,MAKE UP FOR EVER 定妝噴霧 vs 活氧水不同線直接 veto;多款任選對單一款與單側色號改送 `variant_selection_review`,涵蓋私密潔浴露、身體去角質、美體乳液與染眉膏等。 - 2026-05-25 21:05 CST 起,`V10.480` 補 accepted-current 風險樣本防線:rom&nd 零絲絨/果凍唇釉 vs 果汁唇釉多款 listing 直接 `romand_lip_line_conflict` hard veto;Relove 潔淨凝露若傳明酸/淨白活性只出現在單側,保留高分但進 `variant_selection_review`;1990 融燭燈不同設計(歐式可彎 vs 韓風原木底座)直接 `selection1990_wax_lamp_design_conflict` hard veto。 - 2026-05-25 21:25 CST 起,`V10.481` 補 rescore accepted retraction 工具缺口:退回工具會用當前 matcher 重判 latest `rescore_accepted_current`,凡新版已變 `variant_selection_review / low_score_current` 的舊 accepted 會追加退回 `true_low_confidence`,避免人工覆核隊列保留舊版安全閘門放行的候選。Production 已部署 `/health=V10.481`;保守 materialize 15 筆安全 SKU 後再退回 7 筆舊 accepted 變體風險,最新 accepted audit 為 `scanned=89 / gate_pass=89 / still_low=0`。 +- 2026-05-25 21:47 CST 起,`V10.482` 補 exact variant-safe 回收:LUSH 櫻之花身體噴霧 200ml、ARTMIS 金縷梅/蔓越莓私密清潔慕斯 250ml、SO NATURAL FIXX 120ml plain 與 Baan 原味/草莓同 catalog,若雙方同品名、同規格且同明確 variant,移除過度保守的 `variant_selection_review` 並進 `exact / total_price / price_alert_exact`;SO NATURAL 經典款/光澤款/霧面款/夏日款 catalog 對單款 120ml 仍維持人工覆核。Production 已部署 `/health=V10.482`,只 materialize 5 筆新增 exact-line SKU 到 `rescore_accepted_current`;latest accepted audit 為 `scanned=94 / gate_pass=94 / still_low=0`,三應用容器 healthy、`momo-db` 未 recreate。 - 2026-05-25 12:05 CST 狀態:`main` 已部署到 188,正式 `/health` 為 `V10.467`,待推 Gitea。兩段變更已合併驗證:V10.466 rescore duplicate 改看 latest-state,7 筆 SKU 最新 attempt 全為 `rescore_accepted_current`,`competitor_prices` / `competitor_price_history` 目標計數未變;V10.467 focused exact matcher 在容器內回 `exact / total_price / price_alert_exact`。本輪 recreate `momo-app`、`scheduler`、`telegram-bot`;未使用 `--remove-orphans`,未碰 `momo-db`。Smoke 通過:三容器 healthy、PChome rescore queue API HTTP 200、Gemini 24 小時無 provider 紀錄、Ollama env 順序維持 GCP-A → GCP-B → 111、3 分鐘三容器 log 未見 Traceback / ERROR / CRITICAL / IntegrityError。 ## 1. MOMO / PChome 核心比價準確率 diff --git a/services/marketplace_product_matcher.py b/services/marketplace_product_matcher.py index 875971e..bc32f19 100644 --- a/services/marketplace_product_matcher.py +++ b/services/marketplace_product_matcher.py @@ -486,6 +486,14 @@ FOCUSED_IDENTITY_REVIEW_ONLY_REASONS = { "the_forest_maple_diffuser_flower_brandless", } +FOCUSED_IDENTITY_VARIANT_REVIEW_BYPASS_REASONS = { + "artmis_cranberry_private_mousse_250ml", + "artmis_witch_hazel_private_mousse_250ml", + "baan_baby_lip_original_strawberry_catalog", + "lush_sakura_body_spray", + "so_natural_fixx_setting_spray_120ml_plain", +} + FOCUSED_IDENTITY_BRANDLESS_REVIEW_REASONS = { "herbacin_classic_hand_cream_20ml_brandless", "muji_aroma_hand_cream_brandless", @@ -504,6 +512,11 @@ FOCUSED_IDENTITY_TOTAL_PRICE_REASONS = { "canmake_tear_bag_palette", "gdesign_aroma_lava_lamp_2", "hooome_classic_white_wax_lamp_bulbs_giftbox", + "artmis_cranberry_private_mousse_250ml", + "artmis_witch_hazel_private_mousse_250ml", + "baan_baby_lip_original_strawberry_catalog", + "lush_sakura_body_spray", + "so_natural_fixx_setting_spray_120ml_plain", } SEARCH_BROAD_ANCHORS = { @@ -2106,6 +2119,9 @@ def score_marketplace_match( focused_exact_line_reason = _has_focused_low_score_exact_identity_line(left, right) if focused_exact_line_reason in FOCUSED_IDENTITY_REVIEW_ONLY_REASONS: reasons.append("variant_selection_review") + if focused_exact_line_reason in FOCUSED_IDENTITY_VARIANT_REVIEW_BYPASS_REASONS: + reasons = [reason for reason in reasons if reason != "variant_selection_review"] + variant_selection_review = False focused_exact_price_safe = ( focused_exact_line_reason and brand_score >= 0.95 @@ -3623,6 +3639,24 @@ def _has_focused_low_score_exact_identity_line(left: ProductIdentity, right: Pro and _has_shared_volume(left, right, 35) ): return "artmis_virile_gel" + if ( + "artmis" in brand_tokens + and "私密清潔慕斯" in left_text + and "私密清潔慕斯" in right_text + and "金縷梅" in left_text + and "金縷梅" in right_text + and _has_shared_volume(left, right, 250) + ): + return "artmis_witch_hazel_private_mousse_250ml" + if ( + "artmis" in brand_tokens + and "私密清潔慕斯" in left_text + and "私密清潔慕斯" in right_text + and "蔓越莓" in left_text + and "蔓越莓" in right_text + and _has_shared_volume(left, right, 250) + ): + return "artmis_cranberry_private_mousse_250ml" if ( "nailmatic" in (left.brand_tokens & right.brand_tokens) and "小精靈" in left_text @@ -3674,6 +3708,17 @@ def _has_focused_low_score_exact_identity_line(left: ProductIdentity, right: Pro and "隔離露" in right_text ): return "shiseido_blue_sunscreen" + if ( + {"baan", "貝恩"} & (left.brand_tokens & right.brand_tokens) + and "嬰兒修護唇膏" in left_text + and "嬰兒修護唇膏" in right_text + and left.product_type == right.product_type == "護唇膏" + and "原味" in left_text + and "原味" in right_text + and "草莓" in left_text + and "草莓" in right_text + ): + return "baan_baby_lip_original_strawberry_catalog" if ( {"baan", "貝恩"} & (left.brand_tokens & right.brand_tokens) and "嬰兒修護唇膏" in left_text @@ -3769,6 +3814,14 @@ def _has_focused_low_score_exact_identity_line(left: ProductIdentity, right: Pro and "涼感" in right_text ): return "im_meme_fixx_cool_setting_spray" + if ( + {"so", "natural", "fixx"} <= (left.brand_tokens & right.brand_tokens) + and "全天候超完美定妝噴霧" in left_text + and "全天候超完美定妝噴霧" in right_text + and _has_shared_volume(left, right, 120) + and not any(term in pair_text for term in ("經典款", "光澤款", "霧面款", "夏日款", "涼感", "一般")) + ): + return "so_natural_fixx_setting_spray_120ml_plain" if ( {"so", "natural", "fixx"} <= (left.brand_tokens & right.brand_tokens) and "全天候超完美定妝噴霧" in left_text diff --git a/tests/test_marketplace_product_matcher.py b/tests/test_marketplace_product_matcher.py index 17143bc..c098dd5 100644 --- a/tests/test_marketplace_product_matcher.py +++ b/tests/test_marketplace_product_matcher.py @@ -1100,9 +1100,50 @@ def test_marketplace_matcher_promotes_baan_lip_catalog_with_same_options(): assert diagnostics.score >= 0.76 assert diagnostics.hard_veto is False + assert diagnostics.price_basis == "total_price" + assert diagnostics.alert_tier == "price_alert_exact" + assert "variant_selection_review" not in diagnostics.reasons + assert "focused_exact_identity_baan_baby_lip_original_strawberry_catalog" in diagnostics.reasons assert "catalog_variant_listing_alignment_baan_lip" in diagnostics.reasons +def test_marketplace_matcher_promotes_exact_variant_safe_review_bypass_lines(): + from services.marketplace_product_matcher import score_marketplace_match + + cases = [ + ( + "【LUSH 嵐舒】櫻之花身體噴霧 200ml(香氛噴霧/茉莉花/檸檬/含羞草/苦橙花/花香)", + "英國原裝LUSH 櫻之花身體噴霧200ml Sakura Body Spray", + "focused_exact_identity_lush_sakura_body_spray", + ), + ( + "【Play&Joy 官方直營】ARTMIS 金縷梅私密清潔慕斯 250ml(私密清潔 胺基酸配方 綿密泡沫 粉嫩如春 私密保養)", + "ARTMIS 金縷梅私密清潔慕斯 250ml", + "focused_exact_identity_artmis_witch_hazel_private_mousse_250ml", + ), + ( + "【Play&Joy 官方直營】ARTMIS 蔓越莓私密清潔慕斯 250ml(私密清潔 胺基酸配方 綿密泡沫 粉嫩如春 私密保養)", + "ARTMIS 蔓越莓私密清潔慕斯 250ml", + "focused_exact_identity_artmis_cranberry_private_mousse_250ml", + ), + ( + "【SO NATURAL】FIXX全天候超完美定妝噴霧 120ml(定妝 保濕 控油 定妝噴霧)", + "【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml", + "focused_exact_identity_so_natural_fixx_setting_spray_120ml_plain", + ), + ] + + for momo_name, competitor_name, expected_reason in cases: + diagnostics = score_marketplace_match(momo_name, competitor_name) + assert diagnostics.score >= 0.76 + assert diagnostics.hard_veto is False + assert diagnostics.match_type == "exact" + assert diagnostics.price_basis == "total_price" + assert diagnostics.alert_tier == "price_alert_exact" + assert "variant_selection_review" not in diagnostics.reasons + assert expected_reason in diagnostics.reasons + + def test_marketplace_matcher_keeps_kiehls_no1_lip_balm_as_product_line_not_color_number(): from services.marketplace_product_matcher import score_marketplace_match @@ -1937,6 +1978,23 @@ def test_marketplace_matcher_keeps_kate_catalog_vs_single_variant_in_review(): assert "variant_selection_review" in diagnostics.reasons +def test_marketplace_matcher_keeps_so_natural_variant_catalog_in_review(): + from services.marketplace_product_matcher import score_marketplace_match + + diagnostics = score_marketplace_match( + "【SO NATURAL】FIXX 全天候超完美定妝噴霧 經典款/光澤款/霧面款/夏日款", + "【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml", + ) + + assert diagnostics.score >= 0.76 + assert diagnostics.hard_veto is False + assert diagnostics.price_basis == "manual_review" + assert diagnostics.alert_tier == "identity_review" + assert "variant_selection_review" in diagnostics.reasons + assert "focused_exact_identity_so_natural_fixx_setting_spray_catalog" in diagnostics.reasons + assert "focused_exact_identity_so_natural_fixx_setting_spray_120ml_plain" not in diagnostics.reasons + + def test_marketplace_matcher_promotes_variant_safe_exact_option(): from services.marketplace_product_matcher import score_marketplace_match