import gradio as gr import torch from transformers import AlbertTokenizer, AlbertForSequenceClassification, BertTokenizer, BertForSequenceClassification import torch.nn.functional as F # Load models albert_model = AlbertForSequenceClassification.from_pretrained("Deepaksai1/albert-fraud-detector-v2").eval() albert_tokenizer = AlbertTokenizer.from_pretrained("Deepaksai1/albert-fraud-detector-v2") finbert_model = BertForSequenceClassification.from_pretrained("Deepaksai1/finbert-fraud-detector-v2").eval() finbert_tokenizer = BertTokenizer.from_pretrained("Deepaksai1/finbert-fraud-detector-v2") # Feature engineering function def engineer_features(step, tx_type, amount, old_org, new_org, old_dest, new_dest): # Calculate derived features orig_diff = amount - (old_org - new_org) dest_diff = (new_dest - old_dest) - amount zero_balance = 1 if new_org == 0 else 0 amount_fraction = amount / old_org if old_org > 0 else 0 # Enhanced text representation with engineered features text = (f"Step: {step}, Type: {tx_type}, Amount: {amount}, " f"OldBalOrig: {old_org}, NewBalOrig: {new_org}, " f"OldBalDest: {old_dest}, NewBalDest: {new_dest}, " f"OrigDiff: {orig_diff}, DestDiff: {dest_diff}, " f"ZeroBalance: {zero_balance}, AmountFraction: {amount_fraction}") # Return text for transformer models and transaction metadata metadata = { 'amount': amount, 'zero_balance': zero_balance, 'orig_diff': orig_diff } return text, metadata # Individual model prediction def predict_single_model(text, model_name): tokenizer = albert_tokenizer if model_name == "ALBERT" else finbert_tokenizer model = albert_model if model_name == "ALBERT" else finbert_model inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=128) with torch.no_grad(): outputs = model(**inputs) probs = F.softmax(outputs.logits, dim=1) fraud_score = probs[0][1].item() return fraud_score # Ensemble prediction with adaptive thresholding def ensemble_predict(step, tx_type, amount, old_org, new_org, old_dest, new_dest, use_ensemble=True): # Engineer features text, metadata = engineer_features(step, tx_type, amount, old_org, new_org, old_dest, new_dest) # Get individual model predictions albert_score = predict_single_model(text, "ALBERT") finbert_score = predict_single_model(text, "FinBERT") if use_ensemble: # Weighted ensemble (ALBERT performs better so weighted higher) weights = {"ALBERT": 0.6, "FinBERT": 0.4} ensemble_score = weights["ALBERT"] * albert_score + weights["FinBERT"] * finbert_score # Adaptive thresholding based on transaction characteristics base_threshold = 0.5 if metadata['amount'] > 1000000: # High-value transaction threshold = base_threshold - 0.1 # Lower threshold for high-risk elif metadata['zero_balance'] == 1: # Account emptying threshold = base_threshold - 0.15 elif abs(metadata['orig_diff']) > 1000: # Suspicious balance difference threshold = base_threshold - 0.08 else: threshold = base_threshold is_fraud = ensemble_score > threshold result = "Fraud" if is_fraud else "Not Fraud" # Return individual scores as well for transparency return result, ensemble_score, albert_score, finbert_score, threshold else: # For comparison, return individual model results return "See individual scores", 0, albert_score, finbert_score, 0.5 # Gradio Interface with gr.Blocks() as demo: gr.Markdown("## 🔎 Advanced Hybrid Fraud Detection System") with gr.Row(): step = gr.Number(label="Step", value=1) tx_type = gr.Dropdown(choices=["CASH_OUT", "TRANSFER", "PAYMENT", "DEBIT", "CASH_IN"], label="Transaction Type") amount = gr.Number(label="Amount", value=0.0) with gr.Row(): old_org = gr.Number(label="Old Balance Orig", value=0.0) new_org = gr.Number(label="New Balance Orig", value=0.0) with gr.Row(): old_dest = gr.Number(label="Old Balance Dest", value=0.0) new_dest = gr.Number(label="New Balance Dest", value=0.0) with gr.Row(): use_ensemble = gr.Checkbox(label="Use Ensemble Model", value=True) with gr.Row(): predict_btn = gr.Button("Predict") with gr.Row(): pred_label = gr.Label(label="Final Prediction") ensemble_score = gr.Number(label="Ensemble Score") with gr.Row(): albert_score = gr.Number(label="ALBERT Score") finbert_score = gr.Number(label="FinBERT Score") threshold = gr.Number(label="Applied Threshold") # Bind function predict_btn.click( fn=ensemble_predict, inputs=[step, tx_type, amount, old_org, new_org, old_dest, new_dest, use_ensemble], outputs=[pred_label, ensemble_score, albert_score, finbert_score, threshold] ) # Example transactions examples = [ [151, "CASH_OUT", 1633227.0, 1633227.0, 0.0, 2865353.22, 4498580.23, True], [353, "CASH_OUT", 174566.53, 174566.53, 0.0, 1191715.74, 1366282.27, True], [357, "TRANSFER", 484493.06, 484493.06, 0.0, 0.0, 0.0, True], [43, "CASH_OUT", 81571.63, 0.0, 0.0, 176194.2, 257765.83, True], [307, "DEBIT", 247.82, 11544.0, 11296.18, 3550535.53, 3550783.36, True], [350, "DEBIT", 4330.57, 3766.0, 0.0, 239435.41, 243765.98, True] ] gr.Examples(examples=examples, inputs=[step, tx_type, amount, old_org, new_org, old_dest, new_dest, use_ensemble]) # Launch app if __name__ == "__main__": demo.launch()