import gradio as gr from huggingface_hub import InferenceClient import PyPDF2 import io from docx import Document import os import pymupdf # Corrected import for PyMuPDF from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib import colors client = InferenceClient( model="meta-llama/Meta-Llama-3-8B-Instruct", token=os.getenv("HF_TOKEN")) def extract_text_from_pdf(pdf_file): try: pdf_document = pymupdf.open(pdf_file) text = "".join(page.get_text() for page in pdf_document) return text.strip() or "No text could be extracted from the PDF." except Exception as e: return f"Error reading PDF: {e}" def extract_text_from_docx(docx_file): try: doc = Document(docx_file) text = "\n".join(para.text for para in doc.paragraphs) return text.strip() or "No text could be extracted from the DOCX file." except Exception as e: return f"Error reading DOCX: {e}" def parse_cv(file, job_description): if file is None: return "Please upload a CV file.", "" try: file_path = file.name file_ext = os.path.splitext(file_path)[1].lower() extracted_text = extract_text_from_pdf(file_path) if file_ext == ".pdf" else extract_text_from_docx(file_path) except Exception as e: return f"Error reading file: {e}", "" if extracted_text.startswith("Error"): return extracted_text, "Error during text extraction." prompt = f"Analyze this CV for job relevance.\nJob Description:\n{job_description}\n\nCV:\n{extracted_text}\n" try: analysis = client.text_generation(prompt, max_new_tokens=512) return extracted_text, f"**Analysis Report:**\n{analysis}" except Exception as e: return extracted_text, f"Analysis Error: {e}" def create_pdf_report(report_text): pdf_buffer = io.BytesIO() doc = SimpleDocTemplate(pdf_buffer, pagesize=letter) styles = getSampleStyleSheet() Story = [Paragraph("Analysis Report", styles['Title']), Spacer(1, 12)] Story.append(Paragraph(report_text.replace("\n", "
"), styles['BodyText'])) doc.build(Story) pdf_buffer.seek(0) return pdf_buffer.getvalue(), "analysis_report.pdf" def process_resume(resume_file, job_title): if resume_file is None: return "Please upload a resume file." try: file_path = resume_file.name file_ext = os.path.splitext(file_path)[1].lower() resume_text = extract_text_from_pdf(file_path) if file_ext == ".pdf" else extract_text_from_docx(file_path) if resume_text.startswith("Error"): return resume_text prompt = f"Optimize this resume for {job_title}:\n{resume_text}\n" optimized_resume = client.text_generation(prompt, max_new_tokens=1024) return optimized_resume.replace("\n", " \n") # Ensure Markdown formatting except Exception as e: return f"Error processing resume: {e}" demo = gr.Blocks() with demo: gr.Markdown("## AI-powered CV Analyzer and Optimizer") with gr.Tab("CV Analyzer"): file_input = gr.File(label="Upload CV", file_types=[".pdf", ".docx"]) job_desc_input = gr.Textbox(label="Job Description", lines=5) extracted_text = gr.Textbox(label="Extracted CV Content", lines=10, interactive=False) analysis_output = gr.Markdown(label="Analysis Report") download_pdf_button = gr.Button("Download Analysis as PDF", visible=False) pdf_file = gr.File(label="Download PDF", interactive=False) analyze_button = gr.Button("Analyze CV") analyze_button.click(parse_cv, [file_input, job_desc_input], [extracted_text, analysis_output]) download_pdf_button.click(create_pdf_report, [analysis_output], [pdf_file]) with gr.Tab("CV Optimizer"): resume_file = gr.File(label="Upload Resume (PDF or Word)", file_types=[".pdf", ".docx"]) job_title_input = gr.Textbox(label="Job Title") optimized_resume_output = gr.Markdown(label="Optimized Resume") optimize_button = gr.Button("Optimize Resume") optimize_button.click(process_resume, [resume_file, job_title_input], [optimized_resume_output]) if __name__ == "__main__": demo.queue().launch()