| import os |
| import gradio as gr |
| from pdfminer.high_level import extract_text |
| from docx import Document |
| from groq import Groq |
|
|
| key = "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" |
| client = Groq(api_key=key) |
|
|
| |
| def read_pdf(file_path): |
| return extract_text(file_path) |
|
|
| |
| def read_docx(file_path): |
| doc = Document(file_path) |
| return "\n".join([paragraph.text for paragraph in doc.paragraphs]) |
|
|
| |
| def optimize_cv_with_llama(cv_text, job_description): |
| try: |
| |
| system_message = ( |
| "You are an experienced Human Resource expert with 30 years of experience working for major international companies. " |
| "Your task is to optimize the following CV or Resume based on the provided job description. Tailor the CV content to align " |
| "with the job requirements and highlight relevant skills, experiences, and achievements. Present the optimized CV in Markdown format. " |
| "Ensure the formatting is professional and avoid adding extra comments." |
| ) |
|
|
| |
| completion = client.chat.completions.create( |
| model="meta-llama/llama-4-maverick-17b-128e-instruct", |
| messages=[ |
| {"role": "system", "content": system_message}, |
| {"role": "user", "content": f"Job Description:\n{job_description}\n\nCV:\n{cv_text}"} |
| ], |
| temperature=0.7, |
| max_tokens=2048, |
| top_p=0.9, |
| stream=False, |
| ) |
|
|
| |
| return ''.join([chunk.message.content for chunk in completion.choices]) |
| except Exception as e: |
| return f"Error optimizing CV: {e}" |
|
|
| |
| from markdown2 import markdown |
| from bs4 import BeautifulSoup |
|
|
| def save_markdown_to_docx(markdown_text, output_docx_path="optimized_cv.docx"): |
| |
| html_content = markdown(markdown_text) |
|
|
| |
| soup = BeautifulSoup(html_content, "html.parser") |
|
|
| |
| doc = Document() |
|
|
| |
| for element in soup.descendants: |
| if element.name == "h1": |
| para = doc.add_paragraph(element.text, style="Heading 1") |
| elif element.name == "h2": |
| para = doc.add_paragraph(element.text, style="Heading 2") |
| elif element.name == "h3": |
| para = doc.add_paragraph(element.text, style="Heading 3") |
| elif element.name == "ul": |
| for li in element.find_all("li"): |
| doc.add_paragraph(li.text, style="List Bullet") |
| elif element.name == "ol": |
| for li in element.find_all("li"): |
| doc.add_paragraph(li.text, style="List Number") |
| elif element.name == "p": |
| doc.add_paragraph(element.text) |
| elif element.name == "strong": |
| para = doc.add_paragraph() |
| run = para.add_run(element.text) |
| run.bold = True |
| elif element.name == "em": |
| para = doc.add_paragraph() |
| run = para.add_run(element.text) |
| run.italic = True |
| elif element.name == "a": |
| para = doc.add_paragraph(element.text) |
| |
| para.add_run(f" ({element.get('href')})").italic = True |
|
|
| |
| doc.save(output_docx_path) |
| return output_docx_path |
|
|
| |
| def process_inputs(cv_file, job_description): |
| try: |
| |
| file_path = cv_file.name |
| file_extension = os.path.splitext(file_path)[1].lower() |
| if file_extension == ".pdf": |
| cv_text = read_pdf(file_path) |
| elif file_extension == ".docx": |
| cv_text = read_docx(file_path) |
| else: |
| return "Unsupported file format", None |
|
|
| |
| optimized_markdown = optimize_cv_with_llama(cv_text, job_description) |
|
|
| |
| output_docx_path = "optimized_cv.docx" |
| save_markdown_to_docx(optimized_markdown, output_docx_path) |
|
|
| return optimized_markdown, output_docx_path |
| except Exception as e: |
| return f"Error processing inputs: {e}", None |
|
|
| |
| def main(): |
| with gr.Blocks() as app: |
| |
| gr.Markdown( |
| """ |
| # **AI-Powered CV or Resume Optimizer** |
| Optimize your CV or Resume to match job descriptions using the power of AI. |
| This application processes your uploaded CV along with a job description and generates a tailored, professional CV ready for submission. |
| """ |
| ) |
|
|
| |
| file_input = gr.File(label="Upload Your Resume (PDF or DOCX)", file_count="single", |
| file_types=[".pdf", ".docx"], |
| type="filepath" |
| ) |
|
|
|
|
| job_description = gr.Textbox( |
| label="Job Description", |
| placeholder="Paste the job description here...", |
| lines=5 |
| ) |
|
|
|
|
| |
| markdown_output = gr.Markdown(label="Optimized CV Preview") |
| download_button = gr.File(label="Download Optimized CV (DOCX)") |
|
|
| |
| run_button = gr.Button("Optimize CV") |
|
|
| |
| def handle_inputs(cv_file, job_description): |
| markdown_text, docx_path = process_inputs(cv_file, job_description) |
| return markdown_text, docx_path |
|
|
| run_button.click( |
| handle_inputs, |
| inputs=[file_input, job_description], |
| outputs=[markdown_output, download_button] |
| ) |
|
|
| app.launch() |
|
|
| if __name__ == "__main__": |
| main() |