Spaces:
Sleeping
Sleeping
Commit
·
a101471
1
Parent(s):
5c6c5b0
Upload 7 files
Browse files- app.py +34 -0
- application_dev.db +0 -0
- llm.py +68 -0
- models.py +86 -0
- pages/Careers.py +259 -0
- pages/Employee.py +324 -0
- requirements.txt +6 -0
app.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from sqlalchemy.orm import Session
|
| 3 |
+
from sqlalchemy import select
|
| 4 |
+
|
| 5 |
+
from models import Job, ENGINE
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def post_jobs() -> None:
|
| 9 |
+
with Session(ENGINE) as session:
|
| 10 |
+
stmt = select(Job)
|
| 11 |
+
jobs = session.scalars(stmt).all()
|
| 12 |
+
if jobs:
|
| 13 |
+
st.markdown("""<h1 style="font-family: Garamond;text-indent: 20px;color:#008DFE;">Submit your job applications today!</h1>""",unsafe_allow_html=True)
|
| 14 |
+
st.caption(f"""<p style="color:red;">Create your profile and start applying for jobs today. We eagerly anticipate the opportunity to collaborate with you!<p>""",unsafe_allow_html=True)
|
| 15 |
+
else:
|
| 16 |
+
st.caption(f"""<p style="color:red;">There are currently no available job vacancies. Please check back later. We are eagerly anticipating the opportunity to begin working together.<p>""",unsafe_allow_html=True)
|
| 17 |
+
|
| 18 |
+
for job in jobs:
|
| 19 |
+
with st.expander(f"{job.job_id}: {job.post_name}"):
|
| 20 |
+
st.markdown(f"""<p style="font-family:'Garamond'"><b>Description</b>:
|
| 21 |
+
<br>{job.description}<br><br>
|
| 22 |
+
<b>Experience</b>:
|
| 23 |
+
<br>{job.min_experience} - {job.max_experience} year(s)<br><br>
|
| 24 |
+
<b>Responsibilities</b>:
|
| 25 |
+
<br>{job.responsibilities}<br><br>
|
| 26 |
+
<b>Primary Skills</b>:<br>
|
| 27 |
+
{job.primary_skills}</p>""",unsafe_allow_html=True)
|
| 28 |
+
if job.secondary_skills:
|
| 29 |
+
st.markdown(f"""<p style="font-family:'Garamond'"><b>Secondary Skills</b>:
|
| 30 |
+
<br>{job.secondary_skills}</p>""",unsafe_allow_html=True)
|
| 31 |
+
st.markdown(f"""<p style="font-family:'Garamond'"><b>Apply before</b>:
|
| 32 |
+
<br>{job.expires_at}</p>""",unsafe_allow_html=True)
|
| 33 |
+
|
| 34 |
+
post_jobs()
|
application_dev.db
ADDED
|
Binary file (41 kB). View file
|
|
|
llm.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pathlib
|
| 2 |
+
import ast
|
| 3 |
+
import os
|
| 4 |
+
from pypdf import PdfReader
|
| 5 |
+
import docx2txt
|
| 6 |
+
from sqlalchemy import select
|
| 7 |
+
from sqlalchemy.orm import Session
|
| 8 |
+
import openai
|
| 9 |
+
import cohere
|
| 10 |
+
from models import Job, ENGINE
|
| 11 |
+
openai.api_key = os.environ["OPEN_API_KEY"]
|
| 12 |
+
co = cohere.Client(os.environ["COHERE_API_KEY"])
|
| 13 |
+
def gpt(user_query):
|
| 14 |
+
response = openai.Completion.create(
|
| 15 |
+
engine="text-davinci-003",
|
| 16 |
+
prompt = user_query,
|
| 17 |
+
max_tokens=1024,
|
| 18 |
+
n=1,
|
| 19 |
+
stop=None,
|
| 20 |
+
temperature=0.5,
|
| 21 |
+
)
|
| 22 |
+
return response['choices'][0]['text']
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def parse_pdf(file_name):
|
| 26 |
+
reader = PdfReader(file_name)
|
| 27 |
+
page = reader.pages[0]
|
| 28 |
+
resume_text = page.extract_text()
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
return resume_text
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def parse_docx(file_name):
|
| 36 |
+
file_text = docx2txt.process(file_name)
|
| 37 |
+
return file_text
|
| 38 |
+
|
| 39 |
+
# def get_dict(resume_text):
|
| 40 |
+
# resume_dict = ast.literal_eval(gpt(f"""parse the resume and convert it into a Python string with the headings as "experience," "skills," "certifications," and "education".
|
| 41 |
+
|
| 42 |
+
# resume: "{resume_text}"
|
| 43 |
+
# resume_dict: """).strip())
|
| 44 |
+
# return resume_dict
|
| 45 |
+
|
| 46 |
+
def parse(filename):
|
| 47 |
+
resume_file = pathlib.Path(filename)
|
| 48 |
+
text = parse_pdf(resume_file) if resume_file.suffix == ".pdf" else parse_docx(resume_file)
|
| 49 |
+
print("parse"+"~"*10,text)
|
| 50 |
+
# dct = get_dict(text)
|
| 51 |
+
# print(dct)
|
| 52 |
+
return text
|
| 53 |
+
|
| 54 |
+
def rerank(job_id,docs,top_n):
|
| 55 |
+
with Session(ENGINE) as session:
|
| 56 |
+
stmt = select(Job).where(Job.job_id == job_id)
|
| 57 |
+
job = session.scalars(stmt).one()
|
| 58 |
+
|
| 59 |
+
post = job.post_name
|
| 60 |
+
|
| 61 |
+
response = co.rerank(
|
| 62 |
+
model = 'rerank-english-v2.0',
|
| 63 |
+
query = f'Which profile suits most for the role of {post}?',
|
| 64 |
+
documents = docs,
|
| 65 |
+
top_n = top_n,
|
| 66 |
+
)
|
| 67 |
+
print(response)
|
| 68 |
+
return response
|
models.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List
|
| 2 |
+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
| 3 |
+
from sqlalchemy import ForeignKey, create_engine
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
ENGINE = create_engine('sqlite:///application_dev.db')
|
| 7 |
+
|
| 8 |
+
class Base(DeclarativeBase):
|
| 9 |
+
pass
|
| 10 |
+
|
| 11 |
+
class Employee(Base):
|
| 12 |
+
__tablename__ = 'employees'
|
| 13 |
+
employee_id: Mapped[str] = mapped_column(primary_key = True)
|
| 14 |
+
email_id: Mapped[str] = mapped_column(unique = True,nullable = False)
|
| 15 |
+
first_name: Mapped[str] = mapped_column(nullable = True)
|
| 16 |
+
last_name: Mapped[str] = mapped_column(nullable = True)
|
| 17 |
+
password: Mapped[str]
|
| 18 |
+
department: Mapped[str]
|
| 19 |
+
# jobs_posted: Mapped[list["Job"]] = relationship(back_populates="jobs")
|
| 20 |
+
|
| 21 |
+
def __repr__(self):
|
| 22 |
+
return f'Employee({self.employee_id!r},{self.email_id!r},{self.first_name!r},{self.department!r})'
|
| 23 |
+
|
| 24 |
+
@property
|
| 25 |
+
def full_name(self):
|
| 26 |
+
return f'{self.first_name.title()} {self.last_name.title()}'
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class Job(Base):
|
| 30 |
+
__tablename__ = 'jobs'
|
| 31 |
+
job_id :Mapped[str] = mapped_column(primary_key = True)
|
| 32 |
+
employee_id :Mapped[str] #= mapped_column(ForeignKey('employees.employee_id'))
|
| 33 |
+
post_name: Mapped[str] = mapped_column(nullable = False)
|
| 34 |
+
description: Mapped[str] = mapped_column(nullable= False)
|
| 35 |
+
responsibilities: Mapped[str]
|
| 36 |
+
min_experience: Mapped[int] = mapped_column(nullable = False)
|
| 37 |
+
max_experience: Mapped[int] = mapped_column(nullable = False)
|
| 38 |
+
primary_skills: Mapped[str] = mapped_column(nullable = False)
|
| 39 |
+
secondary_skills: Mapped[str] = mapped_column(nullable = True)
|
| 40 |
+
vacancies: Mapped[int] = mapped_column(nullable=False)
|
| 41 |
+
# employee: Mapped["Employee"] = relationship(back_populates="employee")
|
| 42 |
+
# users_applied: Mapped[list["User"]] = relationship(back_populates="users")
|
| 43 |
+
created_at: Mapped[str] = mapped_column(nullable=False)
|
| 44 |
+
expires_at: Mapped[str] = mapped_column(nullable = False)
|
| 45 |
+
|
| 46 |
+
def __repr__(self):
|
| 47 |
+
return f"Job({self.job_id!r},{self.post_name!r},{self.min_experience},{self.max_experience})"
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class User(Base):
|
| 51 |
+
__tablename__ = "users"
|
| 52 |
+
email_id: Mapped[str] = mapped_column(primary_key=True)
|
| 53 |
+
password: Mapped[str] = mapped_column(nullable=False)
|
| 54 |
+
first_name: Mapped[str] = mapped_column(nullable = False)
|
| 55 |
+
last_name: Mapped[str] = mapped_column(nullable = False)
|
| 56 |
+
|
| 57 |
+
def __repr__(self):
|
| 58 |
+
return f'User({self.email_id!r},{self.first_name!r},{self.last_name!r})'
|
| 59 |
+
|
| 60 |
+
@property
|
| 61 |
+
def full_name(self):
|
| 62 |
+
return f'{self.first_name.title()} {self.last_name.title()}'
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class JobsApplied(Base):
|
| 67 |
+
__tablename__ = 'jobs_applied'
|
| 68 |
+
email_id: Mapped[str] = mapped_column(primary_key=True)
|
| 69 |
+
job_id: Mapped[str] = mapped_column(ForeignKey('jobs.job_id'))
|
| 70 |
+
rank: Mapped[int] = mapped_column(nullable=False)
|
| 71 |
+
experience: Mapped[int] = mapped_column(nullable=False)
|
| 72 |
+
round_number: Mapped[int] = mapped_column(nullable=False)
|
| 73 |
+
primary_skills: Mapped[int]
|
| 74 |
+
secondary_skills: Mapped[int]
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def __repr__(self):
|
| 78 |
+
return f'JobsApplied({self.email_id!r},{self.job_id!r},{self.rank},{self.experience},{self.round_number})'
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def __create_tables():
|
| 84 |
+
Base.metadata.create_all(bind = ENGINE)
|
| 85 |
+
|
| 86 |
+
|
pages/Careers.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pathlib
|
| 2 |
+
import re
|
| 3 |
+
from typing import Union
|
| 4 |
+
import os
|
| 5 |
+
import ast
|
| 6 |
+
|
| 7 |
+
import streamlit as st
|
| 8 |
+
import sqlalchemy
|
| 9 |
+
from sqlalchemy.orm import Session
|
| 10 |
+
from sqlalchemy import select
|
| 11 |
+
import openai
|
| 12 |
+
|
| 13 |
+
from models import User, Job, JobsApplied, ENGINE
|
| 14 |
+
from llm import gpt
|
| 15 |
+
|
| 16 |
+
openai.api_key = os.environ['OPEN_API_KEY']
|
| 17 |
+
def clear_cache():
|
| 18 |
+
for k in st.session_state:
|
| 19 |
+
del st.session_state[k]
|
| 20 |
+
|
| 21 |
+
def add_user_to_db():
|
| 22 |
+
col1, col2 = st.columns(2)
|
| 23 |
+
with col1:
|
| 24 |
+
first_name = st.text_input(label = "First Name", placeholder="First Name").title().strip()
|
| 25 |
+
with col2:
|
| 26 |
+
last_name = st.text_input(label = "Last Name", placeholder="last Name").title().strip()
|
| 27 |
+
email_id = st.text_input(label = "Email ID", placeholder = "Enter Email ID").strip()
|
| 28 |
+
new_password = st.text_input(label = "New Password",placeholder="New Password", type = "password").strip()
|
| 29 |
+
confirm_password = st.text_input(label = "Password",placeholder="New Password", type = "password").strip()
|
| 30 |
+
col1, col2, col3 = st.columns(3)
|
| 31 |
+
with col3:
|
| 32 |
+
if st.button("Back", key="Mistake"):
|
| 33 |
+
clear_cache()
|
| 34 |
+
with col1:
|
| 35 |
+
|
| 36 |
+
if st.button("Create Profile"):
|
| 37 |
+
if new_password != confirm_password:
|
| 38 |
+
st.error("Passwords do not match")
|
| 39 |
+
return
|
| 40 |
+
|
| 41 |
+
if not(first_name and last_name and email_id and new_password):
|
| 42 |
+
st.error("No text fields must be blank!")
|
| 43 |
+
return
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
if re.search('^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$',email_id) is None:
|
| 48 |
+
st.error("Invalid Email ID")
|
| 49 |
+
return
|
| 50 |
+
|
| 51 |
+
with Session(ENGINE) as session:
|
| 52 |
+
stmt = select(User).where(User.email_id == email_id)
|
| 53 |
+
result = session.scalars(stmt).one_or_none()
|
| 54 |
+
if result is not None:
|
| 55 |
+
st.error("User already exists!")
|
| 56 |
+
else:
|
| 57 |
+
user_object = User(email_id = email_id, password = new_password,
|
| 58 |
+
first_name = first_name, last_name = last_name)
|
| 59 |
+
session.add_all([user_object])
|
| 60 |
+
session.commit()
|
| 61 |
+
st.success("Successfully Created!")
|
| 62 |
+
clear_cache()
|
| 63 |
+
return
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def login() -> None:
|
| 71 |
+
|
| 72 |
+
login_container = st.empty()
|
| 73 |
+
with login_container.container():
|
| 74 |
+
email_id = st.text_input(label=":email: Email ID", placeholder = "Email ID").lower().strip()
|
| 75 |
+
password = st.text_input(label = ":lock: Password", placeholder = "Password", type = "password")
|
| 76 |
+
col1, col2,col3,col4, = st.columns(4)
|
| 77 |
+
with col4:
|
| 78 |
+
if st.button("Sign Up"):
|
| 79 |
+
st.session_state['sign_up_clicked'] = True
|
| 80 |
+
|
| 81 |
+
with col1:
|
| 82 |
+
sign_in = st.button("Sign In")
|
| 83 |
+
if sign_in:
|
| 84 |
+
|
| 85 |
+
with Session(ENGINE) as session:
|
| 86 |
+
stmt = select(User).where(User.email_id == email_id).where(User.password == password)
|
| 87 |
+
user = session.scalars(stmt).one_or_none()
|
| 88 |
+
if user is None:
|
| 89 |
+
st.error("Invalid email ID/password")
|
| 90 |
+
else:
|
| 91 |
+
st.session_state['user_logged'] = True
|
| 92 |
+
st.session_state['user'] = user
|
| 93 |
+
|
| 94 |
+
if st.session_state['sign_up_clicked']:
|
| 95 |
+
login_container.empty()
|
| 96 |
+
add_user_to_db()
|
| 97 |
+
return
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
if st.session_state['user'] is not None:
|
| 101 |
+
login_container.empty()
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def add_to_db(**job_applied):
|
| 105 |
+
with Session(ENGINE) as session:
|
| 106 |
+
obj = JobsApplied(**job_applied)
|
| 107 |
+
session.add_all([obj])
|
| 108 |
+
|
| 109 |
+
session.commit()
|
| 110 |
+
|
| 111 |
+
def apply_for_jobs():
|
| 112 |
+
|
| 113 |
+
with Session(ENGINE) as session:
|
| 114 |
+
stmt = select(Job)
|
| 115 |
+
jobs = session.scalars(stmt).all()
|
| 116 |
+
job_container = st.empty()
|
| 117 |
+
with job_container.container():
|
| 118 |
+
col1, col2 = st.columns(2)
|
| 119 |
+
with col1:
|
| 120 |
+
job_id = st.selectbox(label="Job ID", options = [job.job_id for job in jobs])
|
| 121 |
+
with col2:
|
| 122 |
+
post_name = st.text_input(label="Post",value = [job.post_name for job in jobs if job.job_id == job_id][-1], disabled=True)
|
| 123 |
+
experience = st.number_input(label = 'Expereince',min_value=0)
|
| 124 |
+
col1, col2 = st.columns(2)
|
| 125 |
+
with col1:
|
| 126 |
+
primary_skills = st.text_input(label="Primary Skills",placeholder="Primary Skills", help="Input your skills delimited by a comma").lower().strip()
|
| 127 |
+
with col2:
|
| 128 |
+
secondary_skills = st.text_input(label="Secondary Skills",placeholder="Secondary Skills", help="Input your skills delimited by a comma").lower().strip()
|
| 129 |
+
|
| 130 |
+
uploded_file = st.file_uploader(label = "Resume Upload", type = ["pdf","docx"])
|
| 131 |
+
|
| 132 |
+
col1, col2 = st.columns(2)
|
| 133 |
+
with col2:
|
| 134 |
+
|
| 135 |
+
if st.button("Apply"):
|
| 136 |
+
st.session_state['applied_for_job'] = True
|
| 137 |
+
|
| 138 |
+
if st.session_state['applied_for_job']:
|
| 139 |
+
if uploded_file is None:
|
| 140 |
+
st.error("No Resume Uploaded")
|
| 141 |
+
return False
|
| 142 |
+
|
| 143 |
+
with Session(ENGINE) as session:
|
| 144 |
+
stmt = select(JobsApplied).where(JobsApplied.email_id == st.session_state['user'].email_id)
|
| 145 |
+
res = session.scalars(stmt).one_or_none()
|
| 146 |
+
if res is not None:
|
| 147 |
+
st.info("You have already applied for job")
|
| 148 |
+
return False
|
| 149 |
+
stmt = select(Job).where(Job.job_id == job_id)
|
| 150 |
+
selected_job = session.scalars(stmt).one()
|
| 151 |
+
|
| 152 |
+
if st.session_state['applied_for_job'] and not(selected_job.min_experience <= experience <= selected_job.max_experience):
|
| 153 |
+
return False
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
resumes_dir = pathlib.Path(f'resumes/{job_id}')
|
| 157 |
+
resumes_dir.mkdir(exist_ok = True)
|
| 158 |
+
resume = resumes_dir / f"{st.session_state['user'].email_id} - {st.session_state['user'].full_name}"
|
| 159 |
+
resume.touch()
|
| 160 |
+
resume.write_bytes(uploded_file.read())
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
add_to_db(**{"email_id": st.session_state["user"].email_id,
|
| 164 |
+
"job_id": job_id, 'experience': experience,
|
| 165 |
+
'primary_skills': primary_skills,
|
| 166 |
+
'secondary_skills':secondary_skills,
|
| 167 |
+
'round_number': 0, 'rank': -1})
|
| 168 |
+
return True
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def jobs_applied():
|
| 173 |
+
with Session(ENGINE) as session:
|
| 174 |
+
stmt = select(JobsApplied).where(JobsApplied.email_id == st.session_state['user'].email_id)
|
| 175 |
+
jobs_applied = session.scalars(stmt).all()
|
| 176 |
+
|
| 177 |
+
if jobs_applied:
|
| 178 |
+
for job_applied in jobs_applied:
|
| 179 |
+
with st.expander(f'Job ID: {job_applied.job_id} Round Number: {job_applied.round_number}'):
|
| 180 |
+
if job_applied.round_number > 0:
|
| 181 |
+
temporary = st.empty()
|
| 182 |
+
with temporary.container():
|
| 183 |
+
get_interview_questions(job_applied.job_id)
|
| 184 |
+
temporary.empty()
|
| 185 |
+
st.markdown(f'<p style="font-family:Garamond">You will be notified about the result</p>',unsafe_allow_html=True)
|
| 186 |
+
|
| 187 |
+
if not(st.session_state['rank']) >= 7:
|
| 188 |
+
with Session(ENGINE) as session:
|
| 189 |
+
session.delete(job_applied)
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def get_interview_questions(job_id):
|
| 197 |
+
with Session(ENGINE) as session:
|
| 198 |
+
stmt = select(Job).where(Job.job_id == job_id.strip())
|
| 199 |
+
job = session.scalars(stmt).one_or_none()
|
| 200 |
+
|
| 201 |
+
if job is not None:
|
| 202 |
+
lst = gpt(f"Generate a set of 10 multiple-choice questions (MCQs) based on the subject of {job.post_name} with experience between {job.min_experience} - {job.max_experience} years.Return it as a list of dictionaries with question as key and optionaand correct answer as kets")
|
| 203 |
+
st.write(f"{lst!r}")
|
| 204 |
+
mcqs = ast.literal_eval(lst.strip())
|
| 205 |
+
rank = 0
|
| 206 |
+
for index, mcq in enumerate(mcqs,start=1):
|
| 207 |
+
question = mcq["question"] if 'question' in mcq.keys() else mcq["Question"]
|
| 208 |
+
options = mcq["options"] if 'options' in mcq.keys() else mcq["Options"]
|
| 209 |
+
correct_answer = mcq["correct_answer"] if 'correct_answer' in mcq.keys() else mcq["Correct Answer"]
|
| 210 |
+
answer = st.radio(f'Q{index} {question}',key=mcq,options=answer)
|
| 211 |
+
if answer.strip() == correct_answer.strip():
|
| 212 |
+
rank += 1
|
| 213 |
+
if st.button('Submit'):
|
| 214 |
+
st.session_state['rank'] = rank
|
| 215 |
+
return st.session_state['rank']
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
if 'sign_up_clicked' not in st.session_state:
|
| 237 |
+
st.session_state['sign_up_clicked'] = False
|
| 238 |
+
if 'user_logged' not in st.session_state:
|
| 239 |
+
st.session_state['user_logged'] = False
|
| 240 |
+
if 'user' not in st.session_state:
|
| 241 |
+
st.session_state['user'] = None
|
| 242 |
+
if 'applied_for_job' not in st.session_state:
|
| 243 |
+
st.session_state['applied_for_job'] = False
|
| 244 |
+
|
| 245 |
+
if 'rank' not in st.session_state:
|
| 246 |
+
st.session_state['rank'] = False
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
login()
|
| 251 |
+
if st.session_state['user_logged']:
|
| 252 |
+
col1, col2 = st.columns(2)
|
| 253 |
+
with col2:
|
| 254 |
+
st.button('Log Out',on_click=clear_cache)
|
| 255 |
+
tab1, tab2= st.tabs(["Apply Jobs","Place Holder"])
|
| 256 |
+
with tab1:
|
| 257 |
+
apply_for_jobs()
|
| 258 |
+
with tab2:
|
| 259 |
+
jobs_applied()
|
pages/Employee.py
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import random
|
| 3 |
+
from datetime import datetime, timedelta
|
| 4 |
+
from typing import Union
|
| 5 |
+
import pathlib
|
| 6 |
+
import smtplib
|
| 7 |
+
from email.message import EmailMessage
|
| 8 |
+
import streamlit as st
|
| 9 |
+
from sqlalchemy.orm import Session
|
| 10 |
+
from sqlalchemy import select
|
| 11 |
+
|
| 12 |
+
from models import Employee, Job , JobsApplied,User, ENGINE
|
| 13 |
+
from llm import parse, rerank
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
st.markdown("""-
|
| 18 |
+
<style>
|
| 19 |
+
|
| 20 |
+
.stButton > button{
|
| 21 |
+
border: black;
|
| 22 |
+
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
|
| 23 |
+
}
|
| 24 |
+
</style>""",unsafe_allow_html=True)
|
| 25 |
+
|
| 26 |
+
def clear_cache():
|
| 27 |
+
for k in st.session_state:
|
| 28 |
+
del st.session_state[k]
|
| 29 |
+
|
| 30 |
+
def login() -> Union[Employee,None]:
|
| 31 |
+
login_container = st.empty()
|
| 32 |
+
with login_container.container():
|
| 33 |
+
employee_id = st.text_input(label=":email: User ID", placeholder = "User ID").upper().strip()
|
| 34 |
+
password = st.text_input(label = ":lock: Password", placeholder = "Password", type = "password")
|
| 35 |
+
button = st.button('Login', type = "secondary")
|
| 36 |
+
|
| 37 |
+
if button:
|
| 38 |
+
if employee_id and password:
|
| 39 |
+
with Session(ENGINE) as session:
|
| 40 |
+
stmt = select(Employee).where(Employee.employee_id == employee_id).\
|
| 41 |
+
where(Employee.password == password)
|
| 42 |
+
employee = session.scalars(stmt).one_or_none()
|
| 43 |
+
print(employee)
|
| 44 |
+
|
| 45 |
+
if employee is None:
|
| 46 |
+
st.error('Invalid UserID/password')
|
| 47 |
+
return
|
| 48 |
+
|
| 49 |
+
st.session_state['employee_logged'] = True
|
| 50 |
+
st.session_state['employee'] = employee
|
| 51 |
+
login_container.empty()
|
| 52 |
+
|
| 53 |
+
return employee
|
| 54 |
+
else:
|
| 55 |
+
st.error('Empty UserID/Password')
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def add_to_db(**job) -> None:
|
| 59 |
+
|
| 60 |
+
job_id = ''.join(chr(random.randint(65,90)) for i in range(5))+f'{random.randint(100,1000)}'
|
| 61 |
+
job['job_id'] = job_id
|
| 62 |
+
job['employee_id'] = st.session_state["employee"].employee_id
|
| 63 |
+
job['created_at'] = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
|
| 64 |
+
job['primary_skills'] = ', '.join(job['primary_skills'])
|
| 65 |
+
job['secondary_skills'] = ', '.join(job['secondary_skills'])
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
with Session(ENGINE) as session:
|
| 69 |
+
job_object = Job(**job)
|
| 70 |
+
session.add_all([job_object])
|
| 71 |
+
session.commit()
|
| 72 |
+
st.success(f"Successfully posted job {job['post_name']}!")
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def add_job() -> None:
|
| 76 |
+
post_name = st.text_input(label = 'Post Name').strip().title()
|
| 77 |
+
description = st.text_area(label = 'Job Description').strip()
|
| 78 |
+
responsibilities = st.text_area(label = "Responsibility").strip()
|
| 79 |
+
vacancies = st.number_input(label="Number Vacancies",min_value=1)
|
| 80 |
+
col1, col2 = st.columns(2)
|
| 81 |
+
with col1:
|
| 82 |
+
min_experience = st.number_input(label = "Minimum Experience",min_value = 0, )
|
| 83 |
+
with col2:
|
| 84 |
+
max_experience = st.number_input(label = "Maximum Experience",min_value = 1, )
|
| 85 |
+
number_of_primary_skills = st.number_input(label = "How many primary skills?",min_value = 1, )
|
| 86 |
+
primary_skills = [st.text_input(label = f'Primary Skill {i}',key=f'Primary Skill {i}').strip() for i in range(1,number_of_primary_skills+1)]
|
| 87 |
+
number_of_secondary_skills = st.number_input(label = "How many secondary skills?",min_value = 0, )
|
| 88 |
+
secondary_skills = [st.text_input(label = f'Secondary Skill {i}',key=f'Secondary Skill {i}').strip() for i in range(1,number_of_secondary_skills+1)]
|
| 89 |
+
st.markdown("Expires at")
|
| 90 |
+
col1, col2 = st.columns(2)
|
| 91 |
+
with col1:
|
| 92 |
+
expires_date = st.date_input(label = "expries date",value =datetime.now() + timedelta(days = 1), min_value = datetime.now() + timedelta(days = 1), max_value=None, label_visibility="collapsed")
|
| 93 |
+
print(expires_date )
|
| 94 |
+
with col2:
|
| 95 |
+
expires_time = st.time_input(label = "Time Input", label_visibility="collapsed")
|
| 96 |
+
print(expires_time)
|
| 97 |
+
expires_at = f'{expires_date.strftime("%d-%m-%Y")} {expires_time.strftime("%H:%M:%S")}'
|
| 98 |
+
st.markdown("<p style='color: red'>⚠️ Check before you submit once submitted you cannot make changes</p>", unsafe_allow_html=True)
|
| 99 |
+
if st.button("Post"):
|
| 100 |
+
if (post_name and description and responsibilities and primary_skills):
|
| 101 |
+
if min_experience <= max_experience:
|
| 102 |
+
job = {
|
| 103 |
+
"post_name" : post_name, 'description': description,'min_experience': min_experience,'max_experience': max_experience,
|
| 104 |
+
'primary_skills': primary_skills, 'secondary_skills': secondary_skills,'responsibilities':responsibilities,
|
| 105 |
+
'expires_at': expires_at, 'vacancies': vacancies
|
| 106 |
+
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
add_to_db(**job)
|
| 111 |
+
return True
|
| 112 |
+
st.error("Minimum Experience must be less than maximum experience")
|
| 113 |
+
return
|
| 114 |
+
st.error("Post Name/Description/Responsibility/Primary SKills are required")
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def post_job():
|
| 119 |
+
st.session_state['employee']
|
| 120 |
+
st.session_state['employee_logged']
|
| 121 |
+
if st.session_state['employee_logged']:
|
| 122 |
+
col1, col2 = st.columns([0.001, 0.01])
|
| 123 |
+
with col2:
|
| 124 |
+
st.markdown(f'Would you like to include a job vacancy listing. {st.session_state["employee"].full_name}?')
|
| 125 |
+
with col1:
|
| 126 |
+
if st.button(':heavy_plus_sign:'):
|
| 127 |
+
st.session_state['add_job'] = True
|
| 128 |
+
|
| 129 |
+
if st.session_state['add_job']:
|
| 130 |
+
add_job_container = st.empty()
|
| 131 |
+
with add_job_container.container():
|
| 132 |
+
is_job_posted = add_job()
|
| 133 |
+
if is_job_posted:
|
| 134 |
+
add_job_container.empty()
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def get_jobs_posted() -> None:
|
| 138 |
+
with Session(ENGINE) as session:
|
| 139 |
+
stmt = select(Job).where(Job.employee_id == st.session_state["employee"].employee_id)
|
| 140 |
+
jobs = session.scalars(stmt).all()
|
| 141 |
+
print(jobs)
|
| 142 |
+
for job in jobs:
|
| 143 |
+
with st.expander(f"{job.job_id}: {job.post_name} posted at: {job.created_at}"):
|
| 144 |
+
pass
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def get_users_who_applied_for_jobs():
|
| 149 |
+
|
| 150 |
+
#Get Jobs Posted
|
| 151 |
+
with Session(ENGINE) as session:
|
| 152 |
+
stmt = select(Job).where(Job.employee_id == st.session_state["employee"].employee_id)
|
| 153 |
+
jobs = session.scalars(stmt).all()
|
| 154 |
+
|
| 155 |
+
if not jobs:
|
| 156 |
+
st.info("No jobs posted!")
|
| 157 |
+
return
|
| 158 |
+
|
| 159 |
+
job_id = st.selectbox("Filter by job_id",options=[job.job_id for job in jobs])
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
with Session(ENGINE) as session:
|
| 164 |
+
stmt = select(JobsApplied).where(JobsApplied.job_id == job_id)
|
| 165 |
+
users_applied_for_jobs = session.scalars(stmt).all()
|
| 166 |
+
|
| 167 |
+
if not users_applied_for_jobs:
|
| 168 |
+
st.info('No users have applied for job')
|
| 169 |
+
return False
|
| 170 |
+
|
| 171 |
+
re_rank_resumes_container = st.empty()
|
| 172 |
+
with re_rank_resumes_container.container():
|
| 173 |
+
st.markdown("""<p style="font-family:Garamond;text-indent: 45vh;font-size:25px">Jobs Application Details</p>""",unsafe_allow_html=True)
|
| 174 |
+
col1, col2 = st.columns([0.001, 0.01])
|
| 175 |
+
with col1:
|
| 176 |
+
round_number = users_applied_for_jobs[0].round_number
|
| 177 |
+
st.markdown(f"""<p style="font-size:20px"><span style = "font-family:Garamond;">Round</span><span style="font-family:monospace;padding: 10px 20px">{round_number}</span></p>""", unsafe_allow_html=True)
|
| 178 |
+
with col2:
|
| 179 |
+
num_docs = st.number_input(label="Top Resumes",min_value=1, max_value=len(users_applied_for_jobs))
|
| 180 |
+
for jobs_application in users_applied_for_jobs:
|
| 181 |
+
st.markdown(f"""<p style="border: 2px solid black;padding: 10px 20px; box-shadow: 10px 10px 5px #aaaaaa"><span style="font-family:Garamond;">User Email ID</span>: <span style="font-family:monospace">{jobs_application.email_id}</span><br><span style="font-family:Garamond">Current Rank: <span style="font-family:monospace">{jobs_application.rank}</span></p>""",unsafe_allow_html=True)
|
| 182 |
+
col1,col2, col3 = st.columns(3)
|
| 183 |
+
with col2:
|
| 184 |
+
if st.button("Rank Resumes"):
|
| 185 |
+
st.session_state['rank_resumes'] = True
|
| 186 |
+
|
| 187 |
+
#Ranking Resumes
|
| 188 |
+
if st.session_state['rank_resumes']:
|
| 189 |
+
re_rank_resumes_container.empty()
|
| 190 |
+
docs = get_docs(users_applied_for_jobs,job_id)
|
| 191 |
+
re_ranked = rerank(job_id,docs,num_docs)
|
| 192 |
+
candidates = [r.document['text'].split('-'*50)[0].strip() for r in re_ranked.results]
|
| 193 |
+
st.markdown(f"<p style='font-family:Garamond;text-indent: 45vh;font-size:25px'>Resumes re-ranked:</p>",unsafe_allow_html=True)
|
| 194 |
+
for candidate in candidates:
|
| 195 |
+
st.markdown(f"""<p style="border: 2px solid black;padding: 10px 20px; box-shadow: 10px 10px 5px #aaaaaa"><span style="font-family:Garamond;">User Email ID</span>: <span style="font-family:monospace">{candidate}</span></p>""",unsafe_allow_html=True)
|
| 196 |
+
col1,col2, col3 = st.columns(3)
|
| 197 |
+
with col2:
|
| 198 |
+
if st.button("Send Emails"):
|
| 199 |
+
st.session_state['send_resumes'] = True
|
| 200 |
+
if st.session_state['send_resumes']:
|
| 201 |
+
add_job_aplication_details(job_id,round_number,candidates)
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def add_job_aplication_details(job_id,round_number,candidates):
|
| 205 |
+
def update(job_application):
|
| 206 |
+
print('----------------------------------------4')
|
| 207 |
+
job_application.round_number += 1
|
| 208 |
+
job_application.rank = job_application.round_number
|
| 209 |
+
return job_application
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
with Session(ENGINE) as session:
|
| 214 |
+
stmt = select(JobsApplied).where(JobsApplied.job_id == job_id).where(JobsApplied.email_id.not_in(candidates))
|
| 215 |
+
jobs = session.scalars(stmt).all()
|
| 216 |
+
for job in jobs:
|
| 217 |
+
session.delete(job)
|
| 218 |
+
session.commit()
|
| 219 |
+
print('deleted')
|
| 220 |
+
with Session(ENGINE) as session:
|
| 221 |
+
stmt = select(JobsApplied).where(JobsApplied.job_id == job_id).where(JobsApplied.email_id.in_(candidates))
|
| 222 |
+
jobs = session.scalars(stmt).all()
|
| 223 |
+
for job in jobs:
|
| 224 |
+
update(job)
|
| 225 |
+
session.commit()
|
| 226 |
+
print('updated')
|
| 227 |
+
sending_emails(job_id, candidates)
|
| 228 |
+
|
| 229 |
+
def sending_emails(job_id, candidates):
|
| 230 |
+
email_message = EmailMessage()
|
| 231 |
+
email_message['From'] = st.session_state['employee'].email_id
|
| 232 |
+
email_message['To'] = candidates
|
| 233 |
+
email_message['Subject'] = f'You are selected for Job ID: {job_id}.'
|
| 234 |
+
email_message.set_content('Hello,\nYou are selected to attend the interview. Please login to your profile and attend.')
|
| 235 |
+
with smtplib.SMTP_SSL('smtp.gmail.com',465) as smtp:
|
| 236 |
+
# st.write(os.environ['EMAIL'])
|
| 237 |
+
smtp.login(st.session_state['employee'].email_id, os.environ['EMAIL'])
|
| 238 |
+
smtp.send_message(email_message)
|
| 239 |
+
st.success(f'⚠️Email Sent SUccessfully')
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def get_docs(jobs_applications,job_id):
|
| 245 |
+
docs = []
|
| 246 |
+
print(f'resumes/{job_id}')
|
| 247 |
+
resumes_dir = pathlib.Path(f'resumes/{job_id}')
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
for resume in resumes_dir.iterdir():
|
| 251 |
+
print(resume)
|
| 252 |
+
parsed_text = parse(resume)
|
| 253 |
+
print(parsed_text)
|
| 254 |
+
print('---------------------------------------------------------------------------')
|
| 255 |
+
email_id = resume.stem.split('-')[0]
|
| 256 |
+
text = f"{email_id}"+'-'*50+parsed_text
|
| 257 |
+
docs.append(text)
|
| 258 |
+
return docs
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
print('Before settings')
|
| 270 |
+
|
| 271 |
+
# Setting Session states
|
| 272 |
+
if 'employee_logged' not in st.session_state:
|
| 273 |
+
st.session_state['employee_logged'] = False
|
| 274 |
+
if 'employee' not in st.session_state:
|
| 275 |
+
st.session_state['employee'] = None
|
| 276 |
+
if 'add_job' not in st.session_state:
|
| 277 |
+
st.session_state['add_job'] = False
|
| 278 |
+
|
| 279 |
+
if 'add_new_skill' not in st.session_state:
|
| 280 |
+
st.session_state['add_new_skill'] = False
|
| 281 |
+
|
| 282 |
+
if 'rank_resumes' not in st.session_state:
|
| 283 |
+
st.session_state['rank_resumes'] = False
|
| 284 |
+
|
| 285 |
+
if 'rank_resumes' not in st.session_state:
|
| 286 |
+
st.session_state['rank_resumes'] = False
|
| 287 |
+
|
| 288 |
+
if 'send_resumes' not in st.session_state:
|
| 289 |
+
st.session_state['send_resumes'] = False
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
print('script start')
|
| 302 |
+
|
| 303 |
+
#Login
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
if not st.session_state['employee_logged']:
|
| 307 |
+
employee = login()
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
if st.session_state['employee_logged']:
|
| 311 |
+
col1, col2 = st.columns(2)
|
| 312 |
+
with col2:
|
| 313 |
+
st.button('Log Out',on_click=clear_cache)
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
tab1, tab2, tab3 = st.tabs(["Post Jobs","Jobs Posted","Get Job Applied Details"])
|
| 317 |
+
with tab1:
|
| 318 |
+
post_job()
|
| 319 |
+
with tab2:
|
| 320 |
+
get_jobs_posted()
|
| 321 |
+
with tab3:
|
| 322 |
+
get_users_who_applied_for_jobs()
|
| 323 |
+
|
| 324 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
streamlit==1.25.0
|
| 2 |
+
sqlalchemy==2.0.19
|
| 3 |
+
cohere
|
| 4 |
+
openai
|
| 5 |
+
pypdf
|
| 6 |
+
docx2txt
|