import gradio as gr from openai import OpenAI import os user_profile = { "mode": None, "specific_career": None, "bg_info": None, "work_value": None, "personality_summary": None, "dream_day": None, "forward_direction_choice": None, "recommended_directions": [], "selected_direction": None, "recommended_jobs": [], "final_choice": None } base_questions = [ ("mode", "Do you have any preferred future plans?\n- if yes, reply'Y'(Backward Mode)\n- if NO,reply'N'(Forward Mode)") ] # ============================ Forward Mode Questions ============================ forward_additional_questions = [ ("bg_info", """To get started, please tell me a bit about your academic background and interests. What's your school, year, major, and core courses? If you have a transcript or resume, that would be even better!"""), ("work_value", """Great! What do you think is the meaning or value of 'work'? What should an ideal job provide for you? (e.g., helping others, high income, free time, personal growth, creative space, etc.)"""), ("personality_summary", "Briefly describe your personality: Are you introverted or extroverted? Do you enjoy challenges? Detail-oriented? Do you dislike repetitive work?"), ("dream_day", "Now describe what your ideal workday looks like: Where are you working? What are you doing? Who are you collaborating with? Is it busy or relaxed? More freedom or more structure?") ] # ============================ Backward Mode Questions ============================ backward_additional_questions = [ ("specific_career", "Please describe the specific career path you want to pursue."), ("bg_info", "Please provide your school, year, major, and any internship or project experience you already have, so I can help you build a clearer path to your goal.") ] current_q_index = 0 questions = base_questions[:] in_forward_flow = False in_backward_flow = False forward_index = 0 backward_index = 0 forward_done = False backward_done = False forward_recommendation_given = False recommendation_round = 0 forward_deep_dive_done = False roadmap_offered = False roadmap_done = False direction_chosen = False jobs_recommended = False job_chosen = False post_career_detail_asked = False post_career_detail_done = False model_default = "gpt-4o" token_default = 2000 temp_default = 0.7 top_p_default = 0.95 def backward_strategy_plan(specific_career, bg_info): prompt = f""" You are a professional career planning advisor,use english. A student has the target career: {specific_career} Their current background is: {bg_info} Please help the student build a clear plan to reach their goal, including: 1. Should they consider changing majors or taking a minor? 2. Are there any courses they should take? What are the key course topics? 3. Recommended certificates/exams (e.g., CFA) and study tips 4. Suggested internship directions (based on their background) 5. How to make use of university resources (career center, clubs, networking, etc.) 6. If their background is mismatched (e.g., mechanical engineering to finance), how to bridge the gap? Use Markdown formatting in sections, with a minimum of 300 words. The content must align closely with the student's current background and goals. """ try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong: API_TOKEN not set" client = OpenAI(api_key=api_key) msgs = [ {"role": "system", "content": "You are an experienced career advisor, good at creating roadmaps based on user background. "}, {"role": "user", "content": prompt} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) return resp.choices[0].message.content except Exception as e: return f"Wrong path: {str(e)}" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def answer_abc_questions(selected, bg_info, wv, ps, dd): desired_parts = [] if "a" in selected.lower(): desired_parts.append("A") if "b" in selected.lower(): desired_parts.append("B") if "c" in selected.lower(): desired_parts.append("C") if not desired_parts: return "OK, you don't need ABC" prompt_text = f""" You are a professional career planning advisor. Below is the student's background information. Please provide detailed analysis and suggestions based on the selected module(s): A, B, or C,use english. Student Profile: - Academic Background: {bg_info} - Work Value: {wv} - Personality: {ps} - Ideal Workday: {dd} The student wants insights on the following module(s): {', '.join(desired_parts)} Please write a separate section for each selected module in order, using Markdown formatting. (A: Course Selection & Career Entry) - Analyze the student's current academic background and what capabilities they already have. - Based on their intended career, recommend what types of courses they should focus on. - Suggest course names and keywords to guide their course planning. (B: School Resource Utilization) - Provide 3 types of suggestions: 1. How to utilize the university's career services. 2. How to get involved with career-related clubs, organizations, and platforms. 3. How to network with alumni in their field and improve networking skills. (C: Internships & Experience Building) - Suggest platforms to find internships. - Recommend internship directions aligned with the student's career goal. - Provide tips for preparing materials and applying. - Strategies for gaining experience through networking, internships, or campus jobs. Only include the modules selected by the student. Do not generate content for unselected modules. """ try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN Not set" client = OpenAI(api_key=api_key) msgs = [ {"role": "system", "content": "You are a professional career advisor who provides module-specific (A/B/C) analysis and suggestions."}, {"role": "user", "content": prompt_text} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) return resp.choices[0].message.content except Exception as e: return f"Wrong ABC: {str(e)}" def do_selected_career_detail(selected_career, bg_info, wv, ps, dd): prompt = f""" You are a professional career planning advisor. The student has selected the following specific career: {selected_career} Student Profile: - Academic Background: {bg_info} - Work Value: {wv} - Personality: {ps} - Ideal Workday: {dd} Please write a detailed description of this career including at least the following,use english: 1. Average salary (entry-level / mid-level / senior) 2. Work environment (remote/hybrid/in-office, team size, etc.) 3. Promotion difficulty (what qualifications or milestones are needed) 4. Key skills and certifications required 5. Typical work rhythm (fast-paced or routine?) 6. Industry outlook Please use Markdown formatting in separate sections, with a minimum of 300 words. """ try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN not set" client = OpenAI(api_key=api_key) msgs = [ {"role": "system", "content": "You are a professional career advisor who provides in-depth career descriptions."}, {"role": "user", "content": prompt} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) return resp.choices[0].message.content except Exception as e: return f"Wrong path: {str(e)}" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def do_time_roadmap(): direction = user_profile.get("final_choice") or user_profile.get("selected_direction") or \ user_profile.get("forward_direction_choice") or user_profile.get("specific_career") bg_info = user_profile["bg_info"] or "None" wv = user_profile["work_value"] or "None" ps = user_profile["personality_summary"] or "None" dd = user_profile["dream_day"] or "None" prompt_roadmap = f""" Student Profile: - Academic Background: {bg_info} - Career Direction / Specific Role: {direction} - Work Values: {wv} - Personality: {ps} - Ideal Workday: {dd} Please create a timeline-style career roadmap based on the student's background and goal,use english. Use the following structure as a reference: 📍 Summer after Year 2: [What internship to apply for, what activities to participate in, what certifications to pursue] 🎓 Year 3: [Recommended courses, key projects or academic goals] 💼 Summer after Year 3: [Target internships, certifications, personal/professional development plans] 📄 6–12 Months Before Graduation: [Certifications to complete, job/grad school application materials to prepare] 🚀 Post-Graduation: [Target roles, how to apply, next steps] Please write the roadmap using Markdown formatting and tailor your suggestions specifically to the student's profile. """ try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN NOt set" client = OpenAI(api_key=api_key) msgs = [ {"role":"system","content":"You are a professional career advisor who generates timeline-based career roadmaps"}, {"role":"user","content": prompt_roadmap} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) return resp.choices[0].message.content except Exception as e: return f"Wrong path: {str(e)}" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Recomend jpb ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def recommend_3jobs_for_direction(direction, bg_info, wv, ps, dd): prompt = f""" You are a professional career advisor,use english. The student has selected the following general career direction: {direction} Student background: {bg_info} Work values: {wv} Personality: {ps} Ideal workday: {dd} Please recommend 3 specific job roles related to this direction, and provide details for each: 1) Why this job fits the chosen direction 2) Typical responsibilities 3) Required skills and certifications 4) Future career prospects End your response with this format (do not repeat this format earlier in the message): Please select your ideal job: 1. [Job Title 1] 2. [Job Title 2] 3. [Job Title 3] If none of these suit you, enter 'change'. """ try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN not set" client = OpenAI(api_key=api_key) msgs = [ {"role": "system", "content": "You are a professional career advisor, recommending 3 specific jobs based on the student's chosen direction."}, {"role": "user", "content": prompt} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) output_text = resp.choices[0].message.content import re job_pattern = r'(\d+)\.\s+\[?(.*?)\]?(?:\n|$)' job_matches = re.findall(job_pattern, output_text) job_list = [match[1].strip() for match in job_matches] if len(job_list) < 3: job_list = [ f"{direction} - JobA", f"{direction} - JobB", f"{direction} - JobC" ] user_profile["recommended_jobs"] = job_list[:3] global jobs_recommended jobs_recommended = True return output_text except Exception as e: return f"wrong job: {str(e)}" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ big direction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def recommend_3directions(): bg_info = user_profile["bg_info"] or "None" wv = user_profile["work_value"] or "None" ps = user_profile["personality_summary"] or "None" dd = user_profile["dream_day"] or "None" rec_prompt = f""" Based on the following information, write a structured student profile and recommend 3 general career directions, use english. Address the student as "you" (not he/she). - Academic Background: {bg_info} - Work Values: {wv} - Personality: {ps} - Ideal Workday: {dd} Two parts required: [1. Student Profile]: Briefly summarize their academic background, core values, personality, and career expectations. [2. Recommend 3 General Directions]: For each direction, write 1–2 paragraphs explaining why it's a good fit for the student. End with only the following format (do not repeat it earlier): Please choose your career direction: 1. [Direction Name 1] 2. [Direction Name 2] 3. [Direction Name 3] If none are suitable, type 'change'. """ try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN not set" client = OpenAI(api_key=api_key) msgs = [ {"role":"system","content":"You are a career advisor who recommends 3 general directions based on the user's profile."}, {"role":"user","content": rec_prompt} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) output_text = resp.choices[0].message.content import re dir_pattern = r'(\d+)\.\s+\[?(.*?)\]?(?:\n|$)' dir_matches = re.findall(dir_pattern, output_text) dir_list = [match[1].strip() for match in dir_matches] if len(dir_list) < 3: dir_list = [ "Direction 1", "Directionn2", "Direction 3" ] user_profile["recommended_directions"] = dir_list[:3] return output_text except Exception as e: return f"Wrong direction: {str(e)}" def generate_system_prompt(): mode = user_profile["mode"] sc = user_profile["specific_career"] bg = user_profile["bg_info"] wv = user_profile["work_value"] ps = user_profile["personality_summary"] dd = user_profile["dream_day"] fwd = user_profile["forward_direction_choice"] if mode == "Y": return f""" You are a professional career advisor using the Backward Design method to help students achieve their career goals,use english. Target career: {sc} Background information: {bg} Please provide: 1. A brief analysis of the target career 2. Top companies or organizations in this field 3. Required skills and qualifications 4. Career development path 5. Academic/course suggestions, skill development, use of resources, internship planning, resume tips, etc. Finally, output a career roadmap in Markdown format like this: 📍 Now → 🎓 Learning Suggestions → 💼 Practice Suggestions → 📄 Certification Advice → 🚀 Job Search Suggestions """ else: return f""" You are a professional career advisor using the Forward Design method to help students explore suitable career paths,use english. Student background: {bg} Work values: {wv} Personality summary: {ps} Ideal workday: {dd} Student's selected direction: {fwd} Please provide: 1. An analysis of the student's strengths, personality traits, and values 2. 3 recommended specific jobs, including daily work content, fit, requirements, and preparation pathway 3. A final career roadmap: 📍 Now → 🎓 Learning Suggestions → 💼 Practice Suggestions → 📄 Certification Advice → 🚀 Job Search Suggestions """ def predict(message, history): global current_q_index, questions global in_forward_flow, in_backward_flow global forward_index, backward_index global forward_done, backward_done global forward_recommendation_given global recommendation_round global forward_deep_dive_done global roadmap_offered, roadmap_done global direction_chosen, jobs_recommended, job_chosen global post_career_detail_asked, post_career_detail_done if not history: current_q_index = 0 questions[:] = base_questions for k in user_profile: user_profile[k] = None in_forward_flow = False in_backward_flow = False forward_index = 0 backward_index = 0 forward_done = False backward_done = False forward_recommendation_given = False recommendation_round = 0 forward_deep_dive_done = False roadmap_offered = False roadmap_done = False direction_chosen = False jobs_recommended = False job_chosen = False post_career_detail_asked = False post_career_detail_done = False if 0 < current_q_index <= len(questions): key = questions[current_q_index - 1][0] if key == "mode" and current_q_index == 1: ans = message.strip() user_profile["mode"] = ans questions[:] = [] if "Y" in ans: in_backward_flow = True else: in_forward_flow = True if current_q_index < len(questions)and not in_forward_flow and not in_backward_flow: nxt = questions[current_q_index][1] current_q_index += 1 return nxt mode = user_profile.get("mode") or "" if mode == "Y": if in_backward_flow and not backward_done: if backward_index > 0 and backward_index <= len(backward_additional_questions): prev_key = backward_additional_questions[backward_index - 1][0] user_profile[prev_key] = message.strip() if backward_index < len(backward_additional_questions): k, prompt_text = backward_additional_questions[backward_index] backward_index += 1 return prompt_text else: strategy = backward_strategy_plan( specific_career=user_profile.get("specific_career"), bg_info=user_profile.get("bg_info") ) user_profile["final_choice"] = user_profile.get("specific_career") job_chosen = True forward_deep_dive_done = True post_career_detail_asked = True return strategy + "\n\nI can do further exploration:" \ "\n- A:Major or course & Job direction" \ "\n- B:School Resources" \ "\n- C:Internship & networking " \ "\nEnter A / B / C / AB / BC / AC / ABC" \ "\nif No need'Please NO'。" elif post_career_detail_asked and not post_career_detail_done: user_choice = message.strip().lower() if user_choice in ["Please NO", "no", "n"]: post_career_detail_done = True roadmap_offered = True return "OK, would you like a job path【I need】,or【NO need】。" else: abc_text = answer_abc_questions( selected=user_choice, bg_info=user_profile.get("bg_info", ""), wv=user_profile.get("work_value", "None"), ps=user_profile.get("personality_summary", "None"), dd=user_profile.get("dream_day", "None") ) post_career_detail_done = True roadmap_offered = True return abc_text + "\n\nDo you need a time path plan?enter【I need】,or 【NO need】。" elif job_chosen and not roadmap_offered and not roadmap_done: roadmap_offered = True return "Need a time path map?【I need】,or【NO need】。" elif roadmap_offered and not roadmap_done: ans = message.strip().lower() if ans in ["I need", "yes", "y"]: roadmap_done = True backward_done = True return do_time_roadmap() else: roadmap_done = True backward_done = True return "OK, your plan is finished" if backward_done: try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN not set" client = OpenAI(api_key=api_key) sprompt = generate_system_prompt() msgs = [ {"role": "system", "content": sprompt}, {"role": "user", "content": f"this material: {user_profile}. enter if you need more"} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) return resp.choices[0].message.content except Exception as e: return f"Wrong: {str(e)}" else: if in_forward_flow and not direction_chosen: if forward_index > 0 and forward_index <= len(forward_additional_questions): prev_key = forward_additional_questions[forward_index - 1][0] user_profile[prev_key] = message.strip() if forward_index < len(forward_additional_questions): k, prompt_text = forward_additional_questions[forward_index] forward_index += 1 return prompt_text elif not forward_recommendation_given: forward_recommendation_given = True return recommend_3directions() else: choice = message.strip().lower() if choice in ["1","2","3"]: idx = int(choice) - 1 if idx < len(user_profile["recommended_directions"]): sel_dir = user_profile["recommended_directions"][idx] user_profile["selected_direction"] = sel_dir direction_chosen = True return recommend_3jobs_for_direction( direction=sel_dir, bg_info=user_profile["bg_info"] or "", wv=user_profile["work_value"] or "", ps=user_profile["personality_summary"] or "", dd=user_profile["dream_day"] or "" ) else: return "Enter 1/2/3或'Change'" elif choice == "Change": recommendation_round += 1 if recommendation_round > 2: forward_done = True return "Change too many times" else: return recommend_3directions() else: return "enter 1,2,3 or change" elif direction_chosen and jobs_recommended and not job_chosen: choice = message.strip().lower() if choice in ["1","2","3"]: idx = int(choice) - 1 if idx < len(user_profile["recommended_jobs"]): final_job = user_profile["recommended_jobs"][idx] user_profile["final_choice"] = final_job job_chosen = True detail_msg = do_selected_career_detail( selected_career=final_job, bg_info=user_profile["bg_info"] or "", wv=user_profile["work_value"] or "", ps=user_profile["personality_summary"] or "", dd=user_profile["dream_day"] or "" ) forward_deep_dive_done = True post_career_detail_asked = True return detail_msg + "\n\nI can do futher information for you:" \ "\n- A:major course & job" \ "\n- B:School Resources" \ "\n- C:Internship & networking" \ "\nneed more information A / B / C / AB / BC / AC / ABC" \ "\nNO need,enter'No need'。" else: return "Re enter please" elif choice == "Change": recommendation_round += 1 if recommendation_round > 2: forward_done = True return "too many changes" else: sel_dir = user_profile.get("selected_direction") or "No direction" return recommend_3jobs_for_direction( direction=sel_dir, bg_info=user_profile["bg_info"] or "", wv=user_profile["work_value"] or "", ps=user_profile["personality_summary"] or "", dd=user_profile["dream_day"] or "" ) else: return "enter 1,2,3 or renture" elif post_career_detail_asked and not post_career_detail_done: user_choice = message.strip().lower() if user_choice in ["NO need", "no", "n"]: post_career_detail_done = True roadmap_offered = True return "OK, do you need a time plan, enter 【I need】,or【NO need】。" else: abc_text = answer_abc_questions( selected=user_choice, bg_info=user_profile["bg_info"], wv=user_profile["work_value"], ps=user_profile["personality_summary"], dd=user_profile["dream_day"] ) post_career_detail_done = True roadmap_offered = True return abc_text + "\n\n this is your further information, do you need a time plan, enter【I need】, or【NO need】。" # 已选定具体职业 -> 问是否需要时间轴 elif job_chosen and not roadmap_offered and not roadmap_done: roadmap_offered = True return "Need a time path plan enter【I need】,否则回复【NO need】。" elif roadmap_offered and not roadmap_done: ans = message.strip().lower() if ans in ["I need", "yes", "y"]: roadmap_done = True forward_done = True return do_time_roadmap() else: roadmap_done = True forward_done = True return "OK, plan is finished" if forward_done: try: api_key = os.environ.get("API_TOKEN") if not api_key: return "Wrong:API_TOKEN Not set" client = OpenAI(api_key=api_key) sprompt = generate_system_prompt() msgs = [ {"role":"system","content":sprompt}, {"role":"user","content": f"this is material: {user_profile}. enter to find more"} ] resp = client.chat.completions.create( model=model_default, messages=msgs, max_tokens=token_default, temperature=temp_default, top_p=top_p_default, stream=False ) return resp.choices[0].message.content except Exception as e: return f"Wrong: {str(e)}" return "Information down" # ============================ Gradio UI ============================ # Gradio import is already done at the top of the file css = """ body { background-color: #1e1e1e; color: #ffffff; } .gradio-container { font-family: 'Segoe UI', sans-serif; } .gr-chatbot { background-color: transparent !important; } .message.user { background-color: #cce6ff !important; color: #000000 !important; border-radius: 10px !important; padding: 10px; margin: 6px; } .message.bot { background-color: #99ccff !important; color: #000000 !important; border-radius: 10px !important; padding: 10px; margin: 6px; } .gr-button { border-radius: 8px; } #custom-send { background-color: #3b82f6 !important; color: white !important; border-radius: 999px !important; padding: 10px 24px !important; font-weight: bold; box-shadow: 0 0 10px #3b82f6; transition: all 0.3s ease-in-out; } #custom-send:hover { background-color: #2563eb !important; box-shadow: 0 0 12px #3b82f6; } textarea, input { background-color: #e6f0ff !important; color: #1e3a8a !important; border: 1px solid #3b82f6 !important; } footer { display: none !important; } """ with gr.Blocks(css=css) as demo: with gr.Row(): gr.HTML("""
Hi! Let's Make the Dream Come True 💙