File size: 5,500 Bytes
3935f98
 
71c7cb5
87475e8
ec1a8b9
628f061
 
83eba02
ec1a8b9
 
83eba02
628f061
74f556d
b99d884
 
3935f98
628f061
ec1a8b9
39890ac
74f556d
 
39890ac
 
93e353c
71c7cb5
628f061
ec1a8b9
39890ac
ec1a8b9
39890ac
 
 
93e353c
71c7cb5
628f061
ec1a8b9
 
628f061
39890ac
74f556d
ec1a8b9
628f061
 
 
 
 
 
39890ac
628f061
8af823f
628f061
 
 
 
 
 
 
39890ac
8af823f
628f061
 
 
39890ac
628f061
87475e8
628f061
b99d884
628f061
 
 
 
 
b99d884
628f061
b99d884
628f061
 
 
4aeb0f2
628f061
 
 
 
 
 
c710d9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628f061
71c7cb5
 
6560ce2
71c7cb5
628f061
ec1a8b9
3751b1c
74f556d
628f061
83eba02
c710d9e
 
628f061
c710d9e
 
 
 
 
 
 
83eba02
3935f98
c710d9e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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()