From 69184cb4a5155503d00fb4040441791c538db2c3 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sun, 16 Aug 2026 15:44:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=9B=AE=E5=BD=95=E5=B1=82=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=A2=9E=E5=BC=BA(=E6=8A=80=E8=83=BD=E5=90=8D?= =?UTF-8?q?=E6=8B=86=E5=88=86)+fallback(=E5=8C=B9=E9=85=8D=E4=B8=8D?= =?UTF-8?q?=E5=88=B0=E6=8C=89scope=E5=88=97=E5=87=BA),=E5=85=BC=E5=AE=B9He?= =?UTF-8?q?rmes=E7=9A=84trigger=5Fconditions=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pipeline_core/skill_loader.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/pipeline_core/skill_loader.py b/pipeline_core/skill_loader.py index 5ee78fb..01cf4d8 100644 --- a/pipeline_core/skill_loader.py +++ b/pipeline_core/skill_loader.py @@ -25,6 +25,7 @@ pipeline-core: Skill Loader — 六级可插拔技能隔离 import logging import os +import re from dataclasses import dataclass, field from typing import Dict, List, Optional @@ -280,18 +281,29 @@ class SkillLoader: role: str = "", project_id: str = "", org_id: str = "", user_id: str = "", max_skills: int = 5) -> List[Skill]: - """根据用户输入匹配相关技能(trigger_keywords + scope 加权)""" + """根据用户输入匹配相关技能(trigger_keywords + 技能名拆分 + scope 加权)。 + + 兼容 Hermes 技能格式:多数 Hermes 技能只有 trigger_conditions(自然语言)而无 + trigger_keywords,因此额外用技能名拆分匹配(module-development-spec → module/development/spec) + 兜底,保证英文技能名也能被中文输入触达。 + """ all_skills = list(self.get_merged(pipeline_id, role, project_id, org_id, user_id).values()) scored = [] user_lower = user_input.lower() for skill in all_skills: score = 0 + # 1. 显式 trigger_keywords(中文/英文关键词) for kw in skill.trigger_keywords: if kw.lower() in user_lower: - score += 1 + score += 3 + # 2. 技能名整体匹配 if skill.name.lower() in user_lower: score += 2 - # scope 优先级加权 + # 3. 技能名拆分匹配(module-development-spec → module/development/spec) + for part in re.split(r'[-_]+', skill.name.lower()): + if len(part) >= 3 and part in user_lower: + score += 1 + # 4. scope 优先级加权 score += SCOPE_PRIORITY.get(skill.scope, 0) if score > 0: scored.append((score, skill)) @@ -322,10 +334,16 @@ class SkillLoader: if user_input: skills = self.get_by_trigger(user_input, pipeline_id, role, project_id, org_id, user_id, max_skills) + if not skills: + # 匹配不到时兜底:按 scope 优先级 + 名字稳定排序,避免目录层为空 + merged = self.get_merged(pipeline_id, role, project_id, org_id, user_id) + skills = sorted(merged.values(), + key=lambda s: (SCOPE_PRIORITY.get(s.scope, 9), s.name)) + skills = skills[:max_skills] else: merged = self.get_merged(pipeline_id, role, project_id, org_id, user_id) skills = sorted(merged.values(), - key=lambda s: SCOPE_PRIORITY.get(s.scope, 9)) + key=lambda s: (SCOPE_PRIORITY.get(s.scope, 9), s.name)) skills = skills[:max_skills] if not skills: