chore: T-P-1 工作区收敛——并行会话成果与历史未入库文件整理入库

- 入库历史遗漏源码/测试:router_system 9 模块(agent/executors/inference/knowledge/
  memory/planner/skills/trace)、tests 11 个测试文件、config/knowledge 领域知识
- 入库根目录方案文档(v2/v3/可行性×2)、references 文献(arxiv 14-18/cnki_open/
  参考文献清单)、research 论文素材(routerarena/paper/中文文献 PDF)
- 前端构建产物刷新(新 hash);webapp 误写文档删除
- gitignore 增补:deepseek-harness、research/_refs、.mimosa/.zcode、网关日志/pid、
  临时调试脚本、tests/e2e/node_modules、AI代理功能开发/prefix
- 基线确认:318 passed
This commit is contained in:
tzt
2026-09-05 08:28:25 +08:00
parent 747d85c3ba
commit ce0f6170d3
82 changed files with 74132 additions and 36 deletions
+217
View File
@@ -0,0 +1,217 @@
"""Skill 技能体系(T12Agent-Skill 路由器·先行实现)。
把路由器独立为"技能注册表 + Agent 规划器"
- 用户只需提供需求,无需指定领域/模型
- Agent 路由器自行分析需求 → 规划 skill 调用序列(可组合、可依赖)→ 执行
Skill 抽象:name(唯一标识)+ description(能力描述,供规划器选择)
+ params(参数说明)+ execute(ctx)(执行,返回文本结果)。
内置技能(把专家系统内核能力封装为可调用单元):
- es.<kind> :规则执行器模板生成(analyze/design/implement/solve/... 共 18 种)
- kb.retrieve :知识库事实检索(法律/医疗/金融事实条目)
- kb.answer :规则 output 知识问答(git/docker/天气/翻译等常识条目)
- judge.evaluate:质量评分
- fallback.call :最后处理者(升级)
- cache.get / cache.put:两阶段缓存
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
from .executors import RuleExecutor
from .knowledge import KnowledgeBase
from .memory import TaskNode, WorkingMemory
from .models import ExpertResponse
@dataclass
class SkillContext:
"""一次 skill 调用的执行上下文(黑板 + 输入参数)。"""
query: str
domain: str
difficulty: str
memory: WorkingMemory
kb: Optional[KnowledgeBase] = None
args: Dict[str, Any] = field(default_factory=dict)
class Skill:
"""技能抽象:可被 Agent 路由器调用的能力单元。"""
name: str = "skill"
description: str = ""
params: List[str] = field(default_factory=list)
async def execute(self, ctx: SkillContext) -> str:
raise NotImplementedError
def __repr__(self) -> str:
return f"<Skill {self.name}>"
class SkillRegistry:
"""技能注册表:注册 / 发现 / 执行。"""
def __init__(self):
self._skills: Dict[str, Skill] = {}
def register(self, skill: Skill) -> None:
if skill.name in self._skills:
raise ValueError(f"技能重复注册: {skill.name}")
self._skills[skill.name] = skill
def get(self, name: str) -> Optional[Skill]:
return self._skills.get(name)
def has(self, name: str) -> bool:
return name in self._skills
def list(self) -> List[str]:
return sorted(self._skills.keys())
def catalog(self) -> List[Dict[str, Any]]:
"""技能目录(供 Agent 规划器 / 用户发现使用)。"""
return [
{"name": s.name, "description": s.description, "params": list(s.params)}
for s in sorted(self._skills.values(), key=lambda s: s.name)
]
async def execute(self, name: str, ctx: SkillContext) -> str:
skill = self._skills.get(name)
if skill is None:
raise KeyError(f"未注册技能: {name}(可用: {self.list()}")
return await skill.execute(ctx)
# ===============================================================
# 内置技能实现
# ===============================================================
class TemplateSkill(Skill):
"""es.<kind>:规则执行器模板生成(确定性、零参数)。"""
def __init__(self, kind: str, executor: RuleExecutor):
self.kind = kind
self._executor = executor
self.name = f"es.{kind}"
self.description = f"规则模板生成({kind}):结构化确定性输出"
self.params = ["domain", "difficulty", "memory"]
async def execute(self, ctx: SkillContext) -> str:
node = TaskNode(
id="skill", kind=self.kind, domain=ctx.domain,
query=ctx.query, desc=f"skill:{self.name}",
)
resp: ExpertResponse = await self._executor.generate(
ctx.query, ctx.difficulty, ctx.memory, node)
return resp.text
class KBRetrieveSkill(Skill):
"""kb.retrieve:知识库事实检索(法律/医疗/金融事实条目)。"""
name = "kb.retrieve"
description = "从知识库事实表检索领域知识条目(法条/指南/理财常识等)"
params = ["domain", "query"]
def __init__(self, kb: Optional[KnowledgeBase] = None):
self._kb = kb
async def execute(self, ctx: SkillContext) -> str:
kb = self._kb or ctx.kb
if kb is None:
return "kb.retrieve)未配置知识库。"
facts = kb.facts(ctx.domain)
hits = [f for f in facts if any(k in ctx.query for k in f.get("keywords", []))]
if hits:
lines = [f"- {f['statement']}" for f in hits]
return f"{ctx.domain} 知识检索】\n" + "\n".join(lines)
return (f"{ctx.domain} 知识检索】\n未命中知识库条目;"
f"建议以现行有效法规/最新指南为准。")
class KBAnswerSkill(Skill):
"""kb.answer:规则 output 知识问答(git/docker/天气/翻译等常识条目)。"""
name = "kb.answer"
description = "知识库规则问答:命中 output 规则直接给出知识章节"
params = ["domain", "query"]
def __init__(self, kb: Optional[KnowledgeBase] = None):
self._kb = kb
async def execute(self, ctx: SkillContext) -> str:
kb = self._kb or ctx.kb
if kb is None:
return "kb.answer)未配置知识库。"
hits = kb.match(ctx.query, domain=ctx.domain)
for h in hits:
if h.output:
from .inference import render_template
return render_template(h.output, ctx.query, {})
return "kb.answer)未命中知识规则。"
class JudgeSkill(Skill):
"""judge.evaluate:质量评分(5 维:覆盖/长度/格式/安全/知识引用)。"""
name = "judge.evaluate"
description = "评估回答质量(0-1 分),低于阈值建议升级"
params = ["query", "response", "domain"]
def __init__(self, judge, fallback_threshold: float = 0.70):
self._judge = judge
self._threshold = fallback_threshold
async def execute(self, ctx: SkillContext) -> str:
response = ctx.args.get("response", "")
domain = ctx.args.get("domain", ctx.domain)
eval_result = await self._judge.evaluate(ctx.query, response, domain)
return (f"【质量评分】{eval_result.overall_score:.2f} "
f"{'(需升级)' if eval_result.needs_fallback else '(达标)'} "
f"{'; '.join(eval_result.reasons)}")
class FallbackSkill(Skill):
"""fallback.call:最后处理者(升级/降级兜底)。"""
name = "fallback.call"
description = "调用最后处理者(本地≤8B 模型 / 降级模板 / mock)"
params = ["query"]
def __init__(self, fallback):
self._fallback = fallback
async def execute(self, ctx: SkillContext) -> str:
resp = await self._fallback.generate(ctx.query)
return resp.text
def build_skill_registry(kb: Optional[KnowledgeBase] = None,
executor: Optional[RuleExecutor] = None,
judge=None, fallback=None,
fallback_threshold: float = 0.70) -> SkillRegistry:
"""构建内置技能注册表。
模板技能自动注册 18 种 kindanalyze/design/implement/solve/diagnose/fix/
retrieve/conclude/advise/explain/disclaimer/verify/refactor/testcase/
complexity/optimize/draft/polish);retrieve 由 kb.retrieve 接管(更专)。
"""
reg = SkillRegistry()
exec_ = executor or RuleExecutor("rule-executor", "general", kb=kb)
_EXCLUDED = {"retrieve"} # retrieve 用 kb.retrieve(知识库驱动)
for kind in ("analyze", "design", "implement", "solve", "diagnose", "fix",
"conclude", "advise", "explain", "disclaimer", "verify",
"refactor", "testcase", "complexity", "optimize", "draft",
"polish"):
if kind not in _EXCLUDED:
reg.register(TemplateSkill(kind, exec_))
reg.register(KBRetrieveSkill(kb=kb))
reg.register(KBAnswerSkill(kb=kb))
if judge is not None:
reg.register(JudgeSkill(judge, fallback_threshold=fallback_threshold))
if fallback is not None:
reg.register(FallbackSkill(fallback))
return reg