V10.404 gate Hermes direct price alerts
All checks were successful
CD Pipeline / deploy (push) Successful in 1m6s
All checks were successful
CD Pipeline / deploy (push) Successful in 1m6s
This commit is contained in:
@@ -325,7 +325,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
|
||||
# ==========================================
|
||||
# 系統版本與路徑
|
||||
# ==========================================
|
||||
SYSTEM_VERSION = "V10.403"
|
||||
SYSTEM_VERSION = "V10.404"
|
||||
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
|
||||
public_url = PUBLIC_URL # 用於模板顯示
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
## 📅 詳細更新日誌 (考古存檔)
|
||||
|
||||
### 2026-05-24:PChome 近門檻身份回收第二輪
|
||||
- **V10.404 Hermes 競價威脅漏斗只吃 direct alert**: `HermesAnalystService.fetch_candidates()` 的 `competitor_prices` JOIN 新增硬條件,只讓 `match_type=exact`、`price_basis=total_price`、`alert_tier=price_alert_exact` 的 identity_v2 配對進入 Hermes 競價威脅分析;`identity_review`、`unit_price_review` 與 `suppress` 仍保留在 dashboard / 人工覆核資料流,但不再消耗 Hermes token 或被上游視為直接價格威脅候選。production fresh 配對分布顯示直接告警約 497 筆、覆核型約 216 筆,本版將兩者在 AI 威脅入口切開。同版 matcher 追加 KATE 怪獸級持色唇膏、植村秀武士刀眉筆筆蕊、The Forest 焦糖楓葉擴香禮盒等近門檻 review-only 回收線,仍只進人工覆核,不直接價格告警。
|
||||
- **V10.403 近門檻候選重驗擴池**: production 最新 72h attempt audit 顯示 7853 筆近門檻/被擋候選中,有 105 筆可被現行 matcher 回收,其中 46 筆已達 `price_alert_exact`、59 筆只進 `identity_review`。`CompetitorPriceFeeder._fetch_retryable_candidate_skus()` 擴大每日 revalidation 候選池,納入 `true_low_confidence`、`unit_comparable`、`refresh_unit_comparable` 與高分 `identity_veto`;但仍要求 PChome product_id、`best_match_score >= 0.70`,且正式寫入前必須由現行 matcher 重判、通過 hard-veto 與既有配對保護。
|
||||
- **V10.402 catalog variant identity-review 回收**: marketplace matcher 新增 Johnson’s 嬰兒潤膚乳 catalog 對同香型、IM MEME 涼感定妝噴霧、SO NATURAL FIXX 定妝噴霧三條 review-only focused identity,讓同品線 catalog / variant 候選可脫離 `true_low_confidence` 但只進 `identity_review`,不直接價格告警;同版明確保留 MUJI 品牌缺漏護手霜等 brandless catalog 案例在低信心,避免品牌缺漏與多款任選同時存在時被過度救回。
|
||||
- **V10.401 focused identity 邊界整理**: 將 Laundrin TOKYO 車用夾式消臭芳香劑判定抽成 `_has_laundrin_tokyo_car_freshener_alignment()`,並在 variant descriptor guard 中豁免同一條強身份線,避免 TOKYO / 車用 / 芳香劑語序差異造成誤擋。Yuskin 經典乳霜 30g 6 入組改用 `_has_exact_count_alignment()` 判斷包數,保留 6入 vs 6盒這類同數量但不同容器字詞的人工覆核路徑。
|
||||
|
||||
@@ -449,6 +449,15 @@ class HermesAnalystService:
|
||||
AND cp.expires_at > NOW()
|
||||
AND cp.match_score >= 0.76
|
||||
AND COALESCE(cp.tags, '[]'::jsonb) ? 'identity_v2'
|
||||
AND (
|
||||
cp.match_diagnostic_json @> '{{"match_type":"exact","price_basis":"total_price","alert_tier":"price_alert_exact"}}'::jsonb
|
||||
OR (
|
||||
cp.match_diagnostic_json IS NULL
|
||||
AND COALESCE(cp.tags, '[]'::jsonb) ? 'match_type_exact'
|
||||
AND COALESCE(cp.tags, '[]'::jsonb) ? 'price_basis_total_price'
|
||||
AND COALESCE(cp.tags, '[]'::jsonb) ? 'alert_tier_price_alert_exact'
|
||||
)
|
||||
)
|
||||
WHERE lmp.rn = 1
|
||||
AND rs.sales_7d_prev > 0
|
||||
AND (rs.sales_7d_curr - rs.sales_7d_prev) / rs.sales_7d_prev < -0.10
|
||||
|
||||
@@ -365,6 +365,8 @@ SEARCH_IDENTITY_ANCHORS = (
|
||||
"嬰兒潤膚乳",
|
||||
"我愛超磁妝定妝噴霧",
|
||||
"全天候超完美定妝噴霧",
|
||||
"怪獸級持色唇膏",
|
||||
"焦糖楓葉香氛擴香花禮盒",
|
||||
"香氛蠟燭20種香味",
|
||||
"tokyo車用夾式消臭芳香劑",
|
||||
"北歐簡樸融蠟燈桌面氣氛夜燈",
|
||||
@@ -373,6 +375,7 @@ SEARCH_IDENTITY_ANCHORS = (
|
||||
"細芯睛彩雙頭眉筆",
|
||||
"雙頭旋轉極細眉筆",
|
||||
"武士刀眉筆",
|
||||
"自動武士刀眉筆筆蕊",
|
||||
"無極限保濕防曬妝前乳",
|
||||
"水凝光透 妝前防護乳",
|
||||
"水凝光透妝前防護乳",
|
||||
@@ -466,6 +469,13 @@ FOCUSED_IDENTITY_REVIEW_ONLY_REASONS = {
|
||||
"johnsons_baby_lotion_variant_catalog",
|
||||
"im_meme_fixx_cool_setting_spray",
|
||||
"so_natural_fixx_setting_spray_catalog",
|
||||
"kate_monster_lipstick_catalog",
|
||||
"shu_auto_hard_formula_refill_catalog",
|
||||
"the_forest_maple_diffuser_flower_brandless",
|
||||
}
|
||||
|
||||
FOCUSED_IDENTITY_BRANDLESS_REVIEW_REASONS = {
|
||||
"the_forest_maple_diffuser_flower_brandless",
|
||||
}
|
||||
|
||||
SEARCH_BROAD_ANCHORS = {
|
||||
@@ -1862,6 +1872,25 @@ def score_marketplace_match(
|
||||
and sequence_score >= 0.40
|
||||
and not variant_descriptor_conflict
|
||||
)
|
||||
focused_exact_review_boost_safe = (
|
||||
focused_exact_line_reason
|
||||
and not hard_veto
|
||||
and spec_score >= 0.45
|
||||
and token_score >= 0.30
|
||||
and sequence_score >= 0.40
|
||||
and not variant_descriptor_conflict
|
||||
and (
|
||||
brand_score >= 0.95
|
||||
or (
|
||||
focused_exact_line_reason in FOCUSED_IDENTITY_BRANDLESS_REVIEW_REASONS
|
||||
and brand_score == 0.55
|
||||
and bool(left.brand_tokens) != bool(right.brand_tokens)
|
||||
and spec_score >= 0.85
|
||||
and token_score >= 0.55
|
||||
and sequence_score >= 0.50
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
comparison_mode = "exact_identity"
|
||||
if _is_unit_comparable_candidate(
|
||||
@@ -1974,14 +2003,8 @@ def score_marketplace_match(
|
||||
score += 0.04
|
||||
reasons.append("cushion_refill_pack_alignment_score")
|
||||
if (
|
||||
focused_exact_line_reason
|
||||
and brand_score >= 0.95
|
||||
and not hard_veto
|
||||
focused_exact_review_boost_safe
|
||||
and price_penalty == 0
|
||||
and spec_score >= 0.45
|
||||
and token_score >= 0.30
|
||||
and sequence_score >= 0.40
|
||||
and not variant_descriptor_conflict
|
||||
):
|
||||
score += 0.16
|
||||
reasons.append(f"focused_exact_identity_{focused_exact_line_reason}")
|
||||
@@ -2922,6 +2945,27 @@ def _has_focused_low_score_exact_identity_line(left: ProductIdentity, right: Pro
|
||||
and "全天候超完美定妝噴霧" in right_text
|
||||
):
|
||||
return "so_natural_fixx_setting_spray_catalog"
|
||||
if (
|
||||
{"kate", "凱婷"} & (left.brand_tokens & right.brand_tokens)
|
||||
and "怪獸級持色唇膏" in left_text
|
||||
and "怪獸級持色唇膏" in right_text
|
||||
):
|
||||
return "kate_monster_lipstick_catalog"
|
||||
if (
|
||||
{"shu uemura", "植村秀"} & (left.brand_tokens & right.brand_tokens)
|
||||
and "自動武士刀眉筆" in left_text
|
||||
and "自動武士刀眉筆" in right_text
|
||||
and "筆蕊" in left_text
|
||||
and "筆蕊" in right_text
|
||||
):
|
||||
return "shu_auto_hard_formula_refill_catalog"
|
||||
if (
|
||||
"焦糖楓葉香氛擴香花禮盒" in left_text
|
||||
and "焦糖楓葉香氛擴香花禮盒" in right_text
|
||||
and _has_shared_volume(left, right, 30)
|
||||
and bool(left.brand_tokens) != bool(right.brand_tokens)
|
||||
):
|
||||
return "the_forest_maple_diffuser_flower_brandless"
|
||||
if (
|
||||
"gatsby" in (left.brand_tokens & right.brand_tokens)
|
||||
and "爆水擦澡濕巾" in left_text
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"""Hermes 分析師必須透過 OllamaService 三主機級聯。"""
|
||||
|
||||
import time
|
||||
import inspect
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
@@ -141,3 +142,15 @@ def test_hermes_batch_analyze_uses_ollama_service_and_logs_secondary(monkeypatch
|
||||
assert rec['caller'] == 'hermes_analyst'
|
||||
assert rec['provider'] == 'ollama_secondary'
|
||||
assert rec['meta']['host_label'] == 'GCP-SSD-2'
|
||||
|
||||
|
||||
def test_hermes_candidate_sql_only_joins_direct_price_alert_matches():
|
||||
sql_text = inspect.getsource(hermes_mod.HermesAnalystService.fetch_candidates)
|
||||
compact_sql = "".join(sql_text.split())
|
||||
|
||||
assert '"match_type":"exact"' in compact_sql
|
||||
assert '"price_basis":"total_price"' in compact_sql
|
||||
assert '"alert_tier":"price_alert_exact"' in compact_sql
|
||||
assert "match_type_exact" in sql_text
|
||||
assert "price_basis_total_price" in sql_text
|
||||
assert "alert_tier_price_alert_exact" in sql_text
|
||||
|
||||
@@ -875,6 +875,18 @@ def test_marketplace_matcher_keeps_catalog_variant_recoveries_in_identity_review
|
||||
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 經典款/光澤款/霧面款/夏日款",
|
||||
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml",
|
||||
),
|
||||
(
|
||||
"【KATE 凱婷】怪獸級持色唇膏-經典款(獨家技術持久不沾 高保濕)",
|
||||
"【KATE 凱婷】怪獸級持色唇膏 (3g)",
|
||||
),
|
||||
(
|
||||
"【植村秀】官方直營 自動武士刀眉筆筆蕊(Shu uemura/筆蕊 8色任選)",
|
||||
"《Shu Uemura 植村秀》自動武士刀眉筆 -筆蕊 0.3g",
|
||||
),
|
||||
(
|
||||
"【The Forest 癒森林】焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油(居家香氛/香水精油/香氛擴香花/擴香禮物)",
|
||||
"焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油",
|
||||
),
|
||||
]
|
||||
|
||||
for momo_name, competitor_name in cases:
|
||||
@@ -1172,6 +1184,21 @@ def test_marketplace_matcher_promotes_focused_low_score_exact_identity_lines():
|
||||
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml",
|
||||
"focused_exact_identity_so_natural_fixx_setting_spray_catalog",
|
||||
),
|
||||
(
|
||||
"【KATE 凱婷】怪獸級持色唇膏-經典款(獨家技術持久不沾 高保濕)",
|
||||
"【KATE 凱婷】怪獸級持色唇膏 (3g)",
|
||||
"focused_exact_identity_kate_monster_lipstick_catalog",
|
||||
),
|
||||
(
|
||||
"【植村秀】官方直營 自動武士刀眉筆筆蕊(Shu uemura/筆蕊 8色任選)",
|
||||
"《Shu Uemura 植村秀》自動武士刀眉筆 -筆蕊 0.3g",
|
||||
"focused_exact_identity_shu_auto_hard_formula_refill_catalog",
|
||||
),
|
||||
(
|
||||
"【The Forest 癒森林】焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油(居家香氛/香水精油/香氛擴香花/擴香禮物)",
|
||||
"焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油",
|
||||
"focused_exact_identity_the_forest_maple_diffuser_flower_brandless",
|
||||
),
|
||||
(
|
||||
"【GATSBY】爆水擦澡濕巾24張入(涼感乾洗澡)",
|
||||
"GATSBY 爆水擦澡濕巾24張入(240g)",
|
||||
@@ -1213,8 +1240,30 @@ def test_marketplace_matcher_keeps_high_variant_low_score_lines_outside_focused_
|
||||
"【Schick 舒適牌】舒芙仕女除毛刀把刀片組 (1刀把2刀片+刀片3入)",
|
||||
"【Schick舒適牌】舒綺 仕女除毛刀 敏感肌用 1刀把+2刀片 送卡娜赫拉束口袋",
|
||||
)
|
||||
lancome_line_gap = score_marketplace_match(
|
||||
"【LANCOME 蘭蔻】官方直營 超極光活粹晶露150ml(LANCOME/四重酸極光水/化妝水/精華水)",
|
||||
"LANCOME 蘭蔻 超極限肌因精華露150ml 專櫃公司貨",
|
||||
)
|
||||
mac_finish_gap = score_marketplace_match(
|
||||
"【M.A.C】MACximal極自我柔霧唇膏3.5g(子彈唇膏 #柔霧大巨彈_全新質地_新色登場)",
|
||||
"M.A.C MACximal 極自我緞光唇膏 3.5g 多款可選",
|
||||
)
|
||||
ysl_powder_variant_guard = score_marketplace_match(
|
||||
"【YSL】官方直營 恆久完美持久柔霧蜜粉餅(任選1款/皮革蜜粉)",
|
||||
"YSL 恆久完美持久柔霧蜜粉餅(7.5g) [百貨公司專櫃貨]",
|
||||
)
|
||||
|
||||
for diagnostics in (lush, lactacyd, lunasol, muji_swab, kate_limited, schick_bundle_gap):
|
||||
for diagnostics in (
|
||||
lush,
|
||||
lactacyd,
|
||||
lunasol,
|
||||
muji_swab,
|
||||
kate_limited,
|
||||
schick_bundle_gap,
|
||||
lancome_line_gap,
|
||||
mac_finish_gap,
|
||||
ysl_powder_variant_guard,
|
||||
):
|
||||
assert diagnostics.score < 0.76
|
||||
assert not any(reason.startswith("focused_exact_identity_") for reason in diagnostics.reasons)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user