From 164d55a05a4dbe502313a3648984c488ab6a7b3c Mon Sep 17 00:00:00 2001 From: zhangshy <994452054@qq.com> Date: Sat, 12 Sep 2026 15:05:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=88=E8=A7=84=E9=97=AE?= =?UTF-8?q?=E5=8F=A5=E8=A2=AB=E8=AF=AF=E5=88=A4=E4=B8=BA=E6=94=B6=E7=9B=8A?= =?UTF-8?q?=E6=89=BF=E8=AF=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/core/compliance_context.py | 9 +++++++++ tests/unit/core/test_compliance_context.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/app/core/compliance_context.py b/app/core/compliance_context.py index b32bc98..f9553c1 100644 --- a/app/core/compliance_context.py +++ b/app/core/compliance_context.py @@ -44,6 +44,7 @@ NEGATION_CUES: tuple[str, ...] = ( "严禁", "禁止", "不得", "不可", "不允许", "不准", "杜绝", "严禁使用", "避免", "勿", "拒绝", "防止", "防范", "打击", "处罚", "违规", "不承诺", "不保证", "不作", "不能", "绝不", "从不", + "且不", "并不", "未保证", "不予保证", ) #: 元语言线索:说明"在谈论这个词本身"而不是在作承诺(如『保证收益』等违规表述)。 @@ -52,6 +53,12 @@ METALANGUAGE_CUES: tuple[str, ...] = ( "等违规", "等禁用", "等禁止", "等表述", ) +#: 询问语境:问“能否/是否/会不会保证收益”是在确认或质疑产品属性,不是作出承诺。 +#: 风控回访话术中常见此类问句,若按承诺拦截,会把正常人工回访脚本误判为违规输出。 +QUESTION_CUES: tuple[str, ...] = ( + "能否", "是否", "可否", "会不会", "能不能", "请问", "吗", +) + #: 引号字符:命中词被引号包裹时视为引用(在谈论该表述本身)。 QUOTE_CHARS: tuple[str, ...] = ('"', "'", "“", "”", "‘", "’", "「", "」", "『", "』") @@ -103,6 +110,8 @@ def is_prohibited_context(text: str, index: int, pattern: str) -> bool: return True if any(cue in after for cue in NEGATION_CUES): return True + if any(cue in before or cue in after for cue in QUESTION_CUES): + return True # 元语言线索:前后任一侧出现"表述/话术/字样"等,说明在谈论该词本身。 return any(cue in before or cue in after for cue in METALANGUAGE_CUES) diff --git a/tests/unit/core/test_compliance_context.py b/tests/unit/core/test_compliance_context.py index d29045a..1a45167 100644 --- a/tests/unit/core/test_compliance_context.py +++ b/tests/unit/core/test_compliance_context.py @@ -101,3 +101,19 @@ def test_governance_uses_the_exemption() -> None: ) assert promise.result.transfer_required is True, "真实承诺被放过" assert "需要人工核实" in promise.result.text +def test_question_context_is_exempted() -> None: + """询问产品能否保证收益是核实问题,不是作出收益承诺。""" + assert first_violation( + "该产品是否可能造成较大本金损失,能否保证收益?", + ZERO, + ) is None + assert first_violation("请问该产品保证收益吗?", ZERO) is None + assert first_violation( + "您是否了解产品可能造成较大本金损失,且不保证收益?", + ZERO, + ) is None + + +def test_question_exemption_does_not_release_real_promise() -> None: + """询问语境只豁免问句,明确承诺仍然必须被拦截。""" + assert first_violation("该产品保证收益,请放心购买。", ZERO) == "保证收益"