fix(server): gate_classify 复用 _classify_irrelevant_input 修复 off_topic 误杀

回归问题:P1.3 重构时 gate_classify 的 off_topic 门用了 scene_registry
的 35 个 signal_keywords,丢掉了 legacy 的 73 个关键词(城市名/时间词/金额词/
交通词等),导致'下周去上海''昨天打车30块'等正常业务输入被误判 off_topic,
根本进不了 LLM。

修复:gate_classify 的 off_topic 门改用成熟的 _classify_irrelevant_input
(94 词 + registry 信号词 + greeting/meaningless 细分),scene_registry 的
signal_keywords 只用于规则匹配门(CHOICE 路由)。删除残缺的 _matches_any_signal。

验证:76 passed;实测'下周去上海'→llm_function_call、'昨天打车30块'→
llm_function_call、'你好'→off_topic(正确拦截)。
This commit is contained in:
caoxiaozhu
2026-06-25 16:06:52 +08:00
parent 992cf71fa1
commit 8a2ae6eb75

View File

@@ -24,15 +24,6 @@ from app.services.steward_planner_fallback import StewardPlannerFallbackMixin
# ---- 模块级辅助函数:gate_classify 的判断逻辑 ----
def _matches_any_signal(message: str) -> bool:
"""聚合 scene_registry 所有 signal_keywords,判断输入是否为业务相关。"""
from app.services.scenes import REGISTRY
compact = _compact_text(message)
if not compact:
return False
return any(kw in compact for kw in REGISTRY.all_signal_keywords())
def _compact_text(text: str) -> str:
return re.sub(r"\s+", "", str(text or ""))
@@ -154,13 +145,16 @@ class StewardGraphPlannerService(StewardPlannerFallbackMixin, StewardPlannerExtr
顺序:
① resume 门(用户说"再提交"+ state 有可恢复 flow → 上下文恢复)
② off_topic 门(聚合 scene_registry signal_keywords)
② off_topic 门(复用 _classify_irrelevant_input:legacy 94 词 + registry 信号词 + greeting/meaningless 细分)
③ 规则匹配门(按 priority 遍历 scene_registry,命中 CHOICE 规则的)
④ LLM 门(规则未命中,走 model function call)
"""
from app.services.scenes import REGISTRY
from app.services.scenes.gate_rules import GateRule, SceneRoute
from app.services.scenes.gate_rules import GateRule
request = state.get("request")
if request is None:
return {"gate_decision": "off_topic", "gate_scene_id": None}
message = str(state.get("message") or "").strip()
steward_state = state.get("steward_state") or {}
@@ -169,8 +163,9 @@ class StewardGraphPlannerService(StewardPlannerFallbackMixin, StewardPlannerExtr
if resume_scene:
return {"gate_decision": "resume", "gate_scene_id": resume_scene}
# ② off_topic 门
if not _matches_any_signal(message):
# ② off_topic 门:复用成熟的 _classify_irrelevant_input(含城市名/时间词/金额词等 94 词 + greeting/meaningless 细分)
scenario = self._classify_irrelevant_input(message, request)
if scenario is not None:
return {"gate_decision": "off_topic", "gate_scene_id": None}
# ③ 规则匹配门(按 priority 遍历,命中 CHOICE 规则的)
@@ -186,8 +181,7 @@ class StewardGraphPlannerService(StewardPlannerFallbackMixin, StewardPlannerExtr
# ④ LLM 门(规则未命中)
# 走 model_intent 时,如 state 已有 active_flow 且 LLM 准备 fallback,可优先做 candidate_flow
request = state.get("request")
if request is not None and self._looks_like_ambiguous_travel_flow(
if self._looks_like_ambiguous_travel_flow(
message, self._resolve_base_date_from_request(request), request
):
return {"gate_decision": "ambiguous", "gate_scene_id": None}