Spaces:
Runtime error
Runtime error
File size: 15,448 Bytes
e6c64bf | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | # Resume Shortlister
## Streamlit App in Hugging face
I have provided the resumes and job description that I have tested in the mentioned folders..
And also I have included the results too.. PLEASE DO LOOK INTO THEM.
URL:
## HI, THIS IS A DEMO VIDEO OF THIS APP>>> I HIGHLYYYYYY RECOMMEND YOU TO GO THORUGH IT.. PLEASE
https://drive.google.com/file/d/1r2VM2_8bRmT84uNgboQJDjbllnnvpvNR/view?usp=sharing
## Basic Simple workflow**
## Overview
Resume Shortlister is a multi-agent AI system designed to analyze resumes, compare them against job descriptions, and identify the best candidates. The system is built using Streamlit for the user interface and LangGraph for state management. It leverages the power of Llama models for natural language processing and OpenAI's API for generating responses.
## Features
- **Batch Processing:** Efficiently processes multiple resumes at once to minimize computational load.
- **Job Description Classification:** Parses and classifies job descriptions to identify key criteria.
- **Resume Analysis:** Extracts and analyzes resume content to assess fitment based on job description.
- **Scoring and Grading:** Assigns scores to candidates based on various criteria such as role match, skillset match, experience match, and educational qualifications.
- **Top Candidate Selection:** Filters the top five candidates based on scores.
- **Email Draft Generation:** Generates personalized email drafts for the top candidates.
- **Timing and Schedule Management:** Sorts and assigns interview timings for shortlisted candidates.
## Installation
1. Clone the repository:
```sh
git clone https://github.com/yourusername/Candidate-filtering-system.git
cd Candidate-filtering-system
```
2. Create a virtual environment and install dependencies:
```sh
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
3. Set up environment variables by creating a `.env` file:
```
GROQ_API_KEY=your_groq_api_key
HELICONE_API_KEY=your_helicone_api_key
```
4. The GROQ is for basic LLM calling where as HELICONE helps us to look into the analytics of the api call
## Usage
1. Run the Streamlit app:
```sh
streamlit run app.py
```
2. Upload resumes (in PDF format) and a job description (in PDF format).
3. Enter the timings for the candidates and submit.
## Workflow Explanation
### State Graphs and Nodes
This project uses LangGraph to manage state transitions through two primary workflows:
#### 1. Resume Analysis Workflow
- **Nodes:**
- `start`: Extracts content from resumes.
- `end`: Analyzes resumes and scores them based on job descriptions.
- **Functionality:**
- The `start` node processes batches of resumes, extracting content and initiating analysis.
- The `end` node compares resumes against job descriptions, scores them, and updates the DataFrame with analysis results.
#### 2. Email Draft Workflow
- **Nodes:**
- `timings_sort`: Sorts candidates by score and assigns interview timings.
- `emails_draft`: Generates personalized email drafts for the top candidates.
- **Functionality:**
- The `timings_sort` node sorts candidates by their scores and assigns timings.
- The `emails_draft` node generates personalized email drafts for the top candidates based on their analysis.
### Process Flow
1. **Resume Information Collection:** Extracts information from uploaded resumes.
2. **Job Description Grading:** Classifies job descriptions and compares them against resumes.
3. **Candidate Filtering:** Filters and ranks the top five candidates based on scores.
4. **Email Draft Generation:** Generates email drafts for the top candidates with personalized content.
## Challenges Faced
- **Computational Load:** Managing the batch processing of resumes to minimize computational overhead.
- **JSON Parsing:** Handling cases where the AI model generates incomplete or incorrect JSON responses.
- **Rate Limiting:** Addressing rate limits imposed by the API services.
- **Continuous Node Execution:** Managing the execution flow of nodes to ensure seamless processing.
## Grading Process
1. **Input Texts:**
- Extract the provided job description and resume from the input text.
- Delimit each part using triple backticks for clarity.
2. **Identify Job Description Components:**
- Parse the job description to extract:
- **Role:** Job title or primary role.
- **Skillset:** Specific skills required.
- **Experience:** Years and type of experience required.
- **Educational Qualifications:** Required or preferred educational background.
3. **Identify Resume Components:**
- Parse the resume to extract:
- **Role:** Current or most recent job title.
- **Skillset:** Mentioned skills.
- **Experience:** Years and type of experience.
- **Educational Qualifications:** Educational background.
4. **Matching Criteria:**
- Compare each category from the job description with the resume.
- Assign weightage and scores for each category based on relevance.
- Provide reasoning for each score.
5. **Generate JSON Output:**
- Structure the output in JSON format with detailed analysis for each category.
6. **Final Summary:**
- Summarize the overall match between the job description and resume.
- Provide an overall score and suitability narrative.
7. **Strengths, Weaknesses, and Risk Areas:**
- Identify and list the candidate's strengths, weaknesses, and potential risk areas based on the analysis.
8. **Questions:**
- Generate personalized questions for the candidate based on their profile and the job description.
### Example JSON Output Structure
```json
{
"role_match": {
"weightage": 8,
"score": 90,
"reasoning": "The candidate's current and previous job titles align well with the role specified in the job description."
},
"skillset_match": {
"weightage": 7,
"score": 85,
"reasoning": "The candidate possesses most of the required technical skills, with some minor gaps in specific tools."
},
"experience_match": {
"weightage": 9,
"score": 95,
"reasoning": "The candidate has the required years of experience and relevant industry background."
},
"education_match": {
"weightage": 6,
"score": 80,
"reasoning": "The candidate's educational background meets the requirements but lacks some preferred certifications."
},
"overall_score": 87.5,
"summary": "The candidate is a strong match for the job role, with relevant experience and skills. The educational background is adequate, though additional certifications could enhance suitability.",
"strengths": "1. Good communication skills, 2. Proficient in required technology, 3. Team player.",
"weaknesses": "1. Over-communicates, 2. Gaps in experience with emerging technologies, 3. Challenges with independent decision-making.",
"risk_areas": "1. Over-reliance on existing skills, 2. Resistance to process changes, 3. Overcommitment leading to burnout.",
"questions": "1. How do you handle complex ideas communication? 2. How would you combine your tech stacks? 3. Describe a situation where you worked independently."
}
```
## Basic Code Explanation
This document explains the functionality of several Python functions used in a resume processing application.
### 1. Generating Responses using Llama Models (response function)
This function generates responses using the Llama model from OpenAI.
# Code
```python
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
```
**Parameters:**
* `message`: The input message for which a response is to be generated.
* `model` (optional): The model name to be used (defaults to "llama3-8b-8192").
* `SysPrompt` (optional): The system prompt to guide the response generation (defaults to SysPromptDefault).
* `temperature` (optional): The temperature parameter to control the randomness of the response (defaults to 0.2).
**Functionality:**
1. **Client Initialization:** Initializes the OpenAI client with API keys and default headers.
2. **Message Construction:** Formats the input message and system prompt as a list of messages.
3. **Response Generation:** Uses `client.chat.completions.create` to generate a response based on the specified model, messages, and temperature.
4. **Return Response:** Returns the generated response content.
**Explanation:**
* This function allows generating creative text formats using the Llama model.
* The temperature parameter controls the randomness of the generated response, with higher values leading to more creative but potentially less relevant responses.
### 2. Extracting Content from Resumes (extract_content function)
This function extracts text content from a PDF file:
# Code
```python
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
```
**Parameters:**
* `pdf_content`: The byte content of the PDF file.
**Functionality:**
1. **Open PDF:** Opens the PDF document using the `fitz` library.
2. **Iterate Pages:** Loops through each page of the PDF.
3. **Extract Text:** Extracts text content from each page using `page.get_text("text")` and replaces newlines with tabs.
4. **Append Text:** Appends the extracted text from each page to a list.
5. **Return Text:** Returns the list containing text content from each page.
**Explanation:**
* This function assumes the resumes are in PDF format and utilizes the `fitz` library for efficient text extraction.
### 3. Batch Processing Resumes (function_info function)
This function processes batches of resumes and generates responses for each batch:
# Code
```python
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
```
**Parameters:**
* `x`: A dictionary containing a list of PDF resumes in the "messages" key.
**Functionality:**
1. **Batch Processing:** Iterates through the list of resumes in batches of a specified size.
2. **Generate Context:** Concatenates the text content of the resumes in a batch to form the context.
3. **Generate Responses:** Uses the `response` function to generate a response for each batch context.
4. **Extract and Append Information:** Extracts relevant information (name, email, contact number, resume summary) from the response and appends it to a DataFrame (assumed to be defined elsewhere).
**Explanation:**
* This function enables efficient processing of large numbers of resumes by handling them in batches.
** The above is node function in the first graph of agents. In the same way the batch processing is done for the other nodes as well **
### 4. Classifying Job Descriptions (classify_jd function)
This function classifies a job description and extracts relevant information:
# Code
```python
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
```
**Parameters:**
* `job_description`: The text content of the job description.
**Functionality:**
1. **Generate Message:** Formats the job description for processing.
2. **Generate Response:** Uses the `response` function to generate a response for the job description.
3. **Extract JSON:** Extracts relevant information (presumably classified by the model) from the response string.
4. **Return JSON:** Returns the extracted information as a dictionary.
**Explanation:**
* This function leverages the Llama model to categorize a job description and extract key details.
### Code: Defining and Compiling the Workflow
This code sets up and compiles a state-based workflow using the `StateGraph` class, specifying the sequence of operations for processing resumes and job descriptions.
```python
from langgraph import StateGraph
# Define the workflow
workflow = StateGraph(AgentState)
# Add nodes to the workflow
workflow.add_node("start", function_info)
workflow.add_node("end", function_fitment)
# Define edges between nodes
workflow.add_edge("start", "end")
# Set entry and finish points
workflow.set_entry_point("start")
workflow.set_finish_point("end")
# Compile the workflow
app = workflow.compile()
```
# StateGraph Configuration
```python
# Initialize a new state graph with the AgentState context
StateGraph(AgentState)
# Add a node named "timings_sort" linked to the functions_sort_timings function
add_node("timings_sort", functions_sort_timings)
# Add a node named "emails_draft" linked to the function_email function
add_node("emails_draft", function_email)
# Create a directed edge from the "timings_sort" node to the "emails_draft" node
add_edge("timings_sort", "emails_draft")
# Specify the "timings_sort" node as the entry point of the approach
set_entry_point("timings_sort")
# Specify the "emails_draft" node as the finish point of the approach
set_finish_point("emails_draft")
# Compile the defined approach into an executable application
compile()
```
|