feat: 小财管家意图规划与报销提交编排增强

- 完善管家意图识别、模型计划构建与规划器调度
- 重构差旅报销提交编排器与管家计划流程前端交互
- 优化报销消息项样式与文档中心视图
- 新增小财管家与附件上传风险前置复核设计文档
- 补充管家规划器与文档中心测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-04 14:25:14 +08:00
parent 1cbf3fee44
commit f60cebadb8
19 changed files with 2337 additions and 196 deletions

View File

@@ -68,6 +68,31 @@ class EmptyFunctionCallingIntentAgent:
return None
class EntertainmentFunctionCallingIntentAgent:
def detect(self, request, *, base_date, canonical_fields):
return StewardIntentAgentResult(
payload={
"thinking_events": [],
"tasks": [
{
"task_type": "reimbursement",
"title": "业务招待费报销",
"summary": "报销昨天业务招待费。",
"confidence": 0.9,
"ontology_fields": {
"time_range": "昨天",
"expense_type": "业务招待费",
"reason": "业务招待",
},
"missing_fields": [],
}
],
"attachment_groups": [],
},
model_call_traces=[],
)
def test_steward_planner_uses_llm_function_calling_plan_when_available() -> None:
payload = StewardPlanRequest(
message="我要报销昨天客户现场沟通的交通费",
@@ -98,6 +123,19 @@ def test_steward_planner_uses_llm_function_calling_plan_when_available() -> None
assert result.thinking_events[0].stage == "llm_function_call"
def test_steward_planner_normalizes_llm_business_entertainment_expense_type() -> None:
payload = StewardPlanRequest(
message="报销昨天业务招待费",
client_now_iso="2026-06-04T09:30:00+08:00",
)
result = StewardPlannerService(intent_agent=EntertainmentFunctionCallingIntentAgent()).build_plan(payload)
assert result.planning_source == "llm_function_call"
assert result.tasks[0].ontology_fields["expense_type"] == "entertainment"
assert result.tasks[0].ontology_fields["time_range"] == "2026-06-03"
def test_steward_planner_falls_back_to_rules_when_function_calling_is_unavailable() -> None:
payload = StewardPlanRequest(
message="我要报销昨天的交通费",
@@ -141,6 +179,29 @@ def test_steward_planner_splits_application_and_reimbursement_tasks() -> None:
assert all(action.status == "pending" for action in result.confirmation_groups)
def test_steward_planner_treats_future_travel_without_apply_word_as_application() -> None:
payload = StewardPlanRequest(
message="明天出差北京3天支撑国网仿生产部署并且报销昨天业务招待费",
user_id="u001",
client_now_iso="2026-06-04T09:30:00+08:00",
)
result = StewardPlannerService().build_plan(payload)
assert [task.task_type for task in result.tasks] == [
"expense_application",
"reimbursement",
]
assert result.tasks[0].assigned_agent == "application_assistant"
assert result.tasks[0].ontology_fields["time_range"] == "2026-06-05"
assert result.tasks[0].ontology_fields["location"] == "北京"
assert result.tasks[0].ontology_fields["expense_type"] == "travel"
assert result.tasks[0].ontology_fields["reason"] == "支撑国网仿生产部署"
assert result.tasks[1].assigned_agent == "reimbursement_assistant"
assert result.tasks[1].ontology_fields["time_range"] == "2026-06-03"
assert result.tasks[1].ontology_fields["expense_type"] == "entertainment"
def test_steward_planner_outputs_only_canonical_ontology_fields() -> None:
payload = StewardPlanRequest(
message="我要报销昨天的交通费",
@@ -210,5 +271,6 @@ def test_steward_stream_endpoint_emits_thinking_before_plan() -> None:
]
assert [event["event"] for event in events][:2] == ["thinking", "thinking"]
assert events[0]["data"]["stage"] == "stream_start"
assert events[-1]["event"] == "plan"
assert events[-1]["data"]["tasks"][0]["ontology_fields"]["time_range"] == "2026-06-03"