LPX55 commited on
Commit
3a48c1e
·
verified ·
1 Parent(s): 6ff78ef

Update app.py from anycoder

Browse files
Files changed (1) hide show
  1. app.py +228 -0
app.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import random
4
+ import time
5
+ from datetime import datetime
6
+
7
+ # --- Simulated Backend Logic ---
8
+ # In a real production environment, this would use libraries like `python-telegram-bot` or `Telethon`
9
+ # to connect to the Telegram API and a model like Hugging Face's `toxic-bert` for detection.
10
+
11
+ class TelegramMonitorSimulator:
12
+ def __init__(self):
13
+ self.hate_keywords = ["hate", "violence", "attack", "stupid", "kill", "idiot"]
14
+ self.sample_messages = [
15
+ "Great meeting today everyone!",
16
+ "I really hate the way this is going.",
17
+ "Check out this new article.",
18
+ "This is just stupid, nobody cares.",
19
+ "Lovely weather we are having.",
20
+ "We should attack this problem head on.",
21
+ "Hello world!",
22
+ "I want to kill this process."
23
+ ]
24
+ self.monitored_channels = []
25
+
26
+ def add_channel(self, channel_name):
27
+ if channel_name and channel_name not in self.monitored_channels:
28
+ self.monitored_channels.append(channel_name)
29
+ return f"Added '{channel_name}' to monitoring list."
30
+ return "Channel already exists or name is empty."
31
+
32
+ def process_incoming_message(self):
33
+ """Simulates the bot receiving a message from a monitored channel."""
34
+ if not self.monitored_channels:
35
+ return None, "No channels monitored. Add a channel first."
36
+
37
+ # Pick random channel and message
38
+ channel = random.choice(self.monitored_channels)
39
+ text = random.choice(self.sample_messages)
40
+
41
+ # Simple detection logic (Simulating an AI model)
42
+ detected = any(word in text.lower() for word in self.hate_keywords)
43
+ score = random.uniform(0.7, 0.99) if detected else random.uniform(0.0, 0.3)
44
+
45
+ return {
46
+ "id": int(time.time() * 1000),
47
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
48
+ "channel": channel,
49
+ "message": text,
50
+ "score": round(score, 2),
51
+ "status": "Pending Review"
52
+ }, None
53
+
54
+ # Initialize the simulator
55
+ monitor = TelegramMonitorSimulator()
56
+
57
+ # --- Gradio Application ---
58
+
59
+ def update_dashboard(logs):
60
+ """Helper to convert logs state to dataframe for display."""
61
+ if not logs:
62
+ return pd.DataFrame(columns=["ID", "Time", "Channel", "Message", "Score", "Status"])
63
+ return pd.DataFrame(logs)[["id", "timestamp", "channel", "message", "score", "status"]]
64
+
65
+ def add_channel_handler(channel_input, current_channels):
66
+ result = monitor.add_channel(channel_input)
67
+ # Return updated list of channels for the display/State
68
+ updated_channels = monitor.monitored_channels.copy()
69
+ return result, updated_channels
70
+
71
+ def simulate_traffic_handler(current_logs):
72
+ """Simulates the bot detecting a hate speech event."""
73
+ new_entry, error = monitor.process_incoming_message()
74
+
75
+ if error:
76
+ return current_logs, update_dashboard(current_logs), error
77
+
78
+ # Only log if it looks like hate speech (score > 0.6) for the demo purposes
79
+ # or log everything if you want a full history. Let's log flagged only.
80
+ if new_entry['score'] > 0.6:
81
+ updated_logs = current_logs.copy()
82
+ updated_logs.insert(0, new_entry) # Add to top
83
+ return updated_logs, update_dashboard(updated_logs), "⚠️ New Potential Hate Speech Detected!"
84
+
85
+ return current_logs, update_dashboard(current_logs), "Message received (clean)."
86
+
87
+ def assess_message(logs, selected_id, assessment):
88
+ """Updates the status of a selected message."""
89
+ if not logs or selected_id is None:
90
+ return logs, update_dashboard(logs), gr.Dropdown(choices=[], value=None), "No message selected."
91
+
92
+ updated_logs = []
93
+ found = False
94
+ for log in logs:
95
+ if log['id'] == selected_id:
96
+ log['status'] = assessment
97
+ found = True
98
+ updated_logs.append(log)
99
+
100
+ if found:
101
+ # Refresh dropdown choices (remove the assessed item from pending)
102
+ pending_ids = [l['id'] for l in updated_logs if l['status'] == "Pending Review"]
103
+ return updated_logs, update_dashboard(updated_logs), gr.Dropdown(choices=pending_ids, value=None), f"Message ID {selected_id} marked as {assessment}."
104
+
105
+ return logs, update_dashboard(logs), gr.Dropdown(choices=[l['id'] for l in logs if l['status'] == "Pending Review"], value=None), "Message not found."
106
+
107
+ # --- Gradio UI Construction ---
108
+
109
+ # Note: In Gradio 6, Blocks takes no parameters. Configuration goes in launch().
110
+ with gr.Blocks() as demo:
111
+
112
+ # Header
113
+ gr.HTML("""
114
+ <div style="text-align: center; margin-bottom: 2rem;">
115
+ <h1>🛡️ Telegram Hate Speech Monitor</h1>
116
+ <p>AI-powered monitoring dashboard for public channel safety</p>
117
+ <p style="font-size: 0.9em; color: gray;">
118
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
119
+ </p>
120
+ </div>
121
+ """)
122
+
123
+ with gr.Row():
124
+ # Left Column: Controls
125
+ with gr.Column(scale=1):
126
+ gr.Markdown("### ⚙️ Configuration")
127
+
128
+ with gr.Group():
129
+ channel_input = gr.Textbox(label="Channel Username", placeholder="@example_channel")
130
+ add_channel_btn = gr.Button("Add Channel", variant="primary")
131
+ channel_status = gr.Textbox(label="Status", interactive=False)
132
+
133
+ monitored_list = gr.JSON(label="Monitored Channels", value=[])
134
+
135
+ gr.Markdown("### 📡 Live Monitor (Simulated)")
136
+ gr.Markdown("*Click to simulate incoming messages from monitored channels.*")
137
+ simulate_btn = gr.Button("Simulate Incoming Traffic", variant="secondary")
138
+ monitor_status = gr.Textbox(label="Monitor Log", interactive=False)
139
+
140
+ # Right Column: Dashboard
141
+ with gr.Column(scale=3):
142
+ gr.Markdown("### 📋 Flagged Content Review")
143
+
144
+ # Dataframe to show logs
145
+ logs_df = gr.Dataframe(
146
+ label="Detected Messages",
147
+ headers=["ID", "Time", "Channel", "Message", "Score", "Status"],
148
+ datatype=["number", "str", "str", "str", "number", "str"],
149
+ interactive=False,
150
+ wrap=True
151
+ )
152
+
153
+ gr.Markdown("### ✍️ Human Assessment")
154
+ with gr.Row():
155
+ msg_selector = gr.Dropdown(
156
+ label="Select Pending Message ID",
157
+ choices=[],
158
+ info="Select a message from the list above to review"
159
+ )
160
+
161
+ with gr.Row():
162
+ approve_btn = gr.Button("✅ Confirm Hate Speech", variant="stop")
163
+ reject_btn = gr.Button("❌ False Positive", variant="secondary")
164
+
165
+ assessment_feedback = gr.Textbox(label="Assessment Result", interactive=False)
166
+
167
+ # --- State Management ---
168
+ # We store the raw logs in state so we can manipulate them
169
+ logs_state = gr.State(value=[])
170
+
171
+ # --- Event Listeners ---
172
+
173
+ # 1. Add Channel
174
+ add_channel_btn.click(
175
+ fn=add_channel_handler,
176
+ inputs=[channel_input, monitored_list],
177
+ outputs=[channel_status, monitored_list],
178
+ api_visibility="private"
179
+ )
180
+
181
+ # 2. Simulate Traffic (The Bot Loop)
182
+ simulate_btn.click(
183
+ fn=simulate_traffic_handler,
184
+ inputs=[logs_state],
185
+ outputs=[logs_state, logs_df, monitor_status],
186
+ api_visibility="private"
187
+ )
188
+
189
+ # 3. Assessment Logic
190
+ # Helper to update dropdown choices based on current state
191
+ def update_dropdown(logs):
192
+ pending = [l['id'] for l in logs if l['status'] == "Pending Review"]
193
+ return gr.Dropdown(choices=pending, value=None)
194
+
195
+ # When logs change (via simulation), update the dropdown options
196
+ logs_state.change(
197
+ fn=update_dropdown,
198
+ inputs=[logs_state],
199
+ outputs=[msg_selector]
200
+ )
201
+
202
+ approve_btn.click(
203
+ fn=assess_message,
204
+ inputs=[logs_state, msg_selector, gr.State("Confirmed Hate Speech")],
205
+ outputs=[logs_state, logs_df, msg_selector, assessment_feedback],
206
+ api_visibility="private"
207
+ )
208
+
209
+ reject_btn.click(
210
+ fn=assess_message,
211
+ inputs=[logs_state, msg_selector, gr.State("False Positive")],
212
+ outputs=[logs_state, logs_df, msg_selector, assessment_feedback],
213
+ api_visibility="private"
214
+ )
215
+
216
+ # --- Launch ---
217
+ # In Gradio 6, theme and other app-level params are in launch()
218
+ demo.launch(
219
+ theme=gr.themes.Soft(
220
+ primary_hue="red",
221
+ secondary_hue="orange",
222
+ neutral_hue="slate"
223
+ ),
224
+ footer_links=[
225
+ {"label": "View Source", "url": "https://github.com/gradio-app/gradio"},
226
+ {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}
227
+ ]
228
+ )