AdvanceCovRes / app.py
mgbam's picture
Add application file
38c327b
raw
history blame
7.8 kB
# app.py
import os
import io
import json
from datetime import datetime
import streamlit as st
from transformers import pipeline
from docx import Document
from PyPDF2 import PdfReader
# ------------------------------------------------------------------------------
# Model Pipeline Setup
# ------------------------------------------------------------------------------
# Use an instruction-tuned model (e.g., Flan-T5-xl)
model_name = "google/flan-t5-xl"
instruct_pipeline = pipeline(
"text2text-generation", model=model_name, max_length=1024, truncation=True
)
# ------------------------------------------------------------------------------
# Helper Functions for File Reading
# ------------------------------------------------------------------------------
def read_docx(file_bytes: bytes) -> str:
"""Extract text from a DOCX file."""
document = Document(io.BytesIO(file_bytes))
return "\n".join([para.text for para in document.paragraphs])
def read_pdf(file_bytes: bytes) -> str:
"""Extract text from a PDF file."""
reader = PdfReader(io.BytesIO(file_bytes))
text = []
for page in reader.pages:
extracted = page.extract_text()
if extracted:
text.append(extracted)
return "\n".join(text)
def read_plain(file_bytes: bytes) -> str:
"""Extract text from a plain text file."""
return file_bytes.decode("utf-8", errors="ignore")
def extract_resume_text(file_obj) -> str:
"""
Determine file type and extract text accordingly.
Supports PDF, DOCX, and plain text.
"""
file_bytes = file_obj.read()
file_obj.seek(0) # Reset pointer for potential further use
filename = file_obj.name if hasattr(file_obj, "name") else "resume.txt"
ext = os.path.splitext(filename)[-1].lower()
if ext == ".pdf":
return read_pdf(file_bytes)
elif ext in [".docx", ".doc"]:
return read_docx(file_bytes)
else:
return read_plain(file_bytes)
# ------------------------------------------------------------------------------
# Core AI Functions
# ------------------------------------------------------------------------------
def parse_resume(resume_text: str) -> str:
"""
Extract candidate details from the resume text.
The model returns a JSON with keys: first_name, last_name, location,
work_experience, school_experience, and skills.
"""
prompt = (
"You are an expert resume parser. Extract the following keys from the resume text: "
"first_name, last_name, location, work_experience, school_experience, and skills. "
"Return the answer strictly in JSON format with no extra text.\n\n"
f"Resume:\n{resume_text}"
)
result = instruct_pipeline(prompt, max_length=512)[0]["generated_text"]
return result.strip()
def generate_cover_letter(candidate_json: str, job_description: str, date_str: str) -> str:
"""
Generate a cover letter using the candidate's JSON profile, the job description,
and the current date.
"""
prompt = (
"You are a seasoned career advisor and professional cover letter writer. "
"Using the candidate information provided in JSON format, craft a persuasive and personalized cover letter "
"tailored to the job description. Structure your answer with an introduction, body, and closing, "
"and include the date {date}.\n\n"
"Candidate JSON:\n{candidate_json}\n\n"
"Job Description:\n{job_description}\n\n"
"Cover Letter:".format(
candidate_json=candidate_json, job_description=job_description, date=date_str
)
)
result = instruct_pipeline(prompt, max_length=1024)[0]["generated_text"]
return result.strip()
def generate_resume(first_name: str, last_name: str, location: str,
work_experience: str, school_experience: str, skills: str) -> str:
"""
Generate a professional resume using candidate information provided in a form.
"""
candidate_info = {
"first_name": first_name,
"last_name": last_name,
"location": location,
"work_experience": work_experience,
"school_experience": school_experience,
"skills": skills,
}
candidate_str = json.dumps(candidate_info, indent=2)
prompt = (
"You are a professional resume writer. Using the candidate information provided in JSON, "
"create a compelling, well-organized resume in plain text format. Include clear sections for "
"personal details, work experience, education, and skills. Ensure the resume is concise and professional.\n\n"
"Candidate Information:\n" + candidate_str + "\n\nResume:"
)
result = instruct_pipeline(prompt, max_length=1024)[0]["generated_text"]
return result.strip()
# ------------------------------------------------------------------------------
# Streamlit UI
# ------------------------------------------------------------------------------
st.set_page_config(page_title="AI-Powered Job Application Assistant", layout="wide")
st.title("AI-Powered Job Application Assistant")
st.markdown("Generate a **Cover Letter** from your resume or **Create a Resume** from scratch using AI.")
# Create tabs for the two functionalities
tabs = st.tabs(["Cover Letter Generator", "Resume Creator"])
# ----- Tab 1: Cover Letter Generator -----
with tabs[0]:
st.header("Cover Letter Generator")
st.markdown("Upload your resume (PDF, DOCX, or TXT) and paste the job description below.")
col1, col2 = st.columns(2)
with col1:
resume_file = st.file_uploader("Upload Your Resume", type=["pdf", "docx", "doc", "txt"])
with col2:
job_description = st.text_area("Job Description", height=200, placeholder="Paste the job description here...")
if st.button("Generate Cover Letter"):
if resume_file is None or not job_description.strip():
st.error("Please upload a resume and enter a job description.")
else:
with st.spinner("Processing resume..."):
resume_text = extract_resume_text(resume_file)
candidate_json = parse_resume(resume_text)
current_date = datetime.today().strftime("%d - %b - %Y")
cover_letter = generate_cover_letter(candidate_json, job_description, current_date)
st.subheader("Extracted Candidate Profile (JSON)")
st.code(candidate_json, language="json")
st.subheader("Generated Cover Letter")
st.text_area("", cover_letter, height=300)
# ----- Tab 2: Resume Creator -----
with tabs[1]:
st.header("Resume Creator")
st.markdown("Fill in your details below to generate a professional resume from scratch.")
with st.form("resume_form"):
col1, col2 = st.columns(2)
with col1:
first_name = st.text_input("First Name", placeholder="John")
with col2:
last_name = st.text_input("Last Name", placeholder="Doe")
location = st.text_input("Location", placeholder="City, State, Country")
work_experience = st.text_area("Work Experience", height=150, placeholder="List your past roles and achievements...")
school_experience = st.text_area("Education", height=150, placeholder="List your academic qualifications...")
skills = st.text_area("Skills", height=100, placeholder="List your key skills...")
submit = st.form_submit_button("Generate Resume")
if submit:
with st.spinner("Generating resume..."):
resume_text = generate_resume(first_name, last_name, location, work_experience, school_experience, skills)
st.subheader("Generated Resume")
st.text_area("", resume_text, height=400)