HelenaXH commited on
Commit
ef8b5e6
·
verified ·
1 Parent(s): f611a7c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -124
app.py CHANGED
@@ -9,7 +9,8 @@ user_profile = {
9
  "bg_info": None,
10
  "work_value": None,
11
  "personality_summary": None,
12
- "dream_day": None
 
13
  }
14
 
15
  # ============================ 基础问题 ============================
@@ -19,20 +20,29 @@ base_questions = [
19
 
20
  # ============================ Forward 模式问题 ============================
21
  forward_additional_questions = [
22
- ("bg_info", """那么接下来我会需要你提供一些你的资料,并分享一些你的性格和喜好,我会分析然后给你推荐定制的可行方向。
23
- 接下来,请你首先提供你的学术背景:你的学校、年级、专业,和主修课程是什么?如果能提供你的选课表或 resume 就最好啦。"""),
24
-
25
- ("work_value", """很好!接下来我想更深入地了解你。
 
 
 
 
26
  你认为“工作”的意义是什么?你觉得一份理想的工作,应该带来哪些价值或满足感?
27
  你可以从以下几个角度思考,也可以自由表达:
28
  - 是可以帮助他人?实现社会影响力?
29
  - 还是可以赚大钱?获得物质回报?
30
  - 或者是自由时间?个人成长?创意空间?
31
- 举个例子更好哦~"""),
32
-
33
- ("personality_summary", "你能不能用几句话总结一下你自己的性格?比如:外向、喜欢挑战、注重细节、讨厌重复..."),
34
-
35
- ("dream_day", "你能描述一下你理想工作一天是什么样的吗你在哪工作?做什么?跟谁合作?忙还是闲?更自由还是更有秩序?")
 
 
 
 
 
36
  ]
37
 
38
  # ============================ Backward 模式问题 ============================
@@ -50,9 +60,10 @@ forward_index = 0
50
  backward_index = 0
51
  forward_done = False
52
  backward_done = False
 
53
 
54
  # ============================ 模型设置 ============================
55
- model_default = "gpt-4o"
56
  token_default = 2000
57
  temp_default = 0.7
58
  top_p_default = 0.95
@@ -65,35 +76,39 @@ def generate_system_prompt():
65
  work_value = user_profile["work_value"]
66
  personality_summary = user_profile["personality_summary"]
67
  dream_day = user_profile["dream_day"]
 
68
 
69
  if "是" in (mode or ""):
70
  return f"""
71
  你是一位专业的职业规划顾问,使用Backward Design方法帮助学生达成他们的职业目标。
72
  目标职业: {specific_career}
73
  背景信息: {bg_info}
 
74
  请提供:
75
  1. 该职业的简要分析
76
  2. 排名前列的组织或公司
77
  3. 所需技能和能力
78
  4. 职业发展路径
79
  5. 学术/课程建议、技能培养、资源使用、实习规划、简历优化等
 
80
  最后请用Markdown格式输出职业路径图:
81
  📍 现在 → 🎓 学习建议 → 💼 实践建议 → 📄 认证建议 → 🚀 求职建议
82
  """
83
  else:
84
  return f"""
85
  你是一位专业的职业规划顾问,使用Forward Design方法帮助学生探索合适的职业路径。
 
86
  学生背景:
87
  - 学术背景: {bg_info}
88
  - 工作意义: {work_value}
89
  - 性格总结: {personality_summary}
90
  - 理想一天: {dream_day}
 
 
91
  请输出:
92
  1. 学生的优势、性格、价值观分析
93
- 2. 推荐6个职业方向说明理由
94
- 3. 等学生选择后,再推荐3个具体职业,每个说明日常内容、适配性、要求、准备路径
95
- 最后请用Markdown格式输出职业路径图:
96
- 📍 现在 → 🎓 学习建议 → 💼 实践建议 → 📄 认证建议 → 🚀 求职建议
97
  """
98
 
99
  # ============================ 主逻辑函数 ============================
@@ -101,8 +116,9 @@ def predict(message, history):
101
  global current_q_index, questions
102
  global in_forward_flow, in_backward_flow
103
  global forward_index, backward_index
104
- global forward_done, backward_done
105
 
 
106
  if not history:
107
  current_q_index = 0
108
  questions = base_questions[:]
@@ -114,57 +130,107 @@ def predict(message, history):
114
  backward_index = 0
115
  forward_done = False
116
  backward_done = False
 
117
 
 
118
  if current_q_index > 0 and current_q_index <= len(questions):
 
119
  key = questions[current_q_index - 1][0]
120
  user_profile[key] = message.strip()
 
 
121
  if key == "mode" and "是" in user_profile["mode"]:
 
122
  questions.insert(1, ("specific_career", "请具体描述你想要从事的职业方向。"))
123
  in_backward_flow = True
124
  elif key == "mode" and "否" in user_profile["mode"]:
125
  in_forward_flow = True
126
 
 
127
  if current_q_index < len(questions):
128
  q_text = questions[current_q_index][1]
129
  current_q_index += 1
130
  return q_text
131
 
132
  mode = user_profile["mode"] or ""
 
133
  if "是" in mode:
134
  if in_backward_flow and not backward_done:
 
135
  if backward_index < len(backward_additional_questions):
136
  key, q_text = backward_additional_questions[backward_index]
137
  backward_index += 1
138
  return q_text
139
  else:
 
140
  backward_done = True
 
 
141
  else:
142
  if in_forward_flow and not forward_done:
 
143
  if forward_index < len(forward_additional_questions):
144
  key, q_text = forward_additional_questions[forward_index]
145
  forward_index += 1
146
  return q_text
147
- else:
148
- forward_done = True
149
 
150
- if in_backward_flow and backward_index > 0 and not backward_done:
151
- idx = backward_index - 1
152
- if idx < len(backward_additional_questions):
153
- key = backward_additional_questions[idx][0]
154
- user_profile[key] = message.strip()
 
 
 
 
 
 
 
 
 
 
 
155
 
156
- if in_forward_flow and forward_index > 0 and not forward_done:
157
- idx = forward_index - 1
158
- if idx < len(forward_additional_questions):
159
- key = forward_additional_questions[idx][0]
160
- user_profile[key] = message.strip()
 
 
 
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  if ("是" in mode and backward_done) or ("否" in mode and forward_done):
 
163
  try:
164
  api_key = os.environ.get("API_TOKEN")
165
  if not api_key:
166
  return "错误:API密钥未设置,请在环境变量中添加名为API_TOKEN的Secret。"
167
  client = OpenAI(api_key=api_key)
 
168
  system_prompt = generate_system_prompt()
169
  messages = [
170
  {"role": "system", "content": system_prompt},
@@ -179,121 +245,65 @@ def predict(message, history):
179
  stream=False
180
  )
181
  return response.choices[0].message.content
 
182
  except Exception as e:
183
  return f"发生错误: {str(e)}"
184
 
 
185
  return "信息收集完毕,若尚未得到最终回复,请输入任意文字以继续。"
186
 
187
-
188
  # ============================ Gradio UI ============================
189
- with gr.Blocks(css="""
190
- body {
191
- background-color: #1e1e1e;
192
- color: #ffffff;
193
- }
194
- .gradio-container {
195
- font-family: 'Segoe UI', sans-serif;
196
- }
197
- .message.user {
198
- background-color: #cce6ff !important;
199
- color: #000000 !important;
200
- border-radius: 10px !important;
201
- padding: 10px;
202
- margin: 6px;
203
- }
204
- .message.bot {
205
- background-color: #5599ff !important;
206
- color: #000000 !important;
207
- border-radius: 10px !important;
208
- padding: 10px;
209
- margin: 6px;
210
- }
211
- .gradio-container .chat-msg.bot-msg .message.bot p {
212
- color: #000000 !important;
213
- }
214
- .gr-button {
215
- border-radius: 8px;
216
- }
217
- #custom-send {
218
- background-color: #ec4899 !important;
219
- color: white !important;
220
- border-radius: 999px !important;
221
- padding: 10px 24px !important;
222
- font-weight: bold;
223
- box-shadow: 0 0 10px #ec4899;
224
- transition: all 0.3s ease-in-out;
225
- }
226
- #custom-send:hover {
227
- background-color: #d63384 !important;
228
- box-shadow: 0 0 12px #ec4899;
229
- }
230
- textarea, input {
231
- background-color: #ffe4f1 !important;
232
- color: #5e2c49 !important;
233
- border: 1px solid #ec4899 !important;
234
- }
235
- footer {
236
- display: none !important;
237
- }
238
- """) as demo:
239
- with gr.Row():
240
- gr.HTML("""
241
- <div style='display: flex; align-items: center; justify-content: center; gap: 20px; margin-bottom: 10px;'>
242
- <img src='https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExMmFucGwxbmNsd3J5NXV0Y282NXNtMzNsZW5jMm4wNWh6c2dqbXIwdiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l41m18LjqpzxUr2WA/giphy.gif' width='200' style='border-radius: 12px; box-shadow: 0 0 10px #ec4899;'>
243
- <div style='text-align: left;'>
244
- <h1 style='color:white; font-size: 36px; margin-bottom: 6px;'>🎓 AI职业规划助手(升级版)</h1>
245
- <p style='font-size: 18px; font-weight:bold; color:#ec4899; margin-top: 0;margin-left: 150px'>让梦想照进现实 💖</p>
246
- </div>
247
- </div>
248
- """)
249
  gr.Markdown("""
250
- **📝 个性化职业规划助手:Forward / Backward 多轮交互示例**
251
- - 如果已确定了职业目标,选择 **Backward** 模式(回答“是”)。
252
- - 如果你需要探索适合的职业方向,选择 **Forward** 模式(回答“否”)。
253
- - 我会收集你的基础信息、学术背景,并根据你的回答做多轮引导,最后给出职业规划建议。
254
  """)
255
- chatbot = gr.Chatbot(height=500, show_label=False, show_copy_button=True, type="messages")
256
- with gr.Row():
257
- with gr.Column(scale=8):
258
- msg = gr.Textbox(placeholder="请在这里输入你的回答...", show_label=False, container=False)
259
- with gr.Column(scale=1):
260
- submit_btn = gr.Button("🚀 发送", elem_id="custom-send")
261
- with gr.Row():
262
- reset_btn = gr.Button("🔄 重新开始")
263
- def add_message(message, history):
264
  history = history or []
265
  history.append({"role": "user", "content": message})
266
  return "", history
267
- def bot_response(history):
268
- history = history or []
269
- user_message = history[-1]["content"]
270
- bot_message = predict(user_message, history[:-1] if len(history) > 1 else [])
271
- history.append({"role": "assistant", "content": bot_message})
272
  return history
273
- submit_btn.click(fn=add_message, inputs=[msg, chatbot], outputs=[msg, chatbot]).then(
274
- fn=bot_response, inputs=[chatbot], outputs=[chatbot]
 
275
  )
276
- msg.submit(fn=add_message, inputs=[msg, chatbot], outputs=[msg, chatbot]).then(
277
- fn=bot_response, inputs=[chatbot], outputs=[chatbot]
278
  )
279
- def reset_conversation():
 
280
  global current_q_index, questions
281
  global in_forward_flow, in_backward_flow
282
  global forward_index, backward_index
283
- global forward_done, backward_done
 
284
  current_q_index = 0
285
  questions = base_questions[:]
286
  for key in user_profile:
287
  user_profile[key] = None
288
- in_forward_flow = False
289
- in_backward_flow = False
290
- forward_index = 0
291
- backward_index = 0
292
- forward_done = False
293
- backward_done = False
294
  return []
295
- reset_btn.click(fn=reset_conversation, inputs=None, outputs=chatbot, queue=False)
296
- def auto_first_question():
297
- return [{"role": "assistant", "content": questions[0][1]}]
298
- demo.load(auto_first_question, inputs=None, outputs=chatbot)
299
- demo.launch()
 
 
 
 
 
 
9
  "bg_info": None,
10
  "work_value": None,
11
  "personality_summary": None,
12
+ "dream_day": None,
13
+ "forward_direction_choice": None
14
  }
15
 
16
  # ============================ 基础问题 ============================
 
20
 
21
  # ============================ Forward 模式问题 ============================
22
  forward_additional_questions = [
23
+ (
24
+ "bg_info",
25
+ """那么接下来我会需要你提供一些你的资料,并分享一些你的性格和喜好,我会分析然后给你推荐定制的可行方向。
26
+ 接下来,请首先提供你的学术背景:你的学校、年级、专业,和主修课程是什么?如果能提供你的选课表或 resume 就最好啦"""
27
+ ),
28
+ (
29
+ "work_value",
30
+ """很好!接下来我想更深入地了解你。
31
  你认为“工作”的意义是什么?你觉得一份理想的工作,应该带来哪些价值或满足感?
32
  你可以从以下几个角度思考,也可以自由表达:
33
  - 是可以帮助他人?实现社会影响力?
34
  - 还是可以赚大钱?获得物质回报?
35
  - 或者是自由时间?个人成长?创意空间?
36
+ 举个例子更好哦~"""
37
+ ),
38
+ (
39
+ "personality_summary",
40
+ "你能不能用几句话总结一下你自己性格比如:外向、喜欢挑战、注重细节、讨厌重复..."
41
+ ),
42
+ (
43
+ "dream_day",
44
+ "你能描述一下你理想工作的一天是什么样的吗?你在哪工作?做什么?跟谁合作?忙还是闲?更自由还是更有秩序?"
45
+ )
46
  ]
47
 
48
  # ============================ Backward 模式问题 ============================
 
60
  backward_index = 0
61
  forward_done = False
62
  backward_done = False
63
+ forward_recommendation_given = False
64
 
65
  # ============================ 模型设置 ============================
66
+ model_default = "gpt-4o" # 你可以改成 "gpt-3.5-turbo" 或 "gpt-4"
67
  token_default = 2000
68
  temp_default = 0.7
69
  top_p_default = 0.95
 
76
  work_value = user_profile["work_value"]
77
  personality_summary = user_profile["personality_summary"]
78
  dream_day = user_profile["dream_day"]
79
+ forward_direction_choice = user_profile["forward_direction_choice"]
80
 
81
  if "是" in (mode or ""):
82
  return f"""
83
  你是一位专业的职业规划顾问,使用Backward Design方法帮助学生达成他们的职业目标。
84
  目标职业: {specific_career}
85
  背景信息: {bg_info}
86
+
87
  请提供:
88
  1. 该职业的简要分析
89
  2. 排名前列的组织或公司
90
  3. 所需技能和能力
91
  4. 职业发展路径
92
  5. 学术/课程建议、技能培养、资源使用、实习规划、简历优化等
93
+
94
  最后请用Markdown格式输出职业路径图:
95
  📍 现在 → 🎓 学习建议 → 💼 实践建议 → 📄 认证建议 → 🚀 求职建议
96
  """
97
  else:
98
  return f"""
99
  你是一位专业的职业规划顾问,使用Forward Design方法帮助学生探索合适的职业路径。
100
+
101
  学生背景:
102
  - 学术背景: {bg_info}
103
  - 工作意义: {work_value}
104
  - 性格总结: {personality_summary}
105
  - 理想一天: {dream_day}
106
+ - 选择方向: {forward_direction_choice}
107
+
108
  请输出:
109
  1. 学生的优势、性格、价值观分析
110
+ 2. 推荐具体职业(3个),说明日常内容、适性、要求、准备路径
111
+ 3. 输出职业路径图:📍 现在 → 🎓 → 💼 → 📄 → 🚀
 
 
112
  """
113
 
114
  # ============================ 主逻辑函数 ============================
 
116
  global current_q_index, questions
117
  global in_forward_flow, in_backward_flow
118
  global forward_index, backward_index
119
+ global forward_done, backward_done, forward_recommendation_given
120
 
121
+ # 如果是对话第一次
122
  if not history:
123
  current_q_index = 0
124
  questions = base_questions[:]
 
130
  backward_index = 0
131
  forward_done = False
132
  backward_done = False
133
+ forward_recommendation_given = False
134
 
135
+ # 如果正在问 base_questions
136
  if current_q_index > 0 and current_q_index <= len(questions):
137
+ # 存储上一轮回答
138
  key = questions[current_q_index - 1][0]
139
  user_profile[key] = message.strip()
140
+
141
+ # 根据回答决定 forward / backward
142
  if key == "mode" and "是" in user_profile["mode"]:
143
+ # 如果是Backward模式,插入具体职业问题
144
  questions.insert(1, ("specific_career", "请具体描述你想要从事的职业方向。"))
145
  in_backward_flow = True
146
  elif key == "mode" and "否" in user_profile["mode"]:
147
  in_forward_flow = True
148
 
149
+ # 如果还有基础问题没问完,就问
150
  if current_q_index < len(questions):
151
  q_text = questions[current_q_index][1]
152
  current_q_index += 1
153
  return q_text
154
 
155
  mode = user_profile["mode"] or ""
156
+ # ============ Backward 流程 ============
157
  if "是" in mode:
158
  if in_backward_flow and not backward_done:
159
+ # 如果还没把 Backward 问题问完
160
  if backward_index < len(backward_additional_questions):
161
  key, q_text = backward_additional_questions[backward_index]
162
  backward_index += 1
163
  return q_text
164
  else:
165
+ # Backward 问完
166
  backward_done = True
167
+
168
+ # ============ Forward 流程 ============
169
  else:
170
  if in_forward_flow and not forward_done:
171
+ # 如果还在问 Forward 的问题
172
  if forward_index < len(forward_additional_questions):
173
  key, q_text = forward_additional_questions[forward_index]
174
  forward_index += 1
175
  return q_text
 
 
176
 
177
+ # 已问完 Forward 4 个问题,但还没推荐方向
178
+ elif not forward_recommendation_given:
179
+ forward_recommendation_given = True
180
+ try:
181
+ api_key = os.environ.get("API_TOKEN")
182
+ if not api_key:
183
+ return "错误:API_TOKEN 未设置"
184
+ client = OpenAI(api_key=api_key)
185
+
186
+ # 构造一个 Prompt,让 AI 综合学生信息并推荐 3 个「大方向」
187
+ recommendation_prompt = f"""
188
+ 请你先根据以下信息,生成一段不超过4句话的“学生画像”总结:
189
+ - 学术背景: {user_profile['bg_info']}
190
+ - 工作意义: {user_profile['work_value']}
191
+ - 性格总结: {user_profile['personality_summary']}
192
+ - 理想一天: {user_profile['dream_day']}
193
 
194
+ 然后再推荐3个主要职业方向(大的领域方向,例如:咨询、设计、工程、教育等),并用简短理由说明为什么适合。
195
+ 最后用如下格式结尾:
196
+ 1. xxx
197
+ 2. xxx
198
+ 3. xxx
199
+
200
+ 请学生从中选择一个方向进行下一步。
201
+ """
202
 
203
+ messages = [
204
+ {"role": "system", "content": "你是一位职业规划顾问,善于总结和推荐方向。"},
205
+ {"role": "user", "content": recommendation_prompt}
206
+ ]
207
+ response = client.chat.completions.create(
208
+ model=model_default,
209
+ messages=messages,
210
+ max_tokens=token_default,
211
+ temperature=temp_default,
212
+ top_p=top_p_default,
213
+ stream=False
214
+ )
215
+ return response.choices[0].message.content
216
+
217
+ except Exception as e:
218
+ return f"生成推荐方向时出错: {str(e)}"
219
+
220
+ # 如果已经推荐过方向,这次用户就输入了 1/2/3
221
+ else:
222
+ user_profile["forward_direction_choice"] = message.strip()
223
+ forward_done = True
224
+
225
+ # ============ 如果模式问题结束 (Backward_done / Forward_done) ============
226
  if ("是" in mode and backward_done) or ("否" in mode and forward_done):
227
+ # 进入最终职业规划生成
228
  try:
229
  api_key = os.environ.get("API_TOKEN")
230
  if not api_key:
231
  return "错误:API密钥未设置,请在环境变量中添加名为API_TOKEN的Secret。"
232
  client = OpenAI(api_key=api_key)
233
+
234
  system_prompt = generate_system_prompt()
235
  messages = [
236
  {"role": "system", "content": system_prompt},
 
245
  stream=False
246
  )
247
  return response.choices[0].message.content
248
+
249
  except Exception as e:
250
  return f"发生错误: {str(e)}"
251
 
252
+ # 如果还没结束,就让用户输入下一条
253
  return "信息收集完毕,若尚未得到最终回复,请输入任意文字以继续。"
254
 
 
255
  # ============================ Gradio UI ============================
256
+ with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  gr.Markdown("""
258
+ # 🎓 AI 职业规划助手
259
+ 欢迎!我是职业发展向导~请回答几个问题,我将为你定制专属的职业探索建议!
 
 
260
  """)
261
+
262
+ chatbot = gr.Chatbot()
263
+ msg = gr.Textbox(placeholder="请输入你的回答...", label=None)
264
+ send = gr.Button("发送 🚀")
265
+ reset = gr.Button("🔄 重新开始")
266
+
267
+ def add_user_message(message, history):
 
 
268
  history = history or []
269
  history.append({"role": "user", "content": message})
270
  return "", history
271
+
272
+ def add_bot_response(history):
273
+ message = history[-1]["content"]
274
+ reply = predict(message, history[:-1])
275
+ history.append({"role": "assistant", "content": reply})
276
  return history
277
+
278
+ send.click(add_user_message, [msg, chatbot], [msg, chatbot]).then(
279
+ add_bot_response, chatbot, chatbot
280
  )
281
+ msg.submit(add_user_message, [msg, chatbot], [msg, chatbot]).then(
282
+ add_bot_response, chatbot, chatbot
283
  )
284
+
285
+ def reset_state():
286
  global current_q_index, questions
287
  global in_forward_flow, in_backward_flow
288
  global forward_index, backward_index
289
+ global forward_done, backward_done, forward_recommendation_given
290
+
291
  current_q_index = 0
292
  questions = base_questions[:]
293
  for key in user_profile:
294
  user_profile[key] = None
295
+ in_forward_flow = in_backward_flow = False
296
+ forward_index = backward_index = 0
297
+ forward_done = backward_done = False
298
+ forward_recommendation_given = False
 
 
299
  return []
300
+
301
+ reset.click(reset_state, outputs=chatbot)
302
+
303
+ def auto_intro():
304
+ # 启动时自动显示第一个问题
305
+ return [{"role": "assistant", "content": base_questions[0][1]}]
306
+
307
+ demo.load(auto_intro, outputs=chatbot)
308
+
309
+ demo.launch()