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/miku@1.2.1", 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("""Support Me on Ko-fi""") 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)