Spaces:
Runtime error
Runtime error
| import pickle | |
| import json | |
| import torch | |
| from fastapi import FastAPI | |
| from pydantic import BaseModel | |
| from transformers import BertTokenizer | |
| import io | |
| # 1. Initialize App and Load Assets | |
| # ================================== | |
| app = FastAPI( | |
| title="TEXI'OR Sentiment Analysis API", | |
| description="An API to classify text into different sentiments using a fine-tuned BERT model.", | |
| version="1.0" | |
| ) | |
| class TextInput(BaseModel): | |
| text: str | |
| device = torch.device('cpu') | |
| print(f"β Using device: {device}") | |
| # Custom Unpickler to load a GPU-trained model onto a CPU | |
| class CPU_Unpickler(pickle.Unpickler): | |
| def find_class(self, module, name): | |
| if module == 'torch.storage' and name == '_load_from_bytes': | |
| return lambda b: torch.load(io.BytesIO(b), map_location='cpu') | |
| else: | |
| return super().find_class(module, name) | |
| # Load the fine-tuned model and tokenizer | |
| try: | |
| with open('bert_sentiment_model.pkl', 'rb') as f: | |
| model = CPU_Unpickler(f).load() | |
| model.to(device) | |
| model.eval() | |
| print("β Model 'bert_sentiment_model.pkl' loaded successfully onto CPU.") | |
| except FileNotFoundError: | |
| print("β Model file not found. Make sure 'bert_sentiment_model.pkl' is uploaded.") | |
| model = None | |
| try: | |
| with open('Label_Dict.json', 'r') as f: | |
| label_dict = json.load(f) | |
| idx2label = {int(v): k for k, v in label_dict.items()} | |
| print("β Label dictionary 'Label_Dict.json' loaded successfully.") | |
| except FileNotFoundError: | |
| print("β Label dictionary 'Label_Dict.json' not found.") | |
| idx2label = None | |
| tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') | |
| print("β Tokenizer loaded successfully.") | |
| # 2. Define API Endpoints | |
| # ======================== | |
| def read_root(): | |
| return {"message": "Welcome to the TEXI'OR API. Use the /predict endpoint to get a sentiment."} | |
| def predict_sentiment(text_input: TextInput): | |
| if not all([model, idx2label, tokenizer]): | |
| return {"error": "API is not ready. A model, label, or tokenizer component failed to load."} | |
| text = text_input.text | |
| inputs = tokenizer( | |
| text, padding=True, truncation=True, max_length=150, return_tensors='pt' | |
| ) | |
| input_ids = inputs['input_ids'].to(device) | |
| attention_mask = inputs['attention_mask'].to(device) | |
| with torch.no_grad(): | |
| outputs = model(input_ids=input_ids, attention_mask=attention_mask) | |
| logits = outputs.logits | |
| probabilities = torch.nn.functional.softmax(logits, dim=-1) | |
| confidence, predicted_class_idx = torch.max(probabilities, dim=1) | |
| predicted_label = idx2label.get(predicted_class_idx.item(), "Unknown Label") | |
| confidence_score = confidence.item() | |
| return { | |
| "sentiment": predicted_label, | |
| "confidence": round(confidence_score, 4) | |
| } |