| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- from __future__ import annotations
- """路线评估阶段子图:组合候选航班与酒店,调用高德距离工具评估酒店位置与景点路线。"""
- from langchain_core.tools import BaseTool
- from langgraph.graph import (
- END,
- START,
- StateGraph,
- )
- from app.agents.map_agent import (
- MapResearchAgent,
- )
- from app.agents.requirement_agent import (
- RequirementAgent,
- )
- from app.agents.resource_agent import (
- ResourceSearchAgent,
- )
- from app.graph.map_nodes import (
- make_map_research_node,
- )
- from app.graph.nodes import (
- clarification_node,
- error_node,
- make_parse_request_node,
- route_after_parse,
- )
- from app.graph.resource_nodes import (
- make_resource_search_node,
- )
- from app.graph.route_nodes import (
- make_route_evaluation_node,
- route_after_map_research,
- route_after_selection,
- )
- from app.graph.selection_nodes import (
- make_candidate_selection_node,
- route_after_resources_to_selection,
- )
- from app.graph.state import TravelState
- from app.mcp_client import load_mcp_tools
- def find_tool(
- tools: list[BaseTool],
- *names: str,
- ) -> BaseTool | None:
- """按名称在MCP工具列表中查找目标工具,未找到返回None。"""
- for name in names:
- for tool in tools:
- if tool.name == name:
- return tool
- return None
- async def build_route_graph():
- """构建从需求解析到酒店路线评估的完整流程。"""
- tool_bundle = await load_mcp_tools()
- return_flight_tool = find_tool(
- tool_bundle.travel_tools,
- "search_return_flights",
- )
- distance_tool = find_tool(
- tool_bundle.amap_tools,
- "maps_distance",
- )
- around_search_tool = find_tool(
- tool_bundle.amap_tools,
- "maps_around_search",
- "maps_search_around",
- )
- if return_flight_tool is None:
- raise RuntimeError(
- "没有加载search_return_flights工具。"
- )
- if distance_tool is None:
- raise RuntimeError(
- "没有加载maps_distance工具。"
- )
- requirement_agent = RequirementAgent()
- resource_agent = ResourceSearchAgent(
- tools=tool_bundle.travel_tools,
- )
- map_agent = MapResearchAgent(
- tools=tool_bundle.amap_tools,
- )
- builder = StateGraph(TravelState)
- builder.add_node(
- "parse_request",
- make_parse_request_node(
- requirement_agent
- ),
- )
- builder.add_node(
- "clarify",
- clarification_node,
- )
- builder.add_node(
- "error",
- error_node,
- )
- builder.add_node(
- "search_resources",
- make_resource_search_node(
- resource_agent
- ),
- )
- builder.add_node(
- "select_candidates",
- make_candidate_selection_node(
- return_flight_tool,
- max_outbound_queries=2,
- max_returns_per_outbound=5,
- ),
- )
- builder.add_node(
- "research_destination",
- make_map_research_node(
- map_agent
- ),
- )
- builder.add_node(
- "evaluate_routes",
- make_route_evaluation_node(
- distance_tool=distance_tool,
- around_search_tool=(
- around_search_tool
- ),
- max_hotels=3,
- max_attractions=4,
- ),
- )
- builder.add_edge(
- START,
- "parse_request",
- )
- builder.add_conditional_edges(
- "parse_request",
- route_after_parse,
- {
- "clarify": "clarify",
- "error": "error",
- "ready": "search_resources",
- },
- )
- builder.add_edge("clarify", END)
- builder.add_edge("error", END)
- builder.add_conditional_edges(
- "search_resources",
- route_after_resources_to_selection,
- {
- "select_candidates": (
- "select_candidates"
- ),
- "end": END,
- },
- )
- builder.add_conditional_edges(
- "select_candidates",
- route_after_selection,
- {
- "research_destination": (
- "research_destination"
- ),
- "end": END,
- },
- )
- builder.add_conditional_edges(
- "research_destination",
- route_after_map_research,
- {
- "evaluate_routes": (
- "evaluate_routes"
- ),
- "end": END,
- },
- )
- builder.add_edge(
- "evaluate_routes",
- END,
- )
- return builder.compile()
|