|
@@ -0,0 +1,122 @@
|
|
|
|
|
+from .state import TravelState
|
|
|
|
|
+from .tools import get_transport_tools,get_hotel_tools,get_attraction_tools
|
|
|
|
|
+from langchain.agents import create_agent
|
|
|
|
|
+from llm import create_model
|
|
|
|
|
+from config import load_config
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+config=load_config()
|
|
|
|
|
+llm = create_model(config)
|
|
|
|
|
+
|
|
|
|
|
+def coordinator_node(state: TravelState)->dict:
|
|
|
|
|
+ return{}
|
|
|
|
|
+#路线agent节点
|
|
|
|
|
+async def transport_agent_node(state: TravelState) -> dict:
|
|
|
|
|
+
|
|
|
|
|
+ user_request= state["user_request"]
|
|
|
|
|
+ tools=await get_transport_tools()
|
|
|
|
|
+ agent = create_agent(
|
|
|
|
|
+ model=llm,
|
|
|
|
|
+ tools=tools,
|
|
|
|
|
+ system_prompt="""你是旅行规划系统中的交通专家,只负责交通与市内通勤建议。
|
|
|
|
|
+根据用户需求,必要时调用地图工具查询路线、距离或交通方式。
|
|
|
|
|
+优先提供公共交通建议;用户明确自驾时再提供驾车建议。
|
|
|
|
|
+若用户未提供出发地、日期等关键条件,应明确说明你的假设或待确认信息。
|
|
|
|
|
+不得推荐酒店、景点或编造工具未返回的路线数据。
|
|
|
|
|
+输出应包含:推荐交通方式、预计耗时、关键换乘/路线信息、出行提醒。"""
|
|
|
|
|
+ )
|
|
|
|
|
+ result = await agent.ainvoke({"messages":[{"role":"user","content":user_request}]})
|
|
|
|
|
+ return {"transport_plan":result["messages"][-1].content}
|
|
|
|
|
+
|
|
|
|
|
+#酒店agent节点
|
|
|
|
|
+async def hotel_agent_node(state:TravelState)->dict:
|
|
|
|
|
+
|
|
|
|
|
+ user_request= state["user_request"]
|
|
|
|
|
+ tools=await get_hotel_tools()
|
|
|
|
|
+ agent = create_agent(
|
|
|
|
|
+ model=llm,
|
|
|
|
|
+ tools=tools,
|
|
|
|
|
+ system_prompt="""你是旅行规划系统中的住宿专家,只负责查询与推荐住宿。
|
|
|
|
|
+
|
|
|
|
|
+当用户给出了目的地时,必要时调用 hotel_search_and_recommend。
|
|
|
|
|
+调用时:
|
|
|
|
|
+- destination 必填,从用户请求中提取城市、区域或地标;
|
|
|
|
|
+- query 传入完整用户原始需求;
|
|
|
|
|
+- scene 可映射为商务、亲子、度假、背包或通用;
|
|
|
|
|
+- 用户明确给出入住/退房日期时,才传 YYYY-MM-DD 格式的 check_in/check_out;
|
|
|
|
|
+- guests 取用户明确人数,未说明时可省略;
|
|
|
|
|
+- max_price 只在用户明确给出“每晚预算”时传入;总旅行预算不能直接当作每晚预算。
|
|
|
|
|
+
|
|
|
|
|
+如果用户没有目的地,不调用工具,并要求补充目的地。
|
|
|
|
|
+不得编造酒店名称、价格、位置、评分或是否有房。
|
|
|
|
|
+推荐结果不代表已完成预订。
|
|
|
|
|
+不得规划交通、景点或完整行程。
|
|
|
|
|
+
|
|
|
|
|
+输出格式:
|
|
|
|
|
+1. 推荐住宿
|
|
|
|
|
+2. 每晚价格与位置
|
|
|
|
|
+3. 适合原因
|
|
|
|
|
+4. 需用户确认的信息"""
|
|
|
|
|
+ )
|
|
|
|
|
+ result = await agent.ainvoke({"messages":[{"role":"user","content":user_request}]})
|
|
|
|
|
+ return {"hotel_plan":result["messages"][-1].content}
|
|
|
|
|
+
|
|
|
|
|
+#景点agent节点
|
|
|
|
|
+async def attraction_agent_node(state:TravelState)->dict:
|
|
|
|
|
+
|
|
|
|
|
+ user_request= state["user_request"]
|
|
|
|
|
+ tools=await get_attraction_tools()
|
|
|
|
|
+ agent = create_agent(
|
|
|
|
|
+ model=llm,
|
|
|
|
|
+ tools=tools,
|
|
|
|
|
+ system_prompt="""你是旅行规划系统中的景点与活动专家,只负责景点推荐和游玩建议。
|
|
|
|
|
+用户提供目的地时,必须调用地图工具查询景点或天气后再回答。
|
|
|
|
|
+优先使用关键词搜索查找与用户偏好匹配的 POI。
|
|
|
|
|
+需要了解特定地点时,使用详情搜索;需要查询某个地点周边内容时,先获得其坐标,再使用周边搜索。
|
|
|
|
|
+根据天气工具结果给出合理出行提醒。
|
|
|
|
|
+
|
|
|
|
|
+不得虚构景点地址、营业时间、门票、评分、距离或天气数据。
|
|
|
|
|
+不得推荐酒店、规划交通路线或声称已完成预约。
|
|
|
|
|
+
|
|
|
|
|
+输出应包含:
|
|
|
|
|
+1. 推荐景点或区域;
|
|
|
|
|
+2. 每个推荐的类型、位置或商圈信息;
|
|
|
|
|
+3. 适合用户偏好的原因;
|
|
|
|
|
+4. 天气与游玩提醒;
|
|
|
|
|
+5. 需要用户确认的信息。"""
|
|
|
|
|
+ )
|
|
|
|
|
+ result = await agent.ainvoke({"messages":[{"role":"user","content":user_request}]})
|
|
|
|
|
+ return {"attraction_plan":result["messages"][-1].content}
|
|
|
|
|
+
|
|
|
|
|
+#整合agent
|
|
|
|
|
+async def integrator_agent_node(state: TravelState) -> dict:
|
|
|
|
|
+
|
|
|
|
|
+ user_request= state["user_request"]
|
|
|
|
|
+ transport_plan=state.get("transport_plan")
|
|
|
|
|
+ hotel_plan=state.get("hotel_plan")
|
|
|
|
|
+ attraction_plan=state.get("attraction_plan")
|
|
|
|
|
+ agent = create_agent(
|
|
|
|
|
+ model=llm,
|
|
|
|
|
+ tools=[],
|
|
|
|
|
+ system_prompt="""你是旅行规划系统中的方案整合专家。
|
|
|
|
|
+只能依据用户需求及交通、住宿、景点专家提供的结果生成方案。
|
|
|
|
|
+不得自行调用工具、补充未经专家结果支持的酒店、路线、景点价格、天气或营业信息。
|
|
|
|
|
+若专家结果冲突、缺失或信息不足,明确标记“待确认”,不要编造。
|
|
|
|
|
+
|
|
|
|
|
+输出格式:
|
|
|
|
|
+1. 旅行概览
|
|
|
|
|
+2. 交通与市内通勤
|
|
|
|
|
+3. 住宿建议
|
|
|
|
|
+4. 每日行程建议
|
|
|
|
|
+5. 注意事项与待确认事项"""
|
|
|
|
|
+ )
|
|
|
|
|
+ compose_text=f"""【用户需求】{user_request}
|
|
|
|
|
+ 【交通专家结果】
|
|
|
|
|
+ {transport_plan}
|
|
|
|
|
+ 【住宿专家结果】
|
|
|
|
|
+ {hotel_plan}
|
|
|
|
|
+ 【景点专家结果】
|
|
|
|
|
+ {attraction_plan}
|
|
|
|
|
+ """
|
|
|
|
|
+ result=await agent.ainvoke({"messages":[{"role":"user","content":compose_text}]})
|
|
|
|
|
+ return {"final_plan":result["messages"][-1].content}
|