fix(review): apply code review fixes from ce-code-review
- P1: Use _resolve_execution_mode() instead of hardcoding SKILL_REACT in semantic_low_complexity, semantic_high, and merged_llm paths - P1: QualityGate escalation uses name-based check (c.name) instead of identity check (c is) for robustness - P2: Remove tautological complexity >= 0.3 in short_text_llm_hint - P2: Add empty query guard in SemanticRouter.route() - P2: Upgrade debug → warning log level for low-complexity fallback errors - P2: Validate skill_hint against _SKILL_NAME_RE in _classify_merged - P2: Rename has_high_signal → has_non_low_signal for clarity
This commit is contained in:
parent
11e2009cb8
commit
f99b3517d9
|
|
@ -178,6 +178,9 @@ class SemanticRouter:
|
|||
if self._index.size == 0:
|
||||
return SemanticRouteResult(confidence="low", skill_name=None, similarity=0.0)
|
||||
|
||||
if not query or not query.strip():
|
||||
return SemanticRouteResult(confidence="low", skill_name=None, similarity=0.0)
|
||||
|
||||
try:
|
||||
# Get query embedding (with cache)
|
||||
query_embedding = self._query_cache.get(query)
|
||||
|
|
|
|||
|
|
@ -643,10 +643,10 @@ class HeuristicClassifier:
|
|||
self._MEDIUM_EXACT_RE.findall(content)
|
||||
)
|
||||
|
||||
has_high_signal = high_hits > 0 or medium_hits > 0
|
||||
has_non_low_signal = high_hits > 0 or medium_hits > 0
|
||||
|
||||
# 低复杂度信号仅在无高/中复杂度信号时生效
|
||||
if has_low_signal and not has_high_signal:
|
||||
if has_low_signal and not has_non_low_signal:
|
||||
score = 0.05 # 问候/闲聊直接给极低分
|
||||
length = len(content)
|
||||
if length > 200:
|
||||
|
|
@ -853,8 +853,11 @@ class CostAwareRouter:
|
|||
merged_complexity = max(0.0, min(1.0, merged_complexity))
|
||||
skill_hint = data.get("skill_hint")
|
||||
|
||||
# If skill_hint provided and valid, route directly to that skill
|
||||
# Validate skill_hint against name pattern before lookup
|
||||
if skill_hint and skill_registry:
|
||||
if not _SKILL_NAME_RE.match(str(skill_hint).strip().lower()):
|
||||
logger.warning(f"Invalid skill_hint from LLM: {skill_hint!r}")
|
||||
skill_hint = None
|
||||
try:
|
||||
matched_skill = skill_registry.get(skill_hint)
|
||||
result = SkillRoutingResult(
|
||||
|
|
@ -866,7 +869,7 @@ class CostAwareRouter:
|
|||
match_method="merged_llm",
|
||||
match_confidence=0.7,
|
||||
complexity=merged_complexity,
|
||||
execution_mode=ExecutionMode.SKILL_REACT,
|
||||
execution_mode=_resolve_execution_mode(matched_skill.config),
|
||||
)
|
||||
# Merge tools
|
||||
agent_tools = (
|
||||
|
|
@ -1355,14 +1358,14 @@ class CostAwareRouter:
|
|||
result.match_confidence = semantic_result.similarity
|
||||
result.complexity = complexity
|
||||
if result.matched:
|
||||
result.execution_mode = ExecutionMode.SKILL_REACT
|
||||
result.execution_mode = _resolve_execution_mode(result.skill_config)
|
||||
result.execution_trace = trace if transparency != "SILENT" else []
|
||||
result.transparency_level = transparency
|
||||
span.set_attribute("route.layer", "semantic_low_complexity")
|
||||
span.set_attribute("route.target", result.skill_name or "default")
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.debug(f"Semantic routing for low-complexity query failed: {e}")
|
||||
logger.warning(f"Semantic routing for low-complexity query failed: {e}")
|
||||
|
||||
# Try IntentRouter keyword match before falling back to direct chat
|
||||
# Low-complexity queries like "翻译这段话" should still match skills
|
||||
|
|
@ -1396,7 +1399,7 @@ class CostAwareRouter:
|
|||
span.set_attribute("route.target", result.skill_name or "default")
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.debug(f"Intent routing for low-complexity query failed: {e}")
|
||||
logger.warning(f"Intent routing for low-complexity query failed: {e}")
|
||||
|
||||
# No semantic or intent match → direct chat
|
||||
result = SkillRoutingResult(
|
||||
|
|
@ -1457,7 +1460,7 @@ class CostAwareRouter:
|
|||
result.match_confidence = semantic_result.similarity
|
||||
result.complexity = complexity
|
||||
if result.matched:
|
||||
result.execution_mode = ExecutionMode.SKILL_REACT
|
||||
result.execution_mode = _resolve_execution_mode(result.skill_config)
|
||||
result.execution_trace = trace if transparency != "SILENT" else []
|
||||
result.transparency_level = transparency
|
||||
span.set_attribute("route.layer", "semantic_high")
|
||||
|
|
@ -1490,7 +1493,6 @@ class CostAwareRouter:
|
|||
if (
|
||||
skill_hint is None
|
||||
and len(clean_content) < 20
|
||||
and complexity >= 0.3
|
||||
and self._merged_llm_classify
|
||||
and self._llm_gateway is not None
|
||||
):
|
||||
|
|
|
|||
|
|
@ -126,12 +126,12 @@ class QualityGate:
|
|||
and skill_match_check.message
|
||||
and "Warning" in skill_match_check.message
|
||||
):
|
||||
other_failed = any(not c.passed for c in checks if c is not skill_match_check)
|
||||
other_failed = any(not c.passed for c in checks if c.name != "skill_match")
|
||||
if other_failed:
|
||||
# 升级:将 skill_match 的 passed 也设为 False
|
||||
checks = [
|
||||
QualityCheck(name=c.name, passed=False, message=c.message)
|
||||
if c is skill_match_check
|
||||
if c.name == "skill_match"
|
||||
else c
|
||||
for c in checks
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue