test_sku_intent_selector.py 3.74 KB
from types import SimpleNamespace

from config import QueryConfig
from query.style_intent import DetectedStyleIntent, StyleIntentProfile, StyleIntentRegistry
from search.sku_intent_selector import StyleSkuSelector


def test_style_sku_selector_matches_first_sku_by_attribute_terms():
    registry = StyleIntentRegistry.from_query_config(
        QueryConfig(
            style_intent_terms={
                "color": [{"en_terms": ["navy"], "zh_terms": ["藏青"], "attribute_terms": ["navy"]}],
                "size": [{"en_terms": ["xl"], "zh_terms": ["加大码"], "attribute_terms": ["x-large"]}],
            },
            style_intent_dimension_aliases={
                "color": ["color", "颜色"],
                "size": ["size", "尺码"],
            },
        )
    )
    selector = StyleSkuSelector(registry)
    parsed_query = SimpleNamespace(
        style_intent_profile=StyleIntentProfile(
            intents=(
                DetectedStyleIntent(
                    intent_type="color",
                    canonical_value="navy",
                    matched_term="藏青",
                    matched_query_text="藏青",
                    attribute_terms=("navy",),
                    dimension_aliases=("color", "颜色"),
                ),
                DetectedStyleIntent(
                    intent_type="size",
                    canonical_value="x-large",
                    matched_term="xl",
                    matched_query_text="xl",
                    attribute_terms=("x-large",),
                    dimension_aliases=("size", "尺码"),
                ),
            ),
        )
    )
    source = {
        "option1_name": "Color",
        "option2_name": "Size",
        "skus": [
            {"sku_id": "1", "option1_value": "Black", "option2_value": "M"},
            {"sku_id": "2", "option1_value": "Navy Blue", "option2_value": "X-Large", "image_src": "matched.jpg"},
            {"sku_id": "3", "option1_value": "Navy", "option2_value": "XL"},
        ],
    }
    hits = [{"_id": "spu-1", "_source": source}]

    decisions = selector.prepare_hits(hits, parsed_query)
    decision = decisions["spu-1"]

    assert decision.selected_sku_id == "2"
    assert decision.selected_text == "Navy Blue X-Large"
    assert decision.matched_stage == "text"

    selector.apply_precomputed_decisions(hits, decisions)

    assert source["skus"][0]["sku_id"] == "2"
    assert source["image_url"] == "matched.jpg"


def test_style_sku_selector_returns_no_match_without_attribute_contains():
    registry = StyleIntentRegistry.from_query_config(
        QueryConfig(
            style_intent_terms={
                "color": [{"en_terms": ["beige"], "zh_terms": ["米色"], "attribute_terms": ["beige"]}],
            },
            style_intent_dimension_aliases={"color": ["color", "颜色"]},
        )
    )
    selector = StyleSkuSelector(registry)
    parsed_query = SimpleNamespace(
        style_intent_profile=StyleIntentProfile(
            intents=(
                DetectedStyleIntent(
                    intent_type="color",
                    canonical_value="beige",
                    matched_term="米色",
                    matched_query_text="米色",
                    attribute_terms=("beige",),
                    dimension_aliases=("color", "颜色"),
                ),
            ),
        )
    )
    hits = [{
        "_id": "spu-1",
        "_source": {
            "option1_name": "Color",
            "skus": [
                {"sku_id": "1", "option1_value": "Khaki"},
                {"sku_id": "2", "option1_value": "Light Brown"},
            ],
        },
    }]

    decisions = selector.prepare_hits(hits, parsed_query)

    assert decisions["spu-1"].selected_sku_id is None
    assert decisions["spu-1"].matched_stage == "no_match"