Spaces:
Sleeping
Sleeping
File size: 5,203 Bytes
958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b 69ac61f 958590b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | """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
# ============================================================================
@dataclass
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"
@property
def remote(self) -> bool:
return self.location.lower() == "remote"
@property
def job_type(self) -> str:
return self.type
@property
def salary_min(self) -> int:
"""Parse salary_range to get minimum salary in thousands"""
return self._parse_salary(min)
@property
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
@dataclass
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)
@dataclass
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
@dataclass
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
# ============================================================================
@dataclass
class StepResult:
"""Result of executing an action"""
observation: JobAppObservation
reward: float
done: bool
info: Dict = field(default_factory=dict)
|