| import torch, torch.nn.functional as F |
| import gradio as gr |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification |
|
|
| MODEL_CKPT = "distilbert-base-uncased" |
| DEVICE = "cpu" |
|
|
| print("--- Loading tokenizer & base model ---") |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_CKPT) |
| model = AutoModelForSequenceClassification.from_pretrained(MODEL_CKPT) |
|
|
| print("--- Loading merged fine-tuned weights ---") |
| model.load_state_dict(torch.load("DISTILBERT_MERGED.pth", map_location=DEVICE)) |
| model.to(DEVICE).eval() |
|
|
| |
| model.config.id2label = {0: "NEGATIVE", 1: "POSITIVE"} |
| model.config.label2id = {v: k for k, v in model.config.id2label.items()} |
|
|
| def predict(text): |
| tokens = tokenizer( |
| text, |
| return_tensors="pt", |
| padding="max_length", |
| truncation=True, |
| max_length=256 |
| ).to(DEVICE) |
|
|
| with torch.no_grad(): |
| probs = F.softmax(model(**tokens).logits, dim=-1)[0] |
| return {model.config.id2label[i]: float(p) for i, p in enumerate(probs)} |
|
|
| demo = gr.Interface( |
| fn=predict, |
| inputs=gr.Textbox(lines=3, label="Movie Review"), |
| outputs=gr.Label(num_top_classes=2, label="Sentiment"), |
| title="Sentiment Analysis (LoRA-merged DistilBERT)", |
| description=( |
| "DistilBERT fine-tuned on IMDB with a custom LoRA adapter. " |
| "Adapters have been merged so the model runs with no extra parameters." |
| ), |
| examples=[ |
| ["An absolute masterpiece with brilliant acting!"], |
| ["Total waste of two hours."], |
| ["Predictable plot but gorgeous visuals."] |
| ] |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch() |