planner_nodes.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. from __future__ import annotations
  2. """行程规划节点:调用ItineraryPlannerAgent根据候选资源和修改意见生成多日行程。"""
  3. from typing import Any, Literal
  4. from app.agents.itinerary_agent import (
  5. ItineraryPlannerAgent,
  6. )
  7. from app.graph.state import TravelState
  8. from app.schemas.itinerary import ItineraryPlan
  9. def route_after_route_evaluation(
  10. state: TravelState,
  11. ) -> Literal[
  12. "plan_itinerary",
  13. "end",
  14. ]:
  15. """路线评估成功后进入行程规划。"""
  16. if state.get("errors"):
  17. return "end"
  18. if not state.get(
  19. "candidate_selection_result"
  20. ):
  21. return "end"
  22. if not state.get(
  23. "map_research_result"
  24. ):
  25. return "end"
  26. if not state.get(
  27. "route_evaluation_result"
  28. ):
  29. return "end"
  30. return "plan_itinerary"
  31. def make_itinerary_planner_node(
  32. agent: ItineraryPlannerAgent,
  33. ):
  34. """创建行程规划角色节点。"""
  35. async def itinerary_planner_node(
  36. state: TravelState,
  37. ) -> dict[str, Any]:
  38. """行程规划节点:调用Agent生成ItineraryPlan,必要时合并revision_feedback进行重规划。"""
  39. attempts = (
  40. state.get("planning_attempts", 0)
  41. + 1
  42. )
  43. try:
  44. result = await agent.plan(
  45. request=state["travel_request"],
  46. selection=state[
  47. "candidate_selection_result"
  48. ],
  49. map_result=state[
  50. "map_research_result"
  51. ],
  52. route_result=state[
  53. "route_evaluation_result"
  54. ],
  55. revision_feedback=state.get(
  56. "revision_feedback",
  57. [],
  58. ),
  59. )
  60. structured_response = result.get(
  61. "structured_response"
  62. )
  63. if structured_response is None:
  64. message = (
  65. "行程规划Agent没有返回"
  66. "结构化结果。"
  67. )
  68. return {
  69. "planning_attempts": attempts,
  70. "planner_messages": result.get(
  71. "messages",
  72. [],
  73. ),
  74. "errors": [message],
  75. "final_answer": message,
  76. }
  77. if not isinstance(
  78. structured_response,
  79. ItineraryPlan,
  80. ):
  81. structured_response = (
  82. ItineraryPlan.model_validate(
  83. structured_response
  84. )
  85. )
  86. day_count = len(
  87. structured_response.days
  88. )
  89. activity_count = sum(
  90. len(day.activities)
  91. for day
  92. in structured_response.days
  93. )
  94. return {
  95. "itinerary_plan": (
  96. structured_response
  97. ),
  98. "planner_messages": result.get(
  99. "messages",
  100. [],
  101. ),
  102. "planning_attempts": attempts,
  103. "final_answer": (
  104. "行程规划角色执行完成:"
  105. f"生成{day_count}天行程,"
  106. f"共安排{activity_count}项活动;"
  107. "等待预算和规则校验。"
  108. ),
  109. }
  110. except Exception as exc:
  111. message = (
  112. "行程规划Agent执行失败:"
  113. f"{type(exc).__name__}: {exc}"
  114. )
  115. existing_errors = list(
  116. state.get("errors", [])
  117. )
  118. existing_errors.append(message)
  119. return {
  120. "planning_attempts": attempts,
  121. "errors": existing_errors,
  122. "final_answer": message,
  123. }
  124. return itinerary_planner_node