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.")