Spaces:
Sleeping
Sleeping
File size: 21,717 Bytes
3741806 38b4374 e944dc7 1563988 3741806 e944dc7 1563988 3741806 fcaf14a 3741806 1563988 49470f9 1563988 49470f9 3741806 1563988 3741806 49470f9 3741806 5d45a78 3741806 0eddb80 3741806 1563988 3741806 95e832d 3741806 1563988 3741806 1563988 3741806 49cc82e 0afa2a7 49cc82e 3fbff0b 95e832d 3fbff0b 5d45a78 3fbff0b 49cc82e 95e832d 3741806 3fbff0b 3741806 afd1d0b 3741806 afd1d0b 3741806 1563988 95e832d 3741806 1563988 3741806 1563988 3741806 1563988 3741806 1563988 3741806 afd1d0b 3741806 95e832d 3741806 134dbf5 |
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 |
from utils import draw_radar_chart
import json
import gradio as gr
from pydantic import BaseModel
import openai
import os
openai.api_base = "https://api.wzunjh.top/v1"
def ask_gpt(prompt):
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo", # here we use `gpt-3.5-turbo` model, while Stanford-Alpaca uses `text-davinci-003`
messages=[
{"role": "user", "content": prompt},
]
)
print(response)
return response.choices[0].message.content.strip()
def ask_gpt_with_history(history):
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo", # here we use `gpt-3.5-turbo` model, while Stanford-Alpaca uses `text-davinci-003`
messages=history
)
print(response)
return response.choices[0].message.content.strip()
async def predict(input, history):
"""
Predict the response of the chatbot and complete a running list of chat history.
"""
history.append({"role": "user", "content": input})
response = ask_gpt_with_history(history)
history.append({"role": "assistant", "content": response})
messages = [(history[i]["content"], history[i + 1]["content"]) for i in range(0, len(history) - 1, 2)]
return messages, history
class Message(BaseModel):
role: str
content: str
def parse_file(file):
print(file.name)
with open(file.name, encoding="utf8") as in_file:
txt = in_file.read()
return txt, gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)
# 生成人才画像
def generate_talent_portrait(resume):
prompt = f"你现在是HR招聘专家,下面是候选人的简历:\n\"\"\"\"{resume}\"\"\"\"\n请你分析候选人的教育背景、工作经验、技能等方面的特点,给出候选人的人才画像,并概括性的分析候选人的优点和不足。"
return ask_gpt(prompt)
# 人岗匹配度
def person_job_fit_gene(resume, jd):
# prompt = f"你现在是HR招聘专家,某职位要求是:{{{jd}}}\n某候选人简历如下:{{{get_talent_outline(resume)}}}" + "。岗位与候选人之间的匹配度可以用0-1之间的数字表示,0表示完全不匹配,1表示完全匹配。请你评估应聘岗位与候选人的匹配度,并给出理由。"
prompt = '''你现在是HR招聘专家,某职位要求是:
{}
某候选人简历信息如下:{}。
针对候选人的简历与职位要求进行匹配度评估,采取以下规则:1. 教育背景匹配度评估:
- 完全匹配:候选人的教育背景与职位要求完全符合。
- 较为匹配:候选人的教育背景与职位要求有一定的相关性,但不完全符合。
- 较不匹配:候选人的教育背景与职位要求有一些不相关的情况。
- 完全不匹配:候选人的教育背景与职位要求完全不符合。
2. 工作经验匹配度评估:
- 完全匹配:候选人的工作经验与职位要求完全符合。
- 较为匹配:候选人的工作经验与职位要求具备相应的技能和经验,但可能缺少某些方面的经验。
- 较不匹配:候选人的工作经验与职位要求相差较大,缺乏相关的技能和经验。
- 完全不匹配:候选人的工作经验与职位要求完全不符合。
3. 技能与能力匹配度评估:
- 完全匹配:候选人具备职位要求的所有必备技能和能力。
- 较为匹配:候选人具备部分职位要求的技能和能力,但可能缺少某些方面的能力。
- 较不匹配:候选人缺乏职位要求的关键技能和能力。
- 完全不匹配:候选人的技能和能力与职位要求完全不符合。
4. 其他因素综合考虑:
- 完全匹配:候选人除了教育背景、工作经验和技能与能力外,还具备其他与职位要求相关的因素,如培训经历、认证证书等。
- 较为匹配:候选人除了教育背景、工作经验和技能与能力外,可能还具备一些与职位要求相关的因素。
- 较不匹配:候选人缺乏与职位要求相关的其他因素。
- 完全不匹配:候选人的其他因素与职位要求完全不符合。
5. 整体的人岗匹配度:
综合考量候选人的教育背景、工作经验、技能与能力以及其他因素得到整体的岗位匹配度。
根据以上规则,对简历与职位要求之间的匹配度进行评估,并划分为完全匹配、较为匹配、较不匹配和完全不匹配四个档次。
评估结果请以json格式返回给我,下面是返回结果的示例:
{
"教育背景匹配度":{
"结果":"",
"评估说明":""
},
"工作经验匹配度":{
"结果":"",
"评估说明":""
},
"技能与能力匹配度":{
"结果":"",
"评估说明":""
},
"其他因素匹配度":{
"结果":"",
"评估说明":""
},
"整体匹配度":{
"结果":"",
"评估说明":""
}
}
'''.format(jd, resume)
data = json.loads(ask_gpt(prompt))
edu_matching = data['教育背景匹配度']['结果']
edu_description = data['教育背景匹配度']['评估说明']
work_exp_matching = data['工作经验匹配度']['结果']
work_exp_description = data['工作经验匹配度']['评估说明']
skill_matching = data['技能与能力匹配度']['结果']
skill_description = data['技能与能力匹配度']['评估说明']
other_matching = data['其他因素匹配度']['结果']
other_description = data['其他因素匹配度']['评估说明']
overall_matching = data['整体匹配度']['结果']
overall_description = data['整体匹配度']['评估说明']
return gr.update(value=edu_matching), gr.update(value=work_exp_matching, ), gr.update(
value=skill_matching, ), gr.update(value=other_matching, ), gr.update(
value=overall_matching, ), edu_description, work_exp_description, skill_description, other_description, overall_description
# interview_questions
def generate_interview_questions(work_experience):
prompt = f"你现在是HR招聘专家,下面是候选人A的工作经历:{work_experience}\n我可以问哪些问题来判断该候选人的能力水平?"
return ask_gpt(prompt)
# interview_questions
def generate_interview_questions_new(resume, jd):
prompt = f"你现在是HR高级面试官,某职位要求是:{{{jd}}}\n下面是候选人A简历的:\n{resume}\n请你生成一些面试问题来判断该候选人的能力水平。注意,请把面试问题以python列表格式返回给我,不要返回任何额外内容。"
print(prompt)
res = ask_gpt(prompt)
print(res)
print(eval(res))
return gr.update(choices=eval(res), value=eval(res), interactive=True), gr.update(visible=True)
def generate_jd(jobTitle, eduLevel, workYearArr):
prompt = "你现在是HR招聘专家,你需要发布一个名称为\"" + jobTitle + "\"的职位,请你撰写一份该职位的JD,内容包括工作职责和任职要求。"
if eduLevel != "":
prompt += "该岗位的最低学历要求为" + eduLevel + "。"
if workYearArr != "":
prompt += "该岗位的工作年限要求为" + workYearArr + "。"
prompt += "注意:非必要情况不要使用英文,内容不要包含薪酬福利等敏感信息。"
return ask_gpt(prompt)
def generate_test_resume(target_job, item_list):
resume_gene_prompt = f"你现在是HR测试数据生成器,请帮我生成一份求职目标为{target_job}的候选人简历,需要包含以下关键信息:\n{item_list}。\n注意,结果请以markdown格式返回给我,并且不要返回额外信息。"
print(resume_gene_prompt)
return ask_gpt(resume_gene_prompt)
def generate_interview_feedback(commu_skills, pro_skills, tech_skills, solve_skills, team_skills, pressure_resistance,
if_ok):
prompt = f"""
你现在是HR招聘专家,下面是某候选人的面试评估结果:
***
沟通能力:{commu_skills}
专业知识:{pro_skills}
技术能力:{tech_skills}
解决问题的能力:{solve_skills}
团队合作能力:{team_skills}
抗压能力:{pressure_resistance}
是否录用:{if_ok}
***
请你根据是否录用结果和其他各项能力的表现生成一份面试评价。
"""
print(prompt)
return ask_gpt(prompt)
def gene_ability_score(resume, jd):
prompt = f"""你现在是HR招聘专家.
某候选人简历如下:
{{{resume}}}
请你从[教育背景、工作经验、技能特长、项目经历和成果、领导力和管理能力、自我学习和发展能力、沟通和协作能力、岗位匹配度]这八个维度对候选人进行打分,分数范围是0-100,并针对每个维度的分数给出相应的打分理由。
教育背景:
评价规则:80-100表示教育背景优秀,毕业于985、211大学;70-80表示教育背景良好、毕业于普通重点大学;70分以下表示毕业于普通大学。
工作经验:
评价规则:80-100表示候选人具有丰富的相关工作经验,曾承担重要职责并取得显著的成绩;60-79表示候选人有一定的工作经验,能够胜任职务,但成绩一般;60分以下表示候选人工作经验较少或表现普通。
技能特长:
评价规则:80-100表示候选人在相关技能方面突出,掌握了多项技能,具备深厚的专业知识;60-79表示候选人具备一些相关技能,能够熟练运用;60分以下表示候选人技能较少或掌握程度一般。
项目经历和成果:
评价规则:80-100表示候选人在项目中表现出色,取得了显著的项目成果,具备解决问题和团队合作能力;60-79表示候选人在项目中有一些成绩,能够参与并完成任务;60分以下表示候选人在项目中表现一般或成绩较少。
领导力和管理能力:
评价规则:80-100表示候选人具备优秀的领导力和管理能力,曾成功承担过领导职责或项目管理职务;60-79表示候选人具备一定的领导力和管理能力,曾有一定的领导经验;60分以下表示候选人领导能力较弱或未有相关经验。
自我学习和发展能力:
评价规则:80-100表示候选人具有积极主动地学习和扩充知识的意愿和能力,持续学习并不断提升自己;60-79表示候选人有一些学习和发展的意愿和能力,但不够积极主动;60分以下表示候选人学习和发展能力较弱或缺乏积极性。
沟通和协作能力:
评价规则:80-100表示候选人具备良好的沟通和协作能力,能够与他人有效地进行交流和合作;60-79表示候选人具备一定的沟通和协作能力,能够与他人合作完成任务;60分以下表示候选人沟通和协作能力较弱或简历中描述有限。
注意,结果参考下面的JSON字符串,以json格式返回给我,不要返回任何额外信息。
返回结果参考:
{
"教育背景": "81",
"工作经验":"68",
"技能特长":"69",
"项目经历和成果":"85",
"领导力和管理能力":"96",
"自我学习和发展能力":"100",
"沟通和协作能力":"56",
"打分理由":"理性评估"
}
"""
print(prompt)
return ask_gpt(prompt)
def gene_talent_radar(resume, jd):
res = gene_ability_score(resume, jd)
json_res = json.loads(res)
print(json_res)
score_list = []
cat_list = []
for key, value in json_res.items():
if key != "打分理由":
cat_list.append(key)
score_list.append(int(value))
print(score_list)
print(cat_list)
return draw_radar_chart(score_list, cat_list), json_res["打分理由"]
with gr.Blocks(title="HRMaster", theme="soft") as demo:
gr.Markdown("# HRMaster")
gr.Markdown("HRMaster usage demo.")
with gr.Tab("岗位JD生成器"):
with gr.Row():
with gr.Column():
jobTitle_input = gr.Textbox(label="岗位名称")
eduLevel_input = gr.Textbox(label="最低学历要求")
workYearArr_input = gr.Textbox(label="工作年限要求")
with gr.Column():
jd_output_text = gr.Textbox(label="生成的岗位JD")
jd_button = gr.Button(value="岗位JD生成")
jd_button.click(generate_jd, [jobTitle_input, eduLevel_input, workYearArr_input], jd_output_text)
with gr.Column():
gr.Examples([["java开发工程师", "本科", "三年以上"], ["算法工程师", "研究生", "一年以上"]],
[jobTitle_input, eduLevel_input, workYearArr_input], [jd_output_text], fn=generate_jd,)
with gr.Tab("简历筛选辅助"):
with gr.Row():
resume_file = gr.File(label="请上传简历(目前仅支持上传txt格式简历)", file_types=["text"])
text_output = gr.Textbox(label="简历信息")
talent_row = gr.Row(visible=False)
with talent_row:
resume_text = gr.Textbox(label="人才画像")
hua_button = gr.Button(value="生成人才画像", )
hua_button.click(generate_talent_portrait, text_output, resume_text)
jd_row = gr.Row(visible=False)
with jd_row:
with gr.Column():
jd = gr.Textbox(label="岗位JD", lines=20)
test_jd = '''
职位名称:Java开发工程师
工作职责:
1. 根据业务需求,参与需求分析、系统设计和架构设计。
2. 开发和维护基于Java技术的Web应用程序、服务端组件和工具。
3. 编写高质量的可维护、可扩展的代码,并进行单元测试和代码审查。
4. 对现有系统进行优化和性能调优,确保系统的高可用性和稳定性。
5. 与产品经理、设计师和测试人员紧密合作,确保产品质量和用户体验。
6. 持续学习和研究新的技术和开发工具,提出并实施技术创新和改进。
任职要求:
1. 精通Java编程语言,熟悉Java相关的开发框架和工具,如Spring、Hibernate等。
2. 具备扎实的计算机基础知识,熟悉面向对象设计和设计模式。
3. 具备良好的数据结构和算法基础,对系统性能优化有一定的经验。
4. 熟悉Web开发相关的技术,如HTML、CSS、JavaScript等。
5. 具备良好的沟通能力和团队协作能力,能够与团队成员和其他相关岗位进行有效的沟通和合作。
6. 具备良好的问题解决能力和学习能力,能够快速地理解和解决技术问题。
7. 具备良好的代码风格和规范意识,注重代码质量和可维护性。
'''
gr.Examples([test_jd], [jd])
with gr.Column():
# person_job_fit = gr.Textbox(label="人岗匹配度")
edu_matching = gr.CheckboxGroup(["完全匹配", "较为匹配", "较不匹配", "完全不匹配"], label="教育背景匹配度", info="")
edu_description = gr.Textbox(label="评估说明",)
work_exp_matching = gr.CheckboxGroup(["完全匹配", "较为匹配", "较不匹配", "完全不匹配"], label="工作经验匹配度", info="")
work_exp_description = gr.Textbox(label="评估说明")
skill_matching = gr.CheckboxGroup(["完全匹配", "较为匹配", "较不匹配", "完全不匹配"], label="技能与能力匹配度", info="")
skill_description = gr.Textbox(label="评估说明")
other_matching = gr.CheckboxGroup(["完全匹配", "较为匹配", "较不匹配", "完全不匹配"], label="其他因素匹配度", info="")
other_description = gr.Textbox(label="评估说明")
overall_matching = gr.CheckboxGroup(["完全匹配", "较为匹配", "较不匹配", "完全不匹配"], label="整体匹配度", info="")
overall_description = gr.Textbox(label="评估说明")
fit_button = gr.Button(value="计算人岗匹配度", )
fit_button.click(person_job_fit_gene, [text_output, jd],
[edu_matching, work_exp_matching, skill_matching, other_matching, overall_matching,
edu_description, work_exp_description, skill_description, other_description,
overall_description])
radar_row = gr.Row(visible=False)
with radar_row:
radar_outputs = gr.Plot(label="能力雷达图")
radar_reasons = gr.Textbox(label="打分理由")
radar_button = gr.Button(value="生成能力雷达图")
radar_button.click(gene_talent_radar, [text_output, jd], [radar_outputs, radar_reasons])
gr.Examples([os.path.join(os.path.dirname(__file__), "test_resume.txt")], resume_file,
[text_output, talent_row, jd_row, radar_row], fn=parse_file, cache_examples=True)
resume_file.change(parse_file, resume_file, [text_output, talent_row, jd_row, radar_row])
with gr.Tab("面试过程辅助"):
interview_row = gr.Row(visible=True)
with interview_row:
interview_questions_text = gr.Checkboxgroup(label="面试问题", show_copy_button=True)
interview_questions_generator_button = gr.Button(value="面试问题生成")
interview_questions_generator_button.click(generate_interview_questions_new, [text_output, jd],
[interview_questions_text])
with gr.Tab("测试数据生成"):
with gr.Row():
targrt_job = gr.Textbox(label="求职目标")
resume_item_list = gr.Dropdown(
["个人信息", "教育背景", "工作经历", "实习经历", "技能专长", "项目经验", "获奖与荣誉", "自我评价"],
value=["个人信息", "教育背景", "工作经历", "技能专长", "项目经验", "自我评价"], multiselect=True, label="简历维度",
info="测试简历维度信息"
)
test_resume_text = gr.Textbox(label="生成的测试简历信息", show_copy_button=True)
resume_gene_button = gr.Button("测试数据生成")
resume_gene_button.click(generate_test_resume, [targrt_job, resume_item_list], test_resume_text)
test_targrt_job = "java开发工程师"
test_resume_item_list = ["个人信息", "教育背景", "工作经历", "实习经历", "技能专长", "项目经验", "获奖与荣誉", "自我评价"]
gr.Examples([[test_targrt_job, test_resume_item_list]], targrt_job, resume_item_list,
fn=generate_test_resume,
)
with gr.Tab("面试评价生成器"):
with gr.Row():
with gr.Column():
commu_skills = gr.Radio(["强", "中", "弱"], label="沟通能力",
info="评估候选人的口头表达能力、听取并理解问题的能力、回答问题的清晰度和逻辑性等。")
pro_skills = gr.Radio(["强", "中", "弱"], label="专业知识", info="评估候选人在岗位所需的专业知识的掌握程度。")
tech_skills = gr.Radio(["强", "中", "弱"], label="技术能力", info="评估候选人在岗位所需的专业技能方面的掌握程度。")
solve_skills = gr.Radio(["强", "中", "弱"], label="解决问题的能力",
info="评估候选人在面对问题时的分析能力、创新思维、解决问题的方法和结果。")
team_skills = gr.Radio(["强", "中", "弱"], label="团队合作能力",
info="评估候选人在与他人合作、协调和沟通方面的能力,包括与面试官的互动、参与小组讨论等。")
pressure_resistance = gr.Radio(["强", "中", "弱"], label="抗压能力",
info="评估候选人在应对压力、处理复杂情境以及适应变化上的能力。")
if_ok = gr.Radio(["是", "否"], label="是否录用", info="最终结果")
with gr.Column():
interview_feedback_text = gr.Textbox(label="面试评价", show_copy_button=True)
result_button = gr.Button(value="面试评价生成")
result_button.click(generate_interview_feedback,
inputs=[commu_skills, pro_skills, tech_skills, solve_skills, team_skills,
pressure_resistance, if_ok],
outputs=interview_feedback_text)
gr.Examples([["强", "中", "弱", "强", "中", "弱", "是"], ["弱", "中", "弱", "强", "中", "弱", "否"]],
[commu_skills, pro_skills, tech_skills, solve_skills, team_skills,
pressure_resistance, if_ok], interview_feedback_text,
fn=generate_interview_feedback,
)
with gr.Tab("HRChat"):
with gr.Column():
chatbot = gr.Chatbot(label="HRChat")
state = gr.State([])
clear = gr.Button("Clear")
txt = gr.Textbox(show_label=False, placeholder="Enter text and press enter").style(container=False)
txt.submit(predict, [txt, state], [chatbot, state])
clear.click(lambda: None, None, chatbot, queue=False)
if __name__ == "__main__":
demo.launch(debug=True)
|