TRUTHLENSAI / web_app /backend /models.py
gregorio
fix: resolve Bi-LSTM model loading error and adjust frontend input UI to fit single page
c07a5d9
Raw
History Blame Contribute Delete
2.5 kB
import torch
import torch.nn as nn
from transformers import AutoModelForSequenceClassification
# Bi-LSTM Components
class AttentionPool(nn.Module):
def __init__(self, h):
super().__init__()
self.w = nn.Linear(h * 2, 1)
def forward(self, x):
# x: (batch, seq, hidden*2)
attn_weights = torch.softmax(self.w(x), dim=1)
return (x * attn_weights).sum(1)
class BiLSTMClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim, n_layers, dropout):
super().__init__()
self.emb = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.lstm = nn.LSTM(embed_dim, hidden_dim, n_layers,
batch_first=True, bidirectional=True,
dropout=dropout if n_layers > 1 else 0)
self.pool = AttentionPool(hidden_dim)
self.fake_real_head = nn.Linear(hidden_dim * 2, 2)
self.ai_human_head = nn.Linear(hidden_dim * 2, 2)
def forward(self, x):
emb_out = self.emb(x)
lstm_out, _ = self.lstm(emb_out)
pooled = self.pool(lstm_out)
logits_fake_real = self.fake_real_head(pooled)
logits_ai_human = self.ai_human_head(pooled)
return logits_fake_real, logits_ai_human
# Transformer Wrapper
class TransformerClassifier(nn.Module):
def __init__(self, model_name):
super().__init__()
from transformers import AutoModel
self.encoder = AutoModel.from_pretrained(model_name)
h_size = self.encoder.config.hidden_size
self.fake_real_head = nn.Sequential(
nn.Dropout(0.1), nn.Linear(h_size, h_size), nn.Tanh(),
nn.Dropout(0.1), nn.Linear(h_size, 2)
)
self.ai_human_head = nn.Sequential(
nn.Dropout(0.1), nn.Linear(h_size, h_size), nn.Tanh(),
nn.Dropout(0.1), nn.Linear(h_size, 2)
)
def forward(self, **kwargs):
# RoBERTa and DistilRoBERTa do not use token_type_ids
if 'token_type_ids' in kwargs and self.encoder.config.model_type in ['roberta', 'distilroberta']:
kwargs.pop('token_type_ids', None)
out = self.encoder(**kwargs)
cls_rep = out.last_hidden_state[:, 0, :]
# Cast cls_rep to match head parameter dtype to prevent half/float mismatch
head_dtype = next(self.fake_real_head.parameters()).dtype
cls_rep = cls_rep.to(head_dtype)
return self.fake_real_head(cls_rep), self.ai_human_head(cls_rep)