Spaces:
Sleeping
Sleeping
import os | |
import gradio as gr | |
from dotenv import load_dotenv | |
from app.constants import ROLE_PLACEHOLDER, SAMPLE_RESULT | |
from app.utils import copy_to_clipboard, export_state | |
from linkedinadvice.career_analysis import CareerAnalyzer | |
from linkedinadvice.monitoring import monitor_api | |
# Load environment variables | |
load_dotenv() | |
# Check if API key is set | |
if not os.getenv("OPENAI_API_KEY"): | |
raise ValueError("OPENAI_API_KEY not found in environment variables") | |
# Initialize career analyzer | |
analyzer = CareerAnalyzer(model_name="gpt-4o-mini") | |
def analyze_career( | |
*args, | |
): | |
result = analyzer.analyze(*args) | |
return result | |
# Building the interface | |
with gr.Blocks(theme="soft") as demo: | |
# State for number of roles | |
role_count = gr.State(1) # Start with 1 role field | |
education_count = gr.State(1) # Start with 1 education field | |
professional_background_dict = gr.State({}) # State to store combined roles data | |
education_background_dict = gr.State({}) # State to store combined education data | |
professional_background = gr.State("") # State to store combined roles data | |
professional_achievements = gr.State("") # State to store combined roles data | |
education_background = gr.State("") # State to store combined education background | |
education_achievements = gr.State("") # State to store education achievements | |
goals = gr.State("") # State to store combined goals | |
insights = gr.State("") # State to store combined insights | |
time_preference = gr.State("Mid-term (10 years)") # State to store time preference | |
financial_weight = gr.State(2) # State to store financial weight | |
impact_weight = gr.State(2) # State to store impact weight | |
opportunity_weight = gr.State(2) # State to store opportunity weight | |
output = gr.State("") # State to store output | |
raw_list_inputs = gr.State([]) # State to store raw list inputs | |
gr.Markdown( | |
""" | |
# Career Pathway Analysis | |
This tool analyzes your professional background and provides tailored career path recommendations. | |
It evaluates options based on financial potential, human impact, and opportunity creation. | |
""" | |
) | |
with gr.Row(): | |
submit_btn = gr.Button("Analyze Career Paths", variant="primary", size="lg") | |
clear_btn = gr.Button("Clear", variant="stop", size="lg") | |
example_btn = gr.Button("Load Example", variant="secondary", size="lg") | |
with gr.Row(): | |
with gr.Column(scale=3): | |
with gr.Group(): | |
gr.Markdown("### Professional Information") | |
gr.Markdown("*Add your current and previous professional roles*") | |
with gr.Row(): | |
add_role_btn = gr.Button( | |
"β Add", variant="secondary", size="sm", key="add_role_btn" | |
) | |
remove_role_btn = gr.Button( | |
"β Remove", | |
variant="secondary", | |
size="sm", | |
key="remove_role_btn", | |
) | |
add_role_btn.click( | |
lambda x: x + 1, | |
inputs=[role_count], | |
outputs=[role_count], | |
) | |
remove_role_btn.click( | |
lambda x: max(x - 1, 1), | |
inputs=[role_count], | |
outputs=[role_count], | |
) | |
def render_roles(r_count): | |
for i in range(r_count): | |
if i not in professional_background_dict.value: | |
professional_background_dict.value[i] = { | |
"role": "", | |
"exp": "", | |
"professional_achievement": "", | |
} | |
with gr.Row(): | |
interactive = i == r_count - 1 | |
role = gr.Textbox( | |
key=f"role_{i}", | |
label=f"Role {i + 1}" | |
+ (" (Current)" if i == 0 else ""), | |
placeholder=ROLE_PLACEHOLDER[i % len(ROLE_PLACEHOLDER)], | |
scale=3, | |
interactive=interactive, | |
inputs=professional_background_dict.value[i].get( | |
"role", "" | |
), | |
) | |
def update_professional_background_dict(key, value, i): | |
professional_background_dict.value[i][key] = value | |
final_string = "" | |
for i in professional_background_dict.value: | |
role = professional_background_dict.value[i].get( | |
"role" | |
) | |
exp = professional_background_dict.value[i].get( | |
"exp" | |
) | |
professional_achievement = ( | |
professional_background_dict.value[i].get( | |
"professional_achievement" | |
) | |
) | |
final_string += f"{role} - {exp} years. Achieved: \n{professional_achievement}\n\n" | |
return professional_background_dict.value, final_string | |
role.input( | |
lambda x: update_professional_background_dict( | |
"role", x, i | |
), | |
inputs=[role], | |
outputs=[ | |
professional_background_dict, | |
professional_background, | |
], | |
) | |
exp = gr.Number( | |
key=f"exp_{i}", | |
label="Years", | |
value=1, | |
minimum=0, | |
scale=1, | |
interactive=interactive, | |
) | |
exp.input( | |
lambda x: update_professional_background_dict( | |
"exp", x, i | |
), | |
inputs=[exp], | |
outputs=[ | |
professional_background_dict, | |
professional_background, | |
], | |
) | |
professional_achievement = gr.Textbox( | |
key=f"professional_achievement_{i}", | |
label="Notable Achievements", | |
lines=2, | |
placeholder="List key accomplishments, awards, or significant contributions.", | |
interactive=interactive, | |
) | |
professional_achievement.input( | |
lambda x: update_professional_background_dict( | |
"professional_achievement", x, i | |
), | |
inputs=[professional_achievement], | |
outputs=[ | |
professional_background_dict, | |
professional_background, | |
], | |
) | |
raw_list_inputs.value.extend( | |
[role, exp, professional_achievement] | |
) | |
with gr.Group(): | |
gr.Markdown("### Educational Background") | |
gr.Markdown("*Add your current and previous academic experiences*") | |
with gr.Row(): | |
add_education_btn = gr.Button( | |
"β Add", | |
variant="secondary", | |
size="sm", | |
key="add_education_btn", | |
) | |
remove_education_btn = gr.Button( | |
"β Remove", | |
variant="secondary", | |
size="sm", | |
key="remove_education_btn", | |
) | |
add_education_btn.click( | |
lambda x: x + 1, | |
inputs=[education_count], | |
outputs=[education_count], | |
) | |
remove_education_btn.click( | |
lambda x: max(x - 1, 1), | |
inputs=[education_count], | |
outputs=[education_count], | |
) | |
def render_education(e_count): | |
for i in range(e_count): | |
if i not in education_background_dict.value: | |
education_background_dict.value[i] = { | |
"education": "", | |
"education_achievement": "", | |
} | |
with gr.Row(): | |
education = gr.Textbox( | |
key=f"education_{i}", | |
label="Academic Experience", | |
lines=3, | |
placeholder="e.g. Bachelor of Science in Computer Science, University of Technology", | |
) | |
def update_educational_background_dict(key, value, i): | |
education_background_dict.value[i][key] = value | |
final_string = "" | |
for i in education_background_dict.value: | |
education = education_background_dict.value[i].get( | |
"education" | |
) | |
edu_achievement = education_background_dict.value[ | |
i | |
].get("edu_achievement") | |
final_string += f"{education}. Achieved: \n{edu_achievement}\n\n" | |
return education_background_dict.value, final_string | |
education.input( | |
lambda x: update_educational_background_dict( | |
"education", x, i | |
), | |
inputs=[education], | |
outputs=[ | |
education_background_dict, | |
education_background, | |
], | |
) | |
edu_achievement = gr.Textbox( | |
key=f"edu_achievement_{i}", | |
label="Academic Achievements", | |
lines=3, | |
placeholder="Awards, honors, notable projects or research during your education", | |
) | |
edu_achievement.input( | |
lambda x: update_educational_background_dict( | |
"education_achievement", x, i | |
), | |
inputs=[education_achievements], | |
outputs=[ | |
education_background_dict, | |
education_background, | |
], | |
) | |
if education.value: | |
education_background.value += education.value | |
if edu_achievement.value: | |
education_achievements.value += edu_achievement.value | |
raw_list_inputs.value.extend([education, edu_achievement]) | |
with gr.Group(): | |
gr.Markdown("### Future Plans") | |
goals = gr.Textbox( | |
label="Career Goals", | |
lines=3, | |
placeholder="Describe your short-term and long-term career objectives", | |
key="goals", | |
) | |
insights = gr.Textbox( | |
label="Additional Insights", | |
lines=3, | |
placeholder="Other relevant information like skills, interests, or constraints", | |
key="insights", | |
) | |
with gr.Group(): | |
gr.Markdown("### Analysis Preferences") | |
gr.Markdown( | |
"*Adjust the importance of each factor in career evaluation*" | |
) | |
time_preference = gr.Radio( | |
[ | |
"Short-term (3 years)", | |
"Mid-term (10 years)", | |
"Long-term (10+ years)", | |
], | |
label="Time Horizon Preference", | |
value="Mid-term (10 years)", | |
key="time_preference", | |
) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
financial_weight = gr.Radio( | |
[1, 2, 3], | |
value=2, | |
label="π° Financial Potential", | |
info="Earning potential and financial growth", | |
elem_classes=["weight-radio"], | |
key="financial_weight", | |
) | |
with gr.Column(scale=1): | |
impact_weight = gr.Radio( | |
[1, 2, 3], | |
value=2, | |
label="π« Human Impact", | |
info="Positive impact on others and society", | |
elem_classes=["weight-radio"], | |
key="impact_weight", | |
) | |
with gr.Column(scale=1): | |
opportunity_weight = gr.Radio( | |
[1, 2, 3], | |
value=2, | |
label="πͺ Opportunity Creation", | |
info="Doors opened for future growth and options", | |
elem_classes=["weight-radio"], | |
key="opportunity_weight", | |
) | |
with gr.Column(scale=2): | |
output_box = gr.Markdown( | |
output.value, | |
container=True, | |
height=614, | |
show_copy_button=True, | |
key="output_box", | |
) | |
with gr.Row(): | |
copy_btn = gr.Button("π Copy to Clipboard", variant="secondary") | |
share_btn = gr.Button("π Share on LinkedIn", variant="secondary") | |
# Copy and share functionality | |
copy_btn.click( | |
copy_to_clipboard, | |
inputs=output_box, | |
) | |
# Add info section at the bottom | |
with gr.Accordion("About This Tool", open=False): | |
gr.Markdown( | |
""" | |
This career analysis tool uses AI to generate personalized career path recommendations | |
based on your professional background, education, and goals. | |
**How It Works:** | |
1. Enter your current and previous roles with years of experience | |
2. Provide information about your achievements and education | |
3. Set your preferences for analysis (time horizon and factor weights) | |
4. Get a detailed analysis of potential career paths with scoring | |
The analysis evaluates each career path on three dimensions: | |
- **Financial Potential**: Earning capacity and financial growth | |
- **Human Impact**: Contribution to society and positive influence | |
- **Opportunity Creation**: Future opportunities and career flexibility | |
You can adjust the weights to prioritize what matters most to you. | |
""" | |
) | |
submit_btn.click( | |
lambda *args: analyze_career(*args) if export_state(*args) or True else None, | |
inputs=[ | |
professional_background, | |
education_background, | |
goals, | |
insights, | |
time_preference, | |
financial_weight, | |
impact_weight, | |
opportunity_weight, | |
], | |
outputs=[output_box], | |
) | |
clear_btn.click( | |
fn=lambda: None, inputs=[], outputs=[], js="() => location.reload()" | |
) | |
example_btn.click( | |
fn=lambda _: SAMPLE_RESULT, | |
inputs=[output_box], | |
outputs=[output_box], | |
) | |
# Launch the app | |
if __name__ == "__main__": | |
demo.launch() | |