From afa91755c1f8bca515ab29b4c4db39321babc917 Mon Sep 17 00:00:00 2001 From: OoO Date: Fri, 29 May 2026 10:32:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A3=9C=E5=BC=B7=20PChome=20near-threshold=20?= =?UTF-8?q?=E9=A2=A8=E9=9A=AA=E9=82=8A=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO_NEXT_STEPS.txt | 1 + config.py | 2 +- .../current_execution_queue_20260524.md | 1 + services/marketplace_product_matcher.py | 31 +++++++++++- tests/test_marketplace_product_matcher.py | 47 +++++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/TODO_NEXT_STEPS.txt b/TODO_NEXT_STEPS.txt index 2be0fe1..ea5e5d5 100644 --- a/TODO_NEXT_STEPS.txt +++ b/TODO_NEXT_STEPS.txt @@ -4,6 +4,7 @@ ================================================================================ 【已完成】 + - V10.486 補 PChome near-threshold 風險邊界:NEW DIRECTIONS 甜杏仁油 vs 酪梨油直接 `core_ingredient_line_conflict` hard veto;COCODOR 經典擴香瓶多款任選 vs generic、KAMERIA 足膜任選三款 vs 單一涼感足膜、Hakugen 白元入浴劑橘盒/綠盒不同變體都保留 `variant_selection_review`,不進可採用 gate。Production 已部署 `/health=V10.486`;240 筆 near-threshold audit `gate_pass 83→79`、`identity_veto 0→1`、`still_low 157→160`。測試:`tests/test_marketplace_product_matcher.py`、`tests/test_competitor_match_attempts_persistence.py`、`tests/test_competitor_match_attempt_rescore_audit.py` 通過。 - V10.485 補 NITORI 香氛噴霧器短型號防線:read-only near-threshold pilot 找到唯一 gate pass 為 5510 vs J82 LBR,不應入隊;matcher 現在會把 `J82` 這類短英數型號納入 NITORI diffuser model conflict,與 5510 / YX168 等不同型號一樣 hard veto。Production 已部署 `/health=V10.485`;120 筆 near-threshold audit 由 `gate_pass=1` 變 `gate_pass=0`,accepted audit `scanned=89 / gate_pass=89 / 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.484 拆分 PChome manual gate:POWERMAN 男性私密養護液 30ml、PHYSIOGEL AI 冰鎮精華露 200ml 2入、TS6 緊彈水嫩凝膠 40g、DERMA 寶寶洗髮沐浴露 150/500ml、Clarins 黃金亮眼萃 20ml、Cetaphil 長效潤膚乳 237/473ml 等明確同款可走 `exact / total_price / price_alert_exact`;COCODOR 大豆蠟燭單側多款任選改留 `variant_selection_review`,Pavaruni 雙側 20 香味蠟燭不受新型錄保護誤傷。Production 曾部署 `/health=V10.484`,並退回 COCODOR 舊 accepted 風險 1 筆。測試:`tests/test_marketplace_product_matcher.py`、`tests/test_competitor_match_attempts_persistence.py`、`tests/test_competitor_match_attempt_rescore_audit.py` 通過。 - V10.483 收斂舊 gate pass 風險:NARS 遮瑕蜜任選、LOREAL 玻尿酸啵啵精華水/液態紫熨斗 vs 水光精華、SEBAMED 洗髮乳任選、Schick 舒綺 2-in-1 型號落差、TAICEND 保護膜 vs 噴霧,現在都會保留高分但加 `variant_selection_review` 與專屬 reason,不再被 rescore 自動送進 accepted queue。Production 已部署 `/health=V10.483`;目標 5 SKU audit `gate_pass=0 / still_low=5`,並用 `--retract-variant-accepted` 退回 4 筆舊 accepted 變體風險,latest accepted audit `scanned=90 / gate_pass=90 / still_low=0`。測試:`tests/test_marketplace_product_matcher.py`、`tests/test_competitor_match_attempts_persistence.py`、`tests/test_competitor_match_attempt_rescore_audit.py` 通過。 diff --git a/config.py b/config.py index c1cb1da..7848836 100644 --- a/config.py +++ b/config.py @@ -350,7 +350,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.485" +SYSTEM_VERSION = "V10.486" 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 402612d..8aa90a6 100644 --- a/docs/memory/current_execution_queue_20260524.md +++ b/docs/memory/current_execution_queue_20260524.md @@ -82,6 +82,7 @@ - 2026-05-25 21:25 CST 起,accepted queue 清潔不再只靠舊 `diagnostic_codes`:`--retract-variant-accepted` 改為先抓 latest accepted,再用當前 matcher 判斷是否需要退回。這能清掉 V10.480 後才被新規則判為 `variant_selection_review` 的舊 accepted。正式最新狀態:`true_low_confidence=751`、`rescore_accepted_current=89`、`identity_veto=3994`、`matched=1570`、`unit_comparable=379`。 - 2026-05-25 23:45 CST 起,`V10.484` 拆分 manual gate exact 與型錄風險:POWERMAN 男性私密養護液 30ml、PHYSIOGEL AI 冰鎮精華露 200ml 2入、TS6 緊彈水嫩凝膠 40g、DERMA 寶寶洗髮沐浴露 150/500ml、Clarins 黃金亮眼萃 20ml、Cetaphil 長效潤膚乳 237/473ml 等明確同款可走 `exact / total_price / price_alert_exact`;COCODOR 大豆蠟燭單側多款任選保留 `variant_selection_review`,Pavaruni 雙側 20 香味蠟燭保持 total-price exact。測試:`tests/test_marketplace_product_matcher.py`、`tests/test_competitor_match_attempts_persistence.py`、`tests/test_competitor_match_attempt_rescore_audit.py` 通過。 - 2026-05-25 23:55 CST 起,`V10.485` 補 NITORI 香氛噴霧器短型號防線:near-threshold read-only pilot 中唯一 gate pass 為 5510 vs J82 LBR,已判定不該入隊;matcher 將 `J82` 這類短英數型號納入 NITORI diffuser model conflict,與 5510 / YX168 等不同型號一樣 hard veto。Production 已部署 `/health=V10.485`;120 筆 near-threshold audit 由 `gate_pass=1` 變 `gate_pass=0`,accepted audit `scanned=89 / gate_pass=89 / still_low=0`。 +- 2026-05-29 起,`V10.486` 補 PChome near-threshold 風險邊界:NEW DIRECTIONS 甜杏仁油 vs 酪梨油直接 hard veto;COCODOR 經典擴香瓶多款任選、KAMERIA 足膜任選三款、Hakugen 白元入浴劑橘盒/綠盒不同變體都保留 `variant_selection_review`,不進可採用 gate。Production 已部署 `/health=V10.486`;240 筆 near-threshold audit `gate_pass 83→79`、`identity_veto 0→1`、`still_low 157→160`。 ## 3. 12 Agent 決策信封整合 diff --git a/services/marketplace_product_matcher.py b/services/marketplace_product_matcher.py index 9e3cd7b..d0d7021 100644 --- a/services/marketplace_product_matcher.py +++ b/services/marketplace_product_matcher.py @@ -2061,6 +2061,9 @@ def score_marketplace_match( candle_catalog_selection_gap = _has_candle_catalog_selection_gap(left, right) if candle_catalog_selection_gap: reasons.append("candle_catalog_selection_gap") + bath_additive_variant_gap = _has_bath_additive_variant_gap(left, right) + if bath_additive_variant_gap: + reasons.append("bath_additive_variant_gap") makeup_catalog_selection_gap = _has_makeup_catalog_selection_gap(left, right) if makeup_catalog_selection_gap: reasons.append("makeup_catalog_selection_gap") @@ -2081,6 +2084,7 @@ def score_marketplace_match( or commercial_condition_gap or relove_private_cleanser_variant_gap or candle_catalog_selection_gap + or bath_additive_variant_gap or makeup_catalog_selection_gap or loreal_serum_variant_gap or sebamed_shampoo_variant_catalog_gap @@ -3257,11 +3261,13 @@ def _has_aroma_scent_variant_conflict(left: ProductIdentity, right: ProductIdent def _has_core_ingredient_line_conflict(left: ProductIdentity, right: ProductIdentity) -> bool: pair_text = f"{left.searchable_name} {right.searchable_name}" - if not any(term in pair_text for term in ("油膏", "護膚油", "身體油", "精油", "霜", "乳霜")): + if not any(term in pair_text for term in ("油膏", "護膚油", "身體油", "精油", "基礎油", "按摩油", "甜杏仁油", "酪梨油", "霜", "乳霜")): return False ingredient_groups = { "coconut_oil": ("椰子油", "coconut"), "shea_butter": ("乳木果油", "shea"), + "sweet_almond_oil": ("甜杏仁油", "sweet almond"), + "avocado_oil": ("酪梨油", "avocado"), } left_groups = { group @@ -3556,10 +3562,14 @@ def _has_catalog_specific_variant_selection_gap(left: ProductIdentity, right: Pr "車用擴香", "車用擴香蕊", "香氛擴香罐", + "擴香瓶", "擴香罐", "擴香蕊", "水性指甲油", "指甲油", + "足膜", + "泡澡入浴劑", + "入浴劑", "融蠟小夜燈", "融蠟燈", "滋養霜", @@ -3571,6 +3581,25 @@ def _has_catalog_specific_variant_selection_gap(left: ProductIdentity, right: Pr return left_catalog != right_catalog +def _has_bath_additive_variant_gap(left: ProductIdentity, right: ProductIdentity) -> bool: + pair_text = f"{left.searchable_name} {right.searchable_name}" + if not any(term in pair_text for term in ("入浴劑", "泡澡錠", "泡澡包", "泡澡")): + return False + if not (left.brand_tokens & right.brand_tokens): + return False + left_terms = { + term + for term in ("馨香", "懷舊", "橘盒", "綠盒", "粉盒", "藍盒") + if term in left.searchable_name + } + right_terms = { + term + for term in ("馨香", "懷舊", "橘盒", "綠盒", "粉盒", "藍盒") + if term in right.searchable_name + } + return bool(left_terms and right_terms and not (left_terms & right_terms)) + + def _has_taicend_baby_spray_equivalence(left: ProductIdentity, right: ProductIdentity) -> bool: brand_tokens = {"taicend", "泰陞"} return ( diff --git a/tests/test_marketplace_product_matcher.py b/tests/test_marketplace_product_matcher.py index a7cd699..16e1fc1 100644 --- a/tests/test_marketplace_product_matcher.py +++ b/tests/test_marketplace_product_matcher.py @@ -1246,6 +1246,53 @@ def test_marketplace_matcher_keeps_same_candle_catalog_alignment_as_total_price( assert "focused_exact_identity_pavaruni_20_scent_candle" in diagnostics.reasons +def test_marketplace_matcher_blocks_different_carrier_oil_core_ingredients(): + from services.marketplace_product_matcher import score_marketplace_match + + diagnostics = score_marketplace_match( + "【NEW DIRECTIONS】甜杏仁油1000ml+按壓頭1入組(澳洲原裝進口-新方向按摩油保濕油基礎油)", + "【NEW DIRECTIONS】酪梨油1000ml+按壓頭1入組(澳洲原裝進口-新方向按摩油保濕油基礎油)", + ) + + assert diagnostics.hard_veto is True + assert diagnostics.comparison_mode == "not_comparable" + assert "core_ingredient_line_conflict" in diagnostics.reasons + + +def test_marketplace_matcher_sends_fragrance_and_foot_mask_catalog_gaps_to_review(): + from services.marketplace_product_matcher import score_marketplace_match + + cocodor = score_marketplace_match( + "【COCODOR】經典擴香瓶200mlx4入(多款任選/官方直營/韓國香氛)", + "COCODOR 經典擴香瓶200mlx4", + ) + kameria = score_marketplace_match( + "【KAMERIA】凱蜜菈 足足稱奇足膜17ml*2枚入(任選三款)", + "Kameria足足稱奇涼感去皮嫩足膜 17ml*2枚入", + ) + + for diagnostics in (cocodor, kameria): + 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 + + +def test_marketplace_matcher_sends_bath_additive_box_variants_to_review(): + from services.marketplace_product_matcher import score_marketplace_match + + diagnostics = score_marketplace_match( + "【日本Hakugen白元】濁湯溫泉之旅炭酸泡澡入浴劑45gx16錠/馨香-橘盒(含4種湯色發泡沐浴劑草本溫泉粉泡澡錠)", + "日本Hakugen白元-濁湯溫泉之旅炭酸泡澡入浴劑-懷舊45gx16錠/綠盒", + ) + + assert diagnostics.hard_veto is False + assert diagnostics.price_basis == "manual_review" + assert diagnostics.alert_tier == "identity_review" + assert "bath_additive_variant_gap" in diagnostics.reasons + assert "variant_selection_review" 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