HelenaXH commited on
Commit
4e12a10
·
verified ·
1 Parent(s): a866be3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -90
app.py CHANGED
@@ -57,7 +57,7 @@ direction_chosen = False # 是否已经选定大方向
57
  jobs_recommended = False # 是否已给出3个具体职业
58
  job_chosen = False # 是否选定了具体职业
59
 
60
- # ========== 新增:处理 A/B/C 三部分问题的标记 ==========
61
  post_career_detail_asked = False # 是否已询问用户要看A/B/C
62
  post_career_detail_done = False # 是否已回答完A/B/C
63
 
@@ -67,14 +67,11 @@ token_default = 2000
67
  temp_default = 0.7
68
  top_p_default = 0.95
69
 
 
70
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71
- # 新的动态函数: 根据用户选择的 A/B/C,调用 OpenAI 生成相应分析
72
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73
  def answer_abc_questions(selected, bg_info, wv, ps, dd):
74
- """
75
- 动态地向OpenAI发起请求,让AI针对“专业/选课方向 & 求职入门(A)”、“本校资源利用(B)”、“实习 & networking(C)”
76
- 三个模块,基于用户背景信息做个性化分析。
77
- """
78
  desired_parts = []
79
  if "a" in selected:
80
  desired_parts.append("A")
@@ -95,17 +92,11 @@ def answer_abc_questions(selected, bg_info, wv, ps, dd):
95
  - 理想工作: {dd}
96
 
97
  学生目前想要的额外信息模块:{', '.join(desired_parts)}
98
-
99
  请分别按顺序为每个模块写一段分析和建议,可以使用Markdown分段形式。
100
  (A: 专业/选课方向 & 求职入门建议部分的回答请根据学生的学术背景信息分析学生已经有的能力,然后根据其选择的职业方向分析该学生未来的选课应该注重什么课程方向,提示学生课程名称和关键词)
101
- (‘B: 本校资源利用建议‘部分的回答请你从3个方面回答学生,包括1.如何利用学生所在学校的career service的指导;2.如何关注学校与职业准备和证书考试相关的club、组织和平台;3.学生如何与学校的及其所在专业的校友取得联系和networking技巧)
102
  (‘C: 实习 & Experience积累’部分的回答请你从申请internship的平台、达成目前职业目标需要的internship方向,申请需要的资料和准备技巧、通过networking获得实习或者学生工作经历的策略)
103
 
104
- 模块说明:
105
- A: 专业和选课方向 & 求职入门建议
106
- B: 本校资源利用建议(如Career Center、校友资源)
107
- C: 实习 & Experience积累(networking)
108
-
109
  请只回答用户所选模块,不要回答未选的模块。
110
  """
111
  try:
@@ -113,9 +104,8 @@ C: 实习 & Experience积累(networking)
113
  if not api_key:
114
  return "错误:API_TOKEN 未设置"
115
  client = OpenAI(api_key=api_key)
116
-
117
  msgs = [
118
- {"role": "system", "content": "你是一位专业职业顾问,能够根据用户选择的A/B/C模块做深度分析。"},
119
  {"role": "user", "content": prompt_text}
120
  ]
121
  resp = client.chat.completions.create(
@@ -131,7 +121,7 @@ C: 实习 & Experience积累(networking)
131
  return f"生成A/B/C专项信息时出错: {str(e)}"
132
 
133
 
134
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 提供具体职业后,再深入介绍 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
135
  def do_selected_career_detail(selected_career, bg_info, wv, ps, dd):
136
  prompt = f"""
137
  你是一位专业的职业规划顾问。
@@ -172,7 +162,7 @@ def do_selected_career_detail(selected_career, bg_info, wv, ps, dd):
172
  return f"生成职业详细信息时出错: {str(e)}"
173
 
174
 
175
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 路线图生成函数 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176
  def do_time_roadmap():
177
  direction = user_profile.get("final_choice") or user_profile.get("selected_direction") or \
178
  user_profile.get("forward_direction_choice") or user_profile.get("specific_career")
@@ -219,7 +209,7 @@ def do_time_roadmap():
219
  return f"生成路线图时出错: {str(e)}"
220
 
221
 
222
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 给定大方向后,再给3个具体职业 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223
  def recommend_3jobs_for_direction(direction, bg_info, wv, ps, dd):
224
  prompt = f"""
225
  你是一位专业的职业规划顾问。
@@ -259,64 +249,18 @@ def recommend_3jobs_for_direction(direction, bg_info, wv, ps, dd):
259
  )
260
  output_text = resp.choices[0].message.content
261
 
262
- # 这里可以固定或基于返回文本做解析,我这边演示先手动���值。
263
  user_profile["recommended_jobs"] = [
264
  f"{direction} - 职业A",
265
  f"{direction} - 职业B",
266
  f"{direction} - 职业C"
267
  ]
268
  return output_text
269
-
270
  except Exception as e:
271
  return f"推荐具体职业时出错: {str(e)}"
272
 
273
 
274
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 深度分析函数(可做备用) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
275
- def do_deep_analysis():
276
- direction = user_profile["forward_direction_choice"] or "尚未选择"
277
- bg_info = user_profile["bg_info"] or "未知背景"
278
- wv = user_profile["work_value"] or "无"
279
- ps = user_profile["personality_summary"] or "不详"
280
- dd = user_profile["dream_day"] or "不详"
281
-
282
- deep_prompt = f"""
283
- 学生的最终方向: {direction}
284
- 学生背景: {bg_info}
285
- 价值观: {wv}
286
- 性格: {ps}
287
- 理想工作: {dd}
288
- 请你再深入分析,为学生推荐3个更具体的职业,并说明:
289
- 1. 这些职业对学生背景的契合度
290
- 2. 日常工作内容
291
- 3. 需要哪些课程或考试
292
- 4. 本校资源如何利用
293
- 5. 实习 & 经验积累建议
294
- 6. 简历优化思路
295
- 用中文分段写作,字数500+。
296
- """
297
- try:
298
- api_key = os.environ.get("API_TOKEN")
299
- if not api_key:
300
- return "错误:API_TOKEN 未设置"
301
- client = OpenAI(api_key=api_key)
302
- msgs = [
303
- {"role":"system","content":"你是一位专业职业顾问,会深度分析并列出3个具体职业。"},
304
- {"role":"user","content":deep_prompt}
305
- ]
306
- resp = client.chat.completions.create(
307
- model=model_default,
308
- messages=msgs,
309
- max_tokens=token_default,
310
- temperature=temp_default,
311
- top_p=top_p_default,
312
- stream=False
313
- )
314
- return resp.choices[0].message.content
315
- except Exception as e:
316
- return f"深度分析出错: {str(e)}"
317
-
318
-
319
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 推荐大方向函数 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
320
  def recommend_3directions():
321
  bg_info = user_profile["bg_info"] or "未知"
322
  wv = user_profile["work_value"] or "无"
@@ -324,7 +268,7 @@ def recommend_3directions():
324
  dd = user_profile["dream_day"] or "无"
325
 
326
  rec_prompt = f"""
327
- 请根据以下信息,写一份条理清晰的人物画像+3个大方向,并结尾让学生选1~3,就是回答1or2or3或'换',然后里面的语句要称呼对面能是或者她:
328
  - 学术背景: {bg_info}
329
  - 工作意义: {wv}
330
  - 性格: {ps}
@@ -355,18 +299,15 @@ def recommend_3directions():
355
  top_p=top_p_default,
356
  stream=False
357
  )
358
-
359
  output_text = resp.choices[0].message.content
360
 
361
- # 这里演示写死3个方向,真实场景可再解析大模型返回
362
  user_profile["recommended_directions"] = [
363
  "方向1",
364
  "方向2",
365
  "方向3"
366
  ]
367
-
368
  return output_text
369
-
370
  except Exception as e:
371
  return f"多方向推荐出错: {str(e)}"
372
 
@@ -411,9 +352,9 @@ def generate_system_prompt():
411
  """
412
 
413
 
414
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 主逻辑函数 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
415
  def predict(message, history):
416
- # ========== 必须在函数开头声明全局变量 ==========
417
  global current_q_index, questions
418
  global in_forward_flow, in_backward_flow
419
  global forward_index, backward_index
@@ -473,9 +414,7 @@ def predict(message, history):
473
  # ======================== 分模式处理 =========================
474
  mode = user_profile.get("mode") or ""
475
 
476
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
477
- # Backward模式处理
478
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
479
  if mode == "是":
480
  if in_backward_flow and not backward_done:
481
  if backward_index > 0 and backward_index <= len(backward_additional_questions):
@@ -512,12 +451,10 @@ def predict(message, history):
512
  except Exception as e:
513
  return f"发生错误: {str(e)}"
514
 
515
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
516
- # Forward模式处理
517
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518
  else:
519
- # 如果还没选大方向/没问完前置问题
520
  if in_forward_flow and not forward_done and not direction_chosen and not jobs_recommended and not job_chosen and not roadmap_done:
 
521
  if forward_index > 0 and forward_index <= len(forward_additional_questions):
522
  prev_key = forward_additional_questions[forward_index - 1][0]
523
  user_profile[prev_key] = message.strip()
@@ -527,12 +464,13 @@ def predict(message, history):
527
  forward_index += 1
528
  return prompt_text
529
 
 
530
  elif not forward_recommendation_given:
531
  forward_recommendation_given = True
532
  return recommend_3directions()
533
 
 
534
  else:
535
- # 学生选择大方向 or 换
536
  choice = message.strip().lower()
537
  if choice in ["1","2","3"]:
538
  idx = int(choice) - 1
@@ -559,7 +497,7 @@ def predict(message, history):
559
  else:
560
  return "请回复1/2/3选择方向,或输入'换'来重新推荐"
561
 
562
- # 选定大方向 -> 推荐了3个具体职业
563
  elif direction_chosen and not jobs_recommended and not job_chosen:
564
  choice = message.strip().lower()
565
  if choice in ["1","2","3"]:
@@ -569,7 +507,6 @@ def predict(message, history):
569
  user_profile["final_choice"] = final_job
570
  job_chosen = True
571
 
572
- # 生成更详细介绍
573
  detail_msg = do_selected_career_detail(
574
  selected_career=final_job,
575
  bg_info=user_profile["bg_info"] or "",
@@ -579,17 +516,15 @@ def predict(message, history):
579
  )
580
  forward_deep_dive_done = True
581
 
582
- # 关键:现在我们“询问 A/B/C
583
- global post_career_detail_asked
584
  post_career_detail_asked = True
585
 
586
- return detail_msg + "\n\n我还可以针对以下三方面提供**更深入**的分析建议:" \
587
  "\n- A:专业/选课 & 求职方向" \
588
  "\n- B:本校资源利用建议" \
589
  "\n- C:实习 & networking 积累" \
590
  "\n如果你想查看其中一个或多个,请输入 A / B / C / AB / BC / AC / ABC" \
591
  "\n如果都不需要,请回复“不需要”。"
592
-
593
  else:
594
  return "无效的选项,请重新输入1/2/3或'换'"
595
  elif choice == "换":
@@ -609,7 +544,7 @@ def predict(message, history):
609
  else:
610
  return "请回复1/2/3选择具体职业,或输入'换'来重新推荐"
611
 
612
- # ============== 处理 A/B/C答疑 ==============
613
  elif post_career_detail_asked and not post_career_detail_done:
614
  user_choice = message.strip().lower()
615
  if user_choice in ["不需要", "no", "n"]:
@@ -644,7 +579,7 @@ def predict(message, history):
644
  forward_done = True
645
  return "好的,不生成时间轴,本次规划结束。"
646
 
647
- # 全流程结束后额外结果
648
  if forward_done:
649
  try:
650
  api_key = os.environ.get("API_TOKEN")
@@ -668,6 +603,7 @@ def predict(message, history):
668
  except Exception as e:
669
  return f"发生错误: {str(e)}"
670
 
 
671
  return "信息收集完毕,如还未得到最终回复,请再输入任意文字继续。"
672
 
673
 
@@ -724,7 +660,6 @@ footer {
724
  display: none !important;
725
  }
726
  """) as demo:
727
- # 可以在这里加一个带Row的顶部区域
728
  with gr.Row():
729
  gr.HTML("""
730
  <div style='display: flex; align-items: center; justify-content: center; gap: 20px; margin-bottom: 10px;'>
 
57
  jobs_recommended = False # 是否已给出3个具体职业
58
  job_chosen = False # 是否选定了具体职业
59
 
60
+ # ========== 用于 A/B/C 专项问题的标记 ==========
61
  post_career_detail_asked = False # 是否已询问用户要看A/B/C
62
  post_career_detail_done = False # 是否已回答完A/B/C
63
 
 
67
  temp_default = 0.7
68
  top_p_default = 0.95
69
 
70
+
71
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72
+ # 动态函数:根据用户选择的 A/B/C, OpenAI 生成相应分析
73
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74
  def answer_abc_questions(selected, bg_info, wv, ps, dd):
 
 
 
 
75
  desired_parts = []
76
  if "a" in selected:
77
  desired_parts.append("A")
 
92
  - 理想工作: {dd}
93
 
94
  学生目前想要的额外信息模块:{', '.join(desired_parts)}
 
95
  请分别按顺序为每个模块写一段分析和建议,可以使用Markdown分段形式。
96
  (A: 专业/选课方向 & 求职入门建议部分的回答请根据学生的学术背景信息分析学生已经有的能力,然后根据其选择的职业方向分析该学生未来的选课应该注重什么课程方向,提示学生课程名称和关键词)
97
+ (‘B: 本校资源利用建议‘部分的回答请你从3个方面回答学生,包括1.如何利用学校的career service;2.如何关注学校与职业准备和证书考试相关的club、组织和平台;3.学生如何与学校的及其所在专业的校友取得联系和networking技巧)
98
  (‘C: 实习 & Experience积累’部分的回答请你从申请internship的平台、达成目前职业目标需要的internship方向,申请需要的资料和准备技巧、通过networking获得实习或者学生工作经历的策略)
99
 
 
 
 
 
 
100
  请只回答用户所选模块,不要回答未选的模块。
101
  """
102
  try:
 
104
  if not api_key:
105
  return "错误:API_TOKEN 未设置"
106
  client = OpenAI(api_key=api_key)
 
107
  msgs = [
108
+ {"role": "system", "content": "你是一位专业职业顾问,会针对A/B/C进行分析。"},
109
  {"role": "user", "content": prompt_text}
110
  ]
111
  resp = client.chat.completions.create(
 
121
  return f"生成A/B/C专项信息时出错: {str(e)}"
122
 
123
 
124
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 职业详细介绍 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125
  def do_selected_career_detail(selected_career, bg_info, wv, ps, dd):
126
  prompt = f"""
127
  你是一位专业的职业规划顾问。
 
162
  return f"生成职业详细信息时出错: {str(e)}"
163
 
164
 
165
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 时间轴式规划 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
166
  def do_time_roadmap():
167
  direction = user_profile.get("final_choice") or user_profile.get("selected_direction") or \
168
  user_profile.get("forward_direction_choice") or user_profile.get("specific_career")
 
209
  return f"生成路线图时出错: {str(e)}"
210
 
211
 
212
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 推荐具体职业 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213
  def recommend_3jobs_for_direction(direction, bg_info, wv, ps, dd):
214
  prompt = f"""
215
  你是一位专业的职业规划顾问。
 
249
  )
250
  output_text = resp.choices[0].message.content
251
 
252
+ # 演示:固定写死3个职业
253
  user_profile["recommended_jobs"] = [
254
  f"{direction} - 职业A",
255
  f"{direction} - 职业B",
256
  f"{direction} - 职业C"
257
  ]
258
  return output_text
 
259
  except Exception as e:
260
  return f"推荐具体职业时出错: {str(e)}"
261
 
262
 
263
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 推荐大方向 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  def recommend_3directions():
265
  bg_info = user_profile["bg_info"] or "未知"
266
  wv = user_profile["work_value"] or "无"
 
268
  dd = user_profile["dream_day"] or "无"
269
 
270
  rec_prompt = f"""
271
+ 请根据以下信息,写一份条理清晰的人物画像+3个大方向,并结尾让学生选1~3(或'换'),其中称呼对面用""要用"/"
272
  - 学术背景: {bg_info}
273
  - 工作意义: {wv}
274
  - 性格: {ps}
 
299
  top_p=top_p_default,
300
  stream=False
301
  )
 
302
  output_text = resp.choices[0].message.content
303
 
304
+ # 演示:固定写死3个方向
305
  user_profile["recommended_directions"] = [
306
  "方向1",
307
  "方向2",
308
  "方向3"
309
  ]
 
310
  return output_text
 
311
  except Exception as e:
312
  return f"多方向推荐出错: {str(e)}"
313
 
 
352
  """
353
 
354
 
355
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 主对话逻辑函数 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
356
  def predict(message, history):
357
+ # ========= 在函数开头,提前声明所有 global =========
358
  global current_q_index, questions
359
  global in_forward_flow, in_backward_flow
360
  global forward_index, backward_index
 
414
  # ======================== 分模式处理 =========================
415
  mode = user_profile.get("mode") or ""
416
 
417
+ # ~~~~~~~~~ Backward模式 ~~~~~~~~~
 
 
418
  if mode == "是":
419
  if in_backward_flow and not backward_done:
420
  if backward_index > 0 and backward_index <= len(backward_additional_questions):
 
451
  except Exception as e:
452
  return f"发生错误: {str(e)}"
453
 
454
+ # ~~~~~~~~~ Forward模式 ~~~~~~~~~
 
 
455
  else:
 
456
  if in_forward_flow and not forward_done and not direction_chosen and not jobs_recommended and not job_chosen and not roadmap_done:
457
+ # 收集 4个基础问题
458
  if forward_index > 0 and forward_index <= len(forward_additional_questions):
459
  prev_key = forward_additional_questions[forward_index - 1][0]
460
  user_profile[prev_key] = message.strip()
 
464
  forward_index += 1
465
  return prompt_text
466
 
467
+ # 问完 4个问题 -> 推荐3方向
468
  elif not forward_recommendation_given:
469
  forward_recommendation_given = True
470
  return recommend_3directions()
471
 
472
+ # 等待用户选 1/2/3 or 换
473
  else:
 
474
  choice = message.strip().lower()
475
  if choice in ["1","2","3"]:
476
  idx = int(choice) - 1
 
497
  else:
498
  return "请回复1/2/3选择方向,或输入'换'来重新推荐"
499
 
500
+ # 选定大方向 -> 推荐了3个具体职业
501
  elif direction_chosen and not jobs_recommended and not job_chosen:
502
  choice = message.strip().lower()
503
  if choice in ["1","2","3"]:
 
507
  user_profile["final_choice"] = final_job
508
  job_chosen = True
509
 
 
510
  detail_msg = do_selected_career_detail(
511
  selected_career=final_job,
512
  bg_info=user_profile["bg_info"] or "",
 
516
  )
517
  forward_deep_dive_done = True
518
 
519
+ # **询问 A/B/C 专项**
 
520
  post_career_detail_asked = True
521
 
522
+ return detail_msg + "\n\n我还可以针对以下三方面提供更深入的分析建议:" \
523
  "\n- A:专业/选课 & 求职方向" \
524
  "\n- B:本校资源利用建议" \
525
  "\n- C:实习 & networking 积累" \
526
  "\n如果你想查看其中一个或多个,请输入 A / B / C / AB / BC / AC / ABC" \
527
  "\n如果都不需要,请回复“不需要”。"
 
528
  else:
529
  return "无效的选项,请重新输入1/2/3或'换'"
530
  elif choice == "换":
 
544
  else:
545
  return "请回复1/2/3选择具体职业,或输入'换'来重新推荐"
546
 
547
+ # 处理 A/B/C 答疑
548
  elif post_career_detail_asked and not post_career_detail_done:
549
  user_choice = message.strip().lower()
550
  if user_choice in ["不需要", "no", "n"]:
 
579
  forward_done = True
580
  return "好的,不生成时间轴,本次规划结束。"
581
 
582
+ # 如果 forward_done给个收尾
583
  if forward_done:
584
  try:
585
  api_key = os.environ.get("API_TOKEN")
 
603
  except Exception as e:
604
  return f"发生错误: {str(e)}"
605
 
606
+ # 兜底
607
  return "信息收集完毕,如还未得到最终回复,请再输入任意文字继续。"
608
 
609
 
 
660
  display: none !important;
661
  }
662
  """) as demo:
 
663
  with gr.Row():
664
  gr.HTML("""
665
  <div style='display: flex; align-items: center; justify-content: center; gap: 20px; margin-bottom: 10px;'>