|
|
|
|
|
|
|
|
|
|
|
|
|
import os |
|
import jinja2 |
|
import openai |
|
import pdfkit |
|
import random |
|
import re |
|
import sys |
|
import numpy as np |
|
import gradio as gr |
|
from zipfile import ZipFile |
|
from langchain.llms import OpenAI |
|
from langchain.chat_models import ChatOpenAI |
|
from langchain.output_parsers import ResponseSchema,PydanticOutputParser,StructuredOutputParser |
|
from langchain import PromptTemplate |
|
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate |
|
from langchain.output_parsers import CommaSeparatedListOutputParser |
|
from pydantic import BaseModel, Field, validator |
|
from typing import List |
|
from langchain.text_splitter import CharacterTextSplitter,RecursiveCharacterTextSplitter |
|
|
|
output_parser = CommaSeparatedListOutputParser() |
|
|
|
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
|
|
|
|
|
c_splitter = CharacterTextSplitter(chunk_size = 450,chunk_overlap = 0,separator = ' ') |
|
r_splitter = RecursiveCharacterTextSplitter(chunk_size = 80,chunk_overlap = 0,separators = ["\n\n"]) |
|
|
|
|
|
|
|
|
|
|
|
output_parser = CommaSeparatedListOutputParser() |
|
format_instructions = output_parser.get_format_instructions() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def company_cr(target_company,language,key): |
|
tar_com_prompt = """ List 6 competitors' name of {company} in {lang}.\n{format_instructions} |
|
""" |
|
chat_0_3 = ChatOpenAI(temperature = 0.0,openai_api_key = key) |
|
pTem_tar_c = ChatPromptTemplate.from_template(tar_com_prompt) |
|
prompt_c = pTem_tar_c.format_messages(company = target_company,lang = language,format_instructions = format_instructions) |
|
print(prompt_c) |
|
mock_exp_company = chat_0_3(prompt_c) |
|
print(mock_exp_company) |
|
mock_exp_company_fin = mock_exp_company.content.split(',') |
|
return mock_exp_company_fin |
|
|
|
|
|
def job_cr(target_job,language,key): |
|
tar_job_prompt = """ List 2 similar names of this {job} in {lang}.\n{format_instructions} |
|
""" |
|
chat_0_3 = ChatOpenAI(temperature = 0.0,openai_api_key = key) |
|
pTem_tar_j = ChatPromptTemplate.from_template(tar_job_prompt) |
|
prompt_j = pTem_tar_j.format_messages(job = target_job,lang = language,format_instructions = format_instructions) |
|
mock_exp_job = chat_0_3(prompt_j) |
|
print(mock_exp_job) |
|
mock_exp_job_fin = mock_exp_job.content.split(',') |
|
print(mock_exp_job_fin) |
|
return mock_exp_job_fin |
|
|
|
|
|
def skill_pri_cr(job_req,key): |
|
tar_skill_pri_prompt = """ Assume you are the recruiter, read the {job_requirement}, then list 20 tech terms you want to see on candidates resume.\n{format_instructions} |
|
""" |
|
chat_0_4 = ChatOpenAI(temperature = 0.0,model_name = 'gpt-4',openai_api_key = key) |
|
pTem_tar_skill = ChatPromptTemplate.from_template(tar_skill_pri_prompt) |
|
prompt_skill = pTem_tar_skill.format_messages(job_requirement = job_req,format_instructions = format_instructions) |
|
mock_skill_pri = chat_0_4(prompt_skill) |
|
print(mock_skill_pri) |
|
mock_skill_pri_fin = mock_skill_pri.content.split(',') |
|
print(mock_skill_pri_fin) |
|
return mock_skill_pri_fin |
|
|
|
|
|
|
|
def skill_sec_cr(skill_pri,language,key): |
|
tar_skill_sec_prompt = """ Assume you are the recruiter, read the skill sets in {skill_pri}, list 5 related tech terms for each skill set you want to see on candidates resume in {lang}.\n{format_instructions} |
|
""" |
|
|
|
chat_0_3 = ChatOpenAI(temperature = 0.0,openai_api_key = key) |
|
pTem_tar_skill_sec = ChatPromptTemplate.from_template(tar_skill_sec_prompt) |
|
prompt_skill_sec = pTem_tar_skill_sec.format_messages(skill_pri = skill_pri,lang = language,format_instructions = format_instructions) |
|
|
|
mock_skill_sec = chat_0_3(prompt_skill_sec) |
|
|
|
print(mock_skill_sec) |
|
mock_skill_sec_fin = mock_skill_sec.content.split(',') |
|
print(mock_skill_sec_fin) |
|
return mock_skill_sec_fin |
|
|
|
|
|
def soc_cr(target_job,language,key): |
|
tar_soc_prompt = """ If a student want to become a {job_name} after graduation, list 5 possible school clubs or competitions the student wants to join in {lang}.\n{format_instructions} |
|
""" |
|
chat_0_4 = ChatOpenAI(temperature = 0.0,model_name = 'gpt-4',openai_api_key = key) |
|
pTem_tar_soc = ChatPromptTemplate.from_template(tar_soc_prompt) |
|
prompt_soc = pTem_tar_soc.format_messages(job_name = target_job,lang = language,format_instructions = format_instructions) |
|
|
|
mock_exp_soc = chat_0_4(prompt_soc) |
|
print(mock_exp_soc) |
|
mock_exp_soc_fin = mock_exp_soc.content.split(',') |
|
print(mock_exp_soc_fin) |
|
|
|
return mock_exp_soc_fin |
|
|
|
|
|
|
|
def work_exp(mock_company,mock_title,mock_skill,language,key): |
|
working_exp_prompt = """ Write the working experience in {lang}. Considering my working experience in {company} as a {title}, and I am good at {skill_sec}, write a part of resume for me. A good resume reorganizes the skill set in 3 to 4 examples. Each example must include 60 to 80 words. A good resume must not use pronouns. Each example must have detail numbers to describe result. List each example in a new line without serial numbers. """ |
|
chat_0_4 = ChatOpenAI(temperature = 0.0,model_name = 'gpt-4',openai_api_key = key) |
|
|
|
pTem_tar_working_exp = ChatPromptTemplate.from_template(working_exp_prompt) |
|
prompt_working_exp = pTem_tar_working_exp.format_messages(company = mock_company,lang = language,title = mock_title,skill_sec = mock_skill) |
|
|
|
|
|
mock_working_exp = chat_0_4(prompt_working_exp) |
|
print(mock_working_exp) |
|
mock_working_exp_fin = r_splitter.split_text(mock_working_exp.content) |
|
print(mock_working_exp_fin) |
|
result = [mock_working_exp_fin[0],mock_working_exp_fin[1],mock_working_exp_fin[2]] |
|
|
|
|
|
print(mock_working_exp_fin[3]) |
|
print(result) |
|
return (mock_working_exp_fin[0],mock_working_exp_fin[1],mock_working_exp_fin[2]) |
|
|
|
|
|
def club_exp(mock_soc,mock_skill_soc,language,key): |
|
club_exp_prompt = """ Write the school experience in {lang}. Considering my school experience in {club}, and I am good at {skill_sec_club}, write a part of resume for me. A good resume reorganizes the skill set in 3 examples. Each example must include 60 to 80 words. A good resume must not use pronouns. Each example must have detail numbers to describe result. List each example in a new line without serial numbers. """ |
|
chat_0_4 = ChatOpenAI(temperature = 0.0,model_name = 'gpt-4',openai_api_key = key) |
|
n_range = range(0,80) |
|
rand_value = random.sample(n_range,4) |
|
print(rand_value) |
|
|
|
mock_skill_soc_fin = np.array(mock_skill_soc)[rand_value] |
|
|
|
pTem_tar_club_exp = ChatPromptTemplate.from_template(club_exp_prompt) |
|
prompt_club_exp = pTem_tar_club_exp.format_messages(club = mock_soc,lang = language,skill_sec_club = mock_skill_soc_fin) |
|
|
|
print(pTem_tar_club_exp) |
|
print(prompt_club_exp) |
|
|
|
|
|
mock_club_exp = chat_0_4(prompt_club_exp) |
|
print(mock_club_exp) |
|
|
|
mock_club_exp_fin = r_splitter.split_text(mock_club_exp.content) |
|
print(mock_club_exp_fin) |
|
|
|
print(mock_club_exp_fin[0]) |
|
|
|
return mock_club_exp_fin |
|
|
|
|
|
|
|
def skill_info(job_req,language,key): |
|
|
|
|
|
|
|
|
|
mock_skill_pri = skill_pri_cr(job_req,key) |
|
|
|
|
|
mock_skill_sec = skill_sec_cr(mock_skill_pri,language,key) |
|
|
|
|
|
return mock_skill_sec |
|
|
|
|
|
|
|
|
|
|
|
def resume(name,mobile,email,Gra_beg,Gra_end,Gra_sch,Gra_maj,underGra_beg,underGra_end,underGra_sch,underGra_maj,exp_one_beg,exp_one_end,exp_one_com,exp_one_title,exp_one_1,exp_one_2,exp_one_3,exp_two_beg,exp_two_end,exp_two_com,exp_two_title,exp_two_1,exp_two_2,exp_two_3,exp_three_beg,exp_three_end,exp_three_com,exp_three_title,exp_three_1,exp_three_2,exp_three_3): |
|
|
|
|
|
|
|
pdfkit_options = {'encoding': 'UTF-8'} |
|
body = f""" |
|
|
|
<main role="main"> |
|
<div class="page"><!-- 1. Header --> |
|
<h1 style="text-align: center;">{name}</h1> |
|
<p style="text-align: center;">手机:{mobile} 邮箱:{email}</p> |
|
<hr /><!-- 2a. Resume Content --> |
|
<section class="resume_content"> |
|
<article> |
|
<h3>教育经历</h3> |
|
<div style="float: left;">{Gra_beg}-{Gra_end} <strong>{Gra_sch}</strong></div> |
|
<div style="float: right;">{Gra_maj} <strong>本科</strong></div> |
|
<br /> |
|
<div style="float: left;">{underGra_beg}-{underGra_end} <strong>{underGra_sch}</strong></div> |
|
<div style="float: right;">{underGra_maj} <strong>本科</strong></div> |
|
<br /><hr /> |
|
<h3>工作经历</h3> |
|
<section> |
|
<div style="float: left;">{exp_one_beg}-{exp_one_end} <strong>{exp_one_com}</strong></div> |
|
<div style="float: right;"><strong>{exp_one_title}</strong></div> |
|
<br /> |
|
<ul> |
|
<p><li>{exp_one_1}</li></p> |
|
<p><li>{exp_one_2}</li></p> |
|
<p><li>{exp_one_3}</li></p> |
|
</ul> |
|
<div style="float: left;">{exp_two_beg}-{exp_two_end} <strong>{exp_two_com}</strong></div> |
|
<div style="float: right;"><strong>{exp_two_title}</strong></div> |
|
<br /> |
|
<ul> |
|
<p><li>{exp_two_1}</li></p> |
|
<p><li>{exp_two_2}</li></p> |
|
<p><li>{exp_two_3}</li></p> |
|
</ul> |
|
<div style="float: left;">{exp_three_beg}-{exp_three_end} <strong>{exp_three_com}</strong></div> |
|
<div style="float: right;"><strong>{exp_three_title}</strong></div> |
|
<br /> |
|
<ul> |
|
<p><li>{exp_three_1}</li></p> |
|
<p><li>{exp_three_2}</li></p> |
|
<p><li>{exp_three_3}</li></p> |
|
</ul> |
|
</article> |
|
</section> |
|
</div> |
|
</main> |
|
|
|
|
|
""" |
|
|
|
|
|
pdfkit.from_string(body, 'out.pdf',options=pdfkit_options) |
|
|
|
|
|
|
|
return body |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def Dropdown_list(list_in): |
|
new_options = list_in |
|
return gr.Dropdown.update(choices=new_options) |
|
|
|
def Add_list(list_in,list_add): |
|
list_out = list_in + list_add.split(",") |
|
return list_out |
|
|
|
def Textbox_value(list_in,num): |
|
num = int(num) |
|
new_value = list_in[num] |
|
return gr.Textbox.update(value = new_value) |
|
|
|
def Dropdown_value_rand(list_in,num): |
|
num = int(num) |
|
n_range = range(0,80) |
|
rand_value = random.sample(n_range,num) |
|
list_out = np.array(list_in)[rand_value] |
|
list_out = list_out.tolist() |
|
return list_out |
|
|
|
def Button_visible(): |
|
return gr.Button.update(visible = True) |
|
|
|
def Textbox_value_os(str_in): |
|
return gr.Textbox.update(value = str_in) |
|
|
|
|
|
|
|
|
|
options = ['Select a company'] |
|
|
|
with gr.Blocks() as demo: |
|
with gr.Row(): |
|
with gr.Column(): |
|
|
|
|
|
|
|
txt_key = gr.Textbox(value = "sk...",label = "key") |
|
|
|
txt_key.change(Textbox_value_os,inputs = txt_key) |
|
txt_tarcom_in = gr.Textbox(label = "Target Company",info = "e.g. Amazon") |
|
txt_tarjob_in = gr.Textbox(label = "Target Job",info = "e.g. Data Analyst") |
|
txt_jd_in = gr.Textbox(label = "Job Responsibility",info = "e.g. - Write high quality distributed system software- Build production quality and large scale deployment of applications related to NLP and ML- Use software engineering best practices to ensure a high standard of quality for all team deliverables- Design, implement, test, deploy and maintain innovative software solutions to transform service performance, stability, cost and security- Help drive business decisions with your technical input- Work in an agile, startup-like development environment, where you're always working on the most important stuff") |
|
txt_lang_in = gr.Dropdown(["Chinese", "English"],label="Language", info="Choose the language of your resume") |
|
btn_resume_info = gr.Button(value="Analyze Target Job") |
|
btn_exp_gen = gr.Button(value = "Generate Experience",visible = False) |
|
btn_resume_gen = gr.Button(value = "Generate Resume",visible = False) |
|
with gr.Row(): |
|
name = gr.Textbox(label = "Name") |
|
mobile = gr.Textbox(label = "Mobile") |
|
email = gr.Textbox(label = "Email") |
|
with gr.Row(): |
|
Gra_beg = gr.Textbox(label = "Graduate School Beginning Year") |
|
Gra_end = gr.Textbox(label = "Graduate School End Year") |
|
Gra_sch = gr.Textbox(label = "Graduate School Name") |
|
Gra_maj = gr.Textbox(label = "Graduate School Major") |
|
with gr.Row(): |
|
underGra_beg = gr.Textbox(label = "Undergraduate School Beginning Year") |
|
underGra_end = gr.Textbox(label = "Undergraduate School End Year") |
|
underGra_sch = gr.Textbox(label = "Undergraduate School Name") |
|
underGra_maj = gr.Textbox(label = "Undergraduate School Major") |
|
btn_resume_pre = gr.Button(value = "Preview Resume",visible = False) |
|
js_com_out = gr.JSON(label = "Company output") |
|
js_title_out = gr.JSON(label = "Proper Title",visible = False) |
|
js_sec_skill_out = gr.JSON(label = "Output",visible = False) |
|
js_club_out = gr.JSON(label = "Output",visible = False) |
|
|
|
|
|
btn_resume_info.click(company_cr, inputs = [txt_tarcom_in, txt_lang_in, txt_key], outputs = js_com_out) |
|
btn_resume_info.click(job_cr, inputs = [txt_tarjob_in, txt_lang_in,txt_key], outputs = js_title_out) |
|
btn_resume_info.click(skill_info, inputs = [txt_jd_in, txt_lang_in,txt_key], outputs = js_sec_skill_out) |
|
|
|
|
|
btn_resume_info.click(Button_visible,outputs = btn_exp_gen,queue = True) |
|
|
|
|
|
|
|
|
|
with gr.Row(): |
|
exp_com_one = gr.Textbox(value = options,label="Company Name") |
|
exp_title_one = gr.Textbox(value = options,label="Title Name") |
|
time_beg_one = gr.Textbox(value = '2016') |
|
time_end_one = gr.Textbox(value = '2017') |
|
exp_skill_one = gr.Dropdown(value = options, label = "Skill",multiselect = True) |
|
num_one = gr.Textbox("0",visible = False) |
|
num_two = gr.Textbox("1",visible = False) |
|
num_three = gr.Textbox("2",visible = False) |
|
num_rand = gr.Textbox("10",visible = False) |
|
btn_exp_gen.click(Textbox_value,inputs = [js_com_out,num_one],outputs = exp_com_one) |
|
btn_exp_gen.click(Textbox_value,inputs = [js_title_out,num_one],outputs = exp_title_one) |
|
btn_exp_gen.click(Dropdown_value_rand,inputs = [js_sec_skill_out,num_rand],outputs = exp_skill_one) |
|
|
|
|
|
exp_txt_one_1 = gr.Textbox(value = options,interactive = True) |
|
exp_txt_one_2 = gr.Textbox(value = options,interactive = True) |
|
exp_txt_one_3 = gr.Textbox(value = options,interactive = True) |
|
btn_work_exp_one = gr.Button(value = "Update Working Experience One") |
|
|
|
btn_work_exp_one.click(work_exp, inputs=[exp_com_one,exp_title_one,exp_skill_one,txt_lang_in,txt_key],outputs = [exp_txt_one_1,exp_txt_one_2,exp_txt_one_3]) |
|
|
|
|
|
|
|
with gr.Row(): |
|
exp_com_two = gr.Textbox(value = options,label="Company Name") |
|
exp_title_two = gr.Textbox(value = options,label="Title Name") |
|
time_beg_two = gr.Textbox(value = '2016') |
|
time_end_two = gr.Textbox(value = '2017') |
|
exp_skill_two = gr.Dropdown(value = options, label = "Skill",multiselect = True) |
|
btn_exp_gen.click(Textbox_value,inputs = [js_com_out,num_two],outputs = exp_com_two) |
|
btn_exp_gen.click(Textbox_value,inputs = [js_title_out,num_two],outputs = exp_title_two) |
|
btn_exp_gen.click(Dropdown_value_rand,inputs = [js_sec_skill_out,num_rand],outputs = exp_skill_two) |
|
|
|
exp_txt_two_1 = gr.Textbox(value = options,interactive = True) |
|
exp_txt_two_2 = gr.Textbox(value = options,interactive = True) |
|
exp_txt_two_3 = gr.Textbox(value = options,interactive = True) |
|
btn_work_exp_two = gr.Button(value = "Update Working Experience Two") |
|
|
|
btn_work_exp_two.click(work_exp, inputs=[exp_com_two,exp_title_two,exp_skill_two,txt_lang_in,txt_key],outputs = [exp_txt_two_1,exp_txt_two_2,exp_txt_two_3]) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(): |
|
exp_com_three = gr.Textbox(value = options,label="Company Name") |
|
exp_title_three = gr.Textbox(value = options,label="Title Name") |
|
time_beg_three = gr.Textbox(value = '2016') |
|
time_end_three = gr.Textbox(value = '2017') |
|
exp_skill_three = gr.Dropdown(value = options, label = "Skill",multiselect = True) |
|
btn_exp_gen.click(Textbox_value,inputs = [js_com_out,num_three],outputs = exp_com_three) |
|
btn_exp_gen.click(Textbox_value,inputs = [js_title_out,num_one],outputs = exp_title_three) |
|
btn_exp_gen.click(Dropdown_value_rand,inputs = [js_sec_skill_out,num_rand],outputs = exp_skill_three) |
|
|
|
exp_txt_three_1 = gr.Textbox(value = options,interactive = True) |
|
exp_txt_three_2 = gr.Textbox(value = options,interactive = True) |
|
exp_txt_three_3 = gr.Textbox(value = options,interactive = True) |
|
btn_work_exp_three = gr.Button(value = "Update Working Experience Three") |
|
|
|
btn_work_exp_three.click(work_exp, inputs=[exp_com_three,exp_title_three,exp_skill_three,txt_lang_in,txt_key],outputs = [exp_txt_three_1,exp_txt_three_2,exp_txt_three_3]) |
|
|
|
|
|
|
|
btn_exp_gen.click(Button_visible,outputs = btn_resume_gen) |
|
|
|
btn_resume_gen.click(work_exp, inputs=[exp_com_one,exp_title_one,exp_skill_one,txt_lang_in,txt_key],outputs = [exp_txt_one_1,exp_txt_one_2,exp_txt_one_3]) |
|
btn_resume_gen.click(work_exp, inputs=[exp_com_two,exp_title_two,exp_skill_two,txt_lang_in,txt_key],outputs = [exp_txt_two_1,exp_txt_two_2,exp_txt_two_3]) |
|
btn_resume_gen.click(work_exp, inputs=[exp_com_three,exp_title_three,exp_skill_three,txt_lang_in,txt_key],outputs = [exp_txt_three_1,exp_txt_three_2,exp_txt_three_3]) |
|
btn_resume_gen.click(Button_visible,outputs = btn_resume_pre) |
|
|
|
webpage = gr.HTML() |
|
|
|
btn_resume_pre.click(resume,inputs = [name,mobile,email,Gra_beg,Gra_end,Gra_sch,Gra_maj,underGra_beg,underGra_end,underGra_sch,underGra_maj,time_beg_one,time_end_one,exp_com_one,exp_title_one,exp_txt_one_1,exp_txt_one_2,exp_txt_one_3,time_beg_two,time_end_two,exp_com_two,exp_title_two,exp_txt_two_1,exp_txt_two_2,exp_txt_two_3,time_beg_three,time_end_three,exp_com_three,exp_title_three,exp_txt_three_1,exp_txt_three_2,exp_txt_three_3],outputs = webpage) |
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch(enable_queue = True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|