Spaces:
Sleeping
Sleeping
feat: replace Gradio with Streamlit for better UI presentation
Browse files- Convert app.py to use Streamlit with clean, minimal design
- Add score interpretation with visual feedback (emojis and colors)
- Update README.md configuration for Streamlit SDK
- Update requirements.txt for Streamlit dependencies
- Use
@st
.cache_resource for efficient model loading
π€ Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- README.md +3 -3
- app.py +50 -42
- requirements.txt +1 -1
README.md
CHANGED
@@ -3,8 +3,8 @@ title: Resume Job Matcher
|
|
3 |
emoji: π
|
4 |
colorFrom: blue
|
5 |
colorTo: purple
|
6 |
-
sdk:
|
7 |
-
sdk_version:
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
license: mit
|
@@ -19,7 +19,7 @@ An AI-powered tool that calculates how well a resume matches a job description u
|
|
19 |
- Upload resume files (.txt format)
|
20 |
- Paste job descriptions
|
21 |
- Get similarity scores between resumes and job postings
|
22 |
-
- Built with
|
23 |
- Uses BAAI/bge-large-en-v1.5 model with LoRA fine-tuning
|
24 |
|
25 |
## Usage
|
|
|
3 |
emoji: π
|
4 |
colorFrom: blue
|
5 |
colorTo: purple
|
6 |
+
sdk: streamlit
|
7 |
+
sdk_version: 1.28.1
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
license: mit
|
|
|
19 |
- Upload resume files (.txt format)
|
20 |
- Paste job descriptions
|
21 |
- Get similarity scores between resumes and job postings
|
22 |
+
- Built with Streamlit for clean web interface
|
23 |
- Uses BAAI/bge-large-en-v1.5 model with LoRA fine-tuning
|
24 |
|
25 |
## Usage
|
app.py
CHANGED
@@ -3,7 +3,7 @@ from transformers import AutoModel, AutoTokenizer
|
|
3 |
from peft import PeftModel
|
4 |
import torch
|
5 |
import torch.nn.functional as F
|
6 |
-
import
|
7 |
|
8 |
# --- Configuration ---
|
9 |
logging.basicConfig(level=logging.INFO)
|
@@ -49,47 +49,55 @@ def calculate_match_score(resume_text: str, job_text: str) -> float:
|
|
49 |
return match_score
|
50 |
|
51 |
# --- Initialize Models on Startup ---
|
52 |
-
|
|
|
|
|
|
|
|
|
53 |
|
54 |
-
#
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
with open(resume_file.name, 'r', encoding='utf-8') as f:
|
64 |
-
resume_text = f.read()
|
65 |
-
elif isinstance(resume_file, str):
|
66 |
-
# resume_file is a file path string
|
67 |
-
with open(resume_file, 'r', encoding='utf-8') as f:
|
68 |
-
resume_text = f.read()
|
69 |
-
else:
|
70 |
-
# Try to decode if it's bytes
|
71 |
-
resume_text = resume_file.decode("utf-8")
|
72 |
-
|
73 |
-
score = calculate_match_score(resume_text, job_description)
|
74 |
-
return f"Match Score: {score:.4f}"
|
75 |
-
except ValueError as e:
|
76 |
-
return f"Error: {e}"
|
77 |
-
except Exception as e:
|
78 |
-
logger.error(f"Gradio Error: {e}")
|
79 |
-
return "An unexpected error occurred. Please check the logs."
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
inputs=[
|
84 |
-
gr.File(label="Upload Resume (.txt)"),
|
85 |
-
gr.Textbox(lines=10, label="Job Description", placeholder="Paste the job description here...")
|
86 |
-
],
|
87 |
-
outputs=gr.Textbox(label="Result"),
|
88 |
-
title="π Resume to Job Matcher",
|
89 |
-
description="Find out how well a resume matches a job description. Upload a resume file and paste the job details below.",
|
90 |
-
allow_flagging="never"
|
91 |
-
)
|
92 |
|
93 |
-
#
|
94 |
-
if
|
95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
from peft import PeftModel
|
4 |
import torch
|
5 |
import torch.nn.functional as F
|
6 |
+
import streamlit as st
|
7 |
|
8 |
# --- Configuration ---
|
9 |
logging.basicConfig(level=logging.INFO)
|
|
|
49 |
return match_score
|
50 |
|
51 |
# --- Initialize Models on Startup ---
|
52 |
+
@st.cache_resource
|
53 |
+
def load_models():
|
54 |
+
"""Load models with Streamlit caching."""
|
55 |
+
load_model_artifacts()
|
56 |
+
return models
|
57 |
|
58 |
+
# Load models
|
59 |
+
models_cache = load_models()
|
60 |
+
|
61 |
+
# --- Streamlit App ---
|
62 |
+
st.title("π Resume to Job Matcher")
|
63 |
+
st.write("Find out how well a resume matches a job description. Upload a resume file and paste the job details below.")
|
64 |
+
|
65 |
+
# File upload
|
66 |
+
uploaded_file = st.file_uploader("Upload Resume (.txt)", type=['txt'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
+
# Job description input
|
69 |
+
job_description = st.text_area("Job Description", placeholder="Paste the job description here...", height=200)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
+
# Submit button
|
72 |
+
if st.button("Submit"):
|
73 |
+
if uploaded_file is not None and job_description.strip():
|
74 |
+
try:
|
75 |
+
# Read the uploaded file
|
76 |
+
resume_text = str(uploaded_file.read(), "utf-8")
|
77 |
+
|
78 |
+
# Calculate match score
|
79 |
+
score = calculate_match_score(resume_text, job_description)
|
80 |
+
|
81 |
+
# Display result
|
82 |
+
st.success(f"Match Score: {score:.4f}")
|
83 |
+
|
84 |
+
# Show interpretation
|
85 |
+
if score >= 0.7:
|
86 |
+
st.info("π― Excellent match! Your resume aligns very well with this job.")
|
87 |
+
elif score >= 0.5:
|
88 |
+
st.info("β
Good match! There's solid compatibility between your resume and this job.")
|
89 |
+
elif score >= 0.3:
|
90 |
+
st.warning("β οΈ Moderate match. Consider highlighting relevant skills more prominently.")
|
91 |
+
else:
|
92 |
+
st.error("β Poor match. This job may not align well with your current profile.")
|
93 |
+
|
94 |
+
except ValueError as e:
|
95 |
+
st.error(f"Error: {e}")
|
96 |
+
except Exception as e:
|
97 |
+
logger.error(f"Streamlit Error: {e}")
|
98 |
+
st.error("An unexpected error occurred. Please check your inputs and try again.")
|
99 |
+
else:
|
100 |
+
if uploaded_file is None:
|
101 |
+
st.error("Please upload a resume file.")
|
102 |
+
if not job_description.strip():
|
103 |
+
st.error("Please enter a job description.")
|
requirements.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
transformers>=4.21.0
|
2 |
peft>=0.4.0
|
3 |
torch>=1.12.0
|
4 |
-
|
|
|
1 |
transformers>=4.21.0
|
2 |
peft>=0.4.0
|
3 |
torch>=1.12.0
|
4 |
+
streamlit>=1.28.1
|