Update app.py
Browse files
app.py
CHANGED
|
@@ -415,6 +415,78 @@ def generate_skill_pie_chart(resumes):
|
|
| 415 |
st.session_state.pie_chart_time = time.time() - start_time
|
| 416 |
return fig
|
| 417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
def main():
|
| 419 |
"""Main function to run the Streamlit app for resume screening."""
|
| 420 |
# Render sidebar
|
|
@@ -525,4 +597,39 @@ def main():
|
|
| 525 |
st.write(f"Total Analyze Time: {st.session_state.total_analyze_time:.2f} seconds")
|
| 526 |
st.write(f"Model Load Time: {getattr(st.session_state, 'load_models_time', 0):.2f} seconds")
|
| 527 |
st.write(f"Tokenize Time: {getattr(st.session_state, 'tokenize_time', 0):.2f} seconds")
|
| 528 |
-
st.write(f"Extract Skills Time:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
st.session_state.pie_chart_time = time.time() - start_time
|
| 416 |
return fig
|
| 417 |
|
| 418 |
+
def render_sidebar():
|
| 419 |
+
"""Render sidebar content."""
|
| 420 |
+
with st.sidebar:
|
| 421 |
+
st.markdown("""
|
| 422 |
+
<h1 style='text-align: center; font-size: 32px; margin-bottom: 10px;'>📄 Resume Screening Assistant for Databricks</h1>
|
| 423 |
+
<p style='text-align: center; font-size: 16px; margin-top: 0;'>
|
| 424 |
+
Welcome to our AI-powered resume screening tool, specialized for data science and tech roles! This app evaluates multiple resumes against a single job description, providing suitability classifications, skill summaries, and a skill frequency visualization.
|
| 425 |
+
</p>
|
| 426 |
+
""", unsafe_allow_html=True)
|
| 427 |
+
|
| 428 |
+
# Persist expander states
|
| 429 |
+
if 'expander1' not in st.session_state:
|
| 430 |
+
st.session_state.expander1 = True
|
| 431 |
+
if 'expander2' not in st.session_state:
|
| 432 |
+
st.session_state.expander2 = False
|
| 433 |
+
if 'expander3' not in st.session_state:
|
| 434 |
+
st.session_state.expander3 = False
|
| 435 |
+
if 'expander4' not in st.session_state:
|
| 436 |
+
st.session_state.expander4 = False
|
| 437 |
+
|
| 438 |
+
with st.expander("How to Use the App", expanded=st.session_state.expander1):
|
| 439 |
+
st.session_state.expander1 = True
|
| 440 |
+
st.markdown("""
|
| 441 |
+
- Enter up to 5 candidate resumes in the text boxes below, listing data/tech skills and experience (e.g., "Expert in python, databricks, 6 years experience").
|
| 442 |
+
- Enter the job description, specifying required skills and experience (e.g., "Data engineer requires python, spark, 5 years+").
|
| 443 |
+
- Click the "Analyze" button to evaluate all non-empty resumes (at least one resume required).
|
| 444 |
+
- Use the "Add Resume" or "Remove Resume" buttons to adjust the number of resume fields (1-5).
|
| 445 |
+
- Use the "Reset" button to clear all inputs and results.
|
| 446 |
+
- Results can be downloaded as a CSV file for record-keeping.
|
| 447 |
+
- View the skill frequency pie chart to see the distribution of skills across resumes.
|
| 448 |
+
""")
|
| 449 |
+
|
| 450 |
+
with st.expander("Example Test Cases", expanded=st.session_state.expander2):
|
| 451 |
+
st.session_state.expander2 = True
|
| 452 |
+
st.markdown("""
|
| 453 |
+
- **Test Case 1**:
|
| 454 |
+
- Resume 1: "Expert in python, machine learning, tableau, 4 years experience"
|
| 455 |
+
- Resume 2: "Skilled in sql, pandas, 2 years experience"
|
| 456 |
+
- Resume 3: "Proficient in java, python, 5 years experience"
|
| 457 |
+
- Job Description: "Data scientist requires python, machine learning, 3 years+"
|
| 458 |
+
- **Test Case 2**:
|
| 459 |
+
- Resume 1: "Skilled in databricks, spark, python, 6 years experience"
|
| 460 |
+
- Resume 2: "Expert in sql, tableau, business intelligence, 3 years experience"
|
| 461 |
+
- Resume 3: "Proficient in rust, langchain, 2 years experience"
|
| 462 |
+
- Job Description: "Data engineer requires python, spark, 5 years+"
|
| 463 |
+
""")
|
| 464 |
+
|
| 465 |
+
with st.expander("Guidelines", expanded=st.session_state.expander3):
|
| 466 |
+
st.session_state.expander3 = True
|
| 467 |
+
st.markdown("""
|
| 468 |
+
- Use comma-separated skills from a comprehensive list including python, sql, databricks, etc. (79 skills supported, see Project Report for full list).
|
| 469 |
+
- Include experience in years (e.g., "3 years experience" or "1 year experience") or as "senior".
|
| 470 |
+
- Focus on data/tech skills for accurate summarization.
|
| 471 |
+
- Resumes with only irrelevant skills (e.g., sales, marketing) will be classified as "Irrelevant".
|
| 472 |
+
""")
|
| 473 |
+
|
| 474 |
+
with st.expander("Classification Criteria", expanded=st.session_state.expander4):
|
| 475 |
+
st.session_state.expander4 = True
|
| 476 |
+
st.markdown("""
|
| 477 |
+
Resumes are classified based on:
|
| 478 |
+
- **Skill Overlap**: The resume's data/tech skills are compared to the job's requirements. A skill overlap below 40% results in an "Irrelevant" classification.
|
| 479 |
+
- **Model Confidence**: A finetuned BERT model evaluates skill relevance. If confidence is below 85%, the classification is "Uncertain".
|
| 480 |
+
- **Experience Match**: The resume's experience (in years or seniority) must meet or exceed the job's requirement.
|
| 481 |
+
|
| 482 |
+
**Outcomes**:
|
| 483 |
+
- **Relevant**: Skill overlap ≥ 50%, sufficient experience, and high model confidence (≥ 85%).
|
| 484 |
+
- **Irrelevant**: Skill overlap < 40% or high confidence in low skill relevance.
|
| 485 |
+
- **Uncertain**: Skill overlap ≥ 50% but experience mismatch (e.g., resume has 2 years, job requires 5 years+), or low model confidence (< 85%).
|
| 486 |
+
|
| 487 |
+
**Note**: An experience mismatch warning is shown if the resume's experience is below the job's requirement, overriding the skill overlap and confidence to classify as Uncertain.
|
| 488 |
+
""")
|
| 489 |
+
|
| 490 |
def main():
|
| 491 |
"""Main function to run the Streamlit app for resume screening."""
|
| 492 |
# Render sidebar
|
|
|
|
| 597 |
st.write(f"Total Analyze Time: {st.session_state.total_analyze_time:.2f} seconds")
|
| 598 |
st.write(f"Model Load Time: {getattr(st.session_state, 'load_models_time', 0):.2f} seconds")
|
| 599 |
st.write(f"Tokenize Time: {getattr(st.session_state, 'tokenize_time', 0):.2f} seconds")
|
| 600 |
+
st.write(f"Extract Skills Time: {getattr(st.session_state, 'extract_skills_time', 0):.2f} seconds")
|
| 601 |
+
if st.session_state.results:
|
| 602 |
+
for idx, result in enumerate(st.session_state.results):
|
| 603 |
+
st.write(f"Inference Time for {result['Resume']}: {result['Inference Time']:.2f} seconds")
|
| 604 |
+
st.write(f"Pie Chart Time: {getattr(st.session_state, 'pie_chart_time', 0):.2f} seconds")
|
| 605 |
+
|
| 606 |
+
# Performance note
|
| 607 |
+
if st.session_state.total_analyze_time > 60:
|
| 608 |
+
st.warning("The runtime is longer than expected due to server load on Hugging Face Spaces. For a smoother experience, consider testing locally or deploying on a different platform (e.g., Streamlit Community Cloud or a personal server).")
|
| 609 |
+
|
| 610 |
+
# Display results
|
| 611 |
+
if st.session_state.results:
|
| 612 |
+
with st.container():
|
| 613 |
+
st.subheader("Results")
|
| 614 |
+
df = pd.DataFrame(st.session_state.results)
|
| 615 |
+
df = df[["Resume", "Suitability", "Data/Tech Related Skills Summary", "Warning"]] # Exclude Inference Time from display
|
| 616 |
+
st.dataframe(df, use_container_width=True)
|
| 617 |
+
|
| 618 |
+
csv = df.to_csv(index=False)
|
| 619 |
+
st.download_button(
|
| 620 |
+
label="Download Results as CSV",
|
| 621 |
+
data=csv,
|
| 622 |
+
file_name="resume_screening_results.csv",
|
| 623 |
+
mime="text/csv",
|
| 624 |
+
)
|
| 625 |
+
|
| 626 |
+
# Display pie chart
|
| 627 |
+
if st.session_state.pie_chart:
|
| 628 |
+
with st.container():
|
| 629 |
+
st.subheader("Skill Frequency Across Resumes")
|
| 630 |
+
st.pyplot(st.session_state.pie_chart)
|
| 631 |
+
elif st.session_state.results and not st.session_state.pie_chart:
|
| 632 |
+
st.warning("No recognized data/tech skills found in the resumes to generate a pie chart.")
|
| 633 |
+
|
| 634 |
+
if __name__ == "__main__":
|
| 635 |
+
main()
|