V10.391 handle catalog variant listings
All checks were successful
CD Pipeline / deploy (push) Successful in 1m7s

This commit is contained in:
OoO
2026-05-24 10:32:42 +08:00
committed by AiderHeal Bot
parent 0538c8d5f6
commit 6d4b188787
6 changed files with 174 additions and 4 deletions

View File

@@ -55,7 +55,6 @@ BROWSE_SH_MAX_EXECUTIONS_PER_RUN = int(os.getenv("PCHOME_FEEDER_BROWSE_SH_MAX_PE
BROWSE_SH_OUTPUT_PREVIEW_CHARS = int(os.getenv("PCHOME_FEEDER_BROWSE_SH_OUTPUT_PREVIEW_CHARS", "1200"))
RECOVERABLE_DIAGNOSTIC_REASONS = {
"strong_product_line_match",
"strong_exact_spec_match",
"shared_identity_anchor",
"shared_identity_anchor_no_spec",
"shared_identity_anchor_packaging_variant",
@@ -93,6 +92,15 @@ def _has_recoverable_identity_signal(diagnostics) -> bool:
)
def _is_multi_variant_listing_name(name: str) -> bool:
return bool(
re.search(
r"(多款任選|多款可選|多色任選|多色可選|多種香味|多種香氣|香味任選|香味可選|味道可選)",
name or "",
)
)
def _classify_low_score_attempt(score: float, diagnostics) -> str:
if getattr(diagnostics, "hard_veto", False):
return "identity_veto"
@@ -117,10 +125,11 @@ def _has_variant_selection_gap(
source_identity = parse_product_identity(momo_name)
source_options = set(_explicit_variant_option_tokens(source_identity))
source_multi_listing = _is_multi_variant_listing_name(momo_name)
if re.search(r"任選\s*[一二兩三四五六七八九十0-9]+\s*款", momo_name):
source_options -= {str(value) for value in range(1, 11)}
source_options -= {f"{value:02d}" for value in range(1, 11)}
if source_options:
if source_options and not source_multi_listing:
return False
threshold = max(best_score - 0.02, RECOVERABLE_LOW_SCORE_FLOOR)
@@ -128,7 +137,10 @@ def _has_variant_selection_gap(
for product, score, diagnostics in ranked_matches[:5]:
if getattr(diagnostics, "hard_veto", False) or score < threshold:
continue
candidate_identity = parse_product_identity(getattr(product, "name", "") or "")
candidate_name = getattr(product, "name", "") or ""
if source_multi_listing != _is_multi_variant_listing_name(candidate_name):
return True
candidate_identity = parse_product_identity(candidate_name)
options = _explicit_variant_option_tokens(candidate_identity)
if len(options) >= 2:
return True

View File

@@ -454,6 +454,9 @@ VARIANT_SENSITIVE_KEYWORDS = {
"車用香氛",
"香味",
"私密清潔慕斯",
"私密清潔凝露",
"私密潔淨凝露",
"私密淨白清潔凝露",
"定妝噴霧",
"妝前防護乳",
"妝前乳",
@@ -492,6 +495,8 @@ VARIANT_OPTION_COLOR_WORDS = {
"金縷梅",
"柔焦霧面",
"水光亮面",
"菸鹼醯胺",
"胺基酸",
"黑色",
"棕色",
"咖啡色",
@@ -534,6 +539,20 @@ VARIANT_DESCRIPTOR_NOISE_KEYWORDS = {
"盒組",
}
MULTI_VARIANT_LISTING_PHRASES = (
"多款任選",
"多款可選",
"多色任選",
"多色可選",
"多種香味",
"多種香氣",
"香味任選",
"香味可選",
"味道可選",
"任選",
"可選",
)
SEARCH_AMBIGUOUS_PRODUCT_TERMS = {
"保護膜",
"保護貼",
@@ -2009,6 +2028,18 @@ def score_marketplace_match(
):
score += 0.04
reasons.append("shared_model_token_brush_baby_wildones")
if (
_has_catalog_variant_listing_alignment(left, right)
and brand_score >= 0.95
and not hard_veto
and price_penalty == 0
and spec_score >= 0.85
and type_score >= 0.95
and sequence_score >= 0.50
and not variant_descriptor_conflict
):
score += 0.06
reasons.append("catalog_variant_listing_alignment")
if (
shared_anchor
and len(shared_anchor.replace(" ", "")) >= 5
@@ -2390,6 +2421,37 @@ def _has_brush_baby_wildones_toothbrush_alignment(left: ProductIdentity, right:
)
def _is_relove_private_cleanser_line(left: ProductIdentity, right: ProductIdentity) -> bool:
return (
"relove" in (left.brand_tokens | right.brand_tokens)
and "私密" in left.searchable_name
and "私密" in right.searchable_name
and "凝露" in left.searchable_name
and "凝露" in right.searchable_name
)
def _is_multi_variant_catalog_listing(identity: ProductIdentity) -> bool:
text = identity.normalized_name
return any(phrase in text for phrase in MULTI_VARIANT_LISTING_PHRASES)
def _has_catalog_variant_listing_alignment(left: ProductIdentity, right: ProductIdentity) -> bool:
if not (_is_multi_variant_catalog_listing(left) and _is_multi_variant_catalog_listing(right)):
return False
if left.product_type != right.product_type or left.product_type not in {"精油", "護唇膏"}:
return False
if not _has_overlapping_base_spec(left, right):
return False
shared_core = left.core_tokens & right.core_tokens
if shared_core:
return True
left_text = left.searchable_name
right_text = right.searchable_name
catalog_terms = ("香氛擴香罐", "香氛蠟燭", "蠟燭", "擴香罐", "修護唇膏")
return any(term in left_text and term in right_text for term in catalog_terms)
def _is_variant_sensitive_identity(
left: ProductIdentity,
right: ProductIdentity,
@@ -2412,6 +2474,8 @@ def _has_variant_descriptor_conflict(left: ProductIdentity, right: ProductIdenti
return False
if _has_brush_baby_wildones_toothbrush_alignment(left, right):
return False
if _is_relove_private_cleanser_line(left, right):
return False
if (
shared_anchor
and shared_anchor not in SEARCH_BROAD_ANCHORS