Skip to content

Commit 0eee6dd

Browse files
committed
CV Evaluation code using Langchain
1 parent 8d35413 commit 0eee6dd

File tree

3 files changed

+340
-0
lines changed

3 files changed

+340
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# CV Evaluation App using Oracle Gen AI
2+
3+
This is a Streamlit-based web application that evaluates resumes (CVs) against job descriptions using Oracle Cloud Infrastructure's Generative AI via Langchain `ChatOCIGenAI`.
4+
5+
---
6+
7+
## 🔍 Features
8+
9+
- Upload multiple resumes in PDF format
10+
- Select or input a job description
11+
- Evaluate resumes using Oracle Gen AI
12+
- Receive classification like `Excellent`, `Strong`, `Possible`, etc.
13+
- Get profile summaries, missing keywords, and improvement suggestions
14+
- Interactive Streamlit interface
15+
16+
---
17+
18+
## 📁 Project Structure
19+
20+
```
21+
.
22+
├── main.py # Streamlit application file
23+
├── LoadProperties2.py # Loads configuration details (custom module)
24+
├── requirements.txt # Required packages
25+
```
26+
27+
---
28+
29+
## ⚙️ Setup Instructions
30+
31+
1. **Clone the repository**
32+
```bash
33+
git clone https://github.com/your-repo/cv-evaluation-genai.git
34+
cd cv-evaluation-genai
35+
```
36+
37+
2. **Create a virtual environment (optional but recommended)**
38+
```bash
39+
python -m venv venv
40+
source venv/bin/activate # On Windows: venv\Scripts\activate
41+
```
42+
43+
3. **Install dependencies**
44+
```bash
45+
pip install -r requirements.txt
46+
```
47+
48+
4. **Update the model name and compartment ID**
49+
```bash
50+
streamlit run main.py
51+
```
52+
53+
5. **Run the Streamlit app**
54+
```bash
55+
streamlit run main.py
56+
```
57+
58+
---
59+
60+
## 📦 Dependencies
61+
62+
- `streamlit`
63+
- `PyPDF2`
64+
- `langchain_community`
65+
- `oci` (for Oracle Cloud access)
66+
67+
Make sure you have valid OCI credentials and access to the Generative AI service.
68+
69+
---
70+
71+
## 🧠 Powered By
72+
73+
- **Oracle Generative AI**: For advanced natural language processing and resume evaluation
74+
- **LangChain**: For structured LLM integration
75+
- **Streamlit**: For building a fast, interactive UI
76+
77+
---
78+
79+
## ✅ Example Use Case
80+
81+
1. Choose a job role or paste your custom Job Description.
82+
2. Upload one or more resume PDFs.
83+
3. Click **Submit**.
84+
4. View evaluation results, summaries, and suggested improvements.
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
"""
2+
CV Evaluation App using Oracle Gen AI and Streamlit
3+
4+
This module implements a Streamlit-based web application for evaluating resumes
5+
against job descriptions using Oracle's Generative AI via the ChatOCIGenAI model.
6+
7+
Modules and Functionality:
8+
--------------------------
9+
- Loads job description templates and resume PDFs.
10+
- Uses a predefined prompt to query Oracle Gen AI for resume evaluation.
11+
- Parses and visualizes the response in an interactive format.
12+
- Supports multiple resume uploads.
13+
- Assigns classification labels such as 'Excellent', 'Strong', etc.
14+
- Highlights missing keywords and provides reasoning for classification.
15+
16+
Dependencies:
17+
-------------
18+
- os
19+
- json
20+
- PyPDF2
21+
- streamlit
22+
- langchain_community (ChatOCIGenAI)
23+
24+
Functions:
25+
----------
26+
- input_pdf_text(uploaded_file): Extracts and returns text from a PDF file.
27+
- parse_response(response): Parses the model's JSON response into usable parts.
28+
- cvEvaluate(): Launches the Streamlit UI and handles interactions.
29+
30+
Usage:
31+
------
32+
Run the script with Streamlit:
33+
streamlit run <script_name>.py
34+
35+
Author: Ali Ottoman
36+
"""
37+
38+
import os
39+
import json
40+
import PyPDF2 as pdf
41+
import streamlit as st
42+
from langchain_community.chat_models.oci_generative_ai import ChatOCIGenAI
43+
44+
45+
46+
llm = ChatOCIGenAI(
47+
model_id="", #TO-DO: Add the model name here
48+
compartment_id="", #TO-DO: Add the compartment ID here
49+
model_kwargs={"temperature": 0, "max_tokens": 1000}
50+
)
51+
52+
def input_pdf_text(uploaded_file):
53+
"""
54+
Extracts and returns text from the provided PDF file.
55+
"""
56+
reader = pdf.PdfReader(uploaded_file)
57+
text = ""
58+
for page in range(len(reader.pages)):
59+
page = reader.pages[page]
60+
text += str(page.extract_text())
61+
return text
62+
63+
def parse_response(response):
64+
"""
65+
Parses the model's response JSON and extracts relevant details like name, JD match,
66+
missing keywords, profile summary, and reasoning.
67+
"""
68+
try:
69+
response_json = json.loads(response.split('}')[0] + '}')
70+
name = response_json.get("Name", "N/A")
71+
jd_match = response_json.get("JD Match", "N/A")
72+
missing_keywords = response_json.get("MissingKeywords", [])
73+
profile_summary = response_json.get("Profile Summary", "N/A")
74+
reason = response_json.get("Reason", "N/A")
75+
return name, jd_match, missing_keywords, profile_summary, reason
76+
except (json.JSONDecodeError, IndexError) as e:
77+
st.error(f"Error parsing response: {e}")
78+
return "N/A", "N/A", [], "N/A", "N/A"
79+
80+
81+
# Prompt Template
82+
input_prompt = """
83+
You are a highly advanced and experienced ATS (Application Tracking System) with deep expertise in evaluating resumes in the tech field.
84+
85+
Your task is to:
86+
1. Give a unique name to the candidate
87+
2. Evaluate the resume provided against the given job description (JD).
88+
3. Assign a classification label for the match based on the alignment between the resume and the JD, using the following range:
89+
- "Not Suited" (very low alignment with the JD)
90+
- "Unlikely" (partial alignment but missing key qualifications or skills)
91+
- "Possible" (moderate alignment with some gaps in experience or keywords)
92+
- "Strong" (high alignment with minor gaps)
93+
- "Excellent" (very high alignment with minimal to no gaps)
94+
4. Identify keywords in the job description and list any missing keywords or key competencies essential for the role.
95+
5. Summarize the candidates profile concisely.
96+
6. Clearly explain why the resume is classified as such, including suggestions for improvement if applicable.
97+
98+
Here is the data:
99+
Resume: {text}
100+
Job Description: {jd}
101+
102+
Consider the competitive nature of the job market and ensure high accuracy in your evaluation. Your response MUST and always has to adhere to the following JSON structure:
103+
{{"Name": "name", "JD Match": "classification label", "MissingKeywords": ["list of missing keywords"], "Profile Summary": "concise profile summary", "Reason": "reason for classification with improvement suggestions"}}
104+
"""
105+
106+
def cvEvaluate():
107+
"""
108+
Launches the Streamlit web app, handles user inputs (job descriptions and resumes),
109+
invokes the OCI Gen AI model, and displays the evaluation results.
110+
"""
111+
# Streamlit app
112+
st.title("CV Evaluation (ATS) using Oracle Gen AI")
113+
114+
# Set up the session state for the job description
115+
if "jd" not in st.session_state:
116+
st.session_state["jd"] = ""
117+
118+
st.header("Available Opportunities:")
119+
col1, col2, col3 = st.columns(3)
120+
121+
st.session_state["jd"] = st.text_area("Please provide the job description or select from the below open-opportunities")
122+
# Place buttons in each column
123+
with col1:
124+
if st.button("Human Resources Specialist"):
125+
st.session_state["jd"] = """**Job Title**: Human Resources Specialist
126+
127+
**Company**: XYZ Energy
128+
129+
**Location**: London, UK
130+
131+
**Job Description**:
132+
133+
XYZ Energy is seeking a dedicated and proactive HR Specialist to join our team. In this role, you will support our mission of powering sustainable energy solutions by managing employee relations, recruitment, and organizational development.
134+
135+
**Key Responsibilities**:
136+
137+
- Coordinate end-to-end recruitment for various roles within the energy sector.
138+
- Manage onboarding processes to ensure new hires integrate seamlessly.
139+
- Provide support for employee relations, including conflict resolution and policy interpretation.
140+
- Implement HR initiatives to enhance employee engagement and retention.
141+
- Ensure compliance with employment laws and regulations.
142+
143+
**Qualifications**:
144+
145+
- Bachelor’s degree in Human Resources or related field.
146+
- 2+ years of HR experience, preferably in the energy or utility sector.
147+
- Strong interpersonal and organizational skills.
148+
- Familiarity with HR software and best practices.
149+
150+
Join XYZ Energy and play a key role in fostering a thriving workplace culture that drives our commitment to sustainable energy."""
151+
st.write("Human Resources Specialist role is selected")
152+
with col2:
153+
if st.button("Technical Specialist"):
154+
st.session_state["jd"] = """Job Title: Technical Specialist
155+
156+
Company: XYZ Energy
157+
158+
Location: London, UK
159+
160+
Job Description:
161+
162+
XYZ Energy is seeking a dynamic and skilled Technical Specialist to join our innovative team. In this role, you will contribute to our mission of delivering sustainable energy solutions by leveraging your technical expertise to support and enhance operations, systems, and technology implementations.
163+
164+
Key Responsibilities:
165+
166+
Provide technical support for the implementation, maintenance, and optimization of energy systems and technologies.
167+
Collaborate with cross-functional teams to identify and address technical challenges in energy projects.
168+
Analyze system performance data to identify areas for improvement and recommend solutions.
169+
Manage the integration of new technologies into existing operations, ensuring minimal disruption.
170+
Support troubleshooting efforts, resolve technical issues, and deliver expert guidance to internal and external stakeholders.
171+
Stay updated on emerging technologies and industry trends to maintain XYZ Energy's competitive edge.
172+
Qualifications:
173+
174+
Bachelor’s degree in Engineering, Computer Science, or a related technical field.
175+
3+ years of experience in a technical role, preferably within the energy or utilities sector.
176+
Strong analytical and problem-solving skills with the ability to interpret complex technical data.
177+
Hands-on experience with energy systems, software tools, and technical project management.
178+
Excellent communication and collaboration skills to engage with diverse stakeholders.
179+
A passion for sustainability and a commitment to supporting XYZ Energy's vision for a greener future.
180+
Join XYZ Energy and help us drive innovation in the energy industry as we work together to power a more sustainable tomorrow."""
181+
st.write("Technical Specialist role is selected")
182+
with col3:
183+
if st.button("Customer Support Agent"):
184+
st.session_state["jd"] = """"Job Title: Customer Support Agent
185+
186+
Company: XYZ Energy
187+
188+
Location: London, UK
189+
190+
Job Description:
191+
192+
XYZ Energy is looking for a friendly and proactive Customer Support Agent to join our team. In this role, you will be the first point of contact for our customers, providing exceptional support and ensuring a seamless customer experience as we deliver sustainable energy solutions.
193+
194+
Key Responsibilities:
195+
196+
Respond to customer inquiries via phone, email, and chat, providing timely and accurate information.
197+
Resolve customer issues, including billing, service requests, and technical concerns, with professionalism and efficiency.
198+
Guide customers through the onboarding process and educate them about our energy solutions and services.
199+
Maintain detailed records of customer interactions and escalate complex issues to the appropriate teams.
200+
Collaborate with internal departments to ensure customer needs are met promptly and effectively.
201+
Continuously seek feedback to improve the customer support experience and processes.
202+
Qualifications:
203+
204+
High school diploma or equivalent; a bachelor’s degree is a plus.
205+
1+ years of experience in a customer support or service role, ideally in the energy or utility sector.
206+
Strong communication and interpersonal skills with a customer-first attitude.
207+
Ability to handle challenging situations with empathy and problem-solving skills.
208+
Proficiency in CRM systems and standard office software.
209+
A passion for sustainable energy and a commitment to helping customers achieve their goals.
210+
Join XYZ Energy and be a key player in delivering outstanding service to our customers while contributing to a greener future."""
211+
st.write("Customer Support agent role is selected")
212+
213+
214+
# Resumes to be analyzed
215+
uploaded_files = st.sidebar.file_uploader("Upload Your Resumes", accept_multiple_files=True, type="pdf", help="Please upload the pdfs")
216+
217+
submit = st.button("Submit")
218+
with st.spinner("Processing. Please wait...."):
219+
if submit:
220+
if uploaded_files:
221+
print(st.session_state["jd"])
222+
for uploaded_file in uploaded_files:
223+
if uploaded_file is not None:
224+
resume_text = input_pdf_text(uploaded_file)
225+
resume_name = os.path.splitext(uploaded_file.name)[0] # Use file name without extension as candidate name
226+
formatted_prompt = input_prompt.format(text=resume_text, jd=st.session_state["jd"])
227+
response = llm.invoke(formatted_prompt)
228+
229+
print(response)
230+
231+
name, jd_match, missing_keywords, profile_summary, reason = parse_response(response)
232+
233+
# Determine selection status
234+
if jd_match != "N/A" and jd_match in ['Excellent', 'Strong', 'Possible']:
235+
status = "Selected"
236+
status_color = "green"
237+
else:
238+
status = "Rejected"
239+
status_color = "red"
240+
241+
# Display the result
242+
st.markdown(f"## <span style='color:cadetblue'>{name}'s Resume</span> File ({resume_name})", unsafe_allow_html=True)
243+
st.markdown(f"**<span style='color:Orange'>JD Match:</span>** {jd_match}", unsafe_allow_html=True)
244+
st.markdown(f"**Status:** <span style='color:{status_color}'>{status}</span>", unsafe_allow_html=True)
245+
246+
# Create a collapsible section for additional details
247+
with st.expander("View More Details"):
248+
st.markdown(f"**<span style='color:cadetblue'>Profile Summary:</span>** {profile_summary}", unsafe_allow_html=True)
249+
st.markdown(f"**<span style='color:cadetblue'>Missing Keywords:</span>** {', '.join(missing_keywords) if missing_keywords else 'None'}", unsafe_allow_html=True)
250+
st.markdown(f"**<span style='color:cadetblue'>Reason:</span>** {reason}", unsafe_allow_html=True)
251+
else:
252+
st.error("Please provide both the job description and resumes for matching.")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
streamlit
2+
PyPDF2
3+
langchain-community
4+
oci

0 commit comments

Comments
 (0)