Spaces:
Runtime error
Runtime error
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| import torch | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| from transformers import T5Tokenizer, T5ForConditionalGeneration | |
| import os | |
| app = FastAPI(title="Clickbait Detector API") | |
| # Enable CORS for Chrome Extension | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Global variables for models | |
| tokenizer = None | |
| model = None | |
| t5_tokenizer = None | |
| t5_model = None | |
| device = None | |
| async def load_models(): | |
| """Load models on startup""" | |
| global tokenizer, model, t5_tokenizer, t5_model, device | |
| device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') | |
| print(f"Using device: {device}") | |
| # Load DistilBERT | |
| print("Loading DistilBERT model...") | |
| tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased") | |
| model = AutoModelForSequenceClassification.from_pretrained( | |
| "./clickbait_detector_model" | |
| ) | |
| model.to(device) | |
| model.eval() | |
| print("✓ DistilBERT loaded") | |
| # Load T5 | |
| print("Loading T5 model...") | |
| t5_tokenizer = T5Tokenizer.from_pretrained("t5-base") | |
| t5_model = T5ForConditionalGeneration.from_pretrained( | |
| "./t5_clickbait_rewriter_finetuned" | |
| ) | |
| t5_model.to(device) | |
| t5_model.eval() | |
| print("✓ T5 loaded") | |
| class HeadlineRequest(BaseModel): | |
| headline: str | |
| def root(): | |
| return { | |
| "name": "Clickbait Detector API", | |
| "version": "1.0.0", | |
| "status": "online", | |
| "endpoints": { | |
| "/detect": "POST - Detect if headline is clickbait", | |
| "/rewrite": "POST - Rewrite clickbait to neutral", | |
| "/analyze": "POST - Detect + Rewrite in one call" | |
| } | |
| } | |
| def detect_clickbait(request: HeadlineRequest): | |
| """Detect if headline is clickbait""" | |
| try: | |
| inputs = tokenizer( | |
| request.headline, | |
| return_tensors='pt', | |
| padding=True, | |
| truncation=True, | |
| max_length=128 | |
| ).to(device) | |
| with torch.no_grad(): | |
| outputs = model(**inputs) | |
| probs = torch.softmax(outputs.logits, dim=1) | |
| prediction = torch.argmax(probs, dim=1).item() | |
| confidence = probs[0][prediction].item() | |
| return { | |
| "headline": request.headline, | |
| "is_clickbait": bool(prediction), | |
| "confidence": float(confidence), | |
| "label": "clickbait" if prediction else "neutral" | |
| } | |
| except Exception as e: | |
| return {"error": str(e)} | |
| def rewrite_headline(request: HeadlineRequest): | |
| """Rewrite clickbait headline to neutral""" | |
| try: | |
| prompt = f"rewrite clickbait to neutral: {request.headline}" | |
| inputs = t5_tokenizer( | |
| prompt, | |
| return_tensors='pt', | |
| max_length=128, | |
| truncation=True | |
| ).to(device) | |
| with torch.no_grad(): | |
| outputs = t5_model.generate( | |
| inputs['input_ids'], | |
| max_length=64, | |
| num_beams=5, | |
| early_stopping=True | |
| ) | |
| neutral = t5_tokenizer.decode(outputs[0], skip_special_tokens=True) | |
| return { | |
| "original": request.headline, | |
| "rewritten": neutral | |
| } | |
| except Exception as e: | |
| return {"error": str(e)} | |
| def analyze_headline(request: HeadlineRequest): | |
| """Detect and rewrite in one call""" | |
| try: | |
| detection = detect_clickbait(request) | |
| if detection.get("is_clickbait"): | |
| rewrite = rewrite_headline(request) | |
| return { | |
| **detection, | |
| "rewritten": rewrite.get("rewritten") | |
| } | |
| else: | |
| return { | |
| **detection, | |
| "rewritten": request.headline, | |
| "message": "Headline is already neutral" | |
| } | |
| except Exception as e: | |
| return {"error": str(e)} | |