danivpv commited on
Commit
b3cbb46
·
1 Parent(s): 4246a25

feat: enhance career analysis functionality with detailed career path options and scoring metrics for user profiles

Browse files
Files changed (4) hide show
  1. app/constants.py +146 -0
  2. app/main.py +141 -42
  3. app/utils.py +4 -84
  4. linkedinadvice/career_analysis.py +34 -50
app/constants.py CHANGED
@@ -13,3 +13,149 @@ ROLE_PLACEHOLDER = [
13
  "e.g. Site Reliability Engineer",
14
  "e.g. Infrastructure Engineer",
15
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  "e.g. Site Reliability Engineer",
14
  "e.g. Infrastructure Engineer",
15
  ]
16
+
17
+ SAMPLE_RESULT = """
18
+ Based on the provided career profile, we can identify several potential career paths that align with the individual's experience, skills, and aspirations.
19
+ For each option, I’ll assess its performance in the short, medium, and long term for each criterion. I’ll assign rough scores (1-5, where 1 is low and 5 is high) based on your background and goals, then explain the reasoning.
20
+
21
+ ### Option 1: Pursue a PhD
22
+ - **Short-term** (1-3 years):
23
+ Financial Success: 2 (Stipends are modest, typically $20K-$40K/year, depending on location and funding.)
24
+ Impact on Helping Others: 2 (Focus is on learning and early research, with limited immediate impact.)
25
+ Winning Track Record: 3 (You’re building toward a prestigious degree, but no major achievements yet.)
26
+ - **Medium-term** (3-10 years):
27
+ Financial Success: 4 (Post-PhD, you could secure high-paying roles in industry or academia, e.g., $100K+ in tech.)
28
+ Impact on Helping Others: 4 (Research in AI or data science could address significant problems.)
29
+ Winning Track Record: 5 (A PhD is a globally recognized achievement, opening doors to elite roles.)
30
+ - **Long-term** (10+ years):
31
+ Financial Success: 4 (Potential for six-figure salaries in industry or stable academic positions.)
32
+ Impact on Helping Others: 5 (Breakthrough research or leadership in impactful projects.)
33
+ Winning Track Record: 5 (A PhD can lead to a career of notable contributions.)
34
+
35
+ ### Option 2: Continue in Data Science (Industry)
36
+ - **Short-term**:
37
+ Financial Success: 4 (With 2 years of experience, you can likely secure $80K-$120K roles.)
38
+ Impact on Helping Others: 3 (Depends on projects—e.g., healthcare analytics could be impactful.)
39
+ Winning Track Record: 4 (Successful projects or promotions enhance your resume.)
40
+ - **Medium-term**:
41
+ Financial Success: 4 (Senior roles could exceed $150K with experience.)
42
+ Impact on Helping Others: 4 (Leading impactful initiatives becomes possible.)
43
+ Winning Track Record: 4 (A string of achievements strengthens your profile.)
44
+ - **Long-term**:
45
+ Financial Success: 4 (Potential for executive or specialized roles with high pay.)
46
+ Impact on Helping Others: 4 (Influence grows with seniority or project scope.)
47
+ Winning Track Record: 4 (Consistent success signals expertise.)
48
+ **Notes**: Your current path offers stability and growth, leveraging your existing skills and experience.
49
+
50
+ ### Option 3: Switch to Quantitative Finance or Software Engineering
51
+ - **Short-term**:
52
+ Financial Success: 5 (Entry-level roles in finance or tech often start at $100K+.)
53
+ Impact on Helping Others: 3 (Varies—e.g., less direct in finance, more in software for social good.)
54
+ Winning Track Record: 3 (You’d need to build new credentials, but your skills transfer well.)
55
+ - **Medium-term**:
56
+ Financial Success: 5 (High earning potential, e.g., $200K+ in quant finance.)
57
+ Impact on Helping Others: 3 (Depends on the role—less predictable than data science.)
58
+ Winning Track Record: 4 (Success in these fields is visible and respected.)
59
+ - **Long-term**:
60
+ Financial Success: 5 (Top earners in these fields can make millions.)
61
+ Impact on Helping Others: 3 (Impact varies widely by role.)
62
+ Winning Track Record: 4 (Strong achievements possible.)
63
+ **Notes**: Switching requires some upskilling, but your math and programming background make it feasible.
64
+
65
+ ### Option 4: Entrepreneurship
66
+ - **Short-term**:
67
+ Financial Success: 1 (High risk—little to no income initially.)
68
+ Impact on Helping Others: 4 (A venture solving real problems could have early impact.)
69
+ Winning Track Record: 4 (Starting something is notable, even if small-scale.)
70
+ - **Medium-term**:
71
+ Financial Success: 3 (Success could yield moderate to high returns; failure is common.)
72
+ Impact on Helping Others: 5 (A thriving business could scale solutions widely.)
73
+ Winning Track Record: 5 (A successful startup is a major credential.)
74
+ - **Long-term**:
75
+ Financial Success: 5 (Potential for significant wealth if successful.)
76
+ Impact on Helping Others: 5 (Large-scale impact possible.)
77
+ Winning Track Record: 5 (Entrepreneurial success opens elite opportunities.)
78
+ Notes: High risk, high reward—requires a strong idea and execution, but aligns with your AI and data science skills.
79
+
80
+ ### Option 5: Academia/Research Without a PhD
81
+ - **Short-term**:
82
+ Financial Success: 2 (Low-paying roles like research assistant, ~$30K-$50K.)
83
+ Impact on Helping Others: 2 (Supportive roles with limited influence.)
84
+ Winning Track Record: 2 (Few notable achievements possible.)
85
+ - **Medium-term**:
86
+ Financial Success: 2 (Pay remains modest without a PhD.)
87
+ Impact on Helping Others: 3 (Contributions grow if you co-author or assist.)
88
+ Winning Track Record: 3 (Some recognition possible, but limited.)
89
+ - **Long-term**:
90
+ Financial Success: 2 (Caps out below industry or PhD levels.)
91
+ Impact on Helping Others: 3 (Niche impact possible.)
92
+ Winning Track Record: 3 (Hard to advance significantly.)
93
+ **Notes**: This path is constrained without a PhD, making it less competitive.
94
+
95
+ ### Option 6: Complete or Pursue a Master’s Degree
96
+ - **Short-term**:
97
+ Financial Success: 1 (Costly unless funded; no income during study.)
98
+ Impact on Helping Others: 2 (Limited during the program.)
99
+ Winning Track Record: 3 (A degree builds your profile.)
100
+ - **Medium-term**:
101
+ Financial Success: 4 (Better job prospects post-degree.)
102
+ Impact on Helping Others: 3 (Depends on subsequent career.)
103
+ Winning Track Record: 4 (A prestigious master’s is a strong signal.)
104
+ - **Long-term**:
105
+ Financial Success: 4 (Comparable to industry paths.)
106
+ Impact on Helping Others: 4 (Depends on application.)
107
+ Winning Track Record: 4 (Opens doors, but less than a PhD.)
108
+ **Notes**: Your experience may already suffice for many jobs, but a funded program could be worth considering.
109
+
110
+ ### Next Step: Rank Options with Weighted Scores
111
+ Since you’re willing to sacrifice short-term gains for long-term success, I’ll weigh long-term performance more heavily. Let’s calculate a total score for each option:
112
+
113
+ Formula: Total Score = (Short-term Avg) + (Medium-term Avg) + 2 × (Long-term Avg)
114
+ Averages are computed as (Financial + Impact + Track Record) ÷ 3.
115
+
116
+ **PhD**
117
+ - Short-term: (2+2+3)/3 = 2.33
118
+ - Medium-term: (4+4+5)/3 = 4.33
119
+ - Long-term: (4+5+5)/3 = 4.67
120
+ - Total: 2.33 + 4.33 + 2 × 4.67 = 16
121
+
122
+ **Data Science (Industry)**
123
+ - Short-term: (4+3+4)/3 = 3.67
124
+ - Medium-term: (4+4+4)/3 = 4
125
+ - Long-term: (4+4+4)/3 = 4
126
+ - Total: 3.67 + 4 + 2 × 4 = 15.67
127
+
128
+ **Quant Finance/Software Engineering**
129
+ - Short-term: (5+3+3)/3 = 3.67
130
+ - Medium-term: (5+3+4)/3 = 4
131
+ - Long-term: (5+3+4)/3 = 4
132
+ - Total: 3.67 + 4 + 2 × 4 = 15.67
133
+
134
+ **Entrepreneurship**
135
+ - Short-term: (1+4+4)/3 = 3
136
+ - Medium-term: (3+5+5)/3 = 4.33
137
+ - Long-term: (5+5+5)/3 = 5
138
+ - Total: 3 + 4.33 + 2 × 5 = 17.33
139
+
140
+ **Academia Without PhD**
141
+ - Short-term: (2+2+2)/3 = 2
142
+ - Medium-term: (2+3+3)/3 = 2.67
143
+ - Long-term: (2+3+3)/3 = 2.67
144
+ - Total: 2 + 2.67 + 2 × 2.67 = 10.01
145
+
146
+ **Master’s Degree**
147
+ - Short-term: (1+2+3)/3 = 2
148
+ - Medium-term: (4+3+4)/3 = 3.67
149
+ - Long-term: (4+4+4)/3 = 4
150
+ - Total: 2 + 3.67 + 2 × 4 = 13.67
151
+
152
+ ### Final Ranking
153
+
154
+ ### Final Ranking
155
+ - **Entrepreneurship**: 17.33
156
+ - **PhD**: 16
157
+ - **Data Science (Industry)**: 15.67
158
+ - **Quant Finance/Software Engineering**: 15.67
159
+ - **Master’s Degree**: 13.67
160
+ - **Academia Without PhD**: 10.01
161
+ """
app/main.py CHANGED
@@ -21,36 +21,9 @@ analyzer = CareerAnalyzer(model_name="gpt-4o-mini")
21
 
22
  @monitor_api
23
  def analyze_career(
24
- roles_data,
25
- achievements,
26
- education,
27
- edu_achievements,
28
- goals,
29
- insights,
30
- time_preference,
31
- financial_weight,
32
- impact_weight,
33
- opportunity_weight,
34
  ):
35
- # Normalize weights to ensure they sum to 1
36
-
37
- # Prepare user data
38
- user_data = {
39
- "roles": roles_data,
40
- "achievements": achievements,
41
- "educations": education,
42
- "edu_achievements": edu_achievements,
43
- "goals": goals,
44
- "insights": insights,
45
- "time_preference": time_preference,
46
- "financial_weight": financial_weight,
47
- "impact_weight": impact_weight,
48
- "opportunity_weight": opportunity_weight,
49
- }
50
-
51
- # Get analysis
52
-
53
- result = analyzer.analyze(user_data)
54
 
55
  return result
56
 
@@ -60,17 +33,20 @@ with gr.Blocks(theme="soft") as demo:
60
  # State for number of roles
61
  role_count = gr.State(1) # Start with 1 role field
62
  education_count = gr.State(1) # Start with 1 education field
 
 
63
  professional_background = gr.State("") # State to store combined roles data
64
  professional_achievements = gr.State("") # State to store combined roles data
65
  education_background = gr.State("") # State to store combined education background
66
  education_achievements = gr.State("") # State to store education achievements
67
  goals = gr.State("") # State to store combined goals
68
  insights = gr.State("") # State to store combined insights
69
- time_preference = gr.State("") # State to store time preference
70
  financial_weight = gr.State(2) # State to store financial weight
71
  impact_weight = gr.State(2) # State to store impact weight
72
  opportunity_weight = gr.State(2) # State to store opportunity weight
73
  output = gr.State("") # State to store output
 
74
 
75
  gr.Markdown(
76
  """
@@ -83,7 +59,7 @@ with gr.Blocks(theme="soft") as demo:
83
 
84
  with gr.Row():
85
  submit_btn = gr.Button("Analyze Career Paths", variant="primary", size="lg")
86
- clear_btn = gr.Button("Clear All", variant="stop", size="lg")
87
  example_btn = gr.Button("Load Example", variant="secondary", size="lg")
88
 
89
  with gr.Row():
@@ -117,20 +93,73 @@ with gr.Blocks(theme="soft") as demo:
117
  @gr.render(inputs=role_count)
118
  def render_roles(r_count):
119
  for i in range(r_count):
 
 
 
 
 
 
120
  with gr.Row():
 
121
  role = gr.Textbox(
122
  key=f"role_{i}",
123
  label=f"Role {i + 1}"
124
  + (" (Current)" if i == 0 else ""),
125
  placeholder=ROLE_PLACEHOLDER[i % len(ROLE_PLACEHOLDER)],
126
  scale=3,
 
 
 
 
127
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  exp = gr.Number(
129
  key=f"exp_{i}",
130
  label="Years",
131
  value=1,
132
  minimum=0,
133
  scale=1,
 
 
 
 
 
 
 
 
 
 
 
134
  )
135
 
136
  professional_achievement = gr.Textbox(
@@ -138,13 +167,23 @@ with gr.Blocks(theme="soft") as demo:
138
  label="Notable Achievements",
139
  lines=2,
140
  placeholder="List key accomplishments, awards, or significant contributions.",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  )
142
- if professional_achievement.value:
143
- professional_achievements.value += (
144
- professional_achievement.value
145
- )
146
- if professional_background.value:
147
- professional_background.value += f"{role} - {exp} years\n"
148
 
149
  with gr.Group():
150
  gr.Markdown("### Educational Background")
@@ -179,6 +218,11 @@ with gr.Blocks(theme="soft") as demo:
179
  @gr.render(inputs=education_count)
180
  def render_education(e_count):
181
  for i in range(e_count):
 
 
 
 
 
182
  with gr.Row():
183
  education = gr.Textbox(
184
  key=f"education_{i}",
@@ -186,17 +230,57 @@ with gr.Blocks(theme="soft") as demo:
186
  lines=3,
187
  placeholder="e.g. Bachelor of Science in Computer Science, University of Technology",
188
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  edu_achievement = gr.Textbox(
190
  key=f"edu_achievement_{i}",
191
  label="Academic Achievements",
192
  lines=3,
193
  placeholder="Awards, honors, notable projects or research during your education",
194
  )
 
 
 
 
 
 
 
 
 
 
 
 
195
  if education.value:
196
  education_background.value += education.value
197
  if edu_achievement.value:
198
  education_achievements.value += edu_achievement.value
199
 
 
 
200
  with gr.Group():
201
  gr.Markdown("### Future Plans")
202
  goals = gr.Textbox(
@@ -260,7 +344,13 @@ with gr.Blocks(theme="soft") as demo:
260
  )
261
 
262
  with gr.Column(scale=2):
263
- output_box = gr.Textbox(label="Career Analysis Report", lines=25)
 
 
 
 
 
 
264
 
265
  with gr.Row():
266
  copy_btn = gr.Button("📋 Copy to Clipboard", variant="secondary")
@@ -269,7 +359,7 @@ with gr.Blocks(theme="soft") as demo:
269
  # Copy and share functionality
270
  copy_btn.click(
271
  copy_to_clipboard,
272
- inputs=output,
273
  )
274
 
275
  # Add info section at the bottom
@@ -295,12 +385,10 @@ with gr.Blocks(theme="soft") as demo:
295
  )
296
 
297
  submit_btn.click(
298
- export_state,
299
  inputs=[
300
  professional_background,
301
- professional_achievements,
302
  education_background,
303
- education_achievements,
304
  goals,
305
  insights,
306
  time_preference,
@@ -311,6 +399,17 @@ with gr.Blocks(theme="soft") as demo:
311
  outputs=[output_box],
312
  )
313
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
  # Launch the app
316
  if __name__ == "__main__":
 
21
 
22
  @monitor_api
23
  def analyze_career(
24
+ *args,
 
 
 
 
 
 
 
 
 
25
  ):
26
+ result = analyzer.analyze(*args)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  return result
29
 
 
33
  # State for number of roles
34
  role_count = gr.State(1) # Start with 1 role field
35
  education_count = gr.State(1) # Start with 1 education field
36
+ professional_background_dict = gr.State({}) # State to store combined roles data
37
+ education_background_dict = gr.State({}) # State to store combined education data
38
  professional_background = gr.State("") # State to store combined roles data
39
  professional_achievements = gr.State("") # State to store combined roles data
40
  education_background = gr.State("") # State to store combined education background
41
  education_achievements = gr.State("") # State to store education achievements
42
  goals = gr.State("") # State to store combined goals
43
  insights = gr.State("") # State to store combined insights
44
+ time_preference = gr.State("Mid-term (10 years)") # State to store time preference
45
  financial_weight = gr.State(2) # State to store financial weight
46
  impact_weight = gr.State(2) # State to store impact weight
47
  opportunity_weight = gr.State(2) # State to store opportunity weight
48
  output = gr.State("") # State to store output
49
+ raw_list_inputs = gr.State([]) # State to store raw list inputs
50
 
51
  gr.Markdown(
52
  """
 
59
 
60
  with gr.Row():
61
  submit_btn = gr.Button("Analyze Career Paths", variant="primary", size="lg")
62
+ clear_btn = gr.Button("Clear", variant="stop", size="lg")
63
  example_btn = gr.Button("Load Example", variant="secondary", size="lg")
64
 
65
  with gr.Row():
 
93
  @gr.render(inputs=role_count)
94
  def render_roles(r_count):
95
  for i in range(r_count):
96
+ if i not in professional_background_dict.value:
97
+ professional_background_dict.value[i] = {
98
+ "role": "",
99
+ "exp": "",
100
+ "professional_achievement": "",
101
+ }
102
  with gr.Row():
103
+ interactive = i == r_count - 1
104
  role = gr.Textbox(
105
  key=f"role_{i}",
106
  label=f"Role {i + 1}"
107
  + (" (Current)" if i == 0 else ""),
108
  placeholder=ROLE_PLACEHOLDER[i % len(ROLE_PLACEHOLDER)],
109
  scale=3,
110
+ interactive=interactive,
111
+ inputs=professional_background_dict.value[i].get(
112
+ "role", ""
113
+ ),
114
  )
115
+
116
+ def update_professional_background_dict(key, value, i):
117
+ professional_background_dict.value[i][key] = value
118
+ final_string = ""
119
+ for i in professional_background_dict.value:
120
+ role = professional_background_dict.value[i].get(
121
+ "role"
122
+ )
123
+ exp = professional_background_dict.value[i].get(
124
+ "exp"
125
+ )
126
+ professional_achievement = (
127
+ professional_background_dict.value[i].get(
128
+ "professional_achievement"
129
+ )
130
+ )
131
+ final_string += f"{role} - {exp} years. Achieved: \n{professional_achievement}\n\n"
132
+
133
+ return professional_background_dict.value, final_string
134
+
135
+ role.input(
136
+ lambda x: update_professional_background_dict(
137
+ "role", x, i
138
+ ),
139
+ inputs=[role],
140
+ outputs=[
141
+ professional_background_dict,
142
+ professional_background,
143
+ ],
144
+ )
145
+
146
  exp = gr.Number(
147
  key=f"exp_{i}",
148
  label="Years",
149
  value=1,
150
  minimum=0,
151
  scale=1,
152
+ interactive=interactive,
153
+ )
154
+ exp.input(
155
+ lambda x: update_professional_background_dict(
156
+ "exp", x, i
157
+ ),
158
+ inputs=[exp],
159
+ outputs=[
160
+ professional_background_dict,
161
+ professional_background,
162
+ ],
163
  )
164
 
165
  professional_achievement = gr.Textbox(
 
167
  label="Notable Achievements",
168
  lines=2,
169
  placeholder="List key accomplishments, awards, or significant contributions.",
170
+ interactive=interactive,
171
+ )
172
+
173
+ professional_achievement.input(
174
+ lambda x: update_professional_background_dict(
175
+ "professional_achievement", x, i
176
+ ),
177
+ inputs=[professional_achievement],
178
+ outputs=[
179
+ professional_background_dict,
180
+ professional_background,
181
+ ],
182
+ )
183
+
184
+ raw_list_inputs.value.extend(
185
+ [role, exp, professional_achievement]
186
  )
 
 
 
 
 
 
187
 
188
  with gr.Group():
189
  gr.Markdown("### Educational Background")
 
218
  @gr.render(inputs=education_count)
219
  def render_education(e_count):
220
  for i in range(e_count):
221
+ if i not in education_background_dict.value:
222
+ education_background_dict.value[i] = {
223
+ "education": "",
224
+ "education_achievement": "",
225
+ }
226
  with gr.Row():
227
  education = gr.Textbox(
228
  key=f"education_{i}",
 
230
  lines=3,
231
  placeholder="e.g. Bachelor of Science in Computer Science, University of Technology",
232
  )
233
+
234
+ def update_educational_background_dict(key, value, i):
235
+ education_background_dict.value[i][key] = value
236
+ final_string = ""
237
+ for i in education_background_dict.value:
238
+ education = education_background_dict.value[i].get(
239
+ "education"
240
+ )
241
+ edu_achievement = education_background_dict.value[
242
+ i
243
+ ].get("edu_achievement")
244
+ final_string += f"{education}. Achieved: \n{edu_achievement}\n\n"
245
+
246
+ return education_background_dict.value, final_string
247
+
248
+ education.input(
249
+ lambda x: update_educational_background_dict(
250
+ "education", x, i
251
+ ),
252
+ inputs=[education],
253
+ outputs=[
254
+ education_background_dict,
255
+ education_background,
256
+ ],
257
+ )
258
+
259
  edu_achievement = gr.Textbox(
260
  key=f"edu_achievement_{i}",
261
  label="Academic Achievements",
262
  lines=3,
263
  placeholder="Awards, honors, notable projects or research during your education",
264
  )
265
+
266
+ edu_achievement.input(
267
+ lambda x: update_educational_background_dict(
268
+ "education_achievement", x, i
269
+ ),
270
+ inputs=[education_achievements],
271
+ outputs=[
272
+ education_background_dict,
273
+ education_background,
274
+ ],
275
+ )
276
+
277
  if education.value:
278
  education_background.value += education.value
279
  if edu_achievement.value:
280
  education_achievements.value += edu_achievement.value
281
 
282
+ raw_list_inputs.value.extend([education, edu_achievement])
283
+
284
  with gr.Group():
285
  gr.Markdown("### Future Plans")
286
  goals = gr.Textbox(
 
344
  )
345
 
346
  with gr.Column(scale=2):
347
+ output_box = gr.Markdown(
348
+ output.value,
349
+ label="Career Analysis Report",
350
+ container=True,
351
+ height=614,
352
+ show_copy_button=False,
353
+ )
354
 
355
  with gr.Row():
356
  copy_btn = gr.Button("📋 Copy to Clipboard", variant="secondary")
 
359
  # Copy and share functionality
360
  copy_btn.click(
361
  copy_to_clipboard,
362
+ inputs=output_box,
363
  )
364
 
365
  # Add info section at the bottom
 
385
  )
386
 
387
  submit_btn.click(
388
+ lambda *args: analyze_career(*args) if export_state(*args) or True else None,
389
  inputs=[
390
  professional_background,
 
391
  education_background,
 
392
  goals,
393
  insights,
394
  time_preference,
 
399
  outputs=[output_box],
400
  )
401
 
402
+ clear_btn.click(
403
+ fn=lambda: None, inputs=[], outputs=[], js="() => location.reload()"
404
+ )
405
+
406
+ """
407
+ example_btn.click(
408
+ fn=lambda _: SAMPLE_RESULT,
409
+ inputs=[output_box],
410
+ outputs=[output_box],
411
+ )
412
+ """
413
 
414
  # Launch the app
415
  if __name__ == "__main__":
app/utils.py CHANGED
@@ -3,98 +3,21 @@ Utility functions for the LinkedIn Career Advice application.
3
  Handles input processing, clipboard operations, and sharing functionality.
4
  """
5
 
6
- import re
7
- import urllib.parse
8
-
9
  import pyperclip
10
 
11
 
12
- def combine_roles(count, *args):
13
- roles_text = ""
14
-
15
- for i in range(count):
16
- # Calculate the index in args for this role's name and experience
17
- name_idx = i
18
- exp_idx = i + count // 2 + 1
19
-
20
- if name_idx < len(args) and exp_idx < len(args):
21
- role_name = args[name_idx]
22
- experience = args[exp_idx]
23
-
24
- if role_name and experience is not None:
25
- roles_text += f"{role_name} ({experience} years)\n"
26
-
27
- return roles_text.strip()
28
-
29
-
30
- def share_to_linkedin(text):
31
- """Generate a LinkedIn sharing link"""
32
- share_link = get_share_link(text)
33
- return f"Share on LinkedIn: {share_link}"
34
-
35
-
36
- def combine_text_fields(text_list):
37
- return "\n\n".join([text for text in text_list if text])
38
-
39
-
40
- def format_for_linkedin(text):
41
- """Format analysis for LinkedIn sharing"""
42
- # Extract just the summary/conclusion part to keep LinkedIn share concise
43
- conclusion_match = re.search(
44
- r"(?:Conclusion|Final Recommendation).*?:(.*?)(?=$)", text, re.DOTALL
45
- )
46
-
47
- if conclusion_match:
48
- conclusion = conclusion_match.group(1).strip()
49
- formatted = "I received this career path analysis insight:\n\n" + conclusion
50
- return formatted[:500] + "..." if len(formatted) > 500 else formatted
51
-
52
- # Fallback if no conclusion section found
53
- shortened = text[:500] + "..." if len(text) > 500 else text
54
- return "Career Path Analysis Results:\n\n" + shortened
55
-
56
-
57
- def get_share_link(text):
58
- # Create a shortened version for sharing (LinkedIn has character limits)
59
- summary = text[:500] + "..." if len(text) > 500 else text
60
-
61
- # Get the LinkedIn sharing URL with the text encoded
62
- base_url = "https://www.linkedin.com/sharing/share-offsite/"
63
- params = {
64
- "url": "https://huggingface.co/spaces/LinkedIn-Advice/career-path-advisor",
65
- "title": "My Career Path Analysis",
66
- "summary": summary,
67
- }
68
-
69
- share_url = f"{base_url}?{urllib.parse.urlencode(params)}"
70
- return share_url
71
-
72
-
73
- def process_input_data(
74
- role_count, roles_and_exps, achievements, educations, edu_achievements
75
- ):
76
- # Process roles and experience
77
- roles_data = combine_roles(role_count, *roles_and_exps)
78
-
79
- # Process achievements, education, and educational achievements
80
- achievements_data = combine_text_fields(achievements)
81
- education_data = combine_text_fields(educations)
82
- edu_achievements_data = combine_text_fields(edu_achievements)
83
-
84
- return roles_data, achievements_data, education_data, edu_achievements_data
85
-
86
-
87
  def copy_to_clipboard(text):
88
  """Copy text to clipboard"""
 
 
 
89
  pyperclip.copy(text)
90
- return "Report copied to clipboard!"
91
 
92
 
93
  def export_state(
94
  professional_background,
95
- professional_achievements,
96
  education_background,
97
- education_achievements,
98
  goals,
99
  insights,
100
  time_preference,
@@ -104,9 +27,7 @@ def export_state(
104
  ) -> str:
105
  state_dict = {
106
  "Professional Background": professional_background,
107
- "Professional Achievements": professional_achievements,
108
  "Education Background": education_background,
109
- "Education Achievements": education_achievements,
110
  "Goals": goals,
111
  "Insights": insights,
112
  "Time Preference": time_preference,
@@ -116,6 +37,5 @@ def export_state(
116
  }
117
 
118
  formatted_output = "\n".join(f"{key}: {value}" for key, value in state_dict.items())
119
- print(formatted_output)
120
 
121
  return formatted_output
 
3
  Handles input processing, clipboard operations, and sharing functionality.
4
  """
5
 
 
 
 
6
  import pyperclip
7
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  def copy_to_clipboard(text):
10
  """Copy text to clipboard"""
11
+ if not pyperclip.is_available():
12
+ print("Clipboard is not available on this system")
13
+ return None
14
  pyperclip.copy(text)
15
+ return None
16
 
17
 
18
  def export_state(
19
  professional_background,
 
20
  education_background,
 
21
  goals,
22
  insights,
23
  time_preference,
 
27
  ) -> str:
28
  state_dict = {
29
  "Professional Background": professional_background,
 
30
  "Education Background": education_background,
 
31
  "Goals": goals,
32
  "Insights": insights,
33
  "Time Preference": time_preference,
 
37
  }
38
 
39
  formatted_output = "\n".join(f"{key}: {value}" for key, value in state_dict.items())
 
40
 
41
  return formatted_output
linkedinadvice/career_analysis.py CHANGED
@@ -17,7 +17,17 @@ class CareerAnalyzer:
17
  self.model_name = model_name
18
  self.temperature = temperature
19
 
20
- def analyze(self, user_data):
 
 
 
 
 
 
 
 
 
 
21
  """
22
  Analyze career paths based on user data
23
 
@@ -30,74 +40,48 @@ class CareerAnalyzer:
30
  str: Formatted analysis results
31
  """
32
  # Use default equal weights if none provided
33
- if scoring_weights is None:
34
- scoring_weights = [
35
- 0.33,
36
- 0.33,
37
- 0.34,
38
- ] # Slightly more on opportunity to sum to 1.0
39
-
40
- # Parse the roles data to extract current role and experience
41
- roles_list = user_data.get("roles", "").split("\n")
42
-
43
- # Identify current role (first one in the list)
44
- current_role = ""
45
- current_experience = 0
46
- if roles_list and roles_list[0]:
47
- parts = roles_list[0].split(" (")
48
- if len(parts) == 2:
49
- current_role = parts[0]
50
- exp_part = parts[1].split(" years")[0]
51
- try:
52
- current_experience = int(exp_part)
53
- except ValueError:
54
- current_experience = 0
55
-
56
- # Format previous roles (all except the first one)
57
- prev_roles_str = ", ".join(roles_list[1:]) if len(roles_list) > 1 else ""
58
 
59
  # Create the prompt with all available information
60
  prompt = f"""Analyze the following career profile and generate a taxonomy of potential career paths:
61
 
62
  Current Role: {current_role}
63
- Years in Current Role: {current_experience}
64
  """
65
 
66
  # Add previous roles if present
67
- if prev_roles_str:
68
- prompt += f"Previous Roles: {prev_roles_str}\n"
69
 
70
  # Add all the fields from user_data
71
- prompt += f"""Professional Achievements: {user_data.get("achievements", "")}
72
- Educational Background: {user_data.get("educations", "")}
73
- Educational Achievements: {user_data.get("edu_achievements", "")}
74
- Career Goals: {user_data.get("goals", "")}
75
- Additional Insights: {user_data.get("insights", "")}
76
-
77
- Time Preference: {user_data.get("time_preference")}
78
- Financial Weight: {user_data.get("financial_weight", scoring_weights[0])}
79
- Impact Weight: {user_data.get("impact_weight", scoring_weights[1])}
80
- Opportunity Weight: {user_data.get("opportunity_weight", scoring_weights[2])}
81
 
82
- Generate 5 potential career paths that align with this profile. For each path, evaluate:
83
- 1. Financial potential (scale 1-10) at 3, 10, and 10+ years
84
- 2. Human impact potential (scale 1-10) at 3, 10, and 10+ years
85
- 3. Opportunity creation potential (scale 1-10) at 3, 10, and 10+ years
86
 
87
- Show your reasoning for each score.
 
 
 
88
 
89
- Then calculate a weighted average based on the following weights:
90
- - Financial: {scoring_weights[0]}
91
- - Human Impact: {scoring_weights[1]}
92
- - Opportunity Creation: {scoring_weights[2]}
93
 
94
- And the time preference: {user_data.get("time_preference")}
 
 
 
95
 
96
  Format the output clearly with sections for each career path, the scoring breakdown, and a final recommendation section ranking the paths from highest to lowest score.
97
  """
98
 
99
  # Add novel paths instruction if requested
100
- if user_data.get("include_novel_options"):
101
  prompt += "\nPlease include at least one novel or unconventional career path in your analysis."
102
 
103
  # Print the prompt for debugging
 
17
  self.model_name = model_name
18
  self.temperature = temperature
19
 
20
+ def analyze(
21
+ self,
22
+ professional_background,
23
+ education_background,
24
+ goals,
25
+ insights,
26
+ time_preference,
27
+ financial_weight,
28
+ impact_weight,
29
+ opportunity_weight,
30
+ ):
31
  """
32
  Analyze career paths based on user data
33
 
 
40
  str: Formatted analysis results
41
  """
42
  # Use default equal weights if none provided
43
+ current_role = professional_background.split("\n\n")[0]
44
+ previous_roles = "\n\n".join(professional_background.split("\n\n")[1:])
45
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  # Create the prompt with all available information
48
  prompt = f"""Analyze the following career profile and generate a taxonomy of potential career paths:
49
 
50
  Current Role: {current_role}
 
51
  """
52
 
53
  # Add previous roles if present
54
+ if previous_roles:
55
+ prompt += f"Previous Roles: {previous_roles}\n"
56
 
57
  # Add all the fields from user_data
58
+ prompt += f"""
59
+ Educational Background: {education_background}
60
+ Career Goals: {goals}
61
+ Additional Insights: {insights}
 
 
 
 
 
 
62
 
63
+ Time Preference: {time_preference}
64
+ Financial Weight: {financial_weight}
65
+ Impact Weight: {impact_weight}
66
+ Opportunity Weight: {opportunity_weight}
67
 
68
+ Help me as an expert career advisor. Provide a taxonomy to generate promising career paths on the timescale of {time_preference} and rate them them based on success on the short, medium and long term. For each path, evaluate:
69
+ 1. Financial potential (scale 1-3) at 3, 10, and 10+ years
70
+ 2. Human impact potential (scale 1-3) at 3, 10, and 10+ years
71
+ 3. Opportunity creation potential (scale 1-3) at 3, 10, and 10+ years
72
 
73
+ Show your step by stepreasoning for each score.
 
 
 
74
 
75
+ Then calculate an accurate weighted average based on the following weights:
76
+ - Financial: {financial_weight}
77
+ - Human Impact: {impact_weight}
78
+ - Opportunity Creation: {opportunity_weight}
79
 
80
  Format the output clearly with sections for each career path, the scoring breakdown, and a final recommendation section ranking the paths from highest to lowest score.
81
  """
82
 
83
  # Add novel paths instruction if requested
84
+ if False:
85
  prompt += "\nPlease include at least one novel or unconventional career path in your analysis."
86
 
87
  # Print the prompt for debugging