初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,135 @@
|
||||
"""洛书 Deliberative 规划器测试。"""
|
||||
|
||||
from app.application.planning import (
|
||||
DeliberativePlan,
|
||||
PlanStep,
|
||||
build_planning_prompt,
|
||||
format_plan_for_prompt,
|
||||
parse_plan,
|
||||
should_plan,
|
||||
)
|
||||
|
||||
|
||||
def test_parse_plan_full() -> None:
|
||||
"""完整 JSON 计划解析。"""
|
||||
raw = """```json
|
||||
{
|
||||
"title": "调研项目X",
|
||||
"assumptions": ["需要模型网关RAG能力"],
|
||||
"risks": ["外部API可能超时"],
|
||||
"steps": [
|
||||
{"id": 1, "title": "搜索文档", "description": "搜索关于项目X的文档",
|
||||
"tool": "web_search", "risk_level": "L2"},
|
||||
{"id": 2, "title": "阅读结果", "description": "阅读搜索结果",
|
||||
"tool": "read_file", "risk_level": "L1"},
|
||||
{"id": 3, "title": "汇总", "description": "汇总分析",
|
||||
"tool": null, "risk_level": "L1"}
|
||||
]
|
||||
}
|
||||
```"""
|
||||
plan = parse_plan(raw)
|
||||
assert plan is not None
|
||||
assert plan.title == "调研项目X"
|
||||
assert len(plan.assumptions) == 1
|
||||
assert len(plan.risks) == 1
|
||||
assert len(plan.steps) == 3
|
||||
assert plan.steps[0].tool == "web_search"
|
||||
assert plan.steps[2].tool is None
|
||||
assert plan.steps[0].risk_level == "L2"
|
||||
|
||||
|
||||
def test_parse_plan_no_fence() -> None:
|
||||
"""无 ``` 围栏的 JSON 也能解析。"""
|
||||
raw = '{"title": "简单计划", "steps": [{"id": 1, "title": "执行", "description": ""}]}'
|
||||
plan = parse_plan(raw)
|
||||
assert plan is not None
|
||||
assert plan.title == "简单计划"
|
||||
assert len(plan.steps) == 1
|
||||
|
||||
|
||||
def test_parse_plan_missing_title() -> None:
|
||||
"""缺少标题 → None。"""
|
||||
raw = '{"steps": [{"id": 1, "title": "执行", "description": ""}]}'
|
||||
assert parse_plan(raw) is None
|
||||
|
||||
|
||||
def test_parse_plan_empty_steps() -> None:
|
||||
"""空步骤列表 → None。"""
|
||||
raw = '{"title": "空计划", "steps": []}'
|
||||
assert parse_plan(raw) is None
|
||||
|
||||
|
||||
def test_parse_plan_invalid_json() -> None:
|
||||
"""非法 JSON → None。"""
|
||||
assert parse_plan("根本不是JSON") is None
|
||||
|
||||
|
||||
def test_parse_plan_not_dict() -> None:
|
||||
"""返回非对象 → None。"""
|
||||
assert parse_plan("[1, 2, 3]") is None
|
||||
|
||||
|
||||
def test_should_plan_triggers() -> None:
|
||||
"""包含关键词的请求应触发规划。"""
|
||||
triggers = [
|
||||
"搜索一下项目X的背景",
|
||||
"帮我调研一下最新技术",
|
||||
"分析这个方案的优缺点",
|
||||
"比较A和B的差异",
|
||||
"研究一下这个问题",
|
||||
"search for relevant docs",
|
||||
"research the market",
|
||||
]
|
||||
for t in triggers:
|
||||
assert should_plan(t), f"should plan: {t}"
|
||||
|
||||
|
||||
def test_should_plan_no_triggers() -> None:
|
||||
"""简单请求不应触发。"""
|
||||
no_triggers = [
|
||||
"你好",
|
||||
"再见",
|
||||
"今天天气怎么样",
|
||||
"帮我写首诗",
|
||||
]
|
||||
for t in no_triggers:
|
||||
assert not should_plan(t), f"should not plan: {t}"
|
||||
|
||||
|
||||
def test_build_planning_prompt() -> None:
|
||||
"""规划 prompt 包含必要结构。"""
|
||||
prompt = build_planning_prompt("搜索资料", memory_context="用户关心项目X")
|
||||
assert "NO_PLAN_NEEDED" in prompt
|
||||
assert "搜索资料" in prompt
|
||||
assert "用户关心项目X" in prompt
|
||||
|
||||
|
||||
def test_format_plan_for_prompt() -> None:
|
||||
"""计划格式化后包含步骤和元信息。"""
|
||||
plan = DeliberativePlan(
|
||||
title="测试计划",
|
||||
steps=[
|
||||
PlanStep(id=1, title="第一步", description="做A", tool="tool1", risk_level="L2"),
|
||||
PlanStep(id=2, title="第二步", description="做B", risk_level="L1"),
|
||||
],
|
||||
assumptions=["假设1"],
|
||||
risks=["风险1"],
|
||||
)
|
||||
text = format_plan_for_prompt(plan)
|
||||
assert "测试计划" in text
|
||||
assert "第一步" in text
|
||||
assert "tool1" in text
|
||||
assert "第二步" in text
|
||||
assert "假设1" in text
|
||||
assert "风险1" in text
|
||||
|
||||
|
||||
def test_format_plan_empty_assumptions_and_risks() -> None:
|
||||
"""无假设/风险时格式化正常。"""
|
||||
plan = DeliberativePlan(
|
||||
title="简单",
|
||||
steps=[PlanStep(id=1, title="做", description="")],
|
||||
)
|
||||
text = format_plan_for_prompt(plan)
|
||||
assert "简单" in text
|
||||
assert "做" in text
|
||||
Reference in new issue
Block a user