from pydantic import BaseModel, Field class AVMPredictRequest(BaseModel): area: float = Field(..., gt=0, description="Property area in m²") district: str = Field(..., min_length=1, description="District name") city: str = Field(..., min_length=1, description="City name") property_type: str = Field(..., description="e.g. apartment, house, land") bedrooms: int = Field(0, ge=0) bathrooms: int = Field(0, ge=0) floors: int = Field(0, ge=0) frontage: float = Field(0.0, ge=0, description="Frontage width in meters") road_width: float = Field(0.0, ge=0, description="Adjacent road width in meters") year_built: int | None = Field(None, description="Year the property was built") has_legal_paper: bool = Field(True, description="Whether property has sổ đỏ/sổ hồng") class AVMPredictResponse(BaseModel): estimated_price_vnd: float = Field(..., description="Estimated price in VND") confidence: float = Field(..., ge=0, le=1, description="Prediction confidence score") price_per_m2: float = Field(..., description="Price per m² in VND") price_range_low: float = Field(..., description="Lower bound estimate in VND") price_range_high: float = Field(..., description="Upper bound estimate in VND") class FeatureExtractRequest(BaseModel): text: str = Field(..., min_length=1, description="Vietnamese property listing text") class ExtractedFeatures(BaseModel): area: float | None = None district: str | None = None city: str | None = None property_type: str | None = None bedrooms: int | None = None bathrooms: int | None = None floors: int | None = None frontage: float | None = None road_width: float | None = None price_mentioned: float | None = None has_legal_paper: bool | None = None address_raw: str | None = None class FeatureExtractResponse(BaseModel): features: ExtractedFeatures tokens: list[str] = Field(default_factory=list, description="Tokenized words") entities: list[dict] = Field(default_factory=list, description="Named entities found")