LeoWalker's picture
updated to faster models, now uses mini, mini, and haiku
818408b
from pydantic import BaseModel, Field, conlist
from typing import List, Optional, Sequence, Annotated, Dict
from langchain_core.messages import BaseMessage
from langgraph.graph.message import add_messages
class InitialInput(BaseModel):
"""Raw input from the user."""
resume_text: str = Field(default="", description="Raw text extracted from the resume")
personal_text: Optional[str] = Field(default=None, description="Additional personal information provided by the user")
job_text: Optional[str] = Field(default=None, description="Job description or position-related text")
### These are classes for the build_reference_material_node
class PersonalStory(BaseModel):
"""Key moments that can be used as storytelling elements"""
challenge: str = Field(description="Specific challenge or obstacle faced")
action: str = Field(description="How they addressed the challenge")
result: str = Field(description="Outcome and impact of their actions")
lessons_learned: str = Field(description="Key takeaways from this experience")
class MotivationalElements(BaseModel):
"""Core elements that drive the person"""
key_values: List[str] = Field(
description="Personal and professional values demonstrated in their history"
)
proud_moments: List[str] = Field(
description="Achievements they speak about with genuine enthusiasm"
)
impact_areas: List[str] = Field(
description="Areas where they've made meaningful differences"
)
class RoleConnection(BaseModel):
"""Structured connection between experience and target role"""
experience: str = Field(description="Relevant past experience")
role_requirement: str = Field(description="Matching requirement in target role")
strength_level: str = Field(description="How strongly this experience matches")
class ReferenceMaterial(BaseModel):
"""Essential elements for creating a motivational speech"""
core_narrative: str = Field(
description="The main theme that emerges from their background and aspirations"
)
compelling_stories: List[PersonalStory] = Field(
default_factory=list,
description="Key stories that can be used to illustrate their journey"
)
motivation_profile: MotivationalElements = Field(
description="Elements that genuinely motivate the person"
)
role_summary: str = Field(
description="A summary of the target role and its key requirements"
)
target_role_connections: List[RoleConnection] = Field(
default_factory=list,
description="Clear connections between their experiences and the target role"
)
authenticity_markers: List[str] = Field(
description="Genuine aspects of their personality and experience that make their story unique"
)
# class ReferenceMaterial(BaseModel):
# """Structured analysis of candidate background and target position."""
# personal_history_summary: str = Field(
# description="Summary of candidate's career background and key achievements"
# )
# aspiring_position_summary: str = Field(
# description="Overview of the target role and its key requirements"
# )
# personal_focus_points: List[str] = Field(
# default_factory=list,
# description="Key points highlighting candidate's relevant experiences and skills"
# )
# aspiring_position_focus_points: List[str] = Field(
# default_factory=list,
# description="Essential requirements and expectations of the target role"
# )
### These are the classes for the generate_questions_node
class AnswerChoice(BaseModel):
"""Single answer choice for a question"""
text: str = Field(description="The answer option text")
category: str = Field(description="Simple category this answer aligns with")
class Question(BaseModel):
"""Question with multiple choice options"""
question_text: str = Field(description="The main question to be asked")
context: str = Field(description="Brief context from their background")
choices: Annotated[List[AnswerChoice],
conlist(AnswerChoice, min_length=3, max_length=3)
] = Field(description="Three possible answer choices")
user_answer: str = Field(description="The user's answer to the question", default="")
# Make sure Question is properly defined as a Pydantic model
class QuestionList(BaseModel):
questions: List[Question]
# class QAPair(BaseModel):
# """Individual question-answer interaction during the interview process."""
# question_id: int = Field(description="Unique identifier for the Q&A pair")
# question: str = Field(description="The question asked")
# answer: Optional[str] = Field(default=None, description="The generated or provided answer")
## These are used for the transcript generation node
class HypeCastTranscript(BaseModel):
"""Motivational speech transcript"""
content: str = Field(
description="The complete motivational speech as a single flowing conversation"
)
### This is the main state class
class InterviewState(BaseModel):
"""Current state of the interview process."""
user_initial_input: InitialInput
reference_material: Optional[ReferenceMaterial] = None
qa_history: Optional[QuestionList] = None
transcript: Optional[HypeCastTranscript] = None
messages: Annotated[Sequence[BaseMessage], add_messages] = [] # Add this line
audio_bytes: Optional[bytes] = None
class Config:
arbitrary_types_allowed = True # Enable arbitrary types for BaseMessage