| | import gradio as gr |
| | import requests |
| | import matplotlib.pyplot as plt |
| | import io |
| | import os |
| |
|
| | |
| | API_KEY = os.getenv("GEMINI_API_KEY") |
| | API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent" |
| |
|
| | def analyze_resume(resume_text, job_role): |
| | |
| | if not API_KEY: |
| | return "β No API key found. Please add GEMINI_API_KEY in Hugging Face secrets.", None |
| |
|
| | |
| | if not resume_text.strip(): |
| | return "β Please paste a resume first.", None |
| | if not job_role.strip(): |
| | return "β Please enter a target job role.", None |
| |
|
| | |
| | prompt = f""" |
| | You are an AI Resume Analyzer. |
| | Analyze the following resume for the job role: {job_role}. |
| | Resume: |
| | {resume_text} |
| | Provide output in this format clearly: |
| | 1. Strengths (bullet points) |
| | 2. Weaknesses (bullet points) |
| | 3. Suggested Improvements (bullet points) |
| | 4. Job Match Score (0-100) |
| | """ |
| |
|
| | headers = { |
| | "Content-Type": "application/json", |
| | "X-goog-api-key": API_KEY, |
| | } |
| |
|
| | data = { |
| | "contents": [ |
| | {"parts": [{"text": prompt}]} |
| | ] |
| | } |
| |
|
| | |
| | response = requests.post(API_URL, headers=headers, json=data) |
| |
|
| | if response.status_code != 200: |
| | return "β API Error: " + response.text, None |
| |
|
| | result = response.json() |
| | ai_text = result["candidates"][0]["content"]["parts"][0]["text"] |
| |
|
| | |
| | score = 0 |
| | for line in ai_text.splitlines(): |
| | if "Score" in line or "score" in line: |
| | try: |
| | score = int("".join([c for c in line if c.isdigit()])) |
| | if score > 100: |
| | score = 100 |
| | break |
| | except: |
| | score = 0 |
| |
|
| | |
| | fig, ax = plt.subplots(figsize=(4, 4)) |
| | ax.bar(["Job Match"], [score], color="deepskyblue") |
| | ax.set_ylim(0, 100) |
| | ax.set_ylabel("Score") |
| | ax.set_title(f"Resume Match for {job_role}") |
| |
|
| | buf = io.BytesIO() |
| | plt.savefig(buf, format="png", bbox_inches="tight") |
| | buf.seek(0) |
| |
|
| | return ai_text, buf |
| |
|
| | |
| | with gr.Blocks(theme=gr.themes.Soft()) as demo: |
| | gr.Markdown("<h1 style='text-align: center;'>π AI Resume Analyzer π―</h1>") |
| | gr.Markdown("### Upload or paste your resume + enter job role β Get instant AI feedback & score!") |
| |
|
| | with gr.Row(): |
| | resume_input = gr.Textbox( |
| | label="Paste Resume Text", |
| | lines=18, |
| | placeholder="Paste your resume here..." |
| | ) |
| | job_input = gr.Textbox( |
| | label="Target Job Role", |
| | placeholder="e.g. Data Scientist" |
| | ) |
| |
|
| | analyze_btn = gr.Button("π Analyze Resume", variant="primary") |
| |
|
| | with gr.Row(): |
| | output_text = gr.Textbox(label="AI Feedback", lines=18) |
| | output_plot = gr.Image(type="pil", label="Job Match Score") |
| |
|
| | analyze_btn.click(analyze_resume, inputs=[resume_input, job_input], outputs=[output_text, output_plot]) |
| |
|
| | demo.launch() |
| |
|