mgbam commited on
Commit
38c327b
·
1 Parent(s): 28273c7

Add application file

Browse files
Files changed (1) hide show
  1. app.py +188 -0
app.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+
3
+ import os
4
+ import io
5
+ import json
6
+ from datetime import datetime
7
+
8
+ import streamlit as st
9
+ from transformers import pipeline
10
+ from docx import Document
11
+ from PyPDF2 import PdfReader
12
+
13
+ # ------------------------------------------------------------------------------
14
+ # Model Pipeline Setup
15
+ # ------------------------------------------------------------------------------
16
+
17
+ # Use an instruction-tuned model (e.g., Flan-T5-xl)
18
+ model_name = "google/flan-t5-xl"
19
+ instruct_pipeline = pipeline(
20
+ "text2text-generation", model=model_name, max_length=1024, truncation=True
21
+ )
22
+
23
+ # ------------------------------------------------------------------------------
24
+ # Helper Functions for File Reading
25
+ # ------------------------------------------------------------------------------
26
+
27
+ def read_docx(file_bytes: bytes) -> str:
28
+ """Extract text from a DOCX file."""
29
+ document = Document(io.BytesIO(file_bytes))
30
+ return "\n".join([para.text for para in document.paragraphs])
31
+
32
+ def read_pdf(file_bytes: bytes) -> str:
33
+ """Extract text from a PDF file."""
34
+ reader = PdfReader(io.BytesIO(file_bytes))
35
+ text = []
36
+ for page in reader.pages:
37
+ extracted = page.extract_text()
38
+ if extracted:
39
+ text.append(extracted)
40
+ return "\n".join(text)
41
+
42
+ def read_plain(file_bytes: bytes) -> str:
43
+ """Extract text from a plain text file."""
44
+ return file_bytes.decode("utf-8", errors="ignore")
45
+
46
+ def extract_resume_text(file_obj) -> str:
47
+ """
48
+ Determine file type and extract text accordingly.
49
+ Supports PDF, DOCX, and plain text.
50
+ """
51
+ file_bytes = file_obj.read()
52
+ file_obj.seek(0) # Reset pointer for potential further use
53
+ filename = file_obj.name if hasattr(file_obj, "name") else "resume.txt"
54
+ ext = os.path.splitext(filename)[-1].lower()
55
+
56
+ if ext == ".pdf":
57
+ return read_pdf(file_bytes)
58
+ elif ext in [".docx", ".doc"]:
59
+ return read_docx(file_bytes)
60
+ else:
61
+ return read_plain(file_bytes)
62
+
63
+ # ------------------------------------------------------------------------------
64
+ # Core AI Functions
65
+ # ------------------------------------------------------------------------------
66
+
67
+ def parse_resume(resume_text: str) -> str:
68
+ """
69
+ Extract candidate details from the resume text.
70
+ The model returns a JSON with keys: first_name, last_name, location,
71
+ work_experience, school_experience, and skills.
72
+ """
73
+ prompt = (
74
+ "You are an expert resume parser. Extract the following keys from the resume text: "
75
+ "first_name, last_name, location, work_experience, school_experience, and skills. "
76
+ "Return the answer strictly in JSON format with no extra text.\n\n"
77
+ f"Resume:\n{resume_text}"
78
+ )
79
+ result = instruct_pipeline(prompt, max_length=512)[0]["generated_text"]
80
+ return result.strip()
81
+
82
+ def generate_cover_letter(candidate_json: str, job_description: str, date_str: str) -> str:
83
+ """
84
+ Generate a cover letter using the candidate's JSON profile, the job description,
85
+ and the current date.
86
+ """
87
+ prompt = (
88
+ "You are a seasoned career advisor and professional cover letter writer. "
89
+ "Using the candidate information provided in JSON format, craft a persuasive and personalized cover letter "
90
+ "tailored to the job description. Structure your answer with an introduction, body, and closing, "
91
+ "and include the date {date}.\n\n"
92
+ "Candidate JSON:\n{candidate_json}\n\n"
93
+ "Job Description:\n{job_description}\n\n"
94
+ "Cover Letter:".format(
95
+ candidate_json=candidate_json, job_description=job_description, date=date_str
96
+ )
97
+ )
98
+ result = instruct_pipeline(prompt, max_length=1024)[0]["generated_text"]
99
+ return result.strip()
100
+
101
+ def generate_resume(first_name: str, last_name: str, location: str,
102
+ work_experience: str, school_experience: str, skills: str) -> str:
103
+ """
104
+ Generate a professional resume using candidate information provided in a form.
105
+ """
106
+ candidate_info = {
107
+ "first_name": first_name,
108
+ "last_name": last_name,
109
+ "location": location,
110
+ "work_experience": work_experience,
111
+ "school_experience": school_experience,
112
+ "skills": skills,
113
+ }
114
+ candidate_str = json.dumps(candidate_info, indent=2)
115
+
116
+ prompt = (
117
+ "You are a professional resume writer. Using the candidate information provided in JSON, "
118
+ "create a compelling, well-organized resume in plain text format. Include clear sections for "
119
+ "personal details, work experience, education, and skills. Ensure the resume is concise and professional.\n\n"
120
+ "Candidate Information:\n" + candidate_str + "\n\nResume:"
121
+ )
122
+ result = instruct_pipeline(prompt, max_length=1024)[0]["generated_text"]
123
+ return result.strip()
124
+
125
+ # ------------------------------------------------------------------------------
126
+ # Streamlit UI
127
+ # ------------------------------------------------------------------------------
128
+
129
+ st.set_page_config(page_title="AI-Powered Job Application Assistant", layout="wide")
130
+ st.title("AI-Powered Job Application Assistant")
131
+ st.markdown("Generate a **Cover Letter** from your resume or **Create a Resume** from scratch using AI.")
132
+
133
+ # Create tabs for the two functionalities
134
+ tabs = st.tabs(["Cover Letter Generator", "Resume Creator"])
135
+
136
+ # ----- Tab 1: Cover Letter Generator -----
137
+ with tabs[0]:
138
+ st.header("Cover Letter Generator")
139
+ st.markdown("Upload your resume (PDF, DOCX, or TXT) and paste the job description below.")
140
+
141
+ col1, col2 = st.columns(2)
142
+
143
+ with col1:
144
+ resume_file = st.file_uploader("Upload Your Resume", type=["pdf", "docx", "doc", "txt"])
145
+
146
+ with col2:
147
+ job_description = st.text_area("Job Description", height=200, placeholder="Paste the job description here...")
148
+
149
+ if st.button("Generate Cover Letter"):
150
+ if resume_file is None or not job_description.strip():
151
+ st.error("Please upload a resume and enter a job description.")
152
+ else:
153
+ with st.spinner("Processing resume..."):
154
+ resume_text = extract_resume_text(resume_file)
155
+ candidate_json = parse_resume(resume_text)
156
+ current_date = datetime.today().strftime("%d - %b - %Y")
157
+ cover_letter = generate_cover_letter(candidate_json, job_description, current_date)
158
+
159
+ st.subheader("Extracted Candidate Profile (JSON)")
160
+ st.code(candidate_json, language="json")
161
+
162
+ st.subheader("Generated Cover Letter")
163
+ st.text_area("", cover_letter, height=300)
164
+
165
+ # ----- Tab 2: Resume Creator -----
166
+ with tabs[1]:
167
+ st.header("Resume Creator")
168
+ st.markdown("Fill in your details below to generate a professional resume from scratch.")
169
+
170
+ with st.form("resume_form"):
171
+ col1, col2 = st.columns(2)
172
+ with col1:
173
+ first_name = st.text_input("First Name", placeholder="John")
174
+ with col2:
175
+ last_name = st.text_input("Last Name", placeholder="Doe")
176
+
177
+ location = st.text_input("Location", placeholder="City, State, Country")
178
+ work_experience = st.text_area("Work Experience", height=150, placeholder="List your past roles and achievements...")
179
+ school_experience = st.text_area("Education", height=150, placeholder="List your academic qualifications...")
180
+ skills = st.text_area("Skills", height=100, placeholder="List your key skills...")
181
+
182
+ submit = st.form_submit_button("Generate Resume")
183
+
184
+ if submit:
185
+ with st.spinner("Generating resume..."):
186
+ resume_text = generate_resume(first_name, last_name, location, work_experience, school_experience, skills)
187
+ st.subheader("Generated Resume")
188
+ st.text_area("", resume_text, height=400)