File size: 32,818 Bytes
d50a675
 
 
e1b3ed6
f56bf7c
d3b7d4e
f56bf7c
2032a70
 
 
 
 
925113b
2e5b1f6
f56bf7c
 
 
 
d3b7d4e
 
f56bf7c
d3b7d4e
31ecd77
d3b7d4e
 
f56bf7c
 
 
 
c0ccc4f
f56bf7c
 
 
 
c0ccc4f
 
f56bf7c
c0ccc4f
f56bf7c
 
c0ccc4f
 
f56bf7c
d3b7d4e
049d943
c0ccc4f
44a2029
c0ccc4f
44a2029
c0ccc4f
44a2029
ef8b5e6
150cc6e
 
44a2029
 
150cc6e
f56bf7c
 
 
 
 
 
 
2e5b1f6
16ad07f
d8185d2
33bcb2d
d3b7d4e
 
 
4e12a10
f56bf7c
2d84166
 
5ce9009
f56bf7c
 
 
 
 
 
 
 
 
 
 
 
2d84166
 
 
 
f56bf7c
2d84166
 
f56bf7c
2d84166
 
 
 
 
 
 
 
 
 
 
 
f56bf7c
2d84166
0b6301b
44a2029
0b6301b
b441fb6
0b6301b
b441fb6
0b6301b
b441fb6
0b6301b
 
 
1454d37
0b6301b
 
5ce9009
1454d37
 
 
 
 
 
 
 
 
 
 
76a4e39
1454d37
 
 
 
 
 
 
 
 
 
 
76a4e39
1454d37
 
 
 
16ad07f
0b6301b
 
 
1454d37
0b6301b
 
1454d37
0b6301b
 
 
 
 
 
 
 
 
 
 
 
1454d37
 
16ad07f
 
44a2029
925113b
1454d37
 
 
 
 
 
 
 
 
5ce9009
1454d37
 
 
 
 
 
 
 
925113b
 
 
 
1454d37
925113b
 
 
1454d37
925113b
 
 
 
 
 
 
 
 
 
 
 
1454d37
925113b
 
5102079
49c7b41
44a2029
 
5102079
 
 
 
49c7b41
 
5102079
 
 
 
 
 
 
5ce9009
5102079
 
 
 
 
 
 
 
 
c4b4e0f
2773ed3
 
 
5102079
2773ed3
 
 
5102079
8f59b9d
2773ed3
 
 
 
 
 
 
 
 
 
 
5102079
49c7b41
925113b
5102079
2e5b1f6
 
5ce9009
5102079
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2e5b1f6
 
 
 
5102079
2e5b1f6
 
 
5102079
2e5b1f6
 
 
 
 
 
 
 
 
 
 
 
5102079
b441fb6
 
 
 
8f59b9d
5102079
b441fb6
 
5102079
 
 
b441fb6
8f59b9d
5102079
8f59b9d
5102079
da47433
 
8f59b9d
2e5b1f6
 
5102079
2e5b1f6
 
5102079
49c7b41
5102079
 
 
 
49c7b41
 
5ce9009
5102079
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c4b4e0f
49c7b41
 
 
5102079
49c7b41
 
5102079
8f59b9d
49c7b41
 
 
 
 
 
 
 
 
925113b
 
5102079
b441fb6
 
 
 
8f59b9d
5102079
b441fb6
8f59b9d
5ce9009
 
 
8f59b9d
 
5ce9009
925113b
49c7b41
5102079
2773ed3
925113b
5ce9009
d2d5c74
 
2032a70
 
44a2029
 
 
 
d2d5c74
5102079
d2d5c74
5ce9009
5102079
 
 
 
 
 
 
 
 
 
 
d2d5c74
8f59b9d
d2d5c74
5ce9009
5102079
 
 
 
 
 
76a4e39
5102079
 
 
 
49c7b41
925113b
5102079
049d943
5102079
049d943
 
 
5fc052c
 
49c7b41
 
 
2e5b1f6
16ad07f
 
5102079
049d943
 
f925b72
2f69958
 
2773ed3
2032a70
44a2029
2a75c72
44a2029
2e5b1f6
44a2029
ef8b5e6
49c7b41
 
 
 
44a2029
 
 
 
16ad07f
 
 
5102079
44a2029
 
8f59b9d
6492b16
44a2029
8f59b9d
 
5102079
 
8f59b9d
 
 
 
44a2029
8f59b9d
5fc052c
049d943
5fc052c
 
8f59b9d
2eb0f8f
 
5102079
8f59b9d
007c39c
5102079
 
8f59b9d
2d84166
 
 
 
 
 
 
5102079
2d84166
5102079
2d84166
 
 
 
 
 
 
 
 
5ce9009
 
 
 
 
 
2d84166
8f59b9d
5ce9009
2d84166
 
5ce9009
2d84166
007c39c
5ce9009
2d84166
 
 
 
5ce9009
 
 
2d84166
 
 
5ce9009
2d84166
5ce9009
2d84166
 
5ce9009
2d84166
 
 
5ce9009
2d84166
 
 
 
 
 
5ce9009
 
2d84166
 
 
 
 
5ce9009
2d84166
 
 
 
5ce9009
2d84166
 
 
 
 
 
 
 
 
 
 
5ce9009
 
44a2029
 
8f59b9d
5ce9009
8f59b9d
5ce9009
8f59b9d
 
 
f925b72
8f59b9d
 
 
 
 
5ce9009
8f59b9d
 
 
 
5ce9009
8f59b9d
 
 
 
 
 
 
 
5ce9009
8f59b9d
 
 
 
 
 
 
 
5ce9009
 
8f59b9d
 
 
5ce9009
8f59b9d
 
 
5ce9009
8f59b9d
5ce9009
8f59b9d
2e5b1f6
8f59b9d
2e5b1f6
8f59b9d
 
 
 
 
 
 
2e5b1f6
 
 
 
 
8f59b9d
 
5ce9009
8f59b9d
 
5ce9009
 
 
 
 
 
2e5b1f6
5ce9009
 
2e5b1f6
 
 
5ce9009
2e5b1f6
5ce9009
8f59b9d
 
 
 
 
 
 
 
5ce9009
8f59b9d
5ce9009
8f59b9d
 
5ce9009
8f59b9d
 
5ce9009
16ad07f
8f59b9d
 
 
 
 
 
16ad07f
8f59b9d
 
5ce9009
16ad07f
8f59b9d
 
 
5ce9009
49c7b41
8f59b9d
 
5ce9009
8f59b9d
49c7b41
8f59b9d
2738430
8f59b9d
 
5ce9009
8f59b9d
5ce9009
8f59b9d
 
 
 
5ce9009
8f59b9d
 
 
 
5ce9009
8f59b9d
 
 
 
 
 
 
 
2773ed3
8f59b9d
 
5ce9009
049d943
f56bf7c
 
2773ed3
f925b72
76a4e39
2a75c72
76a4e39
d8185d2
 
 
 
 
 
 
 
 
 
 
 
 
2773ed3
 
 
d8185d2
 
 
 
2773ed3
 
 
d8185d2
 
 
 
 
c3e783d
d8185d2
 
 
 
c3e783d
d8185d2
 
 
c3e783d
 
d8185d2
 
c3e783d
 
 
d8185d2
 
 
 
76a4e39
 
 
a866be3
06ce646
 
a866be3
 
 
06ce646
31ecd77
a866be3
 
 
06ce646
 
 
d8185d2
2a75c72
c0379f6
7692476
 
2a75c72
 
c6753f9
c54bedc
c6753f9
ef8b5e6
7692476
2a75c72
d8185d2
 
c54bedc
c6753f9
ef8b5e6
2a75c72
 
 
 
 
ef8b5e6
c6753f9
3f4d656
 
 
5fc052c
 
49c7b41
 
 
2e5b1f6
16ad07f
 
3f4d656
d8185d2
 
 
2773ed3
c6753f9
 
 
 
d8185d2
 
ef8b5e6
49c7b41
 
 
 
2e5b1f6
 
 
 
16ad07f
 
 
c6753f9
2f69958
2a75c72
 
7692476
d8185d2
c54bedc
d2d5c74
d8185d2
3e89e72
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
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("""
        <div style='display: flex; align-items: center; justify-content: center; gap: 20px; margin-bottom: 10px;'>
         <img src='https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExMmFucGwxbmNsd3J5NXV0Y282NXNtMzNsZW5jMm4wNWh6c2dqbXIwdiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l41m18LjqpzxUr2WA/giphy.gif'
              width='200'
              style='border-radius: 12px; box-shadow: 0 0 10px #3b82f6;'>
         <div style='text-align: left;'>
            <h1 style='color:White; font-size: 36px; margin-bottom: 6px;'>🎓 Explora:AI Career Exploration Assistant</h1>
            <p style='font-size: 18px; font-weight:bold; color:#3b82f6; margin-top: 0; margin-left:150px'>
                Hi! Let's Make the Dream Come True 💙
            </p>
         </div>
        </div>
        """)

    chatbot = gr.Chatbot(height=500, show_label=False, show_copy_button=True, type="messages")
    msg = gr.Textbox(placeholder="请输入你的回答...")
    send = gr.Button("Send 🚀", elem_id="custom-send")
    reset = gr.Button("🔄 Restart")

    def add_user_message(m, hist):
        hist = hist or []
        hist.append({"role": "user", "content": m})
        return "", hist

 
    def add_bot_response(hist):
        user_msg = hist[-1]["content"]
        bot_msg = predict(user_msg, hist[:-1])
        hist.append({"role": "assistant", "content": bot_msg})
        return hist

    send.click(add_user_message, [msg, chatbot], [msg, chatbot]) \
        .then(add_bot_response, chatbot, chatbot)

    msg.submit(add_user_message, [msg, chatbot], [msg, chatbot]) \
       .then(add_bot_response, chatbot, chatbot)

    def reset_state():
        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

        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

        return []

    reset.click(reset_state, outputs=chatbot)


    def auto_first():
        return [{"role": "assistant", "content": questions[0][1]}]

    demo.load(auto_first, outputs=chatbot)
    demo.launch()