- 新增 StewardGraphPlannerService,用 LangGraph 状态图编排意图识别→流程判断→模型/规则分支→兜底,替代原 planner 内线性调用 - 新增 StewardGraphRuntimeService 编排运行时决策与槽位决策;StewardActionContracts/Executor 统一动作合约与执行 - steward_intent_agent/application_fact_resolver/runtime_chat 适配图执行器,config 暴露图相关开关 - pyproject/uv.lock 新增 langgraph 依赖 - 新增 graph_planner/graph_runtime/action_executor 测试,更新 intent_agent/planner/fact_resolver/runtime_chat/reimbursement 测试
71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
from app.services.steward_intent_agent import (
|
||
STEWARD_INTENT_FUNCTION_NAME,
|
||
StewardIntentAgent,
|
||
)
|
||
from app.schemas.steward import StewardPlanRequest
|
||
|
||
|
||
class _NoToolCallRuntimeChatService:
|
||
def __init__(self) -> None:
|
||
self.kwargs = {}
|
||
|
||
def complete_with_tool_call(self, messages, **kwargs):
|
||
self.kwargs = kwargs
|
||
|
||
class _Result:
|
||
tool_call = None
|
||
|
||
@staticmethod
|
||
def calls_as_dicts():
|
||
return []
|
||
|
||
return _Result()
|
||
|
||
|
||
def test_steward_intent_tool_schema_supports_pending_flow_confirmation() -> None:
|
||
schema = StewardIntentAgent._build_intent_tool_schema(
|
||
["expense_type", "time_range", "location", "reason", "transport_mode"]
|
||
)
|
||
|
||
function_schema = schema["function"]
|
||
assert function_schema["name"] == STEWARD_INTENT_FUNCTION_NAME
|
||
properties = function_schema["parameters"]["properties"]
|
||
task_schema = properties["tasks"]["items"]
|
||
pending_schema = properties["pending_flow_confirmation"]
|
||
candidate_schema = pending_schema["properties"]["candidate_flows"]["items"]
|
||
|
||
assert task_schema["properties"]["requested_action"]["enum"] == [
|
||
"preview",
|
||
"save_draft",
|
||
"submit",
|
||
]
|
||
assert "requested_action" in task_schema["required"]
|
||
assert "pending_flow_confirmation" in properties
|
||
assert pending_schema["properties"]["status"]["enum"] == ["none", "pending"]
|
||
assert candidate_schema["properties"]["flow_id"]["enum"] == [
|
||
"travel_application",
|
||
"travel_reimbursement",
|
||
]
|
||
assert candidate_schema["properties"]["missing_fields"]["items"]["enum"] == [
|
||
"expense_type",
|
||
"time_range",
|
||
"location",
|
||
"reason",
|
||
"transport_mode",
|
||
]
|
||
|
||
|
||
def test_steward_intent_agent_uses_ten_second_timeout_and_three_attempts() -> None:
|
||
runtime_chat = _NoToolCallRuntimeChatService()
|
||
agent = StewardIntentAgent(runtime_chat)
|
||
|
||
agent.detect(
|
||
StewardPlanRequest(message="2026-02-20 至 2026-02-23,上海出差,火车,保存草稿。"),
|
||
base_date=__import__("datetime").date(2026, 6, 24),
|
||
canonical_fields=["expense_type", "time_range", "location", "reason", "transport_mode"],
|
||
)
|
||
|
||
assert runtime_chat.kwargs["timeout_seconds"] == 10
|
||
assert runtime_chat.kwargs["max_attempts"] == 3
|
||
assert runtime_chat.kwargs["use_failure_cooldown"] is False
|