from __future__ import annotations """Trip Reviewer节点:调用TripReviewerAgent从风险角度独立评审行程,生成阻塞问题与优化建议。""" from typing import Any, Literal from app.agents.reviewer_agent import ( TripReviewerAgent, ) from app.graph.state import TravelState from app.schemas.review import TripReviewResult def route_after_validation( state: TravelState, ) -> Literal[ "review_plan", "end", ]: """确定性校验执行后进入Reviewer。 即使方案校验失败,也允许Reviewer读取错误, 生成更完整的修改意见。 """ if state.get("errors"): return "end" if not state.get( "plan_validation_result" ): return "end" if not state.get("itinerary_plan"): return "end" return "review_plan" def _unique_feedback( values: list[str], ) -> list[str]: """对修改意见列表去重并去除空字符串,保持原有顺序。""" result: list[str] = [] for value in values: normalized = value.strip() if ( normalized and normalized not in result ): result.append(normalized) return result def make_trip_reviewer_node( agent: TripReviewerAgent, ): """创建Trip Reviewer节点。""" async def trip_reviewer_node( state: TravelState, ) -> dict[str, Any]: """评审节点:调用ReviewerAgent独立审查行程方案,将评审结论与修改意见写入state。""" attempts = ( state.get("review_attempts", 0) + 1 ) validation = state[ "plan_validation_result" ] try: result = await agent.review( request=state["travel_request"], plan=state["itinerary_plan"], validation=validation, map_result=state[ "map_research_result" ], route_result=state[ "route_evaluation_result" ], ) structured_response = result.get( "structured_response" ) if structured_response is None: message = ( "Trip Reviewer没有返回" "结构化结果。" ) existing_errors = list( state.get("errors", []) ) existing_errors.append(message) return { "review_attempts": attempts, "reviewer_messages": ( result.get("messages", []) ), "review_passed": False, "errors": existing_errors, "final_answer": message, } if not isinstance( structured_response, TripReviewResult, ): structured_response = ( TripReviewResult.model_validate( structured_response ) ) # Reviewer不能覆盖Validator结果。 review_passed = ( validation.is_valid and structured_response.approved ) combined_feedback = ( validation.revision_feedback + structured_response .revision_feedback ) combined_feedback = _unique_feedback( combined_feedback ) if review_passed: combined_feedback = [] message = ( "Trip Reviewer审查通过:" f"发现" f"{len(structured_response.issues)}" "项非阻塞问题," "方案可以进入最终输出阶段。" ) else: message = ( "Trip Reviewer审查未通过:" f"Validator错误" f"{validation.error_count}项," "Reviewer发现" f"{len(structured_response.issues)}" "项问题;" "方案需要重新规划。" ) return { "trip_review_result": ( structured_response ), "reviewer_messages": result.get( "messages", [], ), "review_passed": review_passed, "review_attempts": attempts, "revision_feedback": ( combined_feedback ), "final_answer": message, } except Exception as exc: message = ( "Trip Reviewer执行失败:" f"{type(exc).__name__}: {exc}" ) existing_errors = list( state.get("errors", []) ) existing_errors.append(message) return { "review_attempts": attempts, "review_passed": False, "errors": existing_errors, "final_answer": message, } return trip_reviewer_node