File size: 4,285 Bytes
5318b09
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from typing import List, Dict, Any, Optional, Annotated
from pydantic import BaseModel, Field
from langchain_core.messages import BaseMessage
from langgraph.graph import add_messages
class ChatbotState(BaseModel):
    def get(self, key, default=None):
        """

        Allow dict-like .get() access for compatibility.

        """
        # First try attribute directly
        if hasattr(self, key):
            return getattr(self, key)
        # Fallback: check if it's in __dict__
        return self.__dict__.get(key, default)
    def setdefault(self, key, default):
        """

        Dict-like setdefault: if attribute is None, set it to default and return it.

        Otherwise, return existing value.

        """
        if hasattr(self, key):
            value = getattr(self, key)
            if value is None:
                setattr(self, key, default)
                return default
            return value
        else:
            # attribute does not exist: set it
            setattr(self, key, default)
            return default
    profile: Dict[str, Any] = Field(..., description="Preprocessed / summarized profile data")
    profile_url: Optional[str] = Field(
        default=None,
        description="Original LinkedIn profile URL provided by the user."
    )

    # Quick access sections (about, headline, skills etc.)
    sections: Dict[str, str] = Field(..., description="Flattened profile sections for quick access")

    # Enhancements and analysis results
    enhanced_content: Dict[str, str] = Field(
    default_factory=dict,
    description=(
        "Map of improved or rewritten profile sections generated by the ContentGenerator tool. "
        "Keys are section names (e.g., 'about', 'headline'); values are enhanced text."
    )
)

    profile_analysis: Optional[Dict[str, Any]] = Field(
        None,
        description=(
            "Structured analysis of the user's profile produced by the ProfileAnalyzer tool, "
            "including strengths, weaknesses, and actionable suggestions."
        )
    )

    job_fit: Optional[Dict[str, Any]] = Field(
        None,
        description=(
            "Assessment result from the JobMatcher tool, detailing how well the user's profile matches "
            "the target role, including missing skills and match score."
        )
    )

    target_role: Optional[str] = Field(
        None,
        description=(
            "Target job role the user is aiming for. "
            "Can be set by the user directly during the conversation or inferred by the chatbot."
        )
    )

    editing_section: Optional[str] = Field(
        None,
        description=(
            "Name of the profile section currently being edited or improved, "
            "set dynamically when the ContentGenerator tool is invoked."
        )
    )
    next_tool_name: Optional[str] = Field(
        default=None,
        description="Name of the next tool the chatbot wants to call, set dynamically after LLM response."
    )


    # Annotated chat history directly using BaseMessage
    messages: Annotated[List[BaseMessage], add_messages] = Field(
    default_factory=list,
    description="List of user and assistant messages"
)



class ProfileAnalysisStrengths(BaseModel):
    technical: List[str]
    projects: List[str]
    education: List[str]
    soft_skills: List[str]

class ProfileAnalysisWeaknesses(BaseModel):
    technical_gaps: List[str]
    project_or_experience_gaps: List[str]
    missing_context: List[str]

class ProfileAnalysisModel(BaseModel):
    strengths: ProfileAnalysisStrengths
    weaknesses: ProfileAnalysisWeaknesses
    suggestions: List[str]

class JobFitModel(BaseModel):
    match_score: int = Field(..., ge=0, le=100)
    missing_skills: List[str]
    suggestions: List[str]

class ContentGenerationModel(BaseModel):
    new_content: str


# ========== 6. MEMORY SETUP ==========

class UserMemory:
    def __init__(self):
        self.profile = None
        self.target_roles = []
        self.history = []

    def save(self, key, value):
        self.history.append((key, value))

    def get_history(self):
        return self.history