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)