-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
112 lines (76 loc) · 3.03 KB
/
Copy pathapp.py
File metadata and controls
112 lines (76 loc) · 3.03 KB
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
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
from src.preprocessing import clean_text
from src.embeddings import get_embedding
from src.skill_extractor import extract_skills
from src.ranking import rank_resumes
from src.explain import categorize_score, generate_explanation
from src.pdf_parser import extract_text_from_pdf
st.set_page_config(page_title="Resume Matcher", layout="wide")
st.title("Resume Matching System")
jd_input = st.text_area("Paste Job Description")
uploaded_files = st.file_uploader(
"Upload Resume Files (.txt or .pdf)(add multiple peoples files for comparison)",
accept_multiple_files=True,
type=["txt", "pdf"]
)
if st.button("Match Candidates"):
if not jd_input or not uploaded_files:
st.warning("Please provide JD and upload resumes.")
st.stop()
jd_clean = clean_text(jd_input)
jd_embedding = get_embedding(jd_clean)
jd_skills = extract_skills(jd_input)
resume_data = []
for file in uploaded_files:
if file.type == "application/pdf":
file.seek(0)
text = extract_text_from_pdf(file)
else:
text = file.read().decode("utf-8", errors="ignore")
if not text.strip():
continue
cleaned = clean_text(text)
embedding = get_embedding(cleaned)
skills = extract_skills(text)
resume_data.append({
"name": file.name,
"embedding": embedding,
"skills": skills
})
ranked = rank_resumes(resume_data, jd_embedding, jd_skills)
if not ranked:
st.warning("No valid resumes processed.")
st.stop()
df = pd.DataFrame(ranked)
st.subheader("Summary Metrics")
col1, col2, col3 = st.columns(3)
col1.metric("Total Candidates", len(df))
col2.metric("Top Score", round(df.iloc[0]["final_score"], 3))
col3.metric("Average Score", round(df["final_score"].mean(), 3))
st.markdown("---")
st.subheader("Ranked Candidates")
display_df = df[["name", "final_score", "semantic_score", "skill_score"]]
st.dataframe(display_df)
st.subheader("Candidate Score Comparison")
fig, ax = plt.subplots()
ax.bar(df["name"], df["final_score"])
ax.set_ylabel("Final Score")
ax.set_xticklabels(df["name"], rotation=45, ha="right")
st.pyplot(fig)
st.markdown("---")
st.subheader("Candidate Breakdown")
for candidate in ranked:
explanation = generate_explanation(
candidate["skills"],
jd_skills
)
category = categorize_score(candidate["final_score"])
with st.expander(candidate["name"]):
st.write(f"Final Score: {round(candidate['final_score'], 3)}")
st.write(f"Semantic Score: {round(candidate['semantic_score'], 3)}")
st.write(f"Skill Overlap Score: {round(candidate['skill_score'], 3)}")
st.write(f"Category: {category}")
st.write("Matched Skills:", explanation["matched_skills"])
st.write("Missing Skills:", explanation["missing_skills"])