Rustamshry commited on
Commit
1fa05f6
·
verified ·
1 Parent(s): 6de4c2a

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +107 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,109 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ from resume_parsing import parse_resume_with_llm
3
+ from database_integration import save_candidate, save_job, delete_candidate, delete_job, session, Candidate, Job
4
+ from chroma_utils import add_to_job_chroma, get_all_jobs_from_chroma, delete_resume_from_chroma, delete_job_from_chroma
5
+ from embedding_utils import generate_embedding
6
+ from job_matching import calculate_ats_score
7
+ import pandas as pd
8
+ import numpy as np
9
+
10
+ st.set_page_config(page_title="ATS System", layout="wide")
11
+
12
+ st.title("📄 ATS System Dashboard")
13
+
14
+ tabs = st.tabs(["Upload Resume", "Post Job", "Match Candidates", "Delete Resume/Job"])
15
+
16
+ # ---------------- Upload Resume ---------------- #
17
+ with tabs[0]:
18
+ st.header("Upload Candidate Resume")
19
+ name = st.text_input("Candidate Name")
20
+ location = st.text_input("Location")
21
+ uploaded_file = st.file_uploader("Upload PDF/DOCX Resume", type=["pdf", "docx"])
22
+
23
+ if st.button("Submit Resume"):
24
+ if not uploaded_file:
25
+ st.error("Please upload a resume file.")
26
+ elif not name or not location:
27
+ st.error("Please provide both name and location.")
28
+ else:
29
+ file_type = uploaded_file.name.split(".")[-1]
30
+ resume_content = uploaded_file.read()
31
+ result, embedding = parse_resume_with_llm(resume_content, name, location, file_type)
32
+ if "error" in result:
33
+ st.error(result["error"])
34
+ else:
35
+ save_candidate({
36
+ "name": name,
37
+ "location": location,
38
+ "experience": result.get("experience"),
39
+ "education": result.get("education"),
40
+ "skills": result.get("skills")
41
+ }, result["unique_id"])
42
+ st.success(f"Resume uploaded successfully! Candidate ID: {result['unique_id']}")
43
+
44
+ # ---------------- Post Job ---------------- #
45
+ with tabs[1]:
46
+ st.header("Post a New Job")
47
+ job_title = st.text_input("Job Title", key="job_title")
48
+ job_description = st.text_area("Job Description", key="job_description")
49
+
50
+ if st.button("Post Job"):
51
+ if not job_title or not job_description:
52
+ st.error("Both job title and description are required.")
53
+ else:
54
+ job_embedding = generate_embedding(job_description)
55
+ metadata = {"title": job_title, "description": job_description}
56
+ unique_id = add_to_job_chroma(job_embedding, metadata)
57
+ save_job(job_title, job_description, unique_id)
58
+ st.success(f"Job posted successfully! Job ID: {unique_id}")
59
+
60
+ # ---------------- Match Candidates ---------------- #
61
+ with tabs[2]:
62
+ st.header("Match Candidates for All Jobs")
63
+ if st.button("Run Matching"):
64
+ job_ids, job_embeddings, job_metadatas = get_all_jobs_from_chroma()
65
+ if not job_ids:
66
+ st.warning("No jobs found in database.")
67
+ else:
68
+ all_results = []
69
+ for i, job_embedding in enumerate(job_embeddings):
70
+ job_embedding = np.array(job_embedding)
71
+ matched_candidates = calculate_ats_score(job_embedding)
72
+ for candidate in matched_candidates:
73
+ all_results.append({
74
+ "Job ID": job_ids[i],
75
+ "Job Title": job_metadatas[i].get("title"),
76
+ "Candidate ID": candidate["candidate_id"],
77
+ "Candidate Name": candidate["metadata"]["name"],
78
+ "Score": round(candidate["score"], 3)
79
+ })
80
+ if all_results:
81
+ df = pd.DataFrame(all_results)
82
+ st.dataframe(df)
83
+ else:
84
+ st.info("No candidates matched any jobs yet.")
85
+
86
+ # ---------------- Delete Resume/Job ---------------- #
87
+ with tabs[3]:
88
+ st.header("Delete Resume or Job")
89
+ delete_option = st.radio("Select Type to Delete", ["Resume", "Job"])
90
+ unique_id = st.text_input("Enter Unique ID to Delete")
91
 
92
+ if st.button("Delete"):
93
+ if not unique_id:
94
+ st.error("Please provide a unique ID.")
95
+ else:
96
+ if delete_option == "Resume":
97
+ delete_resume_from_chroma(unique_id)
98
+ success = delete_candidate(unique_id)
99
+ if success:
100
+ st.success(f"Resume {unique_id} deleted successfully!")
101
+ else:
102
+ st.warning("Resume not found.")
103
+ elif delete_option == "Job":
104
+ delete_job_from_chroma(unique_id)
105
+ success = delete_job(unique_id)
106
+ if success:
107
+ st.success(f"Job {unique_id} deleted successfully!")
108
+ else:
109
+ st.warning("Job not found.")