Ashish1722's picture
Upload 8 files
e6c64bf verified
Raw
History Blame Contribute Delete
11.2 kB
from openai import OpenAI
from dotenv import load_dotenv
import os
import json
import pandas as pd
import fitz
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
from typing import List,Tuple,TypedDict, Annotated, Sequence
import streamlit as st
import numpy as np
import tiktoken
import tkinter as tk
from tkinter import filedialog, simpledialog
import re
from langgraph.graph import StateGraph, state
import operator
from resume_prompt import resume_prompt
from jd_prompt import jd_prompt
from grading_prompt import grading_prompt
from timings import timings
from emails import email
df = {
"Name":[],
"Email id":[],
"Contact No.":[],
"Resume_Summary": [],
"Fitment":{
"Criteria": [],
"Score": [],
"Weightage": [],
"Reasoning": []
},
"Analysis":{
"Strengths": [],
"Weaknesses": [],
"Risk Areas": [],
},
"Score":[],
"Candidate Summary":[],
"Questions to ask": [],
"Timing/Schedule": [],
"Email_Draft":[],
}
load_dotenv()
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
HELICONE_API_KEY=os.getenv("HELICONE_API_KEY")
SysPromptDefault = "You are now in the role of an expert AI."
pdf_list = []
jd_2 = None
phase_2= False
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]
def response(message: object, model: object = "llama3-8b-8192", SysPrompt: object = SysPromptDefault, temperature: object = 0.2) -> object:
"""
:rtype: object
"""
client = OpenAI(
api_key=GROQ_API_KEY,
base_url="https://gateway.hconeai.com/openai/v1",
default_headers={
"Helicone-Auth": f"Bearer {HELICONE_API_KEY}",
"Helicone-Target-Url": "https://api.groq.com"
}
)
messages = [{"role": "system", "content": SysPrompt}, {"role": "user", "content": message}]
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
frequency_penalty=0.2,
)
return response.choices[0].message.content
def extract_content(pdf_content: bytes) -> List[str]:
"""
Takes PDF (bytes) and returns a list of strings containing text from each page.
"""
pdf_doc = fitz.open(stream=pdf_content, filetype="pdf")
pages_content = []
for page_number in range(pdf_doc.page_count):
# Extracting text content
page = pdf_doc.load_page(page_number)
text_content = page.get_text("text").replace("\n", "\t")
pages_content.append(text_content)
pdf_doc.close()
return pages_content
def function_info(x):
pdf_list = x["messages"]
model = "llama3-70b-8192"
batch_size = 3
all_responses_json = []
for i in range(0, len(pdf_list), batch_size):
batch = pdf_list[i:i + batch_size]
print(f"Processing batch from index {i} to {i + batch_size} ")
context = "Next file\n\n".join([f"Resume File:\n\n{pdf}\n\n" for pdf in batch])
message = f"RESUMES LIST \n\n{context}\n\n"
response_json = extract_json(response(message=message, model=model, SysPrompt=resume_prompt))
all_responses_json.append(response_json)
for response_json in all_responses_json:
for key,value in response_json.items():
print(key)
df["Name"].append(value["name"])
df["Email id"].append(value["email_id"])
df["Contact No."].append(value["contact_no"])
df["Resume_Summary"].append(value["resume_summary"])
x["messages"][-1]= all_responses_json
def classify_jd(job_description):
model = "llama3-70b-8192"
message = f"JOB_DESCRIPTION\n\n{job_description}\n\n"
response_str = response(message=message, model=model, SysPrompt=jd_prompt, temperature=0)
json_part = extract_json(response_str)
return json_part
def function_fitment(x):
global df
global jd_2
jd_2=classify_jd(jd_2)
resumes_json={}
for json_nest in x["messages"][-1]:
resumes_json.update(json_nest)
batch_size = 3
resume_keys = list(resumes_json.keys())
model = "llama3-70b-8192"
all_responses_json = []
for i in range(0, len(resume_keys), batch_size):
batch_keys = resume_keys[i:i + batch_size]
print(f"Processing batch from index {i} to {i + batch_size} (keys: {batch_keys})")
context = f"\n\nNEXT RESUME:\n\n".join(f"RESUME:{json.dumps(resumes_json[key], indent=4)}" for key in batch_keys)
message = f"\n\nJOB_DESCRIPTION:\n\n{json.dumps(jd_2, indent=4)}\n\nRESUMES LIST:\n\n{context}"
output_str = response(message=message, model=model, SysPrompt=grading_prompt, temperature=0)
output = extract_json(output_str)
print(f"Extracted JSON: {output}")
all_responses_json.append(output)
for response_json in all_responses_json:
for key,value in response_json.items():
u = []
v = []
w = []
z = []
for section, values in value.items():
if section!="overall_score" and section!="summary" and section!="strengths" and section!="weaknesses" and section!="risk_areas" and section!="questions":
u.append(section)
v.append(values["score"])
w.append(values["weightage"])
z.append(values["reasoning"])
if section=='strenghts':
df["Analysis"]["Strengths"].append(value["strengths"])
if section=='weaknesses':
df["Analysis"]["Weaknesses"].append(value["weaknesses"])
if section=='risk_areas':
df["Analysis"]["Risk Areas"].append(value["risk_areas"])
df["Fitment"]["Criteria"].append(u)
df["Fitment"]["Score"].append(v)
df["Fitment"]["Weightage"].append(w)
df["Fitment"]["Reasoning"].append(z)
df["Score"].append(value["overall_score"])
df["Questions to ask"].append(value["questions"])
df["Candidate Summary"].append(value["summary"])
df = flatten_dict(df)
def flatten_dict(data):
length = len(data['Name'])
flat_data = []
for i in range(length):
entry = {
'Name': data['Name'][i] if i < len(data['Name']) else None,
'Email id': data['Email id'][i] if i < len(data['Email id']) else None,
'Contact No.': data['Contact No.'][i] if i < len(data['Contact No.']) else None,
'Resume_Summary': data['Resume_Summary'][i] if i < len(data['Resume_Summary']) else None,
'Score': data['Score'][i] if i < len(data['Score']) else None,
'Candidate Summary': data['Candidate Summary'][i] if i < len(data['Candidate Summary']) else None,
'Questions to ask': data['Questions to ask'][i] if i < len(data['Questions to ask']) else None,
'Timing/Schedule': None,
'Email_Draft': None,
}
# Add nested fields
for key in ['Criteria', 'Score', 'Weightage', 'Reasoning']:
if key in data['Fitment']:
if key in ['Score', 'Weightage', 'Reasoning']:
v= 0
for a in data["Fitment"]["Criteria"][0]:
entry[f"Fitment_{a}_{key}"]=data["Fitment"][key][i][v] if i < len(data["Fitment"][key]) else None
v += 1
else:
entry[f'Fitment_{key}'] = None
for key in ['Strengths', 'Weaknesses', 'Risk Areas']:
entry[f'Analysis_{key}'] = data['Analysis'][key][i] if i < len(data['Analysis'][key]) else None
flat_data.append(entry)
return pd.DataFrame(flat_data)
def extract_json(response_str):
"""Extract the JSON part from the response string and handle comments."""
response_str = re.sub(r'//.*?\n|/\*.*?\*/', '', response_str, flags=re.DOTALL)
response_str = re.sub(r'[\x00-\x1F\x7F]', '', response_str)
match = re.search(r"\{.*}", response_str, re.DOTALL)
if match:
json_part = match.group()
try:
parsed_json = json.loads(json_part)
return parsed_json
except json.JSONDecodeError as e:
print("Invalid JSON detected. Error:", e)
print("JSON part:", json_part)
else:
print("No JSON part found in the response string.")
return None
st.title('Resume Shortlister')
def functions_sort_timings(x):
global df
df = df.sort_values(by="Score", ascending=False).head(5)
input_user = x["messages"][-1]
context = f"USER_INPUT:{input_user}\n\nCANDIDATES DETAILS:\n\n"
for index, row in df.iterrows():
context += f"Name: {row['Name']}\nResume Summary: {row['Resume_Summary']}\n\n"
ans = response(message=context,SysPrompt=timings)
response_json = extract_json(ans)
df["Timing/Schedule"] = df["Name"].map(response_json)
def function_email(x):
g = x["messages"][-1]
print(g)
global jd_2
global df
job_role = jd_2["position_role"]
job_req = jd_2["requirements"]
context = f"JOB DETAILS:{job_role}\nJOB REQUIREMENTS:{job_req}\n\n"
for index, row in df.iterrows():
context += f"Name: {row['Name']}\nResume Summary: {row['Resume_Summary']}\n Timinings: {row['Timing/Schedule']}\n\n"
ans = response(message=context,SysPrompt=email)
st.write(ans)
response_json = extract_json(ans)
df["Email_Draft"] = df["Name"].map(response_json)
workflow = StateGraph(AgentState)
workflow.add_node("start",function_info)
workflow.add_node("end",function_fitment)
workflow.add_edge("start","end")
workflow.set_entry_point("start")
workflow.set_finish_point("end")
app = workflow.compile()
approach = StateGraph(AgentState)
approach.add_node("timings_sort",functions_sort_timings)
approach.add_node("emails_draft",function_email)
approach.add_edge("timings_sort","emails_draft")
approach.set_entry_point("timings_sort")
approach.set_finish_point("emails_draft")
app_1 = approach.compile()
x = {}
pdf = st.file_uploader("Choose a CSV file", accept_multiple_files=True)
jd = st.file_uploader("Choose a jd", accept_multiple_files=False)
f = st.text_input("Enter the timings for the candidates that would be sorted")
if pdf and jd:
if st.button("Submit"):
for i in range(len(pdf)):
pdf_content = pdf[i].read()
pdf_list.append(extract_content(pdf_content))
jd_1 = jd.read()
jd_2 = extract_content(jd_1)
a = app.invoke({"messages":pdf_list})
st.dataframe(df)
phase_2 = True
if phase_2==True:
r = app_1.invoke({"messages":[HumanMessage(f)]})
st.dataframe(df)
else:
st.write("Make sure you enter both the jd and resumes in pdf format")