Agentic-ATS / src /streamlit_app.py
Rustamshry's picture
Update src/streamlit_app.py
bbd1ea1 verified
import streamlit as st
from resume_parsing import parse_resume_with_llm
from database_integration import save_candidate, save_job, delete_candidate, delete_job, session, Candidate, Job
from chroma_utils import add_to_job_chroma, get_all_jobs_from_chroma, delete_resume_from_chroma, delete_job_from_chroma
from embedding_utils import generate_embedding
from job_matching import calculate_ats_score
import pandas as pd
import numpy as np
import os
os.environ["HF_HOME"] = "/tmp/huggingface"
os.environ["TRANSFORMERS_CACHE"] = "/tmp/huggingface"
os.environ["SENTENCE_TRANSFORMERS_HOME"] = "/tmp/huggingface"
os.environ["STREAMLIT_SERVER_FILE_WATCHER_TYPE"] = "none"
st.set_page_config(page_title="ATS System", layout="wide")
st.title("๐Ÿ“„ ATS System Dashboard")
tabs = st.tabs(["Upload Resume", "Post Job", "Match Candidates", "Delete Resume/Job"])
# ---------------- Upload Resume ---------------- #
with tabs[0]:
st.header("Upload Candidate Resume")
name = st.text_input("Candidate Name")
location = st.text_input("Location")
uploaded_file = st.file_uploader("Upload PDF/DOCX Resume", type=["pdf", "docx"])
if st.button("Submit Resume"):
if not uploaded_file:
st.error("Please upload a resume file.")
elif not name or not location:
st.error("Please provide both name and location.")
else:
file_type = uploaded_file.name.split(".")[-1]
resume_content = uploaded_file.read()
result, embedding = parse_resume_with_llm(resume_content, name, location, file_type)
if "error" in result:
st.error(result["error"])
else:
save_candidate({
"name": name,
"location": location,
"experience": result.get("experience"),
"education": result.get("education"),
"skills": result.get("skills")
}, result["unique_id"])
st.success(f"Resume uploaded successfully! Candidate ID: {result['unique_id']}")
# ---------------- Post Job ---------------- #
with tabs[1]:
st.header("Post a New Job")
job_title = st.text_input("Job Title", key="job_title")
job_description = st.text_area("Job Description", key="job_description")
if st.button("Post Job"):
if not job_title or not job_description:
st.error("Both job title and description are required.")
else:
job_embedding = generate_embedding(job_description)
metadata = {"title": job_title, "description": job_description}
unique_id = add_to_job_chroma(job_embedding, metadata)
save_job(job_title, job_description, unique_id)
st.success(f"Job posted successfully! Job ID: {unique_id}")
# ---------------- Match Candidates ---------------- #
with tabs[2]:
st.header("Match Candidates for All Jobs")
if st.button("Run Matching"):
job_ids, job_embeddings, job_metadatas = get_all_jobs_from_chroma()
if not job_ids:
st.warning("No jobs found in database.")
else:
all_results = []
for i, job_embedding in enumerate(job_embeddings):
job_embedding = np.array(job_embedding)
matched_candidates = calculate_ats_score(job_embedding)
for candidate in matched_candidates:
all_results.append({
"Job ID": job_ids[i],
"Job Title": job_metadatas[i].get("title"),
"Candidate ID": candidate["candidate_id"],
"Candidate Name": candidate["metadata"]["name"],
"Score": round(candidate["score"], 3)
})
if all_results:
df = pd.DataFrame(all_results)
st.dataframe(df)
else:
st.info("No candidates matched any jobs yet.")
# ---------------- Delete Resume/Job ---------------- #
with tabs[3]:
st.header("Delete Resume or Job")
delete_option = st.radio("Select Type to Delete", ["Resume", "Job"])
unique_id = st.text_input("Enter Unique ID to Delete")
if st.button("Delete"):
if not unique_id:
st.error("Please provide a unique ID.")
else:
if delete_option == "Resume":
delete_resume_from_chroma(unique_id)
success = delete_candidate(unique_id)
if success:
st.success(f"Resume {unique_id} deleted successfully!")
else:
st.warning("Resume not found.")
elif delete_option == "Job":
delete_job_from_chroma(unique_id)
success = delete_job(unique_id)
if success:
st.success(f"Job {unique_id} deleted successfully!")
else:
st.warning("Job not found.")