From 57a9d3f344531371c2db78e82de2d02b3aaa383b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Tue, 20 Oct 2026 20:25:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(site-import):=20specs=5Fpublished=20?= =?UTF-8?q?=E4=B8=A5=E6=A0=BC=20is=20True=20=E5=88=A4=E5=AE=9A=EF=BC=88?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2false=E9=98=B2=E9=9D=99=E9=BB=98?= =?UTF-8?q?=E9=94=99=E5=88=86=E6=94=AF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Code --- app/platform/site_import/generator.py | 4 +++- tests/test_site_import_generator.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) 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"])