umarmajeedofficial commited on
Commit
1e27a1c
1 Parent(s): a62dac6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +184 -0
app.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from openai import OpenAI
4
+ from PyPDF2 import PdfReader
5
+ from docx import Document
6
+ import re
7
+
8
+ # Securely get the API key from environment variables
9
+ api_key = os.getenv("OPENAI_API_KEY")
10
+ base_url = "https://api.aimlapi.com/v1"
11
+ llama_model = "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo"
12
+
13
+ # Initialize the OpenAI API
14
+ api = OpenAI(api_key=api_key, base_url=base_url)
15
+
16
+ # Function to extract text from a PDF file
17
+ def extract_text_from_pdf(pdf_file):
18
+ reader = PdfReader(pdf_file)
19
+ text = ""
20
+ for page in reader.pages:
21
+ text += page.extract_text()
22
+ return text
23
+
24
+ # Function to extract user details from CV (e.g., Name, Contact Info, etc.)
25
+ def extract_user_details(cv_text):
26
+ lines = cv_text.splitlines()
27
+ name = lines[0] if len(lines) > 0 else "Name Not Found"
28
+ title = lines[1] if len(lines) > 1 else "Title Not Found"
29
+ contact_info = lines[2] if len(lines) > 2 else "Contact Info Not Found"
30
+
31
+ return name, title, contact_info
32
+
33
+ # Function to match and regenerate CV content
34
+ def regenerate_cv(cv_text, job_description):
35
+ system_prompt = "You are a world class pro CV writing assistant."
36
+ user_prompt = (f"Here is a CV: {cv_text}\n\n"
37
+ f"And here is the job description: {job_description}\n\n"
38
+ "Please regenerate the CV according to the job description, "
39
+ "fill the gaps, add all sufficient skills that match the job description and provide it in a professional US template that has the highest possible ATS score.")
40
+
41
+ completion = api.chat.completions.create(
42
+ model=llama_model,
43
+ messages=[
44
+ {"role": "system", "content": system_prompt},
45
+ {"role": "user", "content": user_prompt},
46
+ ],
47
+ temperature=0.7,
48
+ max_tokens=4096, # Increase max_tokens to handle larger outputs
49
+ )
50
+
51
+ response = completion.choices[0].message.content
52
+ return response
53
+
54
+ # Function to generate the interview preparation note
55
+ def generate_interview_note(cv_text, updated_cv_text):
56
+ system_prompt = "You are a world class pro interview preparation assistant."
57
+ user_prompt = (f"Here is the original CV: {cv_text}\n\n"
58
+ f"Here is the updated CV: {updated_cv_text}\n\n"
59
+ "Identify the changes made and provide a list of topics the candidate should prepare for the interview based on the updates in a very concise and professional manner with proper headings and bullet points.")
60
+
61
+ completion = api.chat.completions.create(
62
+ model=llama_model,
63
+ messages=[
64
+ {"role": "system", "content": system_prompt},
65
+ {"role": "user", "content": user_prompt},
66
+ ],
67
+ temperature=0.7,
68
+ max_tokens=1024,
69
+ )
70
+
71
+ response = completion.choices[0].message.content
72
+ return response
73
+
74
+ # Function to calculate ATS score
75
+ def calculate_ats_score(cv_text, job_description):
76
+ job_keywords = re.findall(r'\b\w+\b', job_description.lower())
77
+ cv_keywords = re.findall(r'\b\w+\b', cv_text.lower())
78
+
79
+ matching_keywords = set(job_keywords) & set(cv_keywords)
80
+ ats_score = len(matching_keywords) / len(set(job_keywords)) * 100
81
+ return round(ats_score, 2)
82
+
83
+ # Function to create and save the regenerated CV as DOCX (formatted)
84
+ def create_formatted_cv(cv_text, file_name="Updated_CV.docx"):
85
+ doc = Document()
86
+
87
+ # Extract user details (name, title, contact info)
88
+ name, title, contact_info = extract_user_details(cv_text)
89
+
90
+ # Adding CV content with formatting
91
+ doc.add_heading(name, level=1)
92
+ doc.add_paragraph(title)
93
+ doc.add_paragraph(contact_info)
94
+
95
+ # Split the CV into sections
96
+ sections = cv_text.split('\n\n')
97
+
98
+ # Define headings for each section based on the template
99
+ headings = ["ACHIEVEMENTS", "EDUCATION", "SKILLS", "WORK EXPERIENCE", "VOLUNTEER EXPERIENCE", "HACKATHON PROJECTS", "WORKSHOPS AND WEBINARS"]
100
+
101
+ for section in sections:
102
+ for heading in headings:
103
+ if heading in section.upper():
104
+ doc.add_heading(heading, level=2)
105
+ doc.add_paragraph(section)
106
+
107
+ # Save the document
108
+ doc.save(file_name)
109
+ return file_name
110
+
111
+ # Function to process the CV and generate outputs
112
+ def process_cv(cv_pdf, job_description):
113
+ # Extract text from the uploaded CV PDF
114
+ cv_text = extract_text_from_pdf(cv_pdf)
115
+
116
+ # Calculate initial ATS score
117
+ initial_ats_score = calculate_ats_score(cv_text, job_description)
118
+
119
+ # Regenerate the CV
120
+ updated_cv_text = regenerate_cv(cv_text, job_description)
121
+
122
+ # Calculate updated ATS score
123
+ updated_ats_score = calculate_ats_score(updated_cv_text, job_description)
124
+
125
+ # Generate interview preparation note
126
+ interview_note = generate_interview_note(cv_text, updated_cv_text)
127
+
128
+ # Create and save the formatted CV
129
+ formatted_cv_path = create_formatted_cv(updated_cv_text)
130
+
131
+ # Create the interview notes file
132
+ interview_notes_path = "Interview_Notes.txt"
133
+ with open(interview_notes_path, "w") as f:
134
+ f.write(interview_note)
135
+
136
+ return updated_cv_text, initial_ats_score, updated_ats_score, interview_note, formatted_cv_path, interview_notes_path
137
+
138
+ # Define the Gradio app
139
+ def app_interface():
140
+ with gr.Blocks() as interface:
141
+ gr.Markdown("### **HireFit** By team Mixed Intelligence")
142
+
143
+ # Short description
144
+ gr.Markdown("""
145
+ **Version 1.0**
146
+
147
+ This project takes your CV and job description, then provides a new CV optimized for the specific job description. It also highlights gaps in your CV and provides detailed interview preparation notes to help you succeed.
148
+ """)
149
+
150
+ with gr.Row():
151
+ # Left panel
152
+ with gr.Column(scale=1):
153
+ gr.Markdown("### Upload and Generate")
154
+ cv_pdf = gr.File(label="Upload Your CV (PDF)")
155
+ job_description = gr.Textbox(label="Paste Job Description")
156
+ process_btn = gr.Button("Regenerate CV", elem_id="process_btn")
157
+
158
+ # Middle panel
159
+ with gr.Column(scale=2):
160
+ gr.Markdown("### Regenerated CV and Interview Notes")
161
+ updated_cv_text = gr.Textbox(label="Regenerated CV", lines=20, interactive=False)
162
+ interview_note = gr.Textbox(label="Interview Preparation Notes", lines=10, interactive=False)
163
+
164
+ # Right panel
165
+ with gr.Column(scale=1):
166
+ gr.Markdown("### ATS Scores")
167
+ ats_score_before = gr.Number(label="Original ATS Score", value=0)
168
+ ats_score_after = gr.Number(label="Updated ATS Score", value=0)
169
+
170
+ # Adding download buttons to the right panel
171
+ download_cv_btn = gr.File(label="Download Updated CV", elem_id="download_cv_btn")
172
+ download_notes_btn = gr.File(label="Download Interview Notes", elem_id="download_notes_btn")
173
+
174
+ # Button click event
175
+ process_btn.click(
176
+ fn=process_cv,
177
+ inputs=[cv_pdf, job_description],
178
+ outputs=[updated_cv_text, ats_score_before, ats_score_after, interview_note, download_cv_btn, download_notes_btn]
179
+ )
180
+
181
+ return interface
182
+
183
+ if __name__ == "__main__":
184
+ app_interface().launch()