OptiHire / app.py
AdithyaSNair's picture
Update app.py
d4ec820 verified
raw
history blame
38.4 kB
# app.py
import streamlit as st
from streamlit_option_menu import option_menu
from langchain_groq import ChatGroq
import fitz # PyMuPDF
import requests
from bs4 import BeautifulSoup
import plotly.express as px
import re
import pandas as pd
import sqlite3
from datetime import datetime, timedelta
GROQ_API_KEY = "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"
RAPIDAPI_KEY = "2a4a8a38a9msh97ce530a89589a6p1d0106jsn1acc0a5ea6bc"
llm = ChatGroq(
temperature=0,
groq_api_key=GROQ_API_KEY,
model_name="llama-3.1-70b-versatile"
)
def extract_text_from_pdf(pdf_file):
"""
Extracts text from an uploaded PDF file.
"""
text = ""
try:
with fitz.open(stream=pdf_file.read(), filetype="pdf") as doc:
for page in doc:
text += page.get_text()
return text
except Exception as e:
st.error(f"Error extracting text from PDF: {e}")
return ""
def extract_job_description(job_link):
"""
Fetches and extracts job description text from a given URL.
"""
try:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}
response = requests.get(job_link, headers=headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# You might need to adjust the selectors based on the website's structure
job_description = soup.get_text(separator='\n')
return job_description.strip()
except Exception as e:
st.error(f"Error fetching job description: {e}")
return ""
def extract_requirements(job_description):
"""
Uses Groq to extract job requirements from the job description.
"""
prompt = f"""
The following is a job description:
{job_description}
Extract the list of job requirements, qualifications, and skills from the job description. Provide them as a numbered list.
Requirements:
"""
try:
response = llm.invoke(prompt)
requirements = response.content.strip()
return requirements
except Exception as e:
st.error(f"Error extracting requirements: {e}")
return ""
def generate_email(job_description, requirements, resume_text):
"""
Generates a personalized cold email using Groq based on the job description, requirements, and resume.
"""
prompt = f"""
You are Adithya S Nair, a recent Computer Science graduate specializing in Artificial Intelligence and Machine Learning. Craft a concise and professional cold email to a potential employer based on the following information:
**Job Description:**
{job_description}
**Extracted Requirements:**
{requirements}
**Your Resume:**
{resume_text}
**Email Requirements:**
- **Introduction:** Briefly introduce yourself and mention the specific job you are applying for.
- **Body:** Highlight your relevant skills, projects, internships, and leadership experiences that align with the job requirements.
- **Value Proposition:** Explain how your fresh perspective and recent academic knowledge can add value to the company.
- **Closing:** Express enthusiasm for the opportunity, mention your willingness for an interview, and thank the recipient for their time.
**Email:**
"""
try:
response = llm.invoke(prompt)
email_text = response.content.strip()
return email_text
except Exception as e:
st.error(f"Error generating email: {e}")
return ""
def generate_cover_letter(job_description, requirements, resume_text):
"""
Generates a personalized cover letter using Groq based on the job description, requirements, and resume.
"""
prompt = f"""
You are Adithya S Nair, a recent Computer Science graduate specializing in Artificial Intelligence and Machine Learning. Compose a personalized and professional cover letter based on the following information:
**Job Description:**
{job_description}
**Extracted Requirements:**
{requirements}
**Your Resume:**
{resume_text}
**Cover Letter Requirements:**
1. **Greeting:** Address the hiring manager by name if available; otherwise, use a generic greeting such as "Dear Hiring Manager."
2. **Introduction:** Begin with an engaging opening that mentions the specific position you are applying for and conveys your enthusiasm.
3. **Body:**
- **Skills and Experiences:** Highlight relevant technical skills, projects, internships, and leadership roles that align with the job requirements.
- **Alignment:** Demonstrate how your academic background and hands-on experiences make you a suitable candidate for the role.
4. **Value Proposition:** Explain how your fresh perspective, recent academic knowledge, and eagerness to learn can contribute to the company's success.
5. **Conclusion:** End with a strong closing statement expressing your interest in an interview, your availability, and gratitude for the hiring manager’s time and consideration.
6. **Professional Tone:** Maintain a respectful and professional tone throughout the letter.
**Cover Letter:**
"""
try:
response = llm.invoke(prompt)
cover_letter = response.content.strip()
return cover_letter
except Exception as e:
st.error(f"Error generating cover letter: {e}")
return ""
def extract_skills(text):
"""
Extracts a list of skills from the resume text using Groq.
"""
prompt = f"""
Extract a comprehensive list of technical and soft skills from the following resume text. Provide the skills as a comma-separated list.
Resume Text:
{text}
Skills:
"""
try:
response = llm.invoke(prompt)
skills = response.content.strip()
# Clean and split the skills
skills_list = [skill.strip() for skill in re.split(',|\n', skills) if skill.strip()]
return skills_list
except Exception as e:
st.error(f"Error extracting skills: {e}")
return []
def suggest_keywords(resume_text, job_description=None):
"""
Suggests additional relevant keywords to enhance resume compatibility with ATS.
"""
prompt = f"""
Analyze the following resume text and suggest additional relevant keywords that can enhance its compatibility with Applicant Tracking Systems (ATS). If a job description is provided, tailor the keywords to align with the job requirements.
Resume Text:
{resume_text}
Job Description:
{job_description if job_description else "N/A"}
Suggested Keywords:
"""
try:
response = llm.invoke(prompt)
keywords = response.content.strip()
keywords_list = [keyword.strip() for keyword in re.split(',|\n', keywords) if keyword.strip()]
return keywords_list
except Exception as e:
st.error(f"Error suggesting keywords: {e}")
return []
def get_job_recommendations(job_title, location="India"):
"""
Fetches salary estimates using the JSearch API based on the job title and location.
"""
url = "https://jsearch.p.rapidapi.com/estimated-salary"
querystring = {
"job_title": job_title.strip(),
"location": location.strip(),
"radius": "100" # Adjust radius as needed
}
headers = {
"x-rapidapi-key": RAPIDAPI_KEY, # Embedded API key
"x-rapidapi-host": "jsearch.p.rapidapi.com"
}
try:
response = requests.get(url, headers=headers, params=querystring)
response.raise_for_status()
salary_data = response.json()
# Extract relevant data
min_salary = salary_data.get("min_salary")
avg_salary = salary_data.get("avg_salary")
max_salary = salary_data.get("max_salary")
return {
"min_salary": min_salary,
"avg_salary": avg_salary,
"max_salary": max_salary
}
except requests.exceptions.HTTPError as http_err:
st.error(f"HTTP error occurred: {http_err}")
return {}
except Exception as e:
st.error(f"Error fetching salary data: {e}")
return {}
def create_skill_distribution_chart(skills):
"""
Creates a bar chart showing the distribution of skills.
"""
skill_counts = {}
for skill in skills:
skill_counts[skill] = skill_counts.get(skill, 0) + 1
df = pd.DataFrame(list(skill_counts.items()), columns=['Skill', 'Count'])
fig = px.bar(df, x='Skill', y='Count', title='Skill Distribution')
return fig
def create_experience_timeline(resume_text):
"""
Creates an experience timeline from the resume text.
"""
# Extract work experience details using Groq
prompt = f"""
From the following resume text, extract the job titles, companies, and durations of employment. Provide the information in a table format with columns: Job Title, Company, Duration (in years).
Resume Text:
{resume_text}
Table:
"""
try:
response = llm.invoke(prompt)
table_text = response.content.strip()
# Parse the table_text to create a DataFrame
data = []
for line in table_text.split('\n'):
if line.strip() and not line.lower().startswith("job title"):
parts = line.split('|')
if len(parts) == 3:
job_title = parts[0].strip()
company = parts[1].strip()
duration = parts[2].strip()
# Convert duration to a float representing years
duration_years = parse_duration(duration)
data.append({"Job Title": job_title, "Company": company, "Duration (years)": duration_years})
df = pd.DataFrame(data)
if not df.empty:
# Create a cumulative duration for timeline
df['Start Year'] = df['Duration (years)'].cumsum() - df['Duration (years)']
df['End Year'] = df['Duration (years)'].cumsum()
fig = px.timeline(df, x_start="Start Year", x_end="End Year", y="Job Title", color="Company", title="Experience Timeline")
fig.update_yaxes(categoryorder="total ascending")
return fig
else:
return None
except Exception as e:
st.error(f"Error creating experience timeline: {e}")
return None
def parse_duration(duration_str):
"""
Parses duration strings like '2 years' or '6 months' into float years.
"""
try:
if 'year' in duration_str.lower():
years = float(re.findall(r'\d+\.?\d*', duration_str)[0])
return years
elif 'month' in duration_str.lower():
months = float(re.findall(r'\d+\.?\d*', duration_str)[0])
return months / 12
else:
return 0
except:
return 0
def init_db():
"""
Initializes the SQLite database for application tracking.
"""
conn = sqlite3.connect('applications.db')
c = conn.cursor()
c.execute('''
CREATE TABLE IF NOT EXISTS applications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_title TEXT,
company TEXT,
application_date TEXT,
status TEXT,
deadline TEXT,
notes TEXT,
job_description TEXT,
resume_text TEXT,
skills TEXT
)
''')
conn.commit()
conn.close()
def add_application(job_title, company, application_date, status, deadline, notes, job_description, resume_text, skills):
"""
Adds a new application to the database.
"""
conn = sqlite3.connect('applications.db')
c = conn.cursor()
c.execute('''
INSERT INTO applications (job_title, company, application_date, status, deadline, notes, job_description, resume_text, skills)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (job_title, company, application_date, status, deadline, notes, job_description, resume_text, ', '.join(skills)))
conn.commit()
conn.close()
def fetch_applications():
"""
Fetches all applications from the database.
"""
conn = sqlite3.connect('applications.db')
c = conn.cursor()
c.execute('SELECT * FROM applications')
data = c.fetchall()
conn.close()
applications = []
for app in data:
applications.append({
"ID": app[0],
"Job Title": app[1],
"Company": app[2],
"Application Date": app[3],
"Status": app[4],
"Deadline": app[5],
"Notes": app[6],
"Job Description": app[7],
"Resume Text": app[8],
"Skills": app[9].split(', ') if app[9] else []
})
return applications
def update_application_status(app_id, new_status):
"""
Updates the status of an application.
"""
conn = sqlite3.connect('applications.db')
c = conn.cursor()
c.execute('UPDATE applications SET status = ? WHERE id = ?', (new_status, app_id))
conn.commit()
conn.close()
def delete_application(app_id):
"""
Deletes an application from the database.
"""
conn = sqlite3.connect('applications.db')
c = conn.cursor()
c.execute('DELETE FROM applications WHERE id = ?', (app_id,))
conn.commit()
conn.close()
def generate_learning_path(career_goal, current_skills):
"""
Generates a personalized learning path using Groq based on career goal and current skills.
"""
prompt = f"""
Based on the following career goal and current skills, create a personalized learning path that includes recommended courses, projects, and milestones to achieve the career goal.
**Career Goal:**
{career_goal}
**Current Skills:**
{current_skills}
**Learning Path:**
"""
try:
response = llm.invoke(prompt)
learning_path = response.content.strip()
return learning_path
except Exception as e:
st.error(f"Error generating learning path: {e}")
return ""
# -------------------------------
# Page Functions
# -------------------------------
def email_generator_page():
st.header("Automated Email Generator")
st.write("""
Generate personalized cold emails based on job postings and your resume.
""")
# Input fields
job_link = st.text_input("Enter the job link:")
uploaded_file = st.file_uploader("Upload your resume (PDF format):", type="pdf")
if st.button("Generate Email"):
if not job_link:
st.error("Please enter a job link.")
return
if not uploaded_file:
st.error("Please upload your resume.")
return
with st.spinner("Processing..."):
# Extract job description
job_description = extract_job_description(job_link)
if not job_description:
st.error("Failed to extract job description.")
return
# Extract requirements
requirements = extract_requirements(job_description)
if not requirements:
st.error("Failed to extract requirements.")
return
# Extract resume text
resume_text = extract_text_from_pdf(uploaded_file)
if not resume_text:
st.error("Failed to extract text from resume.")
return
# Generate email
email_text = generate_email(job_description, requirements, resume_text)
if email_text:
st.subheader("Generated Email:")
st.write(email_text)
# Provide download option
st.download_button(
label="Download Email",
data=email_text,
file_name="generated_email.txt",
mime="text/plain"
)
else:
st.error("Failed to generate email.")
def cover_letter_generator_page():
st.header("Automated Cover Letter Generator")
st.write("""
Generate personalized cover letters based on job postings and your resume.
""")
# Input fields
job_link = st.text_input("Enter the job link:")
uploaded_file = st.file_uploader("Upload your resume (PDF format):", type="pdf")
if st.button("Generate Cover Letter"):
if not job_link:
st.error("Please enter a job link.")
return
if not uploaded_file:
st.error("Please upload your resume.")
return
with st.spinner("Processing..."):
# Extract job description
job_description = extract_job_description(job_link)
if not job_description:
st.error("Failed to extract job description.")
return
# Extract requirements
requirements = extract_requirements(job_description)
if not requirements:
st.error("Failed to extract requirements.")
return
# Extract resume text
resume_text = extract_text_from_pdf(uploaded_file)
if not resume_text:
st.error("Failed to extract text from resume.")
return
# Generate cover letter
cover_letter = generate_cover_letter(job_description, requirements, resume_text)
if cover_letter:
st.subheader("Generated Cover Letter:")
st.write(cover_letter)
# Provide download option
st.download_button(
label="Download Cover Letter",
data=cover_letter,
file_name="generated_cover_letter.txt",
mime="text/plain"
)
else:
st.error("Failed to generate cover letter.")
def resume_analysis_page():
st.header("Resume Analysis and Optimization")
uploaded_file = st.file_uploader("Upload your resume (PDF format):", type="pdf")
if uploaded_file:
resume_text = extract_text_from_pdf(uploaded_file)
if resume_text:
st.success("Resume uploaded successfully!")
# Perform analysis
st.subheader("Extracted Information")
# Extracted skills
skills = extract_skills(resume_text)
st.write("**Skills:**", ', '.join(skills) if skills else "No skills extracted.")
# Extract keywords
keywords = suggest_keywords(resume_text)
st.write("**Suggested Keywords for ATS Optimization:**", ', '.join(keywords) if keywords else "No keywords suggested.")
# Provide optimization suggestions
st.subheader("Optimization Suggestions")
if keywords:
st.write("- **Keyword Optimization:** Incorporate the suggested keywords to improve ATS compatibility.")
else:
st.write("- **Keyword Optimization:** No keywords suggested.")
st.write("- **Formatting:** Ensure consistent formatting for headings and bullet points to enhance readability.")
st.write("- **Experience Details:** Provide specific achievements and quantify your accomplishments where possible.")
# Visual Resume Analytics
st.subheader("Visual Resume Analytics")
# Skill Distribution Chart
if skills:
st.write("**Skill Distribution:**")
fig_skills = create_skill_distribution_chart(skills)
st.plotly_chart(fig_skills)
else:
st.write("**Skill Distribution:** No skills to display.")
# Experience Timeline (if applicable)
fig_experience = create_experience_timeline(resume_text)
if fig_experience:
st.write("**Experience Timeline:**")
st.plotly_chart(fig_experience)
else:
st.write("**Experience Timeline:** Not enough data to generate a timeline.")
# Save the resume and analysis to the database
if st.button("Save Resume Analysis"):
add_application(
job_title="N/A",
company="N/A",
application_date=datetime.now().strftime("%Y-%m-%d"),
status="N/A",
deadline="N/A",
notes="Resume Analysis",
job_description="N/A",
resume_text=resume_text,
skills=skills
)
st.success("Resume analysis saved successfully!")
else:
st.error("Failed to extract text from resume.")
def application_tracking_dashboard():
st.header("Application Tracking Dashboard")
# Initialize database
init_db()
# Form to add a new application
st.subheader("Add New Application")
with st.form("add_application"):
job_title = st.text_input("Job Title")
company = st.text_input("Company")
application_date = st.date_input("Application Date", datetime.today())
status = st.selectbox("Status", ["Applied", "Interviewing", "Offered", "Rejected"])
deadline = st.date_input("Application Deadline", datetime.today() + timedelta(days=30))
notes = st.text_area("Notes")
uploaded_file = st.file_uploader("Upload Job Description (PDF)", type="pdf")
uploaded_resume = st.file_uploader("Upload Resume (PDF)", type="pdf")
submitted = st.form_submit_button("Add Application")
if submitted:
if uploaded_file:
job_description = extract_text_from_pdf(uploaded_file)
else:
job_description = ""
if uploaded_resume:
resume_text = extract_text_from_pdf(uploaded_resume)
skills = extract_skills(resume_text)
else:
resume_text = ""
skills = []
add_application(
job_title=job_title,
company=company,
application_date=application_date.strftime("%Y-%m-%d"),
status=status,
deadline=deadline.strftime("%Y-%m-%d"),
notes=notes,
job_description=job_description,
resume_text=resume_text,
skills=skills
)
st.success("Application added successfully!")
# Display applications
st.subheader("Your Applications")
applications = fetch_applications()
if applications:
df = pd.DataFrame(applications)
df = df.drop(columns=["Job Description", "Resume Text", "Skills"])
st.dataframe(df)
# Actions: Update Status or Delete
for app in applications:
with st.expander(f"{app['Job Title']} at {app['Company']}"):
st.write(f"**Application Date:** {app['Application Date']}")
st.write(f"**Deadline:** {app['Deadline']}")
st.write(f"**Status:** {app['Status']}")
st.write(f"**Notes:** {app['Notes']}")
if app['Job Description']:
st.write("**Job Description:**")
st.write(app['Job Description'][:500] + "...")
if app['Skills']:
st.write("**Skills:**", ', '.join(app['Skills']))
# Update status
new_status = st.selectbox("Update Status:", ["Applied", "Interviewing", "Offered", "Rejected"], key=f"status_{app['ID']}")
if st.button("Update Status", key=f"update_{app['ID']}"):
update_application_status(app['ID'], new_status)
st.success("Status updated successfully!")
# Delete application
if st.button("Delete Application", key=f"delete_{app['ID']}"):
delete_application(app['ID'])
st.success("Application deleted successfully!")
else:
st.write("No applications found.")
def interview_preparation_module():
st.header("Interview Preparation")
st.write("""
Prepare for your interviews with tailored mock questions and expert tips.
""")
# Input fields
job_title = st.text_input("Enter the job title you're applying for:")
company = st.text_input("Enter the company name:")
if st.button("Generate Mock Interview Questions"):
if not job_title or not company:
st.error("Please enter both job title and company name.")
return
with st.spinner("Generating questions..."):
prompt = f"""
Generate a list of 10 interview questions for a {job_title} position at {company}. Include a mix of technical and behavioral questions.
"""
try:
questions = llm.invoke(prompt).content.strip()
st.subheader("Mock Interview Questions:")
st.write(questions)
# Optionally, provide sample answers or tips
if st.checkbox("Show Sample Answers"):
sample_prompt = f"""
Provide sample answers for the following interview questions for a {job_title} position at {company}.
Questions:
{questions}
Sample Answers:
"""
try:
sample_answers = llm.invoke(sample_prompt).content.strip()
st.subheader("Sample Answers:")
st.write(sample_answers)
except Exception as e:
st.error(f"Error generating sample answers: {e}")
except Exception as e:
st.error(f"Error generating interview questions: {e}")
def personalized_learning_paths_module():
st.header("Personalized Learning Paths")
st.write("""
Receive tailored learning plans to help you acquire the skills needed for your desired career.
""")
# Input fields
career_goal = st.text_input("Enter your career goal (e.g., Data Scientist, Machine Learning Engineer):")
current_skills = st.text_input("Enter your current skills (comma-separated):")
if st.button("Generate Learning Path"):
if not career_goal or not current_skills:
st.error("Please enter both career goal and current skills.")
return
with st.spinner("Generating your personalized learning path..."):
learning_path = generate_learning_path(career_goal, current_skills)
if learning_path:
st.subheader("Your Personalized Learning Path:")
st.write(learning_path)
else:
st.error("Failed to generate learning path.")
def networking_opportunities_module():
st.header("Networking Opportunities")
st.write("""
Expand your professional network by connecting with relevant industry peers and joining professional groups.
""")
user_skills = st.text_input("Enter your key skills (comma-separated):")
industry = st.text_input("Enter your industry (e.g., Technology, Finance):")
if st.button("Find Networking Opportunities"):
if not user_skills or not industry:
st.error("Please enter both key skills and industry.")
return
with st.spinner("Fetching networking opportunities..."):
# Suggest LinkedIn groups or connections based on skills and industry
prompt = f"""
Based on the following skills: {user_skills}, and industry: {industry}, suggest relevant LinkedIn groups, professional organizations, and industry events for networking.
"""
try:
suggestions = llm.invoke(prompt).content.strip()
st.subheader("Recommended Networking Groups and Events:")
st.write(suggestions)
except Exception as e:
st.error(f"Error fetching networking opportunities: {e}")
def salary_estimation_module():
st.header("Salary Estimation and Negotiation Tips")
st.write("""
Understand the salary expectations for your desired roles and learn effective negotiation strategies.
""")
# Input fields
job_title = st.text_input("Enter the job title:")
location = st.text_input("Enter the location (e.g., New York, NY, USA):")
if st.button("Get Salary Estimate"):
if not job_title or not location:
st.error("Please enter both job title and location.")
return
with st.spinner("Fetching salary data..."):
# JSearch API Integration
salary_data = get_job_recommendations(job_title, location)
if salary_data:
min_salary = salary_data.get("min_salary")
avg_salary = salary_data.get("avg_salary")
max_salary = salary_data.get("max_salary")
if min_salary and avg_salary and max_salary:
st.subheader("Salary Estimate:")
st.write(f"**Minimum Salary:** ${min_salary:,}")
st.write(f"**Average Salary:** ${avg_salary:,}")
st.write(f"**Maximum Salary:** ${max_salary:,}")
# Visualization
salary_df = pd.DataFrame({
"Salary Range": ["Minimum", "Average", "Maximum"],
"Amount": [min_salary, avg_salary, max_salary]
})
fig = px.bar(salary_df, x="Salary Range", y="Amount",
title=f"Salary Estimates for {job_title} in {location}",
labels={"Amount": "Salary (USD)"},
text_auto=True)
st.plotly_chart(fig)
else:
st.error("Salary data not available for the provided job title and location.")
# Generate negotiation tips using Groq
tips_prompt = f"""
Provide a list of 5 effective tips for negotiating a salary for a {job_title} position in {location}.
"""
try:
tips = llm.invoke(tips_prompt).content.strip()
st.subheader("Negotiation Tips:")
st.write(tips)
except Exception as e:
st.error(f"Error generating negotiation tips: {e}")
else:
st.error("Failed to retrieve salary data.")
def feedback_and_improvement_module():
st.header("Feedback and Continuous Improvement")
st.write("""
We value your feedback! Let us know how we can improve your experience.
""")
with st.form("feedback_form"):
name = st.text_input("Your Name")
email = st.text_input("Your Email")
feedback_type = st.selectbox("Type of Feedback", ["Bug Report", "Feature Request", "General Feedback"])
feedback = st.text_area("Your Feedback")
submitted = st.form_submit_button("Submit")
if submitted:
if not name or not email or not feedback:
st.error("Please fill in all the fields.")
else:
print(f"Feedback from {name} ({email}): {feedback_type} - {feedback}")
st.success("Thank you for your feedback!")
def gamification_module():
st.header("Gamification and Achievements")
st.write("""
Stay motivated by earning badges and tracking your progress!
""")
# Initialize database
init_db()
# Example achievements
applications = fetch_applications()
num_apps = len(applications)
achievements = {
"First Application": num_apps >= 1,
"5 Applications": num_apps >= 5,
"10 Applications": num_apps >= 10,
"Resume Optimized": any(app['Skills'] for app in applications),
"Interview Scheduled": any(app['Status'] == 'Interviewing' for app in applications)
}
for achievement, earned in achievements.items():
if earned:
st.success(f"🎉 {achievement}")
else:
st.info(f"🔜 {achievement}")
# Progress Bar
progress = min(num_apps / 10, 1.0)
st.write("**Overall Progress:**")
st.progress(progress)
st.write(f"{progress * 100:.0f}% complete")
def resource_library_page():
st.header("Resource Library")
st.write("""
Access a collection of templates and guides to enhance your job search.
""")
resources = [
{
"title": "Resume Template",
"description": "A professional resume template in DOCX format.",
"file": "./resume_template.docx"
},
{
"title": "Cover Letter Template",
"description": "A customizable cover letter template.",
"file": "./cover_letter_template.docx"
},
{
"title": "Job Application Checklist",
"description": "Ensure you have all the necessary steps covered during your job search.",
"file": "./application_checklist.pdf"
}
]
for resource in resources:
st.markdown(f"### {resource['title']}")
st.write(resource['description'])
try:
with open(resource['file'], "rb") as file:
btn = st.download_button(
label="Download",
data=file,
file_name=resource['file'],
mime="application/octet-stream"
)
except FileNotFoundError:
st.error(f"File {resource['file']} not found. Please ensure the file is in the correct directory.")
st.write("---")
def success_stories_page():
st.header("Success Stories")
st.write("""
Hear from our users who have successfully landed their dream jobs with our assistance!
""")
# Example testimonials
testimonials = [
{
"name": "Rahul Sharma",
"position": "Data Scientist at TechCorp",
"testimonial": "This app transformed my job search process. The resume analysis and personalized emails were game-changers!",
"image": "images/user1.jpg" # Replace with actual image paths
},
{
"name": "Priya Mehta",
"position": "Machine Learning Engineer at InnovateX",
"testimonial": "The interview preparation module helped me ace my interviews with confidence. Highly recommended!",
"image": "images/user2.jpg"
}
]
for user in testimonials:
col1, col2 = st.columns([1, 3])
with col1:
try:
st.image(user["image"], width=100)
except:
st.write("![User Image](https://via.placeholder.com/100)")
with col2:
st.write(f"**{user['name']}**")
st.write(f"*{user['position']}*")
st.write(f"\"{user['testimonial']}\"")
st.write("---")
def chatbot_support_page():
st.header("AI-Powered Chatbot Support")
st.write("""
Have questions or need assistance? Chat with our AI-powered assistant!
""")
# Initialize session state for chatbot
if 'chat_history' not in st.session_state:
st.session_state['chat_history'] = []
user_input = st.text_input("You:", key="user_input")
if st.button("Send"):
if user_input:
st.session_state['chat_history'].append(f"You: {user_input}")
prompt = f"""
You are a helpful assistant for a Job Application Assistant app. Answer the user's query based on the following context:
{user_input}
"""
try:
response = llm.invoke(prompt).content.strip()
st.session_state['chat_history'].append(f"Assistant: {response}")
except Exception as e:
st.session_state['chat_history'].append(f"Assistant: Sorry, I encountered an error while processing your request.")
st.error(f"Error in chatbot: {e}")
# Display chat history
for message in st.session_state['chat_history']:
if message.startswith("You:"):
st.markdown(f"<p style='color:blue;'>{message}</p>", unsafe_allow_html=True)
else:
st.markdown(f"<p style='color:green;'>{message}</p>", unsafe_allow_html=True)
def main():
st.set_page_config(page_title="Job Application Assistant", layout="wide")
# Initialize database early to ensure tables exist
init_db()
# Sidebar Navigation
with st.sidebar:
selected = option_menu(
"Main Menu",
["Email Generator", "Cover Letter Generator", "Resume Analysis", "Application Tracking",
"Interview Preparation", "Personalized Learning Paths", "Networking Opportunities",
"Salary Estimation", "Feedback", "Gamification", "Resource Library", "Success Stories", "Chatbot Support"],
icons=["envelope", "file-earmark-text", "file-person", "briefcase", "gear",
"book", "people", "currency-dollar", "chat-left-text", "trophy", "collection", "star", "chat"],
menu_icon="cast",
default_index=0,
)
if selected == "Email Generator":
email_generator_page()
elif selected == "Cover Letter Generator":
cover_letter_generator_page()
elif selected == "Resume Analysis":
resume_analysis_page()
elif selected == "Application Tracking":
application_tracking_dashboard()
elif selected == "Interview Preparation":
interview_preparation_module()
elif selected == "Personalized Learning Paths":
personalized_learning_paths_module()
elif selected == "Networking Opportunities":
networking_opportunities_module()
elif selected == "Salary Estimation":
salary_estimation_module()
elif selected == "Feedback":
feedback_and_improvement_module()
elif selected == "Gamification":
gamification_module()
elif selected == "Resource Library":
resource_library_page()
elif selected == "Success Stories":
success_stories_page()
elif selected == "Chatbot Support":
chatbot_support_page()
if __name__ == "__main__":
main()