Spaces:
Sleeping
Sleeping
| """Job Application Simulator - Data Models""" | |
| from dataclasses import dataclass, field | |
| from typing import Optional, List, Dict | |
| from pydantic import BaseModel, Field | |
| from openenv.core import Action, Observation, State | |
| # ============================================================================ | |
| # DOMAIN MODELS | |
| # ============================================================================ | |
| class JobPosting: | |
| """A job listing from the mock job board""" | |
| id: str | |
| title: str | |
| company: str | |
| location: str | |
| salary_range: str # e.g., "$120k - $150k" | |
| description: str | |
| required_skills: List[str] | |
| preferred_skills: List[str] | |
| experience_required: int | |
| type: str = "full-time" | |
| def remote(self) -> bool: | |
| return self.location.lower() == "remote" | |
| def job_type(self) -> str: | |
| return self.type | |
| def salary_min(self) -> int: | |
| """Parse salary_range to get minimum salary in thousands""" | |
| return self._parse_salary(min) | |
| def salary_max(self) -> int: | |
| """Parse salary_range to get maximum salary in thousands""" | |
| return self._parse_salary(max) | |
| def _parse_salary(self, min_or_max) -> int: | |
| """Parse salary range like '$120k - $150k' to integer (120 or 150)""" | |
| import re | |
| nums = re.findall(r'\$?(\d+)k?', self.salary_range) | |
| if nums: | |
| return min_or_max(int(n) for n in nums) | |
| return 0 | |
| class ApplicantProfile: | |
| """The job seeker's profile and preferences""" | |
| name: str | |
| skills: List[str] | |
| experience_years: int | |
| education: str | |
| current_role: str | |
| target_roles: List[str] | |
| preferred_locations: List[str] | |
| salary_min: int | |
| salary_max: int | |
| resume_sections: Dict[str, str] = field(default_factory=dict) | |
| class JobAnalysis: | |
| """Result of analyzing a job posting""" | |
| job_id: str | |
| match_score: float # 0.0 to 1.0 | |
| matching_skills: List[str] | |
| missing_skills: List[str] | |
| key_requirements: List[str] | |
| recommended_focus: str # What to highlight in application | |
| class SubmittedApplication: | |
| """Record of a submitted application""" | |
| job_id: str | |
| cover_letter: str | |
| tailored_sections: Dict[str, str] | |
| submission_time: str | |
| match_score: float | |
| status: str = "pending" # pending, accepted, rejected | |
| # ============================================================================ | |
| # ENVIRONMENT STATE | |
| # ============================================================================ | |
| class JobAppState(State): | |
| """Episode state for Job Application Simulator""" | |
| current_job: Optional[JobPosting] = None | |
| applicant_profile: Optional[ApplicantProfile] = None | |
| applications_submitted: List[SubmittedApplication] = Field(default_factory=list) | |
| budget_remaining: int = 10 # Max applications per episode | |
| last_search_results: List[JobPosting] = Field(default_factory=list) | |
| last_analysis: Optional[JobAnalysis] = None | |
| total_reward: float = 0.0 | |
| # ============================================================================ | |
| # ACTIONS | |
| # ============================================================================ | |
| class SearchJobs(Action): | |
| """Search for jobs matching criteria""" | |
| keywords: List[str] = Field(default_factory=list) | |
| location: Optional[str] = None | |
| salary_min: Optional[int] = None | |
| job_type: Optional[str] = None # full-time, contract, part-time | |
| remote_only: bool = False | |
| class AnalyzeJob(Action): | |
| """Analyze a job posting for fit""" | |
| job_id: str = "" | |
| class WriteCoverLetter(Action): | |
| """Generate a tailored cover letter""" | |
| job_id: str = "" | |
| tone: str = "professional" # professional, friendly, technical | |
| highlight_skills: List[str] = Field(default_factory=list) | |
| class SubmitApplication(Action): | |
| """Submit application to a job""" | |
| job_id: str = "" | |
| cover_letter: str = "" | |
| tailored_resume_sections: Dict[str, str] = Field(default_factory=dict) | |
| class NextJob(Action): | |
| """Move to the next job in search results""" | |
| pass | |
| # ============================================================================ | |
| # OBSERVATIONS | |
| # ============================================================================ | |
| class JobAppObservation(Observation): | |
| """Observation returned after each action""" | |
| job_listings: List[JobPosting] = Field(default_factory=list) | |
| current_job: Optional[JobPosting] = None | |
| analysis_result: Optional[JobAnalysis] = None | |
| cover_letter: Optional[str] = None | |
| cover_letter_quality: Optional[float] = None # 0.0 to 1.0 | |
| application_status: Optional[str] = None | |
| budget_remaining: int = 10 | |
| applications_count: int = 0 | |
| message: str = "" | |
| done: bool = False | |
| reward: float = 0.0 | |
| # ============================================================================ | |
| # STEP RESULT | |
| # ============================================================================ | |
| class StepResult: | |
| """Result of executing an action""" | |
| observation: JobAppObservation | |
| reward: float | |
| done: bool | |
| info: Dict = field(default_factory=dict) | |