diff --git a/app/platform/site_import/generator.py b/app/platform/site_import/generator.py index 6eca5e2..769f394 100644 --- a/app/platform/site_import/generator.py +++ b/app/platform/site_import/generator.py @@ -417,7 +417,9 @@ def build(gen: dict, analysis: dict, crawl: dict, source_text: str) -> dict: values[name] = v # 2) 行业分支判定(判定依据入 warnings 供审核参考) - specs = bool(analysis.get("specs_published")) + # 严格 is True 判定(评审 #1):LLM 可能回 "false"/"no" 字符串——bool("false") 为 + # True 会静默走错行业分支;仅真布尔 True 算规格公开,其余一律不公开(fail-safe) + specs = analysis.get("specs_published") is True evidence = _clean_str(analysis.get("specs_evidence")) or "产品页参数表判定" warnings.append(f"规格判定:{'公开' if specs else '不公开'}(依据:{evidence})") diff --git a/tests/test_site_import_generator.py b/tests/test_site_import_generator.py index 96b0a60..13752fe 100644 --- a/tests/test_site_import_generator.py +++ b/tests/test_site_import_generator.py @@ -401,3 +401,21 @@ class TestTimeout: with pytest.raises(generator.GenerateError): await generator.analyze(Slow(), "页面文本") + + +class TestSpecsStrictBool: + async def test_字符串false走不公开分支(self): + """评审 #1:LLM 回字符串 "false" 时 bool() 强转为 True 会静默走规格公开分支—— + is True 严格判定后字符串形态一律 fail-safe 到不公开。""" + import json as _json + analysis = _json.loads(_json.dumps({ + "company_name": "X", "product_lines": [{"name": "p", "points": []}], + "specs_published": "false"})) + gen = dict(_MIN_GEN) if "_MIN_GEN" in globals() else { + "身份描述": "你是销售", "产品统称": "产品", "产品统称EN": "products", + "产品类别清单": "产品", "规格追问三要素": "场景", "好差示例组": "示例", + "关注信息": "信息", "固定追问句": "问句", "推荐建议": "建议"} + draft = generator.build(gen, analysis, CRAWL, SOURCE_TEXT) + facts = draft["prompts"]["company_facts"] + assert ("参数未公布" in facts) or ("兜底" in facts) + assert any(w.startswith("规格判定:不公开") for w in draft["warnings"])