from typing import List, Dict, Tuple from pydantic import BaseModel, Field, field_validator class PaperInput(BaseModel): """Validated paper input schema""" paper_title: str = Field(..., min_length=5, max_length=500) paper_abstract: str = Field(..., min_length=50, max_length=5000) reviews: List[str] = Field(..., min_length=1, max_length=10) @field_validator('paper_title') @classmethod def validate_title(cls, v: str) -> str: """Validate paper title""" if not v or not v.strip(): raise ValueError("Paper title cannot be empty") return v.strip() @field_validator('paper_abstract') @classmethod def validate_abstract(cls, v: str) -> str: """Validate paper abstract""" if not v or not v.strip(): raise ValueError("Paper abstract cannot be empty") if len(v.strip()) < 50: raise ValueError("Paper abstract must be at least 50 characters") return v.strip() @field_validator('reviews') @classmethod def validate_reviews(cls, v: List[str]) -> List[str]: """Validate reviews""" if not v: raise ValueError("At least one review is required") valid_reviews = [] for i, review in enumerate(v): if not isinstance(review, str): raise ValueError(f"Review {i} must be a string") cleaned = review.strip() if len(cleaned) < 50: raise ValueError(f"Review {i} must be at least 50 characters") valid_reviews.append(cleaned) return valid_reviews class CritiqueInput(BaseModel): """Validated critique input schema""" reviews: List[str] = Field(..., min_length=1, max_length=10) @field_validator('reviews') @classmethod def validate_reviews(cls, v: List[str]) -> List[str]: """Validate reviews""" if not v: raise ValueError("At least one review is required") valid_reviews = [] for review in v: if isinstance(review, str) and len(review.strip()) >= 50: valid_reviews.append(review.strip()) if not valid_reviews: raise ValueError("No valid reviews found (must be at least 50 characters)") return valid_reviews class DisagreementInput(BaseModel): """Validated disagreement detection input schema""" critiques: List[Dict] = Field(..., min_length=2) @field_validator('critiques') @classmethod def validate_critiques(cls, v: List[Dict]) -> List[Dict]: """Validate critique structure""" if len(v) < 2: raise ValueError("At least 2 critiques required for disagreement detection") required_keys = {'Methodology', 'Experiments', 'Clarity', 'Significance', 'Novelty'} for i, critique in enumerate(v): if not isinstance(critique, dict): raise ValueError(f"Critique {i} must be a dictionary") # Check if critique has the expected structure if not any(key in critique for key in required_keys): raise ValueError(f"Critique {i} missing required categories") return v class SearchInput(BaseModel): """Validated search input schema""" paper_title: str = Field(..., min_length=5, max_length=500) paper_abstract: str = Field(..., min_length=50, max_length=5000) critiques: List[Dict] = Field(..., min_length=1) @field_validator('paper_title') @classmethod def validate_title(cls, v: str) -> str: """Validate paper title""" if not v or not v.strip(): raise ValueError("Paper title cannot be empty") return v.strip() @field_validator('paper_abstract') @classmethod def validate_abstract(cls, v: str) -> str: """Validate paper abstract""" if not v or not v.strip(): raise ValueError("Paper abstract cannot be empty") return v.strip() def validate_paper_input( paper_title: str, paper_abstract: str, reviews: List[str] ) -> Tuple[bool, str]: """ Validate paper input data Args: paper_title: Paper title paper_abstract: Paper abstract reviews: List of review texts Returns: Tuple of (is_valid, error_message) """ try: PaperInput( paper_title=paper_title, paper_abstract=paper_abstract, reviews=reviews ) return True, "" except Exception as e: return False, str(e) def validate_critique_input(reviews: List[str]) -> Tuple[bool, str]: """ Validate critique extraction input Args: reviews: List of review texts Returns: Tuple of (is_valid, error_message) """ try: CritiqueInput(reviews=reviews) return True, "" except Exception as e: return False, str(e) def validate_disagreement_input(critiques: List[Dict]) -> Tuple[bool, str]: """ Validate disagreement detection input Args: critiques: List of critique dictionaries Returns: Tuple of (is_valid, error_message) """ try: DisagreementInput(critiques=critiques) return True, "" except Exception as e: return False, str(e) def validate_search_input( paper_title: str, paper_abstract: str, critiques: List[Dict] ) -> Tuple[bool, str]: """ Validate search input Args: paper_title: Paper title paper_abstract: Paper abstract critiques: List of critique dictionaries Returns: Tuple of (is_valid, error_message) """ try: SearchInput( paper_title=paper_title, paper_abstract=paper_abstract, critiques=critiques ) return True, "" except Exception as e: return False, str(e)