Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from huggingface_hub import InferenceClient | |
| import io | |
| from docx import Document | |
| import os | |
| import pymupdf | |
| # For PDF generation | |
| from reportlab.lib.pagesizes import letter | |
| from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer | |
| from reportlab.lib.styles import getSampleStyleSheet | |
| # Initialize Hugging Face Inference Client | |
| client = InferenceClient( | |
| model="meta-llama/Meta-Llama-3-8B-Instruct", | |
| token=os.getenv("HF_TOKEN")) | |
| # Function to extract text from PDF | |
| 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}" | |
| # Function to extract text from DOCX | |
| 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}" | |
| # Function to analyze CV and generate report | |
| def parse_cv(file, job_description): | |
| if file is None: | |
| return "Please upload a CV file.", "", None | |
| try: | |
| file_path = file.name | |
| file_ext = os.path.splitext(file_path)[1].lower() | |
| if file_ext == ".pdf": | |
| extracted_text = extract_text_from_pdf(file_path) | |
| elif file_ext == ".docx": | |
| extracted_text = extract_text_from_docx(file_path) | |
| else: | |
| return "Unsupported file format. Please upload a PDF or DOCX file.", "", None | |
| except Exception as e: | |
| return f"Error reading file: {e}", "", None | |
| if extracted_text.startswith("Error"): | |
| return extracted_text, "Error during text extraction. Please check the file.", None | |
| prompt = ( | |
| f"Analyze the CV against the job description. Provide a summary, assessment, " | |
| f"and a score 0-10.\n\n" | |
| f"Job Description:\n{job_description}\n\n" | |
| f"Candidate CV:\n{extracted_text}\n" | |
| ) | |
| try: | |
| analysis = client.text_generation(prompt, max_new_tokens=512) | |
| report_text = f"--- Analysis Report ---\n{analysis}" | |
| pdf_path = create_pdf_report(report_text) # Generate PDF in the backend | |
| return extracted_text, report_text, pdf_path | |
| except Exception as e: | |
| return extracted_text, f"Analysis Error: {e}", None | |
| # Function to create PDF report | |
| def create_pdf_report(report_text): | |
| if not report_text.strip(): | |
| report_text = "No analysis report to convert." | |
| pdf_path = "analysis_report.pdf" | |
| doc = SimpleDocTemplate(pdf_path, pagesize=letter) | |
| styles = getSampleStyleSheet() | |
| Story = [] | |
| title = Paragraph("<b>Analysis Report</b>", styles['Title']) | |
| Story.append(title) | |
| Story.append(Spacer(1, 12)) | |
| report_paragraph = Paragraph(report_text.replace("\n", "<br/>"), styles['BodyText']) | |
| Story.append(report_paragraph) | |
| doc.build(Story) | |
| return pdf_path | |
| # Function to process and optimize resume | |
| 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() | |
| if file_ext == ".pdf": | |
| resume_text = extract_text_from_pdf(file_path) | |
| elif file_ext == ".docx": | |
| resume_text = extract_text_from_docx(file_path) | |
| else: | |
| return "Unsupported file format. Please upload a PDF or DOCX file." | |
| if resume_text.startswith("Error"): | |
| return resume_text | |
| prompt = ( | |
| f"Optimize the following resume for the job title: {job_title}.\n" | |
| f"Include relevant skills, experience, and keywords related to the job title.\n\n" | |
| f"Resume:\n{resume_text}\n" | |
| ) | |
| optimized_resume = client.text_generation(prompt, max_new_tokens=1024) | |
| return optimized_resume | |
| except Exception as e: | |
| return f"Error processing resume: {e}" | |
| # Build the Gradio UI | |
| demo = gr.Blocks() | |
| with demo: | |
| gr.Markdown("## AI-powered CV Analyzer and Optimizer") | |
| with gr.Tab("CV Analyzer"): | |
| gr.Markdown("### Upload your CV and provide the job description") | |
| 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.Textbox(label="Analysis Report", lines=10, interactive=False) | |
| analyze_button = gr.Button("Analyze CV") | |
| download_pdf_button = gr.File(label="Download Analysis Report PDF", interactive=False) | |
| analyze_button.click(parse_cv, [file_input, job_desc_input], [extracted_text, analysis_output, download_pdf_button]) | |
| with gr.Tab("CV Optimizer"): | |
| gr.Markdown("### Upload your Resume and Enter Job Title") | |
| resume_file = gr.File(label="Upload Resume (PDF or Word)", file_types=[".pdf", ".docx"]) | |
| job_title_input = gr.Textbox(label="Job Title", lines=1) | |
| optimized_resume_output = gr.Textbox(label="Optimized Resume", lines=20) | |
| 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() |