HelenaXH commited on
Commit
049d943
·
verified ·
1 Parent(s): dc0ee86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -42
app.py CHANGED
@@ -5,20 +5,17 @@ import time
5
 
6
  # ========== 全局变量与基础问题 ==========
7
  user_profile = {
8
- "mode": None, # 是否有明确职业目标:是/否
9
- "age": None, # 年龄范围
10
- "degree": None, # 学历
11
- "interests": None, # 兴趣爱好
12
- "mbti": None, # MBTI类型
13
- "specific_career": None, # Backward模式下的目标职业
14
-
15
- # 以下是为增强多轮交互新增的字段:
16
- "bg_info": None, # 学术背景(学校、年级、专业、主修课程、Resume)
17
- "test_choice": None, # 是否做职业测评或小游戏(Forward模式中示例)
18
- "forward_career_choice": None, # Forward模式下,用户从多个推荐方向中最终选择的方向
19
  }
20
 
21
- # 原始基础问题(5个)
22
  base_questions = [
23
  ("mode", "你是否有心仪的职业方向?\n- 如果有,请回复'是'(Backward模式)\n- 如果没有,请回复'否'(Forward模式)"),
24
  ("age", "你的年龄范围是?(例如:'18岁以下','18-21岁','21-25岁','25-29岁','30岁以上')"),
@@ -27,36 +24,18 @@ base_questions = [
27
  ("mbti", "你的MBTI人格类型是什么?(例如:INFP,INTJ,ENFP等)如果不知道,可以回复'不知道'")
28
  ]
29
 
30
- # Forward模式下的补充问题:示例
31
  forward_additional_questions = [
32
- (
33
- "bg_info",
34
- "请提供你的具体学术背景:你的学校、年级、专、主修课程。如果能简单介绍一下目前选课或实习经历就更好啦。"
35
- ),
36
- (
37
- "test_choice",
38
- "我可以帮你做一个简单的职业性格测评,或玩一个小心理游戏,让你更清晰地认识自己。你想试试看吗?(请输入'是'或'否')"
39
- ),
40
- (
41
- "forward_career_choice",
42
- "基于你的背景和性格,我会给出几个职业大方向,请在这里输入你最感兴趣的1~2个方向,以便深入讨论。"
43
- ),
44
  ]
45
 
46
- # Backward模式下的补充问题:示例
47
  backward_additional_questions = [
48
- # 注意:original code中会在第1个问题之后自动插入("specific_career", "请具体描述你的方向")
49
- (
50
- "bg_info",
51
- "请提供你的学校、年级、专业以及已有的实习或项目经历,以便更好地帮你规划如何达成目标。"
52
- )
53
  ]
54
 
55
- # 记录当前问题索引
56
  current_q_index = 0
57
- questions = base_questions[:] # 基础问题列表的拷贝
58
-
59
- # 标记流程状态
60
  in_forward_flow = False
61
  in_backward_flow = False
62
  forward_index = 0
@@ -64,18 +43,13 @@ backward_index = 0
64
  forward_done = False
65
  backward_done = False
66
 
67
- # ========== 默认模型参数,可自行修改 ==========
68
  system_prompt_default = "你是一位专业的职业规划顾问,帮助学生规划他们的职业路径。"
69
  model_default = "gpt-4o"
70
  temp_default = 0.7
71
  top_p_default = 0.95
72
  token_default = 2000
73
 
74
- # ========== 生成系统提示 ==========
75
  def generate_system_prompt():
76
- """
77
- 根据 Forward / Backward 模式以及收集的用户信息,动态生成 system prompt
78
- """
79
  mode = user_profile["mode"]
80
  age = user_profile["age"]
81
  degree = user_profile["degree"]
@@ -85,8 +59,7 @@ def generate_system_prompt():
85
  bg_info = user_profile["bg_info"]
86
  test_choice = user_profile["test_choice"]
87
  forward_career_choice = user_profile["forward_career_choice"]
88
-
89
- if mode and "是" in mode: # Backward模式
90
  prompt = f"""
91
  你是一位专业的职业规划顾问,使用"Backward Design"方法帮助学生规划他们的职业路径。
92
  学生个人资料:
@@ -113,4 +86,258 @@ def generate_system_prompt():
113
  7. 简历优化建议
114
 
115
  最后,请用Markdown格式提供清晰的职业路线图,格式如下:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
 
5
 
6
  # ========== 全局变量与基础问题 ==========
7
  user_profile = {
8
+ "mode": None,
9
+ "age": None,
10
+ "degree": None,
11
+ "interests": None,
12
+ "mbti": None,
13
+ "specific_career": None,
14
+ "bg_info": None,
15
+ "test_choice": None,
16
+ "forward_career_choice": None
 
 
17
  }
18
 
 
19
  base_questions = [
20
  ("mode", "你是否有心仪的职业方向?\n- 如果有,请回复'是'(Backward模式)\n- 如果没有,请回复'否'(Forward模式)"),
21
  ("age", "你的年龄范围是?(例如:'18岁以下','18-21岁','21-25岁','25-29岁','30岁以上')"),
 
24
  ("mbti", "你的MBTI人格类型是什么?(例如:INFP,INTJ,ENFP等)如果不知道,可以回复'不知道'")
25
  ]
26
 
 
27
  forward_additional_questions = [
28
+ ("bg_info", "请提供你的具体学术背景:你的学校、年级、专业、主修课程。如果能简单介绍一下你目前的选课或实习经历就更好啦。"),
29
+ ("test_choice", "我可以帮你做一个简单的职业性格测评,或玩一个小心理游戏,让你更清晰地认识自己。你想试试看吗?(请输入'是'或'否')"),
30
+ ("forward_career_choice", "基于你的背景和性格,我会给出几个职大方向,请在这里输入最感兴趣1~2个方向,以便深入讨论。")
 
 
 
 
 
 
 
 
 
31
  ]
32
 
 
33
  backward_additional_questions = [
34
+ ("bg_info", "请提供你的学校、年级、专以及已有的实习或项目经历,以便更好地帮你规划如何达成目标。")
 
 
 
 
35
  ]
36
 
 
37
  current_q_index = 0
38
+ questions = base_questions[:]
 
 
39
  in_forward_flow = False
40
  in_backward_flow = False
41
  forward_index = 0
 
43
  forward_done = False
44
  backward_done = False
45
 
 
46
  system_prompt_default = "你是一位专业的职业规划顾问,帮助学生规划他们的职业路径。"
47
  model_default = "gpt-4o"
48
  temp_default = 0.7
49
  top_p_default = 0.95
50
  token_default = 2000
51
 
 
52
  def generate_system_prompt():
 
 
 
53
  mode = user_profile["mode"]
54
  age = user_profile["age"]
55
  degree = user_profile["degree"]
 
59
  bg_info = user_profile["bg_info"]
60
  test_choice = user_profile["test_choice"]
61
  forward_career_choice = user_profile["forward_career_choice"]
62
+ if mode and "是" in mode:
 
63
  prompt = f"""
64
  你是一位专业的职业规划顾问,使用"Backward Design"方法帮助学生规划他们的职业路径。
65
  学生个人资料:
 
86
  7. 简历优化建议
87
 
88
  最后,请用Markdown格式提供清晰的职业路线图,格式如下:
89
+ """
90
+ else:
91
+ prompt = f"""
92
+ 你是一位专业的职业规划顾问,使用"Forward Design"方法帮助学生探索适合的职业路径。
93
+ 学生个人资料:
94
+ - 年龄: {age}
95
+ - 学历: {degree}
96
+ - 兴趣爱好: {interests}
97
+ - MBTI类型: {mbti}
98
+ - 学术背景: {bg_info}
99
+ - 是否做过职业测评: {test_choice}
100
+ - 学生选择感兴趣的��业方向: {forward_career_choice}
101
+
102
+ 请根据学生的背景和个人资料进行分析:
103
+ 1. 总结学生的优势和劣势
104
+ 2. 分析学生的性格特点和职业适配性
105
+ 3. 基于学生的学历背景、兴趣爱好和性格特点,推荐若干可能适合的职业大方向
106
+ 4. 当学生选择了特定方向后,请进一步推荐3个具体职业,并针对每个职业提供:
107
+ - 职业描述和日常工作内容
108
+ - 该职业对学生的适合度分析
109
+ - 入行门槛和要求
110
+ - 详细的准备步骤(如选课、必要技能培训、资格认证或考试、如何利用学校资源、实习积累、简历优化等)
111
+
112
+ 最后,请用Markdown格式提供一个清晰的职业路线图:
113
+ """
114
+ return prompt
115
+
116
+ def predict(message, history):
117
+ global current_q_index, questions
118
+ global in_forward_flow, in_backward_flow
119
+ global forward_index, backward_index
120
+ global forward_done, backward_done
121
+
122
+ if not history:
123
+ current_q_index = 0
124
+ questions = base_questions[:]
125
+ for key in user_profile:
126
+ user_profile[key] = None
127
+ in_forward_flow = False
128
+ in_backward_flow = False
129
+ forward_index = 0
130
+ backward_index = 0
131
+ forward_done = False
132
+ backward_done = False
133
+
134
+ if current_q_index > 0 and current_q_index <= len(questions):
135
+ key = questions[current_q_index - 1][0]
136
+ user_profile[key] = message.strip()
137
+ if key == "mode" and "是" in user_profile["mode"]:
138
+ questions.insert(1, ("specific_career", "请具体描述你想要从事的职业方向。"))
139
+ in_backward_flow = True
140
+ elif key == "mode" and "否" in user_profile["mode"]:
141
+ in_forward_flow = True
142
+
143
+ if current_q_index < len(questions):
144
+ q_text = questions[current_q_index][1]
145
+ current_q_index += 1
146
+ return q_text
147
+
148
+ mode = user_profile["mode"] or ""
149
+ if "是" in mode:
150
+ if in_backward_flow and not backward_done:
151
+ if backward_index < len(backward_additional_questions):
152
+ key, q_text = backward_additional_questions[backward_index]
153
+ backward_index += 1
154
+ return q_text
155
+ else:
156
+ backward_done = True
157
+ else:
158
+ if in_forward_flow and not forward_done:
159
+ if forward_index < len(forward_additional_questions):
160
+ key, q_text = forward_additional_questions[forward_index]
161
+ forward_index += 1
162
+ return q_text
163
+ else:
164
+ forward_done = True
165
+
166
+ if in_backward_flow and backward_index > 0 and not backward_done:
167
+ idx = backward_index - 1
168
+ if idx < len(backward_additional_questions):
169
+ key = backward_additional_questions[idx][0]
170
+ user_profile[key] = message.strip()
171
+
172
+ if in_forward_flow and forward_index > 0 and not forward_done:
173
+ idx = forward_index - 1
174
+ if idx < len(forward_additional_questions):
175
+ key = forward_additional_questions[idx][0]
176
+ user_profile[key] = message.strip()
177
+
178
+ if "是" in mode:
179
+ if backward_index < len(backward_additional_questions):
180
+ key, q_text = backward_additional_questions[backward_index]
181
+ backward_index += 1
182
+ return q_text
183
+ else:
184
+ backward_done = True
185
+ else:
186
+ if forward_index < len(forward_additional_questions):
187
+ key, q_text = forward_additional_questions[forward_index]
188
+ forward_index += 1
189
+ return q_text
190
+ else:
191
+ forward_done = True
192
+
193
+ if ("是" in mode and backward_done) or ("否" in mode and forward_done):
194
+ try:
195
+ api_key = os.environ.get("API_TOKEN")
196
+ if not api_key:
197
+ return "错误:API密钥未设置,请在环境变量中添加名为API_TOKEN的Secret。"
198
+ client = OpenAI(api_key=api_key)
199
+ system_prompt = generate_system_prompt()
200
+ messages = [
201
+ {"role": "system", "content": system_prompt},
202
+ {"role": "user", "content": f"根据我提供的信息,请给我职业规划建议。我的回答是:{user_profile}. {message}"}
203
+ ]
204
+ response = client.chat.completions.create(
205
+ model=model_default,
206
+ messages=messages,
207
+ max_tokens=token_default,
208
+ temperature=temp_default,
209
+ top_p=top_p_default,
210
+ stream=False
211
+ )
212
+ return response.choices[0].message.content
213
+ except Exception as e:
214
+ return f"发生错误: {str(e)}"
215
+
216
+ return "信息收集完毕,若尚未得到最终回复,请输入任意文字以继续。"
217
+
218
+ with gr.Blocks(css="""
219
+ body {
220
+ background-color: #1e1e1e;
221
+ color: #ffffff;
222
+ }
223
+ .gradio-container {
224
+ font-family: 'Segoe UI', sans-serif;
225
+ }
226
+ .message.user {
227
+ background-color: #cce6ff !important;
228
+ color: #000000 !important;
229
+ border-radius: 10px !important;
230
+ padding: 10px;
231
+ margin: 6px;
232
+ }
233
+ .message.bot {
234
+ background-color: #5599ff !important;
235
+ color: #000000 !important;
236
+ border-radius: 10px !important;
237
+ padding: 10px;
238
+ margin: 6px;
239
+ }
240
+ .gradio-container .chat-msg.bot-msg .message.bot p {
241
+ color: #000000 !important;
242
+ }
243
+ .gr-button {
244
+ border-radius: 8px;
245
+ }
246
+ #custom-send {
247
+ background-color: #ec4899 !important;
248
+ color: white !important;
249
+ border-radius: 999px !important;
250
+ padding: 10px 24px !important;
251
+ font-weight: bold;
252
+ box-shadow: 0 0 10px #ec4899;
253
+ transition: all 0.3s ease-in-out;
254
+ }
255
+ #custom-send:hover {
256
+ background-color: #d63384 !important;
257
+ box-shadow: 0 0 12px #ec4899;
258
+ }
259
+ textarea, input {
260
+ background-color: #ffe4f1 !important;
261
+ color: #5e2c49 !important;
262
+ border: 1px solid #ec4899 !important;
263
+ }
264
+ footer {
265
+ display: none !important;
266
+ }
267
+ """) as demo:
268
+ with gr.Row():
269
+ gr.HTML("""
270
+ <div style='display: flex; align-items: center; justify-content: center; gap: 20px; margin-bottom: 10px;'>
271
+ <img src='https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExMmFucGwxbmNsd3J5NXV0Y282NXNtMzNsZW5jMm4wNWh6c2dqbXIwdiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l41m18LjqpzxUr2WA/giphy.gif' width='200' style='border-radius: 12px; box-shadow: 0 0 10px #ec4899;'>
272
+ <div style='text-align: left;'>
273
+ <h1 style='color:white; font-size: 36px; margin-bottom: 6px;'>🎓 AI职业规划助手(升级版)</h1>
274
+ <p style='font-size: 18px; font-weight:bold; color:#ec4899; margin-top: 0;margin-left: 150px'>让梦想照进现实 💖</p>
275
+ </div>
276
+ </div>
277
+ """)
278
+
279
+ gr.Markdown("""
280
+ **📝 个性化职业规划助手:Forward / Backward 多轮交互示例**
281
+
282
+ - 如果你已确定了职业目标,选择 **Backward** 模式(回答“是”)。
283
+ - 如果你需要探索适合的职业方向,选择 **Forward** 模式(回答“否”)。
284
+ - 我会收集你的基础信息、学术背景,并根据你的回答做多轮引导,最后给出职业规划建议。
285
+ """)
286
+
287
+ chatbot = gr.Chatbot(height=500, show_label=False, show_copy_button=True, type="messages")
288
+
289
+ with gr.Row():
290
+ with gr.Column(scale=8):
291
+ msg = gr.Textbox(placeholder="请在这里输入你的回答...", show_label=False, container=False)
292
+ with gr.Column(scale=1):
293
+ submit_btn = gr.Button("🚀 发送", elem_id="custom-send")
294
+
295
+ with gr.Row():
296
+ reset_btn = gr.Button("🔄 重新开始")
297
+
298
+ def add_message(message, history):
299
+ history = history or []
300
+ history.append({"role": "user", "content": message})
301
+ return "", history
302
+
303
+ def bot_response(history):
304
+ history = history or []
305
+ user_message = history[-1]["content"]
306
+ bot_message = predict(user_message, history[:-1] if len(history) > 1 else [])
307
+ history.append({"role": "assistant", "content": bot_message})
308
+ return history
309
+
310
+ submit_btn.click(fn=add_message, inputs=[msg, chatbot], outputs=[msg, chatbot]).then(
311
+ fn=bot_response, inputs=[chatbot], outputs=[chatbot]
312
+ )
313
+
314
+ msg.submit(fn=add_message, inputs=[msg, chatbot], outputs=[msg, chatbot]).then(
315
+ fn=bot_response, inputs=[chatbot], outputs=[chatbot]
316
+ )
317
+
318
+ def reset_conversation():
319
+ global current_q_index, questions
320
+ global in_forward_flow, in_backward_flow
321
+ global forward_index, backward_index
322
+ global forward_done, backward_done
323
+ current_q_index = 0
324
+ questions = base_questions[:]
325
+ for key in user_profile:
326
+ user_profile[key] = None
327
+ in_forward_flow = False
328
+ in_backward_flow = False
329
+ forward_index = 0
330
+ backward_index = 0
331
+ forward_done = False
332
+ backward_done = False
333
+ return []
334
+
335
+ reset_btn.click(fn=reset_conversation, inputs=None, outputs=chatbot, queue=False)
336
+
337
+ def auto_first_question():
338
+ return [{"role": "assistant", "content": questions[0][1]}]
339
+
340
+ demo.load(auto_first_question, inputs=None, outputs=chatbot)
341
+ demo.launch()
342
+
343