From 5f18c123c8aa3814e19be3489ef87f2a167cc93d Mon Sep 17 00:00:00 2001 From: Sadmin Date: Tue, 29 Apr 2025 00:06:25 +0600 Subject: [PATCH 1/3] feat(schema): add automobile insurance form schema --- vlmrun/hub/schemas/contrib/catalog.yaml | 9 ++ .../contrib/document/automobile_insurance.py | 138 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 vlmrun/hub/schemas/contrib/document/automobile_insurance.py diff --git a/vlmrun/hub/schemas/contrib/catalog.yaml b/vlmrun/hub/schemas/contrib/catalog.yaml index bebb954..54653e3 100644 --- a/vlmrun/hub/schemas/contrib/catalog.yaml +++ b/vlmrun/hub/schemas/contrib/catalog.yaml @@ -157,3 +157,12 @@ schemas: metadata: supported_inputs: ["image", "document"] tags: ["tax", "finance", "accounting", "irs", "form-1040"] + + - domain: document.automobile-insurance + schema: vlmrun.hub.schemas.contrib.document.automobile_insurance.AutomobileInsurance + prompt: "You are a detail-oriented automobile insurance document analyst. Extract all the relevant information from the automobile insurance document as accurately as possible." + description: "Automobile insurance document information extraction system that processes automobile insurance documents to extract structured information including applicant details, co-applicant details, address, contact information, ownership status, drivers, vehicles, policy details, current insurance, commercial vehicle details, and declarations." + sample_data: "https://raw.githubusercontent.com/Sadmin23/Resourse/main/insurance-form-filled.pdf" + metadata: + supported_inputs: ["image", "document"] + tags: ["insurance", "automobile", "document"] \ No newline at end of file diff --git a/vlmrun/hub/schemas/contrib/document/automobile_insurance.py b/vlmrun/hub/schemas/contrib/document/automobile_insurance.py new file mode 100644 index 0000000..5b78fd7 --- /dev/null +++ b/vlmrun/hub/schemas/contrib/document/automobile_insurance.py @@ -0,0 +1,138 @@ +from datetime import date +from enum import Enum +from typing import Dict, List, Optional + +from pydantic import BaseModel, Field + + +class OwnershipStatus(str, Enum): + RENT = "rent" + OWN = "own" + # Add capitalized variants + RENT_CAP = "Rent" + OWN_CAP = "Own" + + +class MaritalStatus(str, Enum): + SINGLE = "single" + MARRIED = "married" + DIVORCED = "divorced" + WIDOWED = "widowed" + SEPARATED = "separated" + # Add capitalized variants + SINGLE_CAP = "Single" + MARRIED_CAP = "Married" + DIVORCED_CAP = "Divorced" + WIDOWED_CAP = "Widowed" + SEPARATED_CAP = "Separated" + + +class Gender(str, Enum): + MALE = "male" + FEMALE = "female" + OTHER = "other" + PREFER_NOT_TO_SAY = "prefer_not_to_say" + # Add capitalized variants + MALE_CAP = "Male" + FEMALE_CAP = "Female" + OTHER_CAP = "Other" + PREFER_NOT_TO_SAY_CAP = "Prefer not to say" + + +class UsageType(str, Enum): + BUSINESS = "business" + PLEASURE = "pleasure" + CARPOOL = "carpool" + COMMUTE = "commute" + # Add capitalized variants + BUSINESS_CAP = "Business" + PLEASURE_CAP = "Pleasure" + CARPOOL_CAP = "Carpool" + COMMUTE_CAP = "Commute" + + +class CoverageType(str, Enum): + COMPREHENSIVE = "comprehensive" + THIRD_PARTY = "third_party" + THIRD_PARTY_FIRE_THEFT = "third_party_fire_theft" + LIABILITY_ONLY = "liability_only" + # Add capitalized variants + COMPREHENSIVE_CAP = "Comprehensive" + THIRD_PARTY_CAP = "Third Party" + THIRD_PARTY_FIRE_THEFT_CAP = "Third Party Fire & Theft" + LIABILITY_ONLY_CAP = "Liability Only" + + +class Address(BaseModel): + street: str = Field(..., description="Street address (e.g., '123 Elm St Apt 4B')") + city: str = Field(..., description="City name") + state: str = Field(..., description="State or province (e.g., 'CA', 'NY', 'TX')") + zip_code: str = Field(..., description="ZIP or postal code (e.g., '12345-6789')") + county: Optional[str] = Field(None, description="County name if applicable") + + +class ContactInfo(BaseModel): + home_phone: Optional[str] = Field(None, description="Home telephone number") + business_phone: Optional[str] = Field(None, description="Business or work telephone number") + email: Optional[str] = Field(None, description="Email address") + + +class Conviction(BaseModel): + date: str = Field(..., description="Date of the conviction") + offense_type: str = Field(..., description="Type of offense (e.g., 'speeding', 'DUI')") + details: Optional[str] = Field(None, description="Additional details about the conviction") + points: Optional[int] = Field(None, description="Points assigned to the license for this conviction", ge=0) + + +class Accident(BaseModel): + date: str = Field(..., description="Date of the accident") + description: str = Field(..., description="Brief description of the accident") + at_fault: Optional[bool] = Field(None, description="Whether the driver was at fault") + claim_amount: Optional[float] = Field(None, description="Amount claimed for damages", ge=0) + injuries: Optional[bool] = Field(None, description="Whether the accident involved injuries") + + +class Driver(BaseModel): + name: str = Field(..., description="Full name of the driver") + marital_status: Optional[MaritalStatus] = Field(None, description="Marital status of the driver") + gender: Optional[Gender] = Field(None, description="Gender of the driver") + date_of_birth: str = Field(..., description="Driver's date of birth (YYYY-MM-DD)") + date_licensed: str = Field(..., description="Date when driver was first licensed (YYYY-MM-DD)") + driver_license_number: str = Field(..., description="Driver's license number") + license_state: str = Field(..., description="State that issued the driver's license") + social_security_number: Optional[str] = Field(None, description="Driver's social security number") + occupation: Optional[str] = Field(None, description="Driver's current occupation") + medical_conditions: Optional[List[str]] = Field(None, description="List of medical conditions that may affect driving") + convictions: Optional[List[Conviction]] = Field(None, description="List of motoring or non-motoring offenses") + accident_history: Optional[List[Accident]] = Field(None, description="History of past accidents") + previous_insurance_declined: Optional[bool] = Field(None, description="Whether driver has been declined insurance previously") + license_suspended: Optional[bool] = Field(None, description="Whether driver's license has ever been suspended") + + +class Vehicle(BaseModel): + vin: str = Field(..., description="Vehicle Identification Number") + make_model: str = Field(..., description="Make and model of the vehicle") + year: str = Field(..., description="Year of manufacture") + annual_mileage: Optional[int] = Field(None, description="Estimated annual mileage", ge=0) + usage_type: Optional[UsageType] = Field(None, description="Primary usage of the vehicle") + anti_theft_devices: Optional[List[str]] = Field(None, description="Anti-theft devices installed in the vehicle") + airbag_status: Optional[str] = Field(None, description="Airbag availability (e.g., 'Driver & Passenger')") + garaged_address: Optional[str] = Field(None, description="Address where vehicle is primarily garaged") + modifications: Optional[List[str]] = Field(None, description="Modifications made to the vehicle") + purchase_date: Optional[str] = Field(None, description="Date when vehicle was purchased (YYYY-MM-DD)") + estimated_value: Optional[float] = Field(None, description="Estimated current value of the vehicle", ge=0) + + +class Deductibles(BaseModel): + collision: Optional[float] = Field(None, description="Collision deductible amount", ge=0) + comprehensive: Optional[float] = Field(None, description="Comprehensive deductible amount", ge=0) + + +class AutomobileInsurance(BaseModel): + applicant_name: str = Field(..., description="Full name of the primary applicant") + co_applicant_name: Optional[str] = Field(None, description="Full name of co-applicant, if any") + address: Address = Field(..., description="Primary residence address of the applicant") + contact_info: ContactInfo = Field(..., description="Contact information of the applicant") + ownership_status: Optional[OwnershipStatus] = Field(None, description="Whether applicant rents or owns their residence") + drivers: List[Driver] = Field(..., description="List of drivers to be covered by the policy") + vehicles: List[Vehicle] = Field(..., description="List of vehicles to be covered by the policy") \ No newline at end of file From 29822001e874257bdc6f9f0d97bc3a2a01cd6459 Mon Sep 17 00:00:00 2001 From: Sadmin Date: Tue, 29 Apr 2025 11:40:41 +0600 Subject: [PATCH 2/3] feat(schema): update automobile insurance form schema --- vlmrun/hub/schemas/contrib/catalog.yaml | 2 +- .../schemas/contrib/document/automobile_insurance.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vlmrun/hub/schemas/contrib/catalog.yaml b/vlmrun/hub/schemas/contrib/catalog.yaml index 54653e3..1ea123f 100644 --- a/vlmrun/hub/schemas/contrib/catalog.yaml +++ b/vlmrun/hub/schemas/contrib/catalog.yaml @@ -162,7 +162,7 @@ schemas: schema: vlmrun.hub.schemas.contrib.document.automobile_insurance.AutomobileInsurance prompt: "You are a detail-oriented automobile insurance document analyst. Extract all the relevant information from the automobile insurance document as accurately as possible." description: "Automobile insurance document information extraction system that processes automobile insurance documents to extract structured information including applicant details, co-applicant details, address, contact information, ownership status, drivers, vehicles, policy details, current insurance, commercial vehicle details, and declarations." - sample_data: "https://raw.githubusercontent.com/Sadmin23/Resourse/main/insurance-form-filled.pdf" + sample_data: "https://raw.githubusercontent.com/Sadmin23/Resourse/main/insurance-form-1.pdf" metadata: supported_inputs: ["image", "document"] tags: ["insurance", "automobile", "document"] \ No newline at end of file diff --git a/vlmrun/hub/schemas/contrib/document/automobile_insurance.py b/vlmrun/hub/schemas/contrib/document/automobile_insurance.py index 5b78fd7..e26dce8 100644 --- a/vlmrun/hub/schemas/contrib/document/automobile_insurance.py +++ b/vlmrun/hub/schemas/contrib/document/automobile_insurance.py @@ -97,9 +97,9 @@ class Driver(BaseModel): marital_status: Optional[MaritalStatus] = Field(None, description="Marital status of the driver") gender: Optional[Gender] = Field(None, description="Gender of the driver") date_of_birth: str = Field(..., description="Driver's date of birth (YYYY-MM-DD)") - date_licensed: str = Field(..., description="Date when driver was first licensed (YYYY-MM-DD)") - driver_license_number: str = Field(..., description="Driver's license number") - license_state: str = Field(..., description="State that issued the driver's license") + date_licensed: Optional[str] = Field(None, description="Date when driver was first licensed (YYYY-MM-DD)") + driver_license_number: Optional[str] = Field(None, description="Driver's license number") + license_state: Optional[str] = Field(None, description="State that issued the driver's license") social_security_number: Optional[str] = Field(None, description="Driver's social security number") occupation: Optional[str] = Field(None, description="Driver's current occupation") medical_conditions: Optional[List[str]] = Field(None, description="List of medical conditions that may affect driving") @@ -110,9 +110,9 @@ class Driver(BaseModel): class Vehicle(BaseModel): - vin: str = Field(..., description="Vehicle Identification Number") - make_model: str = Field(..., description="Make and model of the vehicle") - year: str = Field(..., description="Year of manufacture") + vin: Optional[str] = Field(None, description="Vehicle Identification Number") + make_model: Optional[str] = Field(None, description="Make and model of the vehicle") + year: Optional[str] = Field(None, description="Year of manufacture") annual_mileage: Optional[int] = Field(None, description="Estimated annual mileage", ge=0) usage_type: Optional[UsageType] = Field(None, description="Primary usage of the vehicle") anti_theft_devices: Optional[List[str]] = Field(None, description="Anti-theft devices installed in the vehicle") From 16f217b83feaffb2a4adf8401c2e79f2dc2eb09c Mon Sep 17 00:00:00 2001 From: Sadmin Date: Fri, 2 May 2025 16:51:45 +0600 Subject: [PATCH 3/3] feat(schema): add mortgage application form schema --- vlmrun/hub/schemas/contrib/catalog.yaml | 11 +- .../contrib/document/mortgage_application.py | 213 ++++++++++++++++++ 2 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 vlmrun/hub/schemas/contrib/document/mortgage_application.py diff --git a/vlmrun/hub/schemas/contrib/catalog.yaml b/vlmrun/hub/schemas/contrib/catalog.yaml index 1ea123f..5259f42 100644 --- a/vlmrun/hub/schemas/contrib/catalog.yaml +++ b/vlmrun/hub/schemas/contrib/catalog.yaml @@ -165,4 +165,13 @@ schemas: sample_data: "https://raw.githubusercontent.com/Sadmin23/Resourse/main/insurance-form-1.pdf" metadata: supported_inputs: ["image", "document"] - tags: ["insurance", "automobile", "document"] \ No newline at end of file + tags: ["insurance", "automobile", "document"] + + - domain: document.mortgage-application + schema: vlmrun.hub.schemas.contrib.document.mortgage_application.MortgageApplication + prompt: "You are a detail-oriented mortgage application document analyst. Extract all the relevant information from the mortgage application document as accurately as possible." + description: "Mortgage application document information extraction system that processes mortgage application documents to extract structured information including applicant details, co-applicant details, address, contact information, ownership status, drivers, vehicles, policy details, current insurance, commercial vehicle details, and declarations." + sample_data: "https://raw.githubusercontent.com/Sadmin23/Resourse/main/mortgage-application-form-2.pdf" + metadata: + supported_inputs: ["image", "document"] + tags: ["mortgage", "application", "document"] \ No newline at end of file diff --git a/vlmrun/hub/schemas/contrib/document/mortgage_application.py b/vlmrun/hub/schemas/contrib/document/mortgage_application.py new file mode 100644 index 0000000..19b4ed0 --- /dev/null +++ b/vlmrun/hub/schemas/contrib/document/mortgage_application.py @@ -0,0 +1,213 @@ +from datetime import date, datetime +from enum import Enum +from typing import List, Optional + +from pydantic import BaseModel, Field + + +class MaritalStatus(str, Enum): + SINGLE = "single" + SINGLE_CAP = "Single" + MARRIED = "married" + MARRIED_CAP = "Married" + SEPARATED = "separated" + DIVORCED = "divorced" + WIDOWED = "widowed" + COMMON_LAW = "common_law" + + +class ContactMethod(str, Enum): + EMAIL = "email" + PHONE = "phone" + CELL_PHONE = "cell_phone" + MAIL = "mail" + + +class ResidenceStatus(str, Enum): + OWN = "own" + RENT = "rent" + LIVE_WITH_PARENTS = "live_with_parents" + OTHER = "other" + + +class EmploymentType(str, Enum): + FULL_TIME = "full_time" + PART_TIME = "part_time" + SELF_EMPLOYED = "self_employed" + CONTRACT = "contract" + RETIRED = "retired" + UNEMPLOYED = "unemployed" + + +class IncomeType(str, Enum): + SALARY = "salary" + HOURLY = "hourly" + COMMISSION = "commission" + SELF_EMPLOYED = "self_employed" + PENSION = "pension" + DISABILITY = "disability" + OTHER = "other" + + +class HomeType(str, Enum): + SINGLE_FAMILY = "single_family" + CONDO = "condo" + TOWNHOUSE = "townhouse" + MULTI_FAMILY = "multi_family" + MOBILE_HOME = "mobile_home" + OTHER = "other" + + +class MortgageType(str, Enum): + FIXED = "fixed" + VARIABLE = "variable" + ADJUSTABLE = "adjustable" + INTEREST_ONLY = "interest_only" + CONVENTIONAL = "Conventional 30yr Fixed" + HELOC = "HELOC" + OTHER = "other" + + +class CreditStatus(str, Enum): + EXCELLENT = "excellent" + GOOD = "good" + FAIR = "fair" + POOR = "poor" + UNKNOWN = "unknown" + + +class Address(BaseModel): + unit_number: Optional[str] = Field(None, description="Unit or apartment number") + street: str = Field(..., description="Street address including house number and street name") + city: str = Field(..., description="City name") + province_or_state: str = Field(..., description="Province or state") + postal_code_or_zip: str = Field(..., description="Postal code or ZIP code") + residence_status: Optional[ResidenceStatus] = Field(None, description="Current residence status: own, rent, etc.") + rent_payment: Optional[float] = Field(None, description="Monthly rent payment if applicable", ge=0) + time_at_residence_years: Optional[int] = Field(None, description="Time at residence in years", ge=0) + time_at_residence_months: Optional[int] = Field(None, description="Additional months at residence", ge=0, lt=12) + + +class EmploymentHistory(BaseModel): + employer_name: str = Field(..., description="Name of the employer") + employer_address: Optional[str] = Field(None, description="Address of the employer") + employer_city: Optional[str] = Field(None, description="City where employer is located") + employer_province_or_state: Optional[str] = Field(None, description="Province or state where employer is located") + employer_postal_code: Optional[str] = Field(None, description="Postal code or ZIP code of employer") + employment_type: EmploymentType = Field(..., description="Type of employment: full-time, part-time, etc.") + job_title: str = Field(..., description="Current job title") + occupation: str = Field(..., description="Occupation or profession") + industry_sector: Optional[str] = Field(None, description="Industry sector of employment") + income_type: IncomeType = Field(..., description="Type of income: salary, hourly, etc.") + income_amount: float = Field(..., description="Annual income amount", ge=0) + time_at_job_years: Optional[int] = Field(None, description="Years at current job", ge=0) + time_at_job_months: Optional[int] = Field(None, description="Additional months at current job", ge=0, lt=12) + time_in_industry_years: Optional[int] = Field(None, description="Years of experience in the industry", ge=0) + time_in_industry_months: Optional[int] = Field(None, description="Additional months of experience in the industry", ge=0, lt=12) + + +class PreviousEmploymentHistory(BaseModel): + employer_name: Optional[str] = Field(None, description="Name of the employer") + employer_address: Optional[str] = Field(None, description="Address of the employer") + employer_city: Optional[str] = Field(None, description="City where employer is located") + employer_province_or_state: Optional[str] = Field(None, description="Province or state where employer is located") + employer_postal_code: Optional[str] = Field(None, description="Postal code or ZIP code of employer") + employment_type: Optional[EmploymentType] = Field(None, description="Type of employment: full-time, part-time, etc.") + job_title: Optional[str] = Field(None, description="Current job title") + occupation: Optional[str] = Field(None, description="Occupation or profession") + industry_sector: Optional[str] = Field(None, description="Industry sector of employment") + income_type: Optional[IncomeType] = Field(None, description="Type of income: salary, hourly, etc.") + income_amount: Optional[float] = Field(None, description="Annual income amount", ge=0) + time_at_job_years: Optional[int] = Field(None, description="Years at current job", ge=0) + time_at_job_months: Optional[int] = Field(None, description="Additional months at current job", ge=0, lt=12) + time_in_industry_years: Optional[int] = Field(None, description="Years of experience in the industry", ge=0) + time_in_industry_months: Optional[int] = Field(None, description="Additional months of experience in the industry", ge=0, lt=12) + + +class PropertyInformation(BaseModel): + home_type: Optional[HomeType] = Field(None, description="Type of home: single family, condo, etc.") + property_address: Optional[Address] = Field(None, description="Address of the property being mortgaged") + estimated_market_value: Optional[float] = Field(None, description="Estimated current market value of the property", ge=0) + tax_value: Optional[float] = Field(None, description="Assessed value for tax purposes", ge=0) + year_purchased: Optional[int] = Field(None, description="Year the property was purchased") + year_built: Optional[int] = Field(None, description="Year the property was built") + original_cost: Optional[float] = Field(None, description="Original purchase price of the property", ge=0) + years_in_home: Optional[int] = Field(None, description="Number of years living in the property", ge=0) + has_escrow: Optional[bool] = Field(None, description="Whether the mortgage includes an escrow account") + has_mortgage_insurance: Optional[bool] = Field(None, description="Whether the mortgage has mortgage insurance") + monthly_mortgage_payment: Optional[float] = Field(None, description="Current monthly mortgage payment", ge=0) + + +class MortgageDetails(BaseModel): + mortgage_holder: Optional[str] = Field(None, description="Name of the current mortgage holder") + mortgage_type: Optional[MortgageType] = Field(None, description="Type of mortgage: fixed, variable, etc.") + interest_rate: Optional[float] = Field(None, description="Current interest rate of the mortgage", ge=0) + mortgage_term_years: Optional[int] = Field(None, description="Original term of the mortgage in years", ge=0) + mortgage_years_left: Optional[int] = Field(None, description="Remaining years on the mortgage", ge=0) + mortgage_balance: Optional[float] = Field(None, description="Current balance on the mortgage", ge=0) + mortgage_monthly_payment: Optional[float] = Field(None, description="Current monthly mortgage payment", ge=0) + second_mortgage_holder: Optional[str] = Field(None, description="Name of the second mortgage holder, if applicable") + second_mortgage_type: Optional[MortgageType] = Field(None, description="Type of second mortgage") + second_interest_rate: Optional[float] = Field(None, description="Interest rate of the second mortgage", ge=0) + second_term_years: Optional[int] = Field(None, description="Original term of the second mortgage in years", ge=0) + second_years_left: Optional[int] = Field(None, description="Remaining years on the second mortgage", ge=0) + second_balance: Optional[float] = Field(None, description="Current balance on the second mortgage", ge=0) + second_monthly_payment: Optional[float] = Field(None, description="Monthly payment for the second mortgage", ge=0) + + +class FinancialObligations(BaseModel): + child_support_or_alimony: Optional[float] = Field(None, description="Monthly child support or alimony payments", ge=0) + real_estate_taxes_yearly: Optional[float] = Field(None, description="Annual real estate taxes", ge=0) + real_estate_taxes_monthly: Optional[float] = Field(None, description="Monthly real estate taxes", ge=0) + home_insurance_yearly: Optional[float] = Field(None, description="Annual home insurance premium", ge=0) + home_insurance_monthly: Optional[float] = Field(None, description="Monthly home insurance payment", ge=0) + credit_score: Optional[int] = Field(None, description="Current credit score", ge=300, le=850) + credit_status: Optional[CreditStatus] = Field(None, description="Status of credit: excellent, good, fair, etc.") + agreed_to_credit_check: Optional[bool] = Field(None, description="Whether applicant has agreed to a credit check") + credit_check_date: Optional[date] = Field(None, description="Date of the credit check") + mortgage_late_payments: Optional[int] = Field(None, description="Number of late mortgage payments", ge=0) + credit_issues_description: Optional[str] = Field(None, description="Description of any credit issues or concerns") + + +class Assets(BaseModel): + cash_in_bank: Optional[float] = Field(None, description="Amount of cash in bank accounts", ge=0) + investments: Optional[float] = Field(None, description="Value of investments", ge=0) + owned_property: Optional[float] = Field(None, description="Value of other owned property", ge=0) + + +class ApplicantInformation(BaseModel): + salutation: Optional[str] = Field(None, description="Applicant's salutation (Mr., Mrs., Ms., etc.)") + first_name: str = Field(..., description="Applicant's first name") + middle_initial: Optional[str] = Field(None, description="Applicant's middle initial") + last_name: str = Field(..., description="Applicant's last name") + date_of_birth: date = Field(..., description="Applicant's date of birth") + sin: Optional[str] = Field(None, description="Social Insurance Number (SIN)") + marital_status: Optional[MaritalStatus] = Field(None, description="Applicant's marital status") + contact_method: Optional[ContactMethod] = Field(None, description="Preferred contact method") + dependents: Optional[int] = Field(None, description="Number of dependents", ge=0) + email: Optional[str] = Field(None, description="Email address") + work_phone: Optional[str] = Field(None, description="Work phone number") + home_phone: Optional[str] = Field(None, description="Home phone number") + cell_phone: Optional[str] = Field(None, description="Cell phone number") + current_address: Address = Field(..., description="Current residential address") + previous_address: Optional[Address] = Field(None, description="Previous address if less than 3 years at current address") + current_employment: EmploymentHistory = Field(..., description="Current employment details") + previous_employment: Optional[PreviousEmploymentHistory] = Field(None, description="Previous employment if less than 3 years with current employer") + + +class ApplicationMeta(BaseModel): + application_date: Optional[date] = Field(None, description="Date of mortgage application") + application_time: Optional[str] = Field(None, description="Time of mortgage application") + loan_officer: Optional[str] = Field(None, description="Name of the loan officer") + purpose_of_loan: str = Field(..., description="Purpose of the mortgage loan (purchase, refinance, etc.)") + referred_by: Optional[str] = Field(None, description="Person or entity who referred the applicant") + + +class MortgageApplication(BaseModel): + application_meta: ApplicationMeta = Field(..., description="Metadata about the mortgage application") + primary_applicant: ApplicantInformation = Field(..., description="Information about the primary applicant") + co_applicant: Optional[ApplicantInformation] = Field(None, description="Information about the co-applicant, if applicable") + property_information: PropertyInformation = Field(..., description="Information about the property being mortgaged") + mortgage_details: Optional[MortgageDetails] = Field(None, description="Details about current and second mortgages, if applicable") + financial_obligations: Optional[FinancialObligations] = Field(None, description="Information about financial obligations and credit") + assets: Optional[Assets] = Field(None, description="Information about assets and investments") \ No newline at end of file