| 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 | |