File size: 16,031 Bytes
352d473
c672d1b
5cb8fb6
51334e1
352d473
51334e1
 
 
 
 
 
75c603a
 
51334e1
75c603a
f9f18b4
51334e1
 
 
 
 
f9f18b4
c688a70
f9f18b4
51334e1
 
 
2d41771
51334e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2d41771
51334e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75c603a
51334e1
 
 
 
 
 
 
 
 
 
 
c688a70
51334e1
 
 
 
 
 
c688a70
51334e1
 
 
 
 
 
 
 
 
 
 
 
c688a70
51334e1
 
 
 
 
 
 
 
34c5540
51334e1
 
 
 
 
 
 
 
 
c688a70
51334e1
 
 
 
 
c688a70
 
51334e1
 
 
 
 
c688a70
51334e1
 
 
 
 
 
 
 
34c5540
c688a70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51334e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cb8fb6
c688a70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cb8fb6
c688a70
5cb8fb6
 
efc4ecf
 
51334e1
75c603a
51334e1
 
75c603a
51334e1
f9f18b4
51334e1
 
75c603a
51334e1
75c603a
 
51334e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c688a70
 
 
 
 
 
 
 
 
5cb8fb6
51334e1
 
 
 
 
 
 
 
473251f
35e8298
2d41771
75c603a
a05bcb9
75c603a
 
 
 
f2e07fb
75c603a
 
 
 
 
 
 
 
5f147cb
75c603a
 
 
 
 
 
51334e1
c688a70
 
f9f18b4
35e8298
51334e1
 
 
 
75c603a
2d41771
51334e1
2d41771
35e8298
75c603a
51334e1
 
 
f9f18b4
 
 
51334e1
 
 
 
f9f18b4
35e8298
c688a70
a05bcb9
 
 
f9f18b4
5cb8fb6
51334e1
a05bcb9
f9f18b4
51334e1
c688a70
51334e1
c688a70
 
 
 
 
75c603a
f9f18b4
f73c0d1
c688a70
f73c0d1
75c603a
352d473
35e8298
5cb8fb6
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
import streamlit as st
import json
from typing import Dict, List, Any
import re

def format_project_response(project: dict, indent_level: int = 0) -> str:
    """Format project details with proper indentation and spacing"""
    indent = "  " * indent_level
    
    response = [f"{indent}{project['name']}"]
    response.append(f"{indent}  {project['description']}")
    
    if 'skills_used' in project:
        response.append(f"{indent}  Technologies: {', '.join(project['skills_used'])}")
    
    if 'status' in project:
        status = project['status']
        if 'development' in status.lower() or 'progress' in status.lower():
            response.append(f"{indent}  Status: {status}")
            if 'confidentiality_note' in project:
                response.append(f"{indent}  Note: {project['confidentiality_note']}")
    
    return '\n'.join(response) + '\n'

def format_skills_response(skills: dict) -> str:
    """Format skills with proper hierarchy and spacing"""
    response = ["My Technical Expertise:\n"]
    
    categories = {
        'Machine Learning & AI': ['core', 'frameworks', 'focus_areas'],
        'Programming': ['primary', 'libraries', 'tools'],
        'Data & Analytics': ['databases', 'visualization', 'processing']
    }
    
    for category, subcategories in categories.items():
        response.append(f"• {category}")
        for subcat in subcategories:
            if subcat in skills['machine_learning']:
                items = skills['machine_learning'][subcat]
                response.append(f"  - {subcat.title()}: {', '.join(items)}")
        response.append("")  # Add spacing between categories
    
    return '\n'.join(response)

def analyze_job_description(text: str, knowledge_base: dict) -> str:
    """Analyze job description and provide detailed alignment"""
    # Extract key requirements
    requirements = {
        'technical_tools': set(),
        'soft_skills': set(),
        'responsibilities': set()
    }
    
    # Common technical tools and skills
    tech_keywords = {
        'data science', 'analytics', 'visualization', 'tableau', 'python', 
        'machine learning', 'modeling', 'automation', 'sql', 'data analysis'
    }
    
    # Common soft skills
    soft_keywords = {
        'collaborate', 'communicate', 'analyze', 'design', 'implement',
        'produce insights', 'improve', 'support'
    }
    
    text_lower = text.lower()
    
    # Extract company name if present
    companies = ['rbc', 'shopify', 'google', 'microsoft', 'amazon']
    company_name = next((company.upper() for company in companies if company in text_lower), None)
    
    # Extract requirements
    for word in tech_keywords:
        if word in text_lower:
            requirements['technical_tools'].add(word)
    
    for word in soft_keywords:
        if word in text_lower:
            requirements['soft_skills'].add(word)
            
    # Build response
    response_parts = []
    
    # Company-specific introduction if applicable
    if company_name:
        response_parts.append(f"Here's how I align with {company_name}'s requirements:\n")
    else:
        response_parts.append("Based on the job requirements, here's how I align:\n")

    # Technical Skills Alignment
    response_parts.append("• Technical Skills Match:")
    my_relevant_skills = []
    if 'visualization' in requirements['technical_tools'] or 'tableau' in requirements['technical_tools']:
        my_relevant_skills.append("  - Proficient in Tableau and data visualization (used in multiple projects)")
    if 'data analysis' in requirements['technical_tools']:
        my_relevant_skills.append("  - Strong data analysis skills demonstrated in projects like LoanTap Credit Assessment")
    if 'machine learning' in requirements['technical_tools'] or 'modeling' in requirements['technical_tools']:
        my_relevant_skills.append("  - Experienced in building ML models from scratch (demonstrated in algorithm practice projects)")
    
    response_parts.extend(my_relevant_skills)
    response_parts.append("")
    
    # Business Understanding
    response_parts.append("• Business Acumen:")
    response_parts.append("  - Commerce background provides strong understanding of business requirements")
    response_parts.append("  - Experience in translating business needs into technical solutions")
    response_parts.append("  - Proven ability to communicate technical findings to business stakeholders")
    response_parts.append("")
    
    # Project Experience
    response_parts.append("• Relevant Project Experience:")
    relevant_projects = []
    if 'automation' in requirements['technical_tools']:
        relevant_projects.append("  - Developed AI-powered POS system with automated operations")
    if 'data analysis' in requirements['technical_tools']:
        relevant_projects.append("  - Built credit assessment model for LoanTap using comprehensive data analysis")
    if 'machine learning' in requirements['technical_tools']:
        relevant_projects.append("  - Created multiple ML models from scratch, including predictive analytics for Ola")
    
    response_parts.extend(relevant_projects)
    response_parts.append("")
    
    # Education and Additional Qualifications
    response_parts.append("• Additional Strengths:")
    response_parts.append("  - Currently pursuing advanced AI/ML education in Canada")
    response_parts.append("  - Strong foundation in both technical implementation and business analysis")
    response_parts.append("  - Experience in end-to-end project delivery and deployment")
    
    return '\n'.join(response_parts)

def format_story_response(knowledge_base: dict) -> str:
    """Format background story with proper structure"""
    response_parts = ["My Journey from Commerce to ML/AI:\n"]
    
    # Education Background
    response_parts.append("• Education Background:")
    response_parts.append(f"  - Commerce degree from {knowledge_base['education']['undergraduate']['institution']}")
    response_parts.append(f"  - Currently at {knowledge_base['education']['postgraduate'][0]['institution']}")
    response_parts.append(f"  - Also enrolled at {knowledge_base['education']['postgraduate'][1]['institution']}")
    response_parts.append("")
    
    # Career Transition
    response_parts.append("• Career Transition:")
    transition = next((qa['answer'] for qa in knowledge_base['frequently_asked_questions'] 
                      if 'transition' in qa['question'].lower()), '')
    response_parts.append(f"  - {transition[:200]}...")
    response_parts.append("")
    
    # Current Focus
    response_parts.append("• Current Focus:")
    response_parts.append("  - Building practical ML projects")
    response_parts.append("  - Advancing AI/ML education in Canada")
    response_parts.append("")
    
    # Goals
    response_parts.append("• Future Goals:")
    response_parts.append("  - Secure ML Engineering role in Canada")
    response_parts.append("  - Develop innovative AI solutions")
    response_parts.append("  - Contribute to cutting-edge ML projects")
    
    return '\n'.join(response_parts)

def format_standout_response() -> str:
    """Format response about standout qualities"""
    response_parts = ["What Makes Me Stand Out:\n"]
    response_parts.append("• Unique Background:")
    response_parts.append("  - Successfully transitioned from commerce to tech")
    response_parts.append("  - Blend of business acumen and technical expertise")
    response_parts.append("")
    
    response_parts.append("• Practical Experience:")
    response_parts.append("  - Built multiple ML projects from scratch")
    response_parts.append("  - Focus on real-world applications")
    response_parts.append("")
    
    response_parts.append("• Technical Depth:")
    response_parts.append("  - Strong foundation in ML/AI principles")
    response_parts.append("  - Experience with end-to-end project implementation")
    response_parts.append("")
    
    response_parts.append("• Innovation Focus:")
    response_parts.append("  - Developing novel solutions in ML/AI")
    response_parts.append("  - Emphasis on practical impact")
    
    return '\n'.join(response_parts)

def add_relevant_links(response: str, query: str, knowledge_base: dict) -> str:
    """Add relevant links based on query context"""
    query_lower = query.lower()
    links = []
    
    if any(word in query_lower for word in ['project', 'portfolio', 'work']):
        links.append(f"\nView my complete portfolio: {knowledge_base['personal_details']['online_presence']['portfolio']}")
    
    if any(word in query_lower for word in ['background', 'experience', 'work']):
        links.append(f"\nConnect with me: {knowledge_base['personal_details']['online_presence']['linkedin']}")
    
    for post in knowledge_base['personal_details']['online_presence']['blog_posts']:
        if 'link' in post and any(word in query_lower for word in post['title'].lower().split()):
            links.append(f"\nRelated blog post: {post['link']}")
            break
    
    if links:
        response += '\n' + '\n'.join(links)
    
    return response

def handle_market_conditions(knowledge_base: dict) -> str:
    """Handle market condition related queries with perspective"""
    market_outlook = knowledge_base['personal_details']['perspectives']['market_outlook']
    
    response = [
        market_outlook['job_market'],
        market_outlook['value_proposition'],
        market_outlook['strategy']
    ]
    
    return '\n\n'.join(response)

def handle_general_query(query: str, knowledge_base: dict) -> str:
    """Handle general queries using common_queries section"""
    query_lower = query.lower()
    
    # Check for weather-related queries
    if any(word in query_lower for word in ['weather', 'temperature', 'climate']):
        return knowledge_base['personal_details']['common_queries']['weather']
    
    # Check for market-related queries
    if any(word in query_lower for word in ['market', 'job market', 'opportunities']):
        return handle_market_conditions(knowledge_base)
    
    # Default to personal summary for truly general queries
    return knowledge_base['personal_details']['professional_summary']

def generate_response(query: str, knowledge_base: dict) -> str:
    """Enhanced response generation with better query handling"""
    query_lower = query.lower()
    
    # Handle project listing requests
    if any(word in query_lower for word in ['list', 'project', 'portfolio', 'built', 'created', 'developed']):
        response_parts = ["Here are my key projects:\n"]
        
        # Major Projects (under development)
        response_parts.append("Major Projects (In Development):")
        for project in knowledge_base['projects']['major_projects']:
            response_parts.append(format_project_response(project, indent_level=1))
        
        # Algorithm Implementation Projects
        response_parts.append("Completed Algorithm Implementation Projects:")
        for project in knowledge_base['projects']['algorithm_practice_projects']:
            response_parts.append(format_project_response(project, indent_level=1))
        
        response = '\n'.join(response_parts)
        return add_relevant_links(response, query, knowledge_base)
    
    # Handle job description analysis
    elif len(query.split()) > 20 and any(phrase in query_lower for phrase in 
        ['requirements', 'qualifications', 'looking for', 'job description']):
        return analyze_job_description(query, knowledge_base)
    
    # Handle background/story queries
    elif any(word in query_lower for word in ['background', 'journey', 'story', 'transition']):
        return format_story_response(knowledge_base)
    
    # Handle skill-specific queries
    elif any(word in query_lower for word in ['skill', 'know', 'technology', 'stack']):
        return format_skills_response(knowledge_base['skills']['technical_skills'])
    
    # Handle standout/unique qualities queries
    elif any(word in query_lower for word in ['stand out', 'unique', 'different', 'special']):
        return format_standout_response()
    
    # Handle market condition queries
    elif any(phrase in query_lower for phrase in ['market down', 'job market', 'market conditions']):
        return handle_market_conditions(knowledge_base)
    
    # Handle general queries
    elif len(query.split()) < 5 or any(word in query_lower for word in ['weather', 'temperature']):
        return handle_general_query(query, knowledge_base)
    
    # Default response
    return (f"I'm {knowledge_base['personal_details']['professional_summary']}\n\n"
            "You can ask me about:\n"
            "• My projects and portfolio\n"
            "• My journey from commerce to ML/AI\n"
            "• My technical skills and experience\n"
            "• My fit for ML/AI roles\n"
            "Or paste a job description to see how my profile matches!")

def main():
    st.title("💬 Chat with Manyue's Portfolio")
    
    # Initialize session state
    if "messages" not in st.session_state:
        st.session_state.messages = []
    if "knowledge_base" not in st.session_state:
        try:
            with open('knowledge_base.json', 'r', encoding='utf-8') as f:
                st.session_state.knowledge_base = json.load(f)
        except FileNotFoundError:
            st.error("Knowledge base file not found.")
            return
    
    # Display welcome message
    if "displayed_welcome" not in st.session_state:
        st.write("""
        Hi! I'm Manyue's AI assistant. I can tell you about:
        - My journey from commerce to ML/AI
        - My technical skills and projects
        - My fit for ML/AI roles
        - You can also paste job descriptions to see how my profile matches!
        """)
        st.session_state.displayed_welcome = True
    
    # Create two columns with adjusted ratios
    col1, col2 = st.columns([4, 1])
    
    with col1:
        # Display chat messages
        for message in st.session_state.messages:
            with st.chat_message(message["role"]):
                st.markdown(message["content"])
        
        # Chat input
        if prompt := st.chat_input("Ask me anything or paste a job description..."):
            # Add user message
            st.session_state.messages.append({"role": "user", "content": prompt})
            
            try:
                # Generate and display response
                with st.chat_message("assistant"):
                    response = generate_response(prompt, st.session_state.knowledge_base)
                    st.markdown(response)
                    st.session_state.messages.append({"role": "assistant", "content": response})
            except Exception as e:
                st.error(f"An error occurred: {str(e)}")
            
            st.rerun()
    
    with col2:
        st.markdown("### Quick Questions")
        example_questions = [
            "Tell me about your ML projects",
            "What are your technical skills?",
            "What makes you stand out?",
            "What's your journey into ML?",
            "Paste a job description to see how I match!"
        ]
        
        for question in example_questions:
            if st.button(question, key=f"btn_{question}", use_container_width=True):
                st.session_state.messages.append({"role": "user", "content": question})
                try:
                    response = generate_response(question, st.session_state.knowledge_base)
                    st.session_state.messages.append({"role": "assistant", "content": response})
                except Exception as e:
                    st.error(f"An error occurred: {str(e)}")
                st.rerun()
        
        st.markdown("---")
        if st.button("Clear Chat", use_container_width=True):
            st.session_state.messages = []
            st.rerun()

if __name__ == "__main__":
    main()