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