muhammadsalmanalfaridzi commited on
Commit
169b5ce
Β·
verified Β·
1 Parent(s): 82387e7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -38
app.py CHANGED
@@ -1,21 +1,24 @@
1
  import os
2
  import re
3
- from markitdown import MarkItDown
4
- from cerebras.cloud.sdk import Cerebras
5
- from weasyprint import HTML
6
  import markdown
7
  import gradio as gr
 
 
 
8
 
9
- # Ensure you get the API key from environment variables
 
 
 
10
  api_key = os.environ.get("CEREBRAS_API_KEY")
11
 
12
- # Initialize MarkItDown instance
13
  md_converter = MarkItDown()
14
 
15
- # Functions for resume optimization
16
  def create_prompt(resume_string: str, jd_string: str) -> str:
17
  """
18
- Creates a detailed prompt for AI-powered resume optimization based on a job description.
 
19
  """
20
  return f"""
21
  You are a professional resume optimization expert specializing in tailoring resumes to specific job descriptions. Your goal is to optimize my resume and provide actionable suggestions for improvement to align with the target role.
@@ -66,6 +69,9 @@ You are a professional resume optimization expert specializing in tailoring resu
66
  """
67
 
68
  def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b", temperature: float = 0.7) -> str:
 
 
 
69
  client = Cerebras(api_key=api_key)
70
  stream = client.chat.completions.create(
71
  messages=[
@@ -84,77 +90,98 @@ def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b",
84
  response_string += chunk.choices[0].delta.content or ""
85
  return response_string
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  def process_resume(resume, jd_string):
88
  """
89
- Process the uploaded resume and job description, optimize it, and return the result.
 
90
  """
91
- # Supported file extensions
92
  supported_extensions = ('.pptx', '.docx', '.pdf', '.jpg', '.jpeg', '.png', '.xlsx')
93
 
94
- # Check if the uploaded resume has a supported extension
95
  if resume.name.lower().endswith(supported_extensions):
96
- # Convert file to Markdown using MarkItDown
97
  result = md_converter.convert(resume.name)
98
- resume_string = result.text_content # Get the converted Markdown content
99
  else:
100
- return "File format not supported for conversion to Markdown.", "", "", "", "" # Ensure all outputs are returned
101
 
102
- # Create optimization prompt
103
  prompt = create_prompt(resume_string, jd_string)
104
 
105
- # Generate response from AI
106
  response_string = get_resume_response(prompt, api_key)
107
 
108
- # Split response into optimized resume and suggestions
109
  response_list = response_string.split("## Additional Suggestions")
110
  new_resume = response_list[0].strip()
111
  suggestions = "## Additional Suggestions\n\n" + response_list[1].strip() if len(response_list) > 1 else ""
112
-
113
- new_resume = new_resume.replace("# Optimized Resume", "")
114
- new_resume = new_resume.replace("## Optimized Resume", "")
115
- new_resume = new_resume.replace("Optimized Resume", "")
116
- new_resume = re.sub(r'^\* ', '- ', new_resume, flags=re.MULTILINE)
117
 
118
- # You can use the original resume content to create a file link if needed
 
 
 
 
119
  original_resume_path = "resumes/original_resume.md"
120
- with open(original_resume_path, "w") as f:
121
  f.write(resume_string)
122
 
123
- # Create a download path for the optimized resume
124
  optimized_resume_path = "resumes/optimized_resume.md"
125
- with open(optimized_resume_path, "w") as f:
126
  f.write(new_resume)
127
 
128
- # Return the required outputs (5 values)
129
  return resume_string, new_resume, original_resume_path, optimized_resume_path, suggestions
130
 
131
  def export_resume(new_resume):
132
  """
133
- Export the optimized resume (in Markdown format) as a PDF file.
 
134
  """
135
  try:
136
- # Convert Markdown to HTML
137
- html_content = markdown.markdown(new_resume, extensions=['extra', 'nl2br'])
138
 
139
- # Convert HTML to PDF and save
140
  output_pdf_file = "resumes/optimized_resume.pdf"
141
- stylesheets = ['resumes/style.css'] # Ensure this path is correct and accessible
142
 
143
- # Write HTML to PDF with optional styling
144
- HTML(string=html_content).write_pdf(output_pdf_file, stylesheets=['resumes/style.css'])
 
 
 
145
 
146
- return output_pdf_file # Return the file path for download
147
  except Exception as e:
148
  return f"Failed to export resume: {str(e)} πŸ’”"
149
 
150
- # Gradio App
151
  with gr.Blocks() as app:
152
  gr.Markdown("# Resume Optimizer πŸ“„")
153
  gr.Markdown("Upload your resume, paste the job description, and get actionable insights!")
154
 
155
  with gr.Row():
156
  resume_input = gr.File(label="Upload Your Resume")
157
- jd_input = gr.Textbox(label="Paste the Job Description Here", lines=9, interactive=True, placeholder="Paste job description...")
 
 
 
 
 
158
 
159
  run_button = gr.Button("Optimize Resume πŸ€–")
160
 
@@ -170,12 +197,18 @@ with gr.Blocks() as app:
170
  export_button = gr.Button("Export Optimized Resume as PDF πŸš€")
171
  export_result = gr.File(label="Download PDF")
172
 
173
- # Bindings
174
  run_button.click(
175
  process_resume,
176
  inputs=[resume_input, jd_input],
177
  outputs=[before_md, after_md, download_before, download_after, output_suggestions]
178
  )
179
- export_button.click(export_resume, inputs=[after_md], outputs=[export_result])
 
 
 
 
 
 
180
 
181
  app.launch()
 
1
  import os
2
  import re
 
 
 
3
  import markdown
4
  import gradio as gr
5
+ from weasyprint import HTML
6
+ from markitdown import MarkItDown
7
+ from cerebras.cloud.sdk import Cerebras
8
 
9
+ # Pastikan Anda memiliki file style.css di direktori yang sama
10
+ # atau sesuaikan path 'stylesheets' di fungsi export_resume
11
+
12
+ # Dapatkan API key dari environment variables
13
  api_key = os.environ.get("CEREBRAS_API_KEY")
14
 
15
+ # Inisialisasi MarkItDown
16
  md_converter = MarkItDown()
17
 
 
18
  def create_prompt(resume_string: str, jd_string: str) -> str:
19
  """
20
+ Membuat prompt detail untuk AI agar melakukan optimasi resume
21
+ berdasarkan job description.
22
  """
23
  return f"""
24
  You are a professional resume optimization expert specializing in tailoring resumes to specific job descriptions. Your goal is to optimize my resume and provide actionable suggestions for improvement to align with the target role.
 
69
  """
70
 
71
  def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b", temperature: float = 0.7) -> str:
72
+ """
73
+ Mengirim prompt ke model Cerebras (LLM) dan mengembalikan hasil streaming response.
74
+ """
75
  client = Cerebras(api_key=api_key)
76
  stream = client.chat.completions.create(
77
  messages=[
 
90
  response_string += chunk.choices[0].delta.content or ""
91
  return response_string
92
 
93
+ def remove_unwanted_headings(markdown_text: str) -> str:
94
+ """
95
+ Menghapus heading apa pun yang mengandung kata 'resume' atau 'optimized'
96
+ (dalam berbagai huruf besar/kecil).
97
+ Contoh heading yang akan dihapus:
98
+ # Resume
99
+ ## optimized
100
+ ### Optimized Resume
101
+ dsb.
102
+ """
103
+ pattern = r'^#+.*\b(?:[Rr]esume|[Oo]ptimized)\b.*$'
104
+ return re.sub(pattern, '', markdown_text, flags=re.MULTILINE)
105
+
106
  def process_resume(resume, jd_string):
107
  """
108
+ Memproses file resume yang di-upload dan job description, lalu
109
+ menghasilkan resume yang telah dioptimasi + saran perbaikan.
110
  """
111
+ # Format yang didukung
112
  supported_extensions = ('.pptx', '.docx', '.pdf', '.jpg', '.jpeg', '.png', '.xlsx')
113
 
114
+ # Cek apakah file resume memiliki ekstensi yang didukung
115
  if resume.name.lower().endswith(supported_extensions):
116
+ # Konversi file ke Markdown menggunakan MarkItDown
117
  result = md_converter.convert(resume.name)
118
+ resume_string = result.text_content # konten Markdown hasil konversi
119
  else:
120
+ return "File format not supported for conversion to Markdown.", "", "", "", ""
121
 
122
+ # Buat prompt untuk AI
123
  prompt = create_prompt(resume_string, jd_string)
124
 
125
+ # Dapatkan response dari AI
126
  response_string = get_resume_response(prompt, api_key)
127
 
128
+ # Pisahkan response menjadi "optimized resume" dan "additional suggestions"
129
  response_list = response_string.split("## Additional Suggestions")
130
  new_resume = response_list[0].strip()
131
  suggestions = "## Additional Suggestions\n\n" + response_list[1].strip() if len(response_list) > 1 else ""
 
 
 
 
 
132
 
133
+ # ===== Hapus heading yang mengandung kata resume/optimized =====
134
+ new_resume = remove_unwanted_headings(new_resume)
135
+ # ===============================================================
136
+
137
+ # Simpan resume asli (Markdown) jika diperlukan
138
  original_resume_path = "resumes/original_resume.md"
139
+ with open(original_resume_path, "w", encoding='utf-8') as f:
140
  f.write(resume_string)
141
 
142
+ # Simpan resume hasil optimasi (Markdown)
143
  optimized_resume_path = "resumes/optimized_resume.md"
144
+ with open(optimized_resume_path, "w", encoding='utf-8') as f:
145
  f.write(new_resume)
146
 
147
+ # Kembalikan output untuk di-render di Gradio
148
  return resume_string, new_resume, original_resume_path, optimized_resume_path, suggestions
149
 
150
  def export_resume(new_resume):
151
  """
152
+ Meng-export resume hasil optimasi (Markdown) menjadi PDF
153
+ menggunakan WeasyPrint.
154
  """
155
  try:
156
+ # Konversi Markdown ke HTML
157
+ html_content = markdown.markdown(new_resume)
158
 
159
+ # Path output PDF
160
  output_pdf_file = "resumes/optimized_resume.pdf"
 
161
 
162
+ # Gunakan stylesheet (pastikan path style.css benar)
163
+ HTML(string=html_content).write_pdf(
164
+ output_pdf_file,
165
+ stylesheets=["style.css"] # atau "resumes/style.css" jika style.css di folder "resumes"
166
+ )
167
 
168
+ return output_pdf_file
169
  except Exception as e:
170
  return f"Failed to export resume: {str(e)} πŸ’”"
171
 
172
+ # Bangun aplikasi Gradio
173
  with gr.Blocks() as app:
174
  gr.Markdown("# Resume Optimizer πŸ“„")
175
  gr.Markdown("Upload your resume, paste the job description, and get actionable insights!")
176
 
177
  with gr.Row():
178
  resume_input = gr.File(label="Upload Your Resume")
179
+ jd_input = gr.Textbox(
180
+ label="Paste the Job Description Here",
181
+ lines=9,
182
+ interactive=True,
183
+ placeholder="Paste job description..."
184
+ )
185
 
186
  run_button = gr.Button("Optimize Resume πŸ€–")
187
 
 
197
  export_button = gr.Button("Export Optimized Resume as PDF πŸš€")
198
  export_result = gr.File(label="Download PDF")
199
 
200
+ # Saat tombol Optimize Resume diklik
201
  run_button.click(
202
  process_resume,
203
  inputs=[resume_input, jd_input],
204
  outputs=[before_md, after_md, download_before, download_after, output_suggestions]
205
  )
206
+
207
+ # Saat tombol Export PDF diklik
208
+ export_button.click(
209
+ export_resume,
210
+ inputs=[after_md],
211
+ outputs=[export_result]
212
+ )
213
 
214
  app.launch()