AIRecruitHub / app.py
BasitAliii's picture
Update app.py
043568d verified
import os
import gradio as gr
import numpy as np
import faiss
from sentence_transformers import SentenceTransformer
from groq import Groq
# ---------------- CONFIG ----------------
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
if not GROQ_API_KEY:
raise ValueError("Please set GROQ_API_KEY in Hugging Face Secrets")
# ---------------- INIT ----------------
client = Groq(api_key=GROQ_API_KEY)
embedder = SentenceTransformer("all-MiniLM-L6-v2")
EMBED_DIM = 384
faiss_index = faiss.IndexFlatIP(EMBED_DIM)
candidates = []
# ---------------- HELPERS ----------------
def embed_text(text: str):
vec = embedder.encode([text])
vec = vec / np.linalg.norm(vec)
return vec.astype("float32")
def llm_generate(prompt: str):
completion = client.chat.completions.create(
model="llama-3.1-8b-instant",
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return completion.choices[0].message.content
# ---------------- CORE FEATURES ----------------
def add_candidate(name, skills, experience):
if not name or not skills:
return (
"⚠️ Please fill in required fields.",
gr.update(),
gr.update(),
gr.update()
)
profile = f"Name: {name}\nSkills: {skills}\nExperience: {experience}"
vec = embed_text(profile)
faiss_index.add(vec)
candidates.append(profile)
return (
f"✅ Candidate **{name}** added successfully.",
gr.update(value=""), # clear name
gr.update(value=""), # clear skills
gr.update(value="") # clear experience
)
def generate_bio(raw_data):
prompt = f"""
You are a professional HR recruiter.
Write a concise, formal candidate bio.
Rules:
- Professional tone
- No emojis
- No exaggeration
- Max 120 words
Candidate Data:
{raw_data}
"""
return llm_generate(prompt)
def rewrite_job(job_desc):
prompt = f"""
Rewrite the job description below to meet modern recruitment standards.
Make it inclusive, clear, and well-structured.
Job Description:
{job_desc}
"""
return llm_generate(prompt)
def recommend_candidates(job_query):
if not candidates:
return "No candidates available.", "", "⚠️ Add candidates first."
job_vec = embed_text(job_query)
scores, ids = faiss_index.search(job_vec, k=min(3, len(candidates)))
ranked, reasons = [], []
for i, idx in enumerate(ids[0]):
candidate = candidates[idx]
explain_prompt = f"""
Explain why this candidate matches the job.
Focus only on skills and experience.
Candidate:
{candidate}
Job Requirements:
{job_query}
"""
ranked.append(f"### Rank {i+1}\n{candidate}")
reasons.append(llm_generate(explain_prompt))
return "\n\n".join(ranked), "\n\n".join(reasons), "✅ Recommendations generated"
# ---------------- LINKEDIN POST GENERATOR (NEW) ----------------
def generate_linkedin_post(context_type, content):
prompt = f"""
You are a LinkedIn content strategist for HR & AI professionals.
Create a LinkedIn post based on the context below.
Context Type: {context_type}
Rules:
- Professional but engaging tone
- Short paragraphs
- Strong hook at the beginning
- Clear CTA at the end
- 5–8 relevant hashtags
- Max 2 emojis
- Do NOT mention AI model names
Content:
{content}
"""
return llm_generate(prompt)
# ---------------- UI ----------------
theme = gr.themes.Soft(
primary_hue="blue",
secondary_hue="slate",
neutral_hue="gray",
)
with gr.Blocks(theme=theme) as demo:
gr.Markdown("""
# 🤖 AI Recruitment Assistant
**Recruit smarter. Hire faster. Share better.**
""")
gr.Markdown("---")
with gr.Tabs():
# -------- Add Candidate --------
with gr.Tab("➕ Add Candidate"):
with gr.Row():
with gr.Column():
name = gr.Textbox(label="Candidate Name *")
skills = gr.Textbox(label="Key Skills *")
experience = gr.Textbox(label="Experience Summary", lines=4)
add_btn = gr.Button("Add Candidate", variant="primary")
status = gr.Markdown()
with gr.Column():
gr.Markdown("""
### Tips
- Mention years of experience
- Use clear skill names
- Avoid generic wording
""")
add_btn.click(
add_candidate,
inputs=[name, skills, experience],
outputs=[status, name, skills, experience]
)
# -------- Bio Generator --------
with gr.Tab("🧾 Candidate Bio Generator"):
raw_data = gr.Textbox(lines=6, placeholder="Paste raw CV or notes...")
bio_btn = gr.Button("Generate Bio", variant="primary")
bio_output = gr.Textbox(lines=6)
bio_btn.click(generate_bio, raw_data, bio_output)
# -------- Job Rewriter --------
with gr.Tab("📄 Job Description Optimizer"):
job_desc = gr.Textbox(lines=6, placeholder="Paste job description...")
rewrite_btn = gr.Button("Rewrite Professionally", variant="primary")
rewrite_output = gr.Textbox(lines=6)
rewrite_btn.click(rewrite_job, job_desc, rewrite_output)
# -------- Recommendation --------
with gr.Tab("🎯 Candidate Recommendation"):
job_query = gr.Textbox(lines=5, placeholder="Enter job requirements...")
rec_btn = gr.Button("Find Best Matches", variant="primary")
with gr.Row():
rec_candidates = gr.Markdown()
rec_explanation = gr.Textbox(lines=10)
rec_status = gr.Markdown()
rec_btn.click(
recommend_candidates,
job_query,
[rec_candidates, rec_explanation, rec_status]
)
# -------- LinkedIn Post Generator (NEW) --------
with gr.Tab("📣 LinkedIn Post Generator"):
gr.Markdown("### Turn AI outputs into LinkedIn-ready posts")
post_type = gr.Dropdown(
label="Post Context",
choices=[
"Candidate Bio Highlight",
"Job Hiring Announcement",
"AI-Based Candidate Recommendation"
]
)
post_input = gr.Textbox(
lines=8,
placeholder="Paste generated bio, job description, or recommendation..."
)
post_btn = gr.Button("Generate LinkedIn Post", variant="primary")
post_output = gr.Textbox(lines=10, label="LinkedIn Post")
post_btn.click(
generate_linkedin_post,
inputs=[post_type, post_input],
outputs=post_output
)
# -------- About --------
with gr.Tab("📘 About"):
gr.Markdown("""
### What is this app?
An AI-powered recruitment assistant that helps recruiters:
- Manage candidates
- Improve hiring content
- Match talent intelligently
- Generate social media content
### Use Case
Generate → Optimize → Match → Share on LinkedIn
### Ideal for
Recruiters • HR Tech • AI Portfolios • Startups
""")
gr.Markdown("--- Built for Hugging Face Spaces 🚀")
demo.launch()