from __future__ import annotations """行程评审结果模型:TripReviewResult包含评审结论、问题列表与修改意见。""" from typing import Literal from pydantic import Field, model_validator from app.schemas.common import AppModel ReviewCategory = Literal[ "requirement_fit", "pace", "geography", "flight", "hotel", "budget", "completeness", "grounding", "user_experience", "other", ] ReviewSeverity = Literal[ "blocking", "warning", ] class ReviewIssue(AppModel): """Reviewer发现的单个语义问题。""" category: ReviewCategory severity: ReviewSeverity message: str day_index: int | None = Field( default=None, ge=1, le=30, ) activity_name: str | None = None evidence: str | None = None suggestion: str | None = None class TripReviewResult(AppModel): """Trip Reviewer的结构化审查结果。""" approved: bool summary: str strengths: list[str] = Field( default_factory=list ) issues: list[ReviewIssue] = Field( default_factory=list ) # 非阻塞优化建议。 recommendations: list[str] = Field( default_factory=list ) # 仅在方案不通过时填写, # 下一轮Planner必须执行这些修改。 revision_feedback: list[str] = Field( default_factory=list ) @model_validator(mode="after") def validate_review_result( self, ) -> "TripReviewResult": blocking_issues = [ issue for issue in self.issues if issue.severity == "blocking" ] if self.approved: if blocking_issues: raise ValueError( "审查通过时不能包含blocking问题。" ) if self.revision_feedback: raise ValueError( "审查通过时revision_feedback" "必须为空。" ) else: if not self.revision_feedback: raise ValueError( "审查不通过时必须给出" "revision_feedback。" ) return self