career-buddy-V2 / app.py
rivapereira123's picture
Update app.py
80d18b4 verified
import gradio as gr
import datetime
import random
from collections import defaultdict
from utils.constants import TASK_DIFFICULTIES
from utils.data_helpers import smart_label_converter, clean_text, extract_actions_from_feedback
from utils.api_clients import initialize_api_clients
from utils.embedding_model import initialize_embedding_model
from utils.summarizer import initialize_summarizer
from utils.constants import course_suggestions
from modules.rag import load_docs, memo_rag_engine, batch_ingest_from_classcentral
from modules.task_management import display_tasks, add_reward, calculate_progress, claim_reward, add_task, add_course_to_memo, mark_step_completed, calculate_visual_progress, reset_weekly_data
from modules.analysis import analyze_linkedin, analyze_github, analyze_scraped_linkedin_profile, analyze_apify_dataset_ui
from modules.analysis import fetch_and_analyze_linkedin
from utils.constants import completed_tasks
from modules.memory import save_to_memory, recall_from_memory
import textwrap
from modules.analysis import fetch_and_analyze_linkedin # Import the function for LinkedIn analysis
# ==== Global Variables ====
completed_tasks = set()
memo_data = []
visual_steps = []
# ==== API Clients & Models ====
pc, pine_index, APIFY_TOKEN, OPENAI_API_KEY, TAVILY_API_KEY, client = initialize_api_clients()
embedding_model = initialize_embedding_model()
summarizer = initialize_summarizer()
# ==== Gradio UI Components ====
class RoadmapUnlockManager:
def __init__(self):
self.unlocked = False
def unlock_roadmap(self):
self.unlocked = True
return gr.update(visible=True)
def get_roadmap_visibility(self):
return gr.update(visible=self.unlocked)
roadmap_unlock = RoadmapUnlockManager()
with gr.Blocks(theme="NoCrypt/[email protected]", css="""
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap');
body {
font-family: 'Source Sans Pro', sans-serif;
background-color: #121212;
color: #f0f0f0;
}
#nickname-box {
max-width: 300px;
margin: 0 auto;
padding: 20px;
background-color: #1e1e1e;
border-radius: 12px;
box-shadow: 0px 0px 10px rgba(0,0,0,0.2);
}
#planner-card {
max-width: 720px;
margin: 0 auto;
padding: 28px;
background-color: #1e1e1e;
border-radius: 16px;
box-shadow: 0 0 12px rgba(0, 0, 0, 0.4);
}
#planner-card input,
#planner-card textarea,
#planner-card .gr-button {
font-size: 14px;
padding: 8px 12px;
border-radius: 8px;
}
#planner-card .gr-button {
background-color: #3a3aff;
color: #f0f0f0;
font-weight: bold;
}
#planner-card label {
font-weight: 600;
color: #f0f0f0;
}
#planner-card .gr-tab {
margin-top: 12px;
}
#linky-tab {
background-color: #1e1e1e !important;
color: #f0f0f0 !important;
padding: 24px;
border-radius: 16px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}
#linky-tab .gr-block,
#linky-tab .gr-column,
#linky-tab .gr-panel {
background-color: transparent !important;
color: inherit;
box-shadow: none;
}
#linky-tab input,
#linky-tab textarea {
background-color: #2c2c2c !important;
color: #f0f0f0 !important;
border: 1px solid #444 !important;
border-radius: 6px;
}
#linky-tab .gr-button {
background-color: #4444aa !important;
color: #f0f0f0 !important;
border-radius: 6px;
}
#dds-logo img {
max-width: 200px;
display: block;
margin: 0 auto 15px;
}
#user-card {
background-color: #2b2b2b;
border: 1px solid #444;
border-radius: 12px;
padding: 24px;
margin-top: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
color: #e0e0e0;
}
#user-card input,
#user-card textarea {
background-color: #3a3a3a !important;
color: #e0e0e0 !important;
border: 1px solid #555;
border-radius: 6px;
padding: 10px;
}
#user-card label {
color: #cccccc;
}
@media (max-width: 768px) {
.gr-row {
flex-direction: column !important;
}
#user-card {
margin-top: 20px;
}
}
.gradio-container {
color: #f0f0f0 !important;
background-color: #121212 !important;
}
.prose {
color: #f0f0f0 !important;
}
.gr-textbox,
.gr-markdown,
.gr-markdown div,
.gr-markdown p {
color: #f0f0f0 !important;
background: transparent;
}
label {
color: #cccccc !important;
}
input, textarea {
background-color: #1e1e1e !important;
color: #f0f0f0 !important;
border: 1px solid #444 !important;
}
.gr-button {
color: #f0f0f0 !important;
font-weight: bold;
background-color: #3a3aff !important;
}
""") as app:
user_id_state = gr.State()
roadmap_unlock = RoadmapUnlockManager()
start_date = gr.Textbox(label="πŸ“… Start Date", value=str(datetime.date.today()))
with gr.Tabs():
with gr.Tab("✨ Welcome"):
with gr.Row(equal_height=True):
# LEFT: Intro
with gr.Column(scale=2):
gr.Markdown("""
# πŸ‘‹ Welcome to Career Buddy!
**Your AI-powered career planner** for LinkedIn, GitHub, and goal-tracking.**
If you enjoy this project and want to help me beat OpenAI costs; support me below
""")
gr.HTML("""<a href="https://ko-fi.com/wishingonstars" target="_blank"><img src="https://cdn.prod.website-files.com/5c14e387dab576fe667689cf/670f5a0172b90570b1c21dab_kofi_logo.png" alt="Support Me on Ko-fi" style="width: 150px;"></a>""")
gr.Markdown("""
### πŸš€ Get Started
1. **Enter your nickname** to personalize your journey.
2. **Set your weekly goal** to stay on track.
3. **Explore the tabs** for LinkedIn/GitHub analysis, smart planning, and more!
""")
# RIGHT: User Input
with gr.Column(scale=1, elem_id="user-card"):
gr.Markdown("## Your Journey Starts Here")
nickname_input = gr.Textbox(label="Enter your Nickname", placeholder="e.g., DataScientistPro", interactive=True)
weekly_goal_input = gr.Textbox(label="What's your weekly career goal?", placeholder="e.g., Apply to 5 jobs, finish a Python course", interactive=True)
with gr.Row():
save_btn = gr.Button("Save Profile")
load_btn = gr.Button("Load Profile")
gr.Markdown("### Your Progress")
progress_output = gr.Markdown("", elem_id="progress-output")
save_btn.click(
fn=lambda nickname, goal: save_user_profile(nickname, goal),
inputs=[nickname_input, weekly_goal_input],
outputs=progress_output
)
load_btn.click(
fn=lambda: load_user_profile(),
inputs=[],
outputs=[nickname_input, weekly_goal_input, progress_output]
)
with gr.Tab("πŸ”— Linky (LinkedIn Analyzer)", elem_id="linky-tab"):
with gr.Row():
with gr.Column(scale=1):
linkedin_url_input = gr.Textbox(label="LinkedIn Profile URL", placeholder="Paste your LinkedIn profile URL here", interactive=True)
analyze_linkedin_btn = gr.Button("Analyze LinkedIn Profile")
with gr.Column(scale=2):
linkedin_analysis_output = gr.Markdown("", label="LinkedIn Analysis Results")
# When the button is clicked, analyze the LinkedIn profile
analyze_linkedin_btn.click(
fn=fetch_and_analyze_linkedin,
inputs=[linkedin_url_input],
outputs=linkedin_analysis_output
)
with gr.Tab("πŸ™ GitGuru (GitHub Reviewer)"):
with gr.Row():
with gr.Column(scale=1):
github_readme_input = gr.Textbox(label="GitHub README Content", placeholder="Paste your main GitHub README content here", lines=10, interactive=True)
analyze_github_btn = gr.Button("Analyze GitHub README")
with gr.Column(scale=2):
github_analysis_output = gr.Markdown("", label="GitHub Analysis Results")
analyze_github_btn.click(
fn=analyze_github,
inputs=[github_readme_input],
outputs=github_analysis_output
)
with gr.Tab("🧠 Smart Planner"):
with gr.Row():
with gr.Column(scale=1):
planner_goal_input = gr.Textbox(label="Your Goal", placeholder="e.g., Become a Data Scientist", interactive=True)
planner_difficulty_input = gr.Dropdown(label="Difficulty", choices=TASK_DIFFICULTIES, value="Medium", interactive=True)
planner_generate_btn = gr.Button("Generate Roadmap")
with gr.Column(scale=2):
roadmap_output = gr.Markdown("", label="Career Roadmap")
planner_generate_btn.click(
fn=lambda goal, difficulty: generate_roadmap(goal, difficulty, pc, pine_index, client),
inputs=[planner_goal_input, planner_difficulty_input],
outputs=roadmap_output
)
with gr.Tab("🎯 Task Tracker"):
with gr.Row():
with gr.Column(scale=1):
task_name_input = gr.Textbox(label="Task Name", placeholder="e.g., Complete Python course", interactive=True)
task_type_input = gr.Dropdown(label="Task Type", choices=["Learning", "Networking", "Project", "Application"], value="Learning", interactive=True)
task_add_btn = gr.Button("Add Task")
gr.Markdown("### Mark Task Steps Completed")
task_step_input = gr.Textbox(label="Step to Mark Completed", placeholder="e.g., Chapter 1 of Python course", interactive=True)
task_mark_completed_btn = gr.Button("Mark Step Completed")
gr.Markdown("### Rewards")
reward_amount_input = gr.Number(label="Reward Amount", value=10, interactive=True)
reward_claim_btn = gr.Button("Claim Reward")
reset_weekly_btn = gr.Button("Reset Weekly Data")
with gr.Column(scale=2):
tasks_display = gr.Markdown("", label="Your Tasks")
progress_bar = gr.HTML("", label="Weekly Progress")
rewards_display = gr.Markdown("", label="Your Rewards")
task_add_btn.click(
fn=lambda user_id, task_name, task_type: add_task(user_id, task_name, task_type, tasks_display, progress_bar, rewards_display),
inputs=[user_id_state, task_name_input, task_type_input],
outputs=[tasks_display, progress_bar, rewards_display]
)
task_mark_completed_btn.click(
fn=lambda user_id, step: mark_step_completed(user_id, step, tasks_display, progress_bar, rewards_display),
inputs=[user_id_state, task_step_input],
outputs=[tasks_display, progress_bar, rewards_display]
)
reward_claim_btn.click(
fn=lambda user_id, amount: claim_reward(user_id, amount, rewards_display),
inputs=[user_id_state, reward_amount_input],
outputs=rewards_display
)
reset_weekly_btn.click(
fn=lambda user_id: reset_weekly_data(user_id, tasks_display, progress_bar, rewards_display),
inputs=[user_id_state],
outputs=[tasks_display, progress_bar, rewards_display]
)
with gr.Tab("πŸ“š Memo (Course Recommender)"):
with gr.Row():
with gr.Column(scale=1):
memo_query_input = gr.Textbox(label="Ask about a course or topic", placeholder="e.g., Best Python courses for data science", interactive=True)
memo_search_btn = gr.Button("Search Courses")
gr.Markdown("### Add Course to Memo")
memo_course_name_input = gr.Textbox(label="Course Name", interactive=True)
memo_course_url_input = gr.Textbox(label="Course URL", interactive=True)
memo_add_course_btn = gr.Button("Add Course")
with gr.Column(scale=2):
memo_output = gr.Markdown("", label="Course Recommendations")
memo_search_btn.click(
fn=lambda query: memo_rag_engine(query, pine_index, embedding_model, client, summarizer),
inputs=[memo_query_input],
outputs=memo_output
)
memo_add_course_btn.click(
fn=lambda name, url: add_course_to_memo(name, url, pine_index, embedding_model, client, summarizer),
inputs=[memo_course_name_input, memo_course_url_input],
outputs=memo_output
)
with gr.Tab("πŸ“Š Visualizer"):
with gr.Row():
with gr.Column(scale=1):
visualizer_goal_input = gr.Textbox(label="Your Goal", placeholder="e.g., Become a Data Scientist", interactive=True)
visualizer_generate_btn = gr.Button("Generate Visual Roadmap")
with gr.Column(scale=2):
visualizer_output = gr.Plot(label="Visual Roadmap")
visualizer_generate_btn.click(
fn=lambda goal: generate_visual_roadmap(goal, visual_steps),
inputs=[visualizer_goal_input],
outputs=visualizer_output
)
def save_user_profile(nickname, weekly_goal):
user_id = nickname.lower().replace(" ", "_")
summary = f"User profile: {nickname}, goal: {weekly_goal}"
steps = [] # optional placeholder
courses = [] # optional placeholder
success = save_to_memory(user_id, "profile", summary, steps, courses)
if success:
user_id_state.value = user_id
return f"Profile for **{nickname}** saved! Weekly goal: **{weekly_goal}**"
else:
return "❌ Failed to save profile."
def load_user_profile():
user_id = user_id_state.value
if not user_id:
return "", "", "❌ No user loaded."
profile_result = recall_from_memory(user_id, "profile")
if "❌ No saved plan" in profile_result:
return "", "", "❌ Profile not found in memory."
lines = profile_result.splitlines()
nickname_line = next((line for line in lines if "nickname" in line.lower()), "")
goal_line = next((line for line in lines if "goal" in line.lower()), "")
nickname = nickname_line.split(":")[-1].strip() if nickname_line else ""
weekly_goal = goal_line.split(":")[-1].strip() if goal_line else ""
return nickname, weekly_goal, "βœ… Loaded profile from memory."
def generate_roadmap(goal, difficulty, pc, pine_index, client):
# This function would use the RAG system to generate a roadmap
# For now, return a placeholder
steps = [
"Learn Python Basics",
"Understand Data Structures & Algorithms",
"Master SQL",
"Explore Machine Learning Fundamentals",
"Build a Portfolio Project",
"Apply for Jobs"
]
return render_text_roadmap(goal, steps)
import matplotlib.pyplot as plt
from modules.analysis import render_text_roadmap
def generate_visual_roadmap(goal, steps):
text_roadmap = render_text_roadmap(goal, steps, completed_tasks)
print(text_roadmap) # Optional: for debugging/logging
fig, ax = plt.subplots()
ax.barh(range(len(steps)), [1] * len(steps), tick_label=list(reversed(steps)))
ax.set_title(f"Visual Roadmap for {goal}")
ax.invert_yaxis() # So Step 1 is at the top
return fig
app.launch(debug=True)