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("

🔗 JobLink AI Match Scorer

") gr.Markdown("

State-of-the-art semantic matching powered by fine-tuned DeBERTa-v3.

") 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( """
### 📊 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()