Update app.py
Browse files
app.py
CHANGED
@@ -8,43 +8,11 @@ from PyPDF2 import PdfReader
|
|
8 |
import gradio as gr
|
9 |
from PIL import Image
|
10 |
|
|
|
11 |
api_key = os.environ.get("CEREBRAS_API_KEY")
|
12 |
-
md_converter = MarkItDown()
|
13 |
-
|
14 |
-
def extract_file_preview(file_path):
|
15 |
-
"""
|
16 |
-
Extracts a preview of the file based on its format.
|
17 |
-
"""
|
18 |
-
try:
|
19 |
-
file_ext = os.path.splitext(file_path)[-1].lower()
|
20 |
-
|
21 |
-
if file_ext in [".jpg", ".jpeg", ".png"]:
|
22 |
-
return Image.open(file_path)
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
return "\n".join([page.extract_text() for page in reader.pages[:2]])
|
27 |
-
|
28 |
-
elif file_ext in [".docx"]:
|
29 |
-
doc = Document(file_path)
|
30 |
-
return "\n".join([para.text for para in doc.paragraphs[:20]])
|
31 |
-
|
32 |
-
elif file_ext in [".pptx"]:
|
33 |
-
ppt = Presentation(file_path)
|
34 |
-
slides_text = []
|
35 |
-
for slide in ppt.slides[:5]:
|
36 |
-
slide_text = []
|
37 |
-
for shape in slide.shapes:
|
38 |
-
if hasattr(shape, "text"):
|
39 |
-
slide_text.append(shape.text)
|
40 |
-
slides_text.append("\n".join(slide_text))
|
41 |
-
return "\n---\n".join(slides_text)
|
42 |
-
|
43 |
-
else:
|
44 |
-
return "File preview not supported for this format."
|
45 |
-
|
46 |
-
except Exception as e:
|
47 |
-
return f"Error extracting file preview: {str(e)}"
|
48 |
|
49 |
# Functions for resume optimization
|
50 |
def create_prompt(resume_string: str, jd_string: str) -> str:
|
@@ -101,13 +69,7 @@ You are a professional resume optimization expert specializing in tailoring resu
|
|
101 |
"""
|
102 |
|
103 |
def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b", temperature: float = 0.7) -> str:
|
104 |
-
"""
|
105 |
-
Sends a resume optimization prompt to Cerebras' API and returns the optimized resume response.
|
106 |
-
"""
|
107 |
-
# Initialize the Cerebras client with the API key
|
108 |
client = Cerebras(api_key=api_key)
|
109 |
-
|
110 |
-
# Make API call using the Llama 3.3 70B model
|
111 |
stream = client.chat.completions.create(
|
112 |
messages=[
|
113 |
{"role": "system", "content": "Expert resume writer"},
|
@@ -120,91 +82,76 @@ def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b",
|
|
120 |
top_p=1
|
121 |
)
|
122 |
|
123 |
-
# Collect the response chunks from the stream
|
124 |
response_string = ""
|
125 |
for chunk in stream:
|
126 |
response_string += chunk.choices[0].delta.content or ""
|
127 |
-
|
128 |
return response_string
|
129 |
|
130 |
def process_resume(file, jd_string):
|
|
|
|
|
131 |
try:
|
132 |
-
|
133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
|
135 |
-
|
136 |
-
|
|
|
137 |
|
138 |
-
|
139 |
-
|
|
|
140 |
|
141 |
-
# Save the
|
142 |
-
original_file_path = file_path
|
143 |
optimized_file_path = "resumes/optimized_resume.md"
|
144 |
with open(optimized_file_path, "w", encoding="utf-8") as f:
|
145 |
-
f.write(
|
146 |
-
|
147 |
-
return original_preview, resume_string, optimized_resume, original_file_path, optimized_file_path
|
148 |
-
except Exception as e:
|
149 |
-
return f"Error processing file: {str(e)}", "", "", "", ""
|
150 |
|
151 |
-
|
152 |
-
try:
|
153 |
-
pdf_path = "resumes/optimized_resume.pdf"
|
154 |
-
HTML(string=resume_md).write_pdf(pdf_path)
|
155 |
-
return pdf_path
|
156 |
except Exception as e:
|
157 |
-
return f"
|
158 |
|
159 |
-
def
|
160 |
try:
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
return doc_path
|
167 |
except Exception as e:
|
168 |
-
return f"Failed to export
|
169 |
|
170 |
-
# Gradio
|
171 |
with gr.Blocks() as app:
|
172 |
gr.Markdown("# Resume Optimizer π")
|
173 |
gr.Markdown("Upload your resume, paste the job description, and get actionable insights!")
|
174 |
|
175 |
with gr.Row():
|
176 |
-
resume_input = gr.File(label="Upload Your Resume")
|
177 |
-
jd_input = gr.Textbox(label="Paste Job Description", lines=
|
|
|
|
|
178 |
|
179 |
-
run_button = gr.Button("Optimize Resume")
|
180 |
-
|
181 |
with gr.Row():
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
|
186 |
with gr.Row():
|
187 |
-
download_before = gr.File(label="Download Original")
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
)
|
197 |
-
|
198 |
-
gr.Button("Export as PDF").click(
|
199 |
-
export_as_pdf,
|
200 |
-
inputs=[after_md],
|
201 |
-
outputs=[download_after_pdf]
|
202 |
-
)
|
203 |
-
|
204 |
-
gr.Button("Export as Word").click(
|
205 |
-
export_as_word,
|
206 |
-
inputs=[after_md],
|
207 |
-
outputs=[download_after_word]
|
208 |
-
)
|
209 |
|
210 |
app.launch()
|
|
|
8 |
import gradio as gr
|
9 |
from PIL import Image
|
10 |
|
11 |
+
# Ensure you get the API key from environment variables
|
12 |
api_key = os.environ.get("CEREBRAS_API_KEY")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
+
# Initialize MarkItDown instance
|
15 |
+
md_converter = MarkItDown()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
# Functions for resume optimization
|
18 |
def create_prompt(resume_string: str, jd_string: str) -> str:
|
|
|
69 |
"""
|
70 |
|
71 |
def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b", temperature: float = 0.7) -> str:
|
|
|
|
|
|
|
|
|
72 |
client = Cerebras(api_key=api_key)
|
|
|
|
|
73 |
stream = client.chat.completions.create(
|
74 |
messages=[
|
75 |
{"role": "system", "content": "Expert resume writer"},
|
|
|
82 |
top_p=1
|
83 |
)
|
84 |
|
|
|
85 |
response_string = ""
|
86 |
for chunk in stream:
|
87 |
response_string += chunk.choices[0].delta.content or ""
|
|
|
88 |
return response_string
|
89 |
|
90 |
def process_resume(file, jd_string):
|
91 |
+
# Initialize MarkItDown
|
92 |
+
md = MarkItDown()
|
93 |
try:
|
94 |
+
# Convert file to Markdown
|
95 |
+
original_md = md.convert(file.name)
|
96 |
+
original_text = original_md.text_content
|
97 |
+
|
98 |
+
# Save the original Markdown to a file
|
99 |
+
original_file_path = "resumes/original_resume.md"
|
100 |
+
with open(original_file_path, "w", encoding="utf-8") as f:
|
101 |
+
f.write(original_text)
|
102 |
|
103 |
+
# Create optimization prompt
|
104 |
+
prompt = create_prompt(original_text, jd_string)
|
105 |
+
response_string = get_resume_response(prompt, api_key)
|
106 |
|
107 |
+
# Extract optimized resume and suggestions
|
108 |
+
response_list = response_string.split("## Additional Suggestions")
|
109 |
+
new_resume = response_list[0]
|
110 |
|
111 |
+
# Save the optimized Markdown to a file
|
|
|
112 |
optimized_file_path = "resumes/optimized_resume.md"
|
113 |
with open(optimized_file_path, "w", encoding="utf-8") as f:
|
114 |
+
f.write(new_resume)
|
|
|
|
|
|
|
|
|
115 |
|
116 |
+
return original_text, new_resume, "resumes/original_resume.md", "resumes/optimized_resume.md"
|
|
|
|
|
|
|
|
|
117 |
except Exception as e:
|
118 |
+
return f"Error processing file: {str(e)}", "", None, None
|
119 |
|
120 |
+
def export_resume(new_resume):
|
121 |
try:
|
122 |
+
# Save optimized Markdown as PDF
|
123 |
+
output_pdf_file = "resumes/resume_new.pdf"
|
124 |
+
html_content = new_resume
|
125 |
+
HTML(string=html_content).write_pdf(output_pdf_file, stylesheets=['resumes/style.css'])
|
126 |
+
return f"Successfully exported resume to {output_pdf_file} π"
|
|
|
127 |
except Exception as e:
|
128 |
+
return f"Failed to export resume: {str(e)} π"
|
129 |
|
130 |
+
# Gradio App
|
131 |
with gr.Blocks() as app:
|
132 |
gr.Markdown("# Resume Optimizer π")
|
133 |
gr.Markdown("Upload your resume, paste the job description, and get actionable insights!")
|
134 |
|
135 |
with gr.Row():
|
136 |
+
resume_input = gr.File(label="Upload Your Resume")
|
137 |
+
jd_input = gr.Textbox(label="Paste the Job Description Here", lines=9, interactive=True, placeholder="Paste job description...")
|
138 |
+
|
139 |
+
run_button = gr.Button("Optimize Resume π€")
|
140 |
|
|
|
|
|
141 |
with gr.Row():
|
142 |
+
before_md = gr.Markdown(label="Original Resume (Before)")
|
143 |
+
after_md = gr.Markdown(label="Optimized Resume (After)")
|
144 |
+
output_suggestions = gr.Markdown(label="Suggestions")
|
145 |
|
146 |
with gr.Row():
|
147 |
+
download_before = gr.File(label="Download Original Resume")
|
148 |
+
download_after = gr.File(label="Download Optimized Resume")
|
149 |
+
|
150 |
+
export_button = gr.Button("Export Optimized Resume as PDF π")
|
151 |
+
export_result = gr.Markdown(label="Export Result")
|
152 |
+
|
153 |
+
# Bindings
|
154 |
+
run_button.click(process_resume, inputs=[resume_input, jd_input], outputs=[before_md, after_md, download_before, download_after, output_suggestions])
|
155 |
+
export_button.click(export_resume, inputs=[after_md], outputs=[export_result])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
app.launch()
|