abnetsisaynew's picture
Upload app.py with huggingface_hub
7010ae0 verified
Raw
History Blame Contribute Delete
5.44 kB
import time
import gradio as gr
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
MODEL_ID = "abnetsisaynew/joblink-match-scorer"
# ── Model loading ─────────────────────────────────────────────────────────────
_startup_time = time.time()
print(f"⏳ Loading model: {MODEL_ID} ...")
_tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
_model = AutoModelForSequenceClassification.from_pretrained(
MODEL_ID,
num_labels=1,
problem_type="regression",
ignore_mismatched_sizes=True,
)
_model.eval().float()
_load_time = time.time() - _startup_time
print(f"βœ… Model loaded in {_load_time:.1f}s!")
# ── Prediction function ───────────────────────────────────────────────────────
def compute_score(text: str):
if not text or not text.strip():
return {"score": 0.0}
text = text.strip()[:4096]
tokens = _tokenizer(
text, truncation=True, padding="max_length",
max_length=512, return_tensors="pt"
)
with torch.no_grad():
score = _model(**tokens).logits.squeeze().item()
return {"score": round(float(max(0.0, min(1.0, score))), 4)}
custom_css = '''
.gradio-container {
font-family: 'Inter', sans-serif !important;
}
.header-text {
text-align: center;
color: var(--color-accent) !important;
font-weight: 800;
margin-bottom: 0.5rem;
font-size: 2.8rem !important;
letter-spacing: -0.025em;
}
.sub-text {
text-align: center;
color: var(--body-text-color-subdued) !important;
margin-bottom: 2rem;
font-size: 1.2rem !important;
}
.score-box {
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
'''
with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate"), css=custom_css, title="JobLink Matcher") as demo:
gr.Markdown("<h1 class='header-text'>πŸ”— JobLink AI Match Scorer</h1>")
gr.Markdown("<p class='sub-text'>State-of-the-art semantic matching powered by fine-tuned DeBERTa-v3.</p>")
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### πŸ“ Job Description & Candidate CV")
input_text = gr.Textbox(
show_label=False,
placeholder="JOB: Senior Software Engineer... [SEP] CANDIDATE: BSc Computer Science...",
lines=12,
container=False
)
submit_btn = gr.Button("πŸš€ Compute Match Score", variant="primary", size="lg")
with gr.Column(scale=1):
gr.Markdown("### 🎯 Match Score Result")
with gr.Group(elem_classes="score-box"):
output_json = gr.JSON(label="Result JSON")
gr.Markdown(
"""
<br>
### πŸ“Š Score Guide
- 🟒 **β‰₯ 0.85** : Excellent Match
- 🟑 **0.65 - 0.84** : Good Match
- 🟠 **0.40 - 0.64** : Moderate Match
- πŸ”΄ **< 0.40** : Poor Match
"""
)
# api_name="predict" creates the /call/predict endpoints natively!
submit_btn.click(fn=compute_score, inputs=input_text, outputs=output_json, api_name="predict")
gr.Markdown("---")
gr.Markdown("### πŸ§ͺ Quick Tests")
gr.Examples(
examples=[
# 1. Perfect Match
["JOB: Full Stack Developer. Experience: 4+ years. Required Skills: React, Node.js, MongoDB, TypeScript. [SEP] CANDIDATE: Full Stack Engineer. Experience: 5 years. Skills: React, Node.js, MongoDB, TypeScript, AWS."],
# 2. Good Match (Transferable Skills)
["JOB: Machine Learning Engineer. Required Skills: Python, PyTorch, SQL, Data Modeling. [SEP] CANDIDATE: Data Scientist. Experience: 3 years. Skills: Python, TensorFlow, SQL, Pandas."],
# 3. Junior applying for Senior (Experience Gap)
["JOB: Senior DevOps Engineer. Experience: 7+ years. Required Skills: Kubernetes, Terraform, AWS, CI/CD. [SEP] CANDIDATE: Junior Cloud Developer. Experience: 1 year. Skills: AWS, Docker, Git."],
# 4. Partial Skill Match (Skills Gap)
["JOB: UI/UX Designer. Required Skills: Figma, Adobe XD, Prototyping, User Research. [SEP] CANDIDATE: Graphic Designer. Skills: Adobe Illustrator, Photoshop, Branding."],
# 5. Missing Core Requirement
["JOB: Bilingual Customer Support (Spanish/English). Required Skills: Fluent Spanish, CRM, Communication. [SEP] CANDIDATE: Customer Service Rep. Skills: English, Zendesk, Communication."],
# 6. Completely Unrelated Match (Hard Knockout)
["JOB: Heart Surgeon. Field: Health Sciences. Experience: 10+ years. Required Skills: Surgery, Diagnostics. [SEP] CANDIDATE: Truck Driver. Field: Logistics. Experience: 10 years. Skills: Driving, Navigation."]
],
inputs=input_text
)
if __name__ == "__main__":
demo.launch()