Spaces:
Sleeping
Sleeping
File size: 7,801 Bytes
38c327b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# 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)
|