| | import gradio as gr |
| | import torch |
| | from transformers import AutoTokenizer |
| |
|
| | |
| | from model import MultiModalDetector |
| | from utils import collate_twibot_batch |
| |
|
| | |
| | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| | print(f"Initializing Application on {device}...") |
| |
|
| | |
| | model = MultiModalDetector(text_dim=768, vision_dim=512, graph_dim=128) |
| | model_path = "phase2_production_model.pth" |
| |
|
| | try: |
| | model.load_state_dict(torch.load(model_path, map_location=device)) |
| | print(f"β
Success: Weights loaded from {model_path}") |
| | except Exception as e: |
| | print(f"β Error: Could not load weights. Ensure '{model_path}' is in the same directory.") |
| | print(e) |
| |
|
| | model = model.to(device) |
| | model.eval() |
| |
|
| | |
| | tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased") |
| |
|
| | |
| | def gradio_predict(profile_id, bio, tweets, following_count, follower_count, image_url): |
| | following_list = [f"f_{i}" for i in range(int(following_count))] |
| | follower_list = [f"fl_{i}" for i in range(int(follower_count))] |
| | |
| | custom_data = { |
| | "ID": profile_id, |
| | "profile": { |
| | "description": bio, |
| | "profile_image_url": image_url |
| | }, |
| | "tweet": [t.strip() for t in tweets.split("|") if t.strip()], |
| | "neighbor": { |
| | "following": following_list, |
| | "follower": follower_list |
| | }, |
| | "label": 0 |
| | } |
| | |
| | try: |
| | text_inputs, images, graphs, _ = collate_twibot_batch([custom_data], tokenizer) |
| | text_inputs = {k: v.to(device) for k, v in text_inputs.items()} |
| | images = images.to(device) |
| | graphs = graphs.to(device) |
| | |
| | with torch.no_grad(): |
| | logits = model(text_inputs, images, graphs) |
| | logits = torch.clamp(logits, min=-10.0, max=10.0) |
| | probability = torch.sigmoid(logits).item() |
| | |
| | is_bot = probability >= 0.5 |
| | prediction = "π€ BOT (Fake Profile)" if is_bot else "π€ HUMAN (Real Profile)" |
| | confidence = (probability if is_bot else (1.0 - probability)) * 100 |
| | |
| | return f"{prediction}\nConfidence Score: {confidence:.2f}%" |
| | except Exception as e: |
| | return f"Error analyzing profile: {e}" |
| |
|
| | |
| | with gr.Blocks(theme=gr.themes.Soft()) as demo: |
| | gr.Markdown("# π΅οΈ Multi-Modal Fake Profile Detector") |
| | gr.Markdown("Enter the details of a social media account below to analyze if it is a Bot or a Human.") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | prof_id = gr.Textbox(label="Username", placeholder="@username") |
| | bio = gr.Textbox(label="Bio / Description", lines=2, placeholder="e.g., Crypto enthusiast. DM for 100x returns!") |
| | tweets = gr.Textbox(label="Recent Tweets (separate with | )", lines=3, placeholder="Tweet 1 | Tweet 2 | Tweet 3") |
| | img_url = gr.Textbox(label="Profile Image URL", placeholder="https://...") |
| | |
| | with gr.Row(): |
| | following = gr.Number(label="Following Count", value=100, precision=0) |
| | followers = gr.Number(label="Follower Count", value=10, precision=0) |
| | |
| | submit_btn = gr.Button("π Analyze Profile", variant="primary") |
| | |
| | with gr.Column(): |
| | output_res = gr.Textbox(label="Detection Result", lines=3) |
| | |
| | submit_btn.click(gradio_predict, |
| | inputs=[prof_id, bio, tweets, following, followers, img_url], |
| | outputs=output_res) |
| |
|
| | |
| | if __name__ == "__main__": |
| | demo.launch(server_name="0.0.0.0", server_port=7860) |
| |
|