|
import json |
|
import os |
|
|
|
from langchain.chains import LLMChain, SequentialChain |
|
from langchain.chat_models import ChatOpenAI |
|
from langchain.prompts import ChatPromptTemplate |
|
|
|
llm = ChatOpenAI(temperature=0.0, openai_api_key=os.environ["OPENAI"]) |
|
|
|
|
|
def create_intro(vacancy, resume): |
|
|
|
template_vacancy_get_skills = """ |
|
Can you generate me a list of the skills that a candidate is supposed to have for the below vacancy delimited by three backticks. |
|
If you do not know if skills are available mention that you do not know and do not make up an answer. |
|
Mention the skills in 1 to maximum three words for each skill. Return the skills as a JSON list. |
|
|
|
``` |
|
{vacancy} |
|
``` |
|
""" |
|
|
|
prompt_vacancy_get_skills = ChatPromptTemplate.from_template( |
|
template=template_vacancy_get_skills |
|
) |
|
vacancy_skills = LLMChain( |
|
llm=llm, prompt=prompt_vacancy_get_skills, output_key="vacancy_skills" |
|
) |
|
|
|
template_resume_check_skills = """ |
|
``` |
|
{vacancy_skills} |
|
``` |
|
|
|
Based on the above list of skills required by a vacancy delimited by backticks, |
|
Can you create a JSON object based on the below keys each starting with '-', with respect to the resume below delimited by three backticks? |
|
|
|
- "skills_present": <list the skills present. If no skills are present return an empty list, do not make up an answer. > |
|
- "skills_not_present": <list the skills not present. If all skills are present return an empty list, do not make up an answer.> |
|
- "score": <calculate a percentage of the number of skills present with respect to the total skills requested> |
|
|
|
``` |
|
{resume} |
|
``` |
|
""" |
|
|
|
prompt_resume_check_skills = ChatPromptTemplate.from_template( |
|
template=template_resume_check_skills |
|
) |
|
resume_skills = LLMChain( |
|
llm=llm, prompt=prompt_resume_check_skills, output_key="resume_skills" |
|
) |
|
|
|
template_resume_past_experiences = """ |
|
Can you generate me a list of the past work experiences that the candidate has based on the resume below enclosed by three backticks. |
|
Mention the experiences in one sentence of medium length. Return the experiences as a JSON list. |
|
|
|
``` |
|
{resume} |
|
``` |
|
""" |
|
|
|
prompt_resume_past_experiences = ChatPromptTemplate.from_template( |
|
template=template_resume_past_experiences |
|
) |
|
past_experiences = LLMChain( |
|
llm=llm, prompt=prompt_resume_past_experiences, output_key="past_experiences" |
|
) |
|
|
|
template_vacancy_check_past_experiences = """ |
|
``` |
|
{past_experiences} |
|
``` |
|
|
|
Based on the above list of past experiences by a vacancy delimited by backticks, |
|
Can you create a JSON object based on the below keys each starting with '-', with respect to the vacancy below delimited by three backticks? |
|
|
|
- "relevant_experiences": <list the relevant experiences. If no experiences are relevant return an empty list, do not make up an answer. > |
|
- "irrelevant_experiences": <list the irrelevant experiences. If all experiences are relevant return an empty list, do not make up an answer.> |
|
- "score": <calculate a percentage of the number of skills present with respect to the total skills requested> |
|
|
|
``` |
|
{resume} |
|
``` |
|
""" |
|
|
|
prompt_vacancy_check_past_experiences = ChatPromptTemplate.from_template( |
|
template=template_vacancy_check_past_experiences |
|
) |
|
check_past_experiences = LLMChain( |
|
llm=llm, |
|
prompt=prompt_vacancy_check_past_experiences, |
|
output_key="check_past_experiences", |
|
) |
|
|
|
template_introduction_email = """ |
|
You are a recruitment specialist that tries to place the right profiles for the right job. |
|
I have a vacancy below the delimiter <VACANCY> and ends with </VACANCY> |
|
and I have a candidate its resume below the delimiter <RESUME> and it ends with </RESUME>. |
|
|
|
<VACANCY> |
|
{vacancy} |
|
</VACANCY> |
|
|
|
<RESUME> |
|
{resume} |
|
</RESUME> |
|
|
|
Can you fill in the introduction below and only return as answer this introduction? |
|
|
|
- Role: < the role of the vacancy > |
|
- Candidate: < name of the candidate > |
|
- Education: < name the education of the candidate > |
|
- Experience: < name the 2 most relevant experiences from the candidate for this vacancy. Get them from the "relevant_experiences" key of the JSON object {past_experiences}. If there us no relevant experience, leave this empty. Do not make up an answer or get them from the irrelevant experiences. > |
|
- Skills: print here a comma seperated list of the "skills_present" key of the JSON object {resume_skills} |
|
""" |
|
|
|
prompt_introduction_email = ChatPromptTemplate.from_template( |
|
template=template_introduction_email |
|
) |
|
introduction_email = LLMChain( |
|
llm=llm, prompt=prompt_introduction_email, output_key="introduction_email" |
|
) |
|
|
|
match_resume_vacancy_skills_chain = SequentialChain( |
|
chains=[ |
|
vacancy_skills, |
|
resume_skills, |
|
past_experiences, |
|
check_past_experiences, |
|
introduction_email, |
|
], |
|
input_variables=["vacancy", "resume"], |
|
output_variables=[ |
|
"vacancy_skills", |
|
"resume_skills", |
|
"past_experiences", |
|
"check_past_experiences", |
|
"introduction_email", |
|
], |
|
verbose=False, |
|
) |
|
|
|
result = match_resume_vacancy_skills_chain({"vacancy": vacancy, "resume": resume}) |
|
print(result) |
|
|
|
resume_skills = json.loads(result["resume_skills"]) |
|
relevant_skills = len(resume_skills["skills_present"]) |
|
total_skills = len( |
|
resume_skills["skills_present"] + resume_skills["skills_not_present"] |
|
) |
|
score_skills = round(100.0 * (relevant_skills / total_skills), 2) |
|
|
|
check_past_experiences = json.loads(result["check_past_experiences"]) |
|
relevant_experiences = len(check_past_experiences["relevant_experiences"]) |
|
total_experiences = len( |
|
check_past_experiences["relevant_experiences"] |
|
+ check_past_experiences["irrelevant_experiences"] |
|
) |
|
score_experiences = round(100.0 * (relevant_experiences / total_experiences), 2) |
|
|
|
new_line = "\n" |
|
|
|
score = f""" |
|
Skills (Score: {score_skills}%) |
|
Relevant Skills: {",".join(resume_skills["skills_present"])} |
|
Not Relevant Skills: {",".join(resume_skills["skills_not_present"])} |
|
""" |
|
return result["introduction_email"], score |
|
|