root
Fix reset endpoint and environment state handling
69ac61f
Raw
History Blame Contribute Delete
5.2 kB
"""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)