doublechocolatecup's picture
Upload 15 files
61f1214 verified
Raw History Blame Contribute Delete
3.85 kB
"""
Typed Pydantic models for the AI Interview Simulator OpenEnv environment.
Defines Observation, Action, Reward, and State structures.
"""
from __future__ import annotations
from enum import Enum
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
# ──────────────────────────────────────────────
# Enumerations
# ──────────────────────────────────────────────
class InterviewStage(str, Enum):
INTRO = "intro"
BEHAVIORAL = "behavioral"
TECHNICAL = "technical"
SITUATIONAL = "situational"
CLOSING = "closing"
COMPLETE = "complete"
class DifficultyLevel(str, Enum):
EASY = "easy"
MEDIUM = "medium"
HARD = "hard"
# ──────────────────────────────────────────────
# Core OpenEnv Models
# ──────────────────────────────────────────────
class QAPair(BaseModel):
"""A single question + the candidate's answer."""
question: str
answer: str
stage: InterviewStage
question_score: Optional[float] = None # filled after grading
class InterviewObservation(BaseModel):
"""
Observation returned by reset() and step().
Contains everything the agent needs to formulate its next response.
"""
task_id: str
job_title: str
company_context: str
difficulty: DifficultyLevel
current_question: str
question_number: int # 1-indexed
total_questions: int
stage: InterviewStage
previous_qa: List[QAPair] = Field(default_factory=list)
cumulative_score: float = 0.0
time_elapsed: float = 0.0 # seconds since reset
interview_complete: bool = False
class InterviewAction(BaseModel):
"""
Action submitted by the agent β€” the candidate's spoken response.
"""
response: str = Field(
...,
min_length=1,
description="The candidate's answer to the current interview question.",
)
class InterviewReward(BaseModel):
"""
Detailed reward breakdown for a single step.
All sub-scores are in [0.0, 1.0]; total_score is their weighted sum.
"""
total_score: float # 0.0 – 1.0, primary signal
relevance: float # Does the answer address the question?
structure: float # Organised response (STAR / step-by-step)?
depth: float # Specificity, examples, numbers
professionalism: float # Tone, vocabulary, no red flags
feedback: str # Human-readable grader feedback
class InterviewState(BaseModel):
"""
Full internal state β€” returned by state().
Useful for debugging, checkpointing, and OpenEnv validators.
"""
task_id: str
difficulty: DifficultyLevel
job_title: str
company_context: str
questions: List[str] # All questions in order
stages: List[InterviewStage] # Stage per question
current_index: int # Which question we're on
qa_history: List[QAPair]
per_question_scores: List[float]
episode_done: bool
total_steps: int
start_time: float
cumulative_reward: float
class StepResult(BaseModel):
"""Return type of env.step()."""
observation: InterviewObservation
reward: float # scalar for RL loop
done: bool
info: Dict[str, Any] = Field(default_factory=dict)