|
import pysqlite3 |
|
import sys |
|
sys.modules["sqlite3"] = sys.modules.pop("pysqlite3") |
|
|
|
import streamlit as st |
|
from uuid import uuid4 |
|
from langchain_cohere import CohereEmbeddings |
|
from langchain_chroma import Chroma |
|
from langchain_core.documents import Document |
|
from langchain_cohere import ChatCohere |
|
import random |
|
|
|
|
|
st.set_page_config(page_title="JobFit CV/Resume Matcher πΌ", page_icon="πΌ", layout="wide") |
|
|
|
|
|
def apply_sidebar_colors(): |
|
st.markdown( |
|
""" |
|
<style> |
|
.sidebar .sidebar-content { |
|
background: linear-gradient(45deg, #ff6f61, #ffcc33, #6f9dff, #93f5a3); |
|
color: white; |
|
} |
|
</style> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
apply_sidebar_colors() |
|
|
|
|
|
st.title("πΌ JobFit CV/Resume Matcher") |
|
|
|
|
|
with st.sidebar: |
|
st.header("π Enter Your Details") |
|
|
|
with st.form(key="user_details_form", clear_on_submit=True): |
|
|
|
st.subheader("π Cohere API Key") |
|
st.markdown("You can get your API key from [Cohere's website](https://dashboard.cohere.com/).") |
|
api_key = st.text_input("Enter your Cohere API Key", type="password") |
|
|
|
|
|
st.subheader("π Job Description") |
|
job_description = st.text_area("Paste the Job Description here", placeholder="Enter the job description you're applying for...") |
|
|
|
|
|
if "name" not in st.session_state: |
|
st.session_state["name"] = "" |
|
if "contact" not in st.session_state: |
|
st.session_state["contact"] = "" |
|
|
|
if "user_id" not in st.session_state: |
|
st.session_state["user_id"] = str(random.randint(1000000000, 9999999999)) |
|
|
|
user_id = st.session_state["user_id"] |
|
|
|
|
|
st.subheader("π€ Personal Information") |
|
name = st.text_input("Name", st.session_state["name"], placeholder="Enter your full name...") |
|
contact = st.text_input("Contact Information", st.session_state["contact"], placeholder="Email, phone number, or LinkedIn...") |
|
|
|
st.subheader("πΌ Professional Background") |
|
skills = st.text_area("Skills", placeholder="List your skills (one per line)...") |
|
experience = st.text_area("Experience", placeholder="Work experience details (one per line)...") |
|
education = st.text_area("Education", placeholder="Educational qualifications (one per line)...") |
|
projects = st.text_area("Projects", placeholder="Notable projects (one per line)...") |
|
|
|
submit_button = st.form_submit_button(label="Save Details") |
|
|
|
|
|
if submit_button: |
|
if all([api_key, job_description, name, contact, skills, experience, education, projects]): |
|
st.session_state["api_key"] = api_key |
|
st.session_state["name"] = name |
|
st.session_state["contact"] = contact |
|
st.session_state["job_description"] = job_description |
|
st.session_state["skills"] = skills |
|
st.session_state["experience"] = experience |
|
st.session_state["education"] = education |
|
st.session_state["projects"] = projects |
|
st.success("β
Details Saved Successfully!") |
|
else: |
|
st.warning("β οΈ Please fill out all fields to proceed.") |
|
|
|
|
|
if "api_key" in st.session_state: |
|
|
|
st.subheader("π οΈ Generate Your Custom Resume") |
|
|
|
|
|
skills_list = st.session_state["skills"].splitlines() |
|
experience_list = st.session_state["experience"].splitlines() |
|
education_list = st.session_state["education"].splitlines() |
|
project_list = st.session_state["projects"].splitlines() |
|
|
|
|
|
embedding_model = CohereEmbeddings(cohere_api_key=st.session_state["api_key"], model="embed-english-light-v3.0") |
|
vector_store = Chroma(collection_name="user_data", embedding_function=embedding_model, persist_directory="chroma") |
|
|
|
|
|
skill_documents = [Document(page_content=skill, metadata={"user_id": user_id, "type": "skill"}, id=str(uuid4())) for skill in skills_list] |
|
experience_documents = [Document(page_content=exp, metadata={"user_id": user_id, "type": "experience"}, id=str(uuid4())) for exp in experience_list] |
|
education_documents = [Document(page_content=edu, metadata={"user_id": user_id, "type": "education"}, id=str(uuid4())) for edu in education_list] |
|
project_documents = [Document(page_content=proj, metadata={"user_id": user_id, "type": "project"}, id=str(uuid4())) for proj in project_list] |
|
|
|
|
|
vector_store.add_documents(skill_documents + experience_documents + education_documents + project_documents) |
|
|
|
|
|
if st.button("π Generate Resume"): |
|
def remove_duplicates(results): |
|
seen = set() |
|
unique_results = [] |
|
for result in results: |
|
if result.page_content not in seen: |
|
unique_results.append(result) |
|
seen.add(result.page_content) |
|
return unique_results |
|
|
|
|
|
relevant_skills = vector_store.similarity_search_by_vector(embedding_model.embed_query(st.session_state["job_description"]), k=10, filter={"type": "skill"}) |
|
relevant_experience = vector_store.similarity_search_by_vector(embedding_model.embed_query(st.session_state["job_description"]), k=4, filter={"type": "experience"}) |
|
relevant_education = vector_store.similarity_search_by_vector(embedding_model.embed_query(st.session_state["job_description"]), k=4, filter={"type": "education"}) |
|
relevant_projects = vector_store.similarity_search_by_vector(embedding_model.embed_query(st.session_state["job_description"]), k=4, filter={"type": "project"}) |
|
|
|
|
|
skills_content = "\n".join([doc.page_content for doc in remove_duplicates(relevant_skills)]) |
|
experience_content = "\n".join([doc.page_content for doc in remove_duplicates(relevant_experience)]) |
|
education_content = "\n".join([doc.page_content for doc in remove_duplicates(relevant_education)]) |
|
projects_content = "\n".join([doc.page_content for doc in remove_duplicates(relevant_projects)]) |
|
|
|
|
|
system_prompt = f""" |
|
Generate a well-structured resume for {st.session_state['name']} with the following details: |
|
|
|
Job Description: {st.session_state['job_description']} |
|
Name: {st.session_state['name']} |
|
Contact: {st.session_state['contact']} |
|
Skills: {skills_content} |
|
Experience: {experience_content} |
|
Education: {education_content} |
|
Projects: {projects_content} |
|
|
|
Follow this structure: |
|
- Name and contact at the top. |
|
- Skills, experience, education, and projects listed clearly. |
|
- Use bullet points and headings where needed. |
|
""" |
|
|
|
|
|
chat_model = ChatCohere(cohere_api_key=st.session_state["api_key"]) |
|
|
|
|
|
resume_output = chat_model.invoke(input=system_prompt) |
|
|
|
|
|
st.subheader("π Generated Resume") |
|
st.text_area("Your Resume", resume_output.content, height=400) |
|
st.button("π Copy Resume to Clipboard") |
|
else: |
|
st.info("π Please enter your details and click Save to generate your resume.") |