- 入库历史遗漏源码/测试: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
91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
"""两级路由(domain_group)测试:用户指定大领域 → 组内路由模型 → 组内执行。"""
|
|
import pytest
|
|
|
|
from router_system.router import build_router
|
|
|
|
|
|
@pytest.fixture()
|
|
def router():
|
|
return build_router()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_explicit_group_tech(router):
|
|
# 指定 tech 组:跳过 8 领域统一分类器,组内路由识别 code
|
|
res = await router.route("用 Python 写一个快速排序函数", domain_group="tech")
|
|
assert res.domain == "code"
|
|
assert res.domain_group == "tech"
|
|
assert any("group:tech@explicit" in s for s in res.route)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_explicit_group_professional(router):
|
|
res = await router.route("加班费怎么计算", domain_group="professional")
|
|
assert res.domain == "legal"
|
|
assert res.domain_group == "professional"
|
|
assert res.subdomain == "labor"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_explicit_group_restricts_domain(router):
|
|
# 在 tech 组内问法律问题:组内分类器只认识 code/math → 低置信走最后处理者
|
|
res = await router.route("劳动合同违约怎么办", domain_group="tech")
|
|
assert res.upgraded is True
|
|
assert "direct_fallback" in res.route
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_auto_group_detection(router):
|
|
# 不指定 group:统一分类器识别 → 自动映射大领域组
|
|
res = await router.route("基金定投的收益率怎么计算")
|
|
assert res.domain == "finance"
|
|
assert res.domain_group == "professional"
|
|
assert any("group:professional@auto" in s for s in res.route)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_auto_group_tech(router):
|
|
res = await router.route("求 ∫ x^2 dx 从 0 到 1 的定积分")
|
|
assert res.domain == "math"
|
|
assert res.domain_group == "tech"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_invalid_group_raises(router):
|
|
with pytest.raises(ValueError):
|
|
await router.route("任意查询", domain_group="不存在的组")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_group_router_is_smaller(router):
|
|
# 组内分类器只认识组内领域:体积/匹配范围 ≈ 全量 1/4
|
|
assert len(router._group_classifiers["tech"].domains) == 2
|
|
assert len(router._group_classifiers["professional"].domains) == 3
|
|
assert len(router.classifier.domains) == 8
|
|
assert len(router.domain_groups) == 4
|
|
|
|
|
|
def test_health_shows_groups(router):
|
|
h = router.health()
|
|
assert "domain_groups" in h
|
|
assert "tech" in h["domain_groups"]
|
|
assert h["domain_groups"]["tech"] == ["code", "math"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_group_with_subdomain2(router):
|
|
res = await router.route("房贷利率是 LPR 加多少", domain_group="professional")
|
|
assert res.domain == "finance"
|
|
assert res.subdomain == "loan"
|
|
assert res.subdomain2 == "loan"
|
|
assert "⚠" in res.response # 金融风险免责
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_group_cache_roundtrip(router):
|
|
q = "加班费怎么计算"
|
|
r1 = await router.route(q, domain_group="professional")
|
|
r2 = await router.route(q, domain_group="professional") # 缓存命中
|
|
assert r2.cache_hit is True
|
|
assert r2.domain_group == r1.domain_group == "professional"
|