File size: 14,282 Bytes
352d473
c672d1b
5cb8fb6
75c603a
352d473
f9f18b4
 
 
 
2d41771
 
75c603a
 
2d41771
75c603a
f9f18b4
 
 
2d41771
75c603a
f9f18b4
 
2d41771
f9f18b4
2d41771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cb8fb6
2d41771
f9f18b4
2d41771
 
75c603a
5cb8fb6
2d41771
 
 
 
efc4ecf
5cb8fb6
2d41771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f9f18b4
2d41771
 
 
 
 
 
 
75c603a
2d41771
 
75c603a
2d41771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cb8fb6
 
 
 
 
efc4ecf
 
2d41771
75c603a
 
2d41771
75c603a
f9f18b4
 
 
2d41771
75c603a
f9f18b4
75c603a
 
 
efc4ecf
75c603a
 
 
2d41771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75c603a
2d41771
 
 
 
75c603a
2d41771
 
 
 
79da7a3
2d41771
 
 
75c603a
f9f18b4
5cb8fb6
f9f18b4
2d41771
 
 
 
 
 
 
473251f
35e8298
2d41771
75c603a
a05bcb9
75c603a
 
 
 
4e2008c
75c603a
 
 
 
 
 
 
 
5f147cb
75c603a
 
 
 
 
 
2d41771
5f147cb
f73c0d1
f9f18b4
35e8298
2d41771
5f147cb
 
 
75c603a
2d41771
75c603a
2d41771
35e8298
75c603a
2d41771
 
 
f9f18b4
 
 
2d41771
 
 
 
f9f18b4
35e8298
f73c0d1
a05bcb9
 
 
f9f18b4
5cb8fb6
2d41771
a05bcb9
f9f18b4
05ce7a2
2d41771
a05bcb9
75c603a
f9f18b4
f73c0d1
2d41771
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
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'  # Add extra newline for spacing

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("")  # Add spacing
    
    # 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("")  # Add spacing
    
    # 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("")  # Add spacing
    
    # 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("")  # Add spacing
    
    # 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]}...")  # Truncate for readability
    response_parts.append("")  # Add spacing
    
    # 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("")  # Add spacing
    
    # 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 add_relevant_links(response: str, query: str, knowledge_base: dict) -> str:
    """Add relevant links based on query context"""
    query_lower = query.lower()
    links = []
    
    # Add links strategically based on context
    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 generate_response(query: str, knowledge_base: dict) -> str:
    """Generate enhanced responses using the knowledge base"""
    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']):
        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)
    
    # 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
    col1, col2 = st.columns([3, 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.subheader("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):
                st.session_state.messages.append({"role": "user", "content": question})
                st.rerun()
        
        st.markdown("---")
        if st.button("Clear Chat"):
            st.session_state.messages = []
            st.rerun()

if __name__ == "__main__":
    main()