muhammadsalmanalfaridzi's picture
Update app.py
dabfbfe verified
import os
from markitdown import MarkItDown
from cerebras.cloud.sdk import Cerebras
from weasyprint import HTML
import markdown
import gradio as gr
# Ensure you get the API key from environment variables
api_key = os.environ.get("CEREBRAS_API_KEY")
# Initialize MarkItDown instance
md_converter = MarkItDown()
# Functions for resume optimization
def create_prompt(resume_string: str, jd_string: str) -> str:
"""
Creates a detailed prompt for AI-powered resume optimization based on a job description.
"""
return f"""
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.
### Guidelines:
1. **Relevance**:
- Prioritize experiences, skills, and achievements **most relevant to the job description**.
- Remove or de-emphasize irrelevant details to ensure a **concise** and **targeted** resume.
- Limit work experience section to 2-3 most relevant roles
- Limit bullet points under each role to 2-3 most relevant impacts
2. **Action-Driven Results**:
- Use **strong action verbs** and **quantifiable results** (e.g., percentages, revenue, efficiency improvements) to highlight impact.
3. **Keyword Optimization**:
- Integrate **keywords** and phrases from the job description naturally to optimize for ATS (Applicant Tracking Systems).
4. **Additional Suggestions** *(If Gaps Exist)*:
- If the resume does not fully align with the job description, suggest:
1. **Additional technical or soft skills** that I could add to make my profile stronger.
2. **Certifications or courses** I could pursue to bridge the gap.
3. **Project ideas or experiences** that would better align with the role.
5. **Formatting**:
- Output the tailored resume in **clean Markdown format**.
- Include an **"Additional Suggestions"** section at the end with actionable improvement recommendations.
---
### Input:
- **My resume**:
{resume_string}
- **The job description**:
{jd_string}
---
### Output:
1. - A resume in **Markdown format** that emphasizes relevant experience, skills, and achievements.
- Incorporates job description **keywords** to optimize for ATS.
- Uses strong language and is no longer than **one page**.
2. **Additional Suggestions** *(if applicable)*:
- List **skills** that could strengthen alignment with the role.
- Recommend **certifications or courses** to pursue.
- Suggest **specific projects or experiences** to develop.
"""
def get_resume_response(prompt: str, api_key: str, model: str = "llama-3.3-70b", temperature: float = 0.7) -> str:
client = Cerebras(api_key=api_key)
stream = client.chat.completions.create(
messages=[
{"role": "system", "content": "Expert resume writer"},
{"role": "user", "content": prompt}
],
model=model,
stream=True,
temperature=temperature,
max_completion_tokens=1024,
top_p=1
)
response_string = ""
for chunk in stream:
response_string += chunk.choices[0].delta.content or ""
return response_string
def process_resume(resume, jd_string):
"""
Process the uploaded resume and job description, optimize it, and return the result.
"""
# Supported file extensions
supported_extensions = ('.pptx', '.docx', '.pdf', '.jpg', '.jpeg', '.png', '.xlsx')
# Check if the uploaded resume has a supported extension
if resume.name.lower().endswith(supported_extensions):
# Convert file to Markdown using MarkItDown
result = md_converter.convert(resume.name)
resume_string = result.text_content # Get the converted Markdown content
else:
return "File format not supported for conversion to Markdown.", "", "", "", "" # Ensure all outputs are returned
# Create optimization prompt
prompt = create_prompt(resume_string, jd_string)
# Generate response from AI
response_string = get_resume_response(prompt, api_key)
# Split response into optimized resume and suggestions
response_list = response_string.split("## Additional Suggestions")
new_resume = response_list[0].strip()
suggestions = "## Additional Suggestions\n\n" + response_list[1].strip() if len(response_list) > 1 else ""
# You can use the original resume content to create a file link if needed
original_resume_path = "resumes/original_resume.md"
with open(original_resume_path, "w") as f:
f.write(resume_string)
# Create a download path for the optimized resume
optimized_resume_path = "resumes/optimized_resume.md"
with open(optimized_resume_path, "w") as f:
f.write(new_resume)
# Return the required outputs (5 values)
return resume_string, new_resume, original_resume_path, optimized_resume_path, suggestions
def export_resume(new_resume):
"""
Export the optimized resume (in Markdown format) as a PDF file.
"""
try:
# Convert Markdown to HTML
html_content = markdown.markdown(new_resume)
# Convert HTML to PDF and save
output_pdf_file = "resumes/optimized_resume.pdf"
stylesheets = ['resumes/style.css'] # Ensure this path is correct and accessible
# Write HTML to PDF with optional styling
HTML(string=html_content).write_pdf(output_pdf_file, stylesheets=['resumes/style.css'])
return output_pdf_file # Return the file path for download
except Exception as e:
return f"Failed to export resume: {str(e)} πŸ’”"
# Gradio App
with gr.Blocks() as app:
gr.Markdown("# Resume Optimizer πŸ“„")
gr.Markdown("Upload your resume, paste the job description, and get actionable insights!")
with gr.Row():
resume_input = gr.File(label="Upload Your Resume")
jd_input = gr.Textbox(label="Paste the Job Description Here", lines=9, interactive=True, placeholder="Paste job description...")
run_button = gr.Button("Optimize Resume πŸ€–")
with gr.Row():
before_md = gr.Markdown(label="Original Resume (Before)")
after_md = gr.Markdown(label="Optimized Resume (After)")
output_suggestions = gr.Markdown(label="Suggestions")
with gr.Row():
download_before = gr.File(label="Download Original Resume")
download_after = gr.File(label="Download Optimized Resume")
export_button = gr.Button("Export Optimized Resume as PDF πŸš€")
export_result = gr.File(label="Download PDF")
# Bindings
run_button.click(
process_resume,
inputs=[resume_input, jd_input],
outputs=[before_md, after_md, download_before, download_after, output_suggestions]
)
export_button.click(export_resume, inputs=[after_md], outputs=[export_result])
app.launch()