mbosse99's picture
Everything changed to GPT 4
30c247b
import gradio as gr
from time import sleep
import openai
from PyPDF2 import PdfReader
def add_text(message, history):
history = history + [(message, None)]
return message, history
def add_file(file, history, job_description_fn,candiate_cv_fn):
try:
if not job_description_fn and not candiate_cv_fn:
pdf_reader = PdfReader(file.name)
text = ""
for page in pdf_reader.pages:
text += page.extract_text()
job_description_fn = text
history = history + [
(
(file.name),
"I received the job description.",
)
]
return history,job_description_fn,candiate_cv_fn
elif job_description_fn and not candiate_cv_fn:
print("ich bin im CV")
pdf_reader = PdfReader(file.name)
text = ""
for page in pdf_reader.pages:
text += page.extract_text()
candiate_cv_fn = text
history = history + [
(
(file.name),
"I received the CV.",
),(
None,
"Generating questions..."
)
]
return history,job_description_fn,candiate_cv_fn
except Exception as e:
clear("", history, None,None,[],[],None,False)
raise gr.Error("There was an error. Please reload the page. Sorry for the inconvenience.")
def respond(message, history, answers_fn, questions_fn, request_mode_fn, job_description_fn, candiate_cv_fn):
if not job_description_fn:
sleep(0.5)
response = "Please upload the pdf of the job description."
elif job_description_fn and not candiate_cv_fn:
sleep(0.5)
response = "Please upload the CV to generate questions."
elif job_description_fn and candiate_cv_fn and len(answers_fn) <= 10 and not request_mode_fn:
answerNumber = len(answers_fn)+1
answers_fn = answers_fn + ["Answer " + str(answerNumber) + ": " + message]
if(len(answers_fn) < 10):
gpt_response = evaluate_answer(questions_fn[-1],message,job_description_fn,candiate_cv_fn)
if(gpt_response == "Thank you" or gpt_response == "Thank you." or gpt_response == "Thank you for your response."):
question = gpt_question_generator(questions_fn, job_description_fn, candiate_cv_fn)
questions_fn = questions_fn + [question]
response = question
request_mode_fn = False
else:
answers_fn[-1] += "; Request from system: " + gpt_response
response = "Request: " + gpt_response
request_mode_fn = True
else:
response = "Thank you for answering the questions. Your evaluation is now being created..."
elif job_description_fn and candiate_cv_fn and request_mode_fn:
print("ich bin im modus drin")
answers_fn[-1] += " Answer on Request: " + message
question = gpt_question_generator(questions_fn, job_description_fn, candiate_cv_fn)
questions_fn = questions_fn + [question]
response = question
request_mode_fn = False
else:
response = ask_gpt_about_evaluation(history[-1][0])
history[-1][1] = response
return "", history, answers_fn, questions_fn, request_mode_fn, job_description_fn, candiate_cv_fn
def evaluate_answer(question,answer,job_description_fn,candiate_cv_fn):
prompt = "You are a professional recruiter who receives a job description and a resume and generates questions based on these two documents, which the candidate then has to answer. You should present your assessment as fact-based as possible. You have now asked a question and the potential candidate has written his answer. Please now evaluate the answer in relation to the question. E.g. Does the answer make sense, is the question answered or are there important details missing in the answer. If something is missing then ask for it or if the answer does not really answer the question then tell the candidate and ask for a new answer. If the question is answered correctly or as well as possible, then your genrated output should simply be 'Thank you'. If a candidate answers a question in the negative, it means that he/she answered the question correctly, e.g. because he/she has no experience in the asked field or something similar. Please answer in such a case also simply 'Thank you'. Keep in mind that your generated output is directed to the potential candidate, so if you have a demand then your output must be formulated as such. Your answer must not include an explanation or anything like that why e.g. you are asking for something, it should only generate the question to the potential candidate. And please double check that a satisfactory answer is really just 'Thank you'. It is very important that your generated output is either a query to the answer or 'Thank you'."
try:
res = openai.ChatCompletion.create(
model="gpt-4",
temperature=0.2,
messages=[
{
"role": "system",
"content": prompt,
},
{"role": "system", "content": "Job description: "+job_description_fn+"; Resume: "+candiate_cv_fn},
{"role": "system", "content": "Question: "+question+ "Answer: "+ answer}
],
)
return res.choices[0]["message"]["content"]
except Exception as e:
clear("", history, None,None,[],[],None,False)
raise gr.Error("There was an error with the Open AI connection. Please reload the page. If the error occurs again, try again later or contact the administrator. Sorry for the inconvenience.")
def generateEvaluation( history, job_description_fn,candiate_cv_fn,questions_fn,answers_fn,evaluation_fn,request_mode_fn):
if(len(answers_fn)==10 and not request_mode_fn):
questionsListString = " ".join(questions_fn)
answersListString = " ".join(answers_fn)
prompt = "You are a professional recruiter who has been given a CV and a job description and has created 10 questions based on that. The eventual applicant has entered his answers to the questions. Now you have to evaluate on the basis of the answers if the applicant fits the job in principle. This is the case when about 70percent of all questions have been answered satisfactorily and positively. Keep in mind that an answer must always be fact-based, so if, for example, the question asks for examples, the potential applicant must also give such examples. Please also provide details of which questions were answered positively and why."
try:
res = openai.ChatCompletion.create(
model="gpt-4",
temperature=0.2,
messages=[
{
"role": "system",
"content": prompt,
},
{"role": "system", "content": "Job description: "+job_description_fn+"; Resume: "+candiate_cv_fn},
{"role": "system", "content": "Fragen: "+questionsListString+"; Resume: "+answersListString},
],
)
evaluation_fn = res.choices[0]["message"]["content"]
history[-1][1] = res.choices[0]["message"]["content"]
return history, job_description_fn,candiate_cv_fn,questions_fn,answers_fn,evaluation_fn,request_mode_fn
except Exception as e:
clear("", history, None,None,[],[],None,False)
raise gr.Error("There was an error with the Open AI connection. Please reload the page. If the error occurs again, try again later or contact the administrator. Sorry for the inconvenience.")
return history, job_description_fn,candiate_cv_fn,questions_fn,answers_fn,evaluation_fn,request_mode_fn
def gpt_question_generator(questions_fn, job_description_fn, candiate_cv_fn):
assert job_description_fn is not None and candiate_cv_fn is not None
questionsListString = " ".join(questions_fn)
prompt = "You are a professional recruiter who receives a job description and a resume and generates questions based on these two documents, which the candidate then has to answer. You should present your assessment as fact-based as possible. You should only ask one question at a time and the question you generate should not coincide with questions you have already asked. You will also receive all the questions you have already asked in order to avoid similar questions. Also, make sure that your question cannot be answered from the applicant's resume. The questions should encourage the potential applicant to give the most helpful answer possible, for example, proving the applicant's professional skills, so that it can be better analyzed whether the applicant fits the job description. It is very very important that you ask only one question per generated output. This means that the generated output right now from you includes only one question. And please number the questions."
try:
res = openai.ChatCompletion.create(
model="gpt-4",
temperature=0.2,
messages=[
{
"role": "system",
"content": prompt,
},
{"role": "system", "content": "Job description: "+job_description_fn+"; Resume: "+candiate_cv_fn},
{"role": "system", "content": "Questions: "+questionsListString}
],
)
return res.choices[0]["message"]["content"]
except Exception as e:
clear("", history, None,None,[],[],None,False)
raise gr.Error("There was an error with the Open AI connection. Please reload the page. If the error occurs again, try again later or contact the administrator. Sorry for the inconvenience.")
def ask_gpt_about_evaluation(query):
assert evaluation is not None
prompt = "You are a professional recruiter who has been given a job description and a CV to generate 10 questions, which the potential candidate then answers. Based on the answers you created an evaluation. Please answer questions as accurately and helpfully as possible. All answers should be fact based."
try:
res = openai.ChatCompletion.create(
model="gpt-4",
temperature=0.2,
messages=[
{
"role": "system",
"content": prompt,
},
{"role": "system", "content": "Job description: "+job_description+"; Resume: "+candiate_cv},
{"role": "user", "content": query},
],
)
return res.choices[0]["message"]["content"]
except Exception as e:
clear("", history, None,None,[],[],None,False)
raise gr.Error("There was an error with the Open AI connection. Please reload the page. If the error occurs again, try again later or contact the administrator. Sorry for the inconvenience.")
def generateQuestions(history, questions_fn, answers_fn, job_description_fn, candiate_cv_fn):
if candiate_cv_fn and job_description_fn:
question = gpt_question_generator(questions_fn, job_description_fn, candiate_cv_fn)
questions_fn = questions_fn + [question]
history = history + [(None, f"You will now be asked 10 questions. Please write your answer to the respective question in the text field. This will be used to create an evaluation that relates to your suitability for the position. Please write with the chat bot as you would write with a human. This helps to better evaluate your answers."),(None, question)]
return history, questions_fn, answers_fn, job_description_fn, candiate_cv_fn
elif job_description_fn:
history = history + [(None, "Please upload the CV to generate questions.")]
return history, questions_fn, answers_fn, job_description_fn, candiate_cv_fn
else:
return history, questions_fn, answers_fn, job_description_fn, candiate_cv_fn
def clear(txt, history, job_description_fn,candiate_cv_fn,questions_fn,answers_fn,evaluation_fn,request_mode_fn):
job_description_fn = None
candiate_cv_fn = None
questions_fn = []
answers_fn = []
evaluation_fn = None
request_mode_fn = False
return "", [(None, "Please upload a job description.")],job_description_fn,candiate_cv_fn,questions_fn,answers_fn,evaluation_fn,request_mode_fn, gr.update(value=[])
with gr.Blocks(
css="footer {visibility: hidden} #component-0{height: 90vh !important} #chatbot{height: 85vh !important} #downloadBtn:hover{background-color: #F0F0F0;box-shadow: 0px 0px 20px -18px;}",
title="Workgenius CV Evaluation",
) as gradioApp:
job_description = gr.State(None)
candiate_cv = gr.State(None)
questions = gr.State([])
answers = gr.State([])
evaluation = gr.State(None)
request_mode = gr.State(False)
gr.Markdown(
f"<div style='display: flex; justify-content: space-between;align-items: center;margin-bottom: 1rem' ><h1>CV Evaluation</h1><img width='150' src='https://www.workgenius.com/wp-content/uploads/2023/03/WorkGenius_navy-1.svg' alt='WorkGeniusLogo' /></div>"
)
history = gr.Chatbot([(None, "Please upload a job description.")], elem_id="chatbot")
with gr.Row():
with gr.Column(scale=0.15, min_width=0):
# clear = gr.ClearButton(clearable_component=history)
clr = gr.Button("Clear")
with gr.Column(scale=0.7):
txt = gr.Textbox(
show_label=False,
placeholder="Please answer the questions and press Enter",
container=False,
)
with gr.Column(scale=0.15, min_width=0):
file = gr.UploadButton("Browse...", file_types=[".pdf"])
txt_msg = txt.submit(add_text, [txt, history], [txt, history], queue=False).then(
respond, [txt, history, answers, questions, request_mode, job_description, candiate_cv], [txt, history, answers, questions, request_mode, job_description, candiate_cv], queue=False
).then(generateEvaluation,[history,job_description,candiate_cv,questions,answers,evaluation,request_mode], [history,job_description,candiate_cv,questions,answers,evaluation,request_mode], queue=False)
# clear.click(clearAll)
clr.click(
clear,
[txt, history,job_description,candiate_cv,questions,answers,evaluation,request_mode],
[txt, history,job_description,candiate_cv,questions,answers,evaluation,request_mode],
queue=False,
api_name=False,
)
file.upload(add_file, [file, history, job_description, candiate_cv], [history, job_description, candiate_cv], queue=False).then(generateQuestions, [history, questions, answers, job_description, candiate_cv], [history, questions, answers, job_description, candiate_cv], queue=False)
gradioApp.launch(show_error=True)
# gradioApp.launch(auth=("recruiter", "summarizethis"))