nixaut-codelabs commited on
Commit
f0b5304
·
verified ·
1 Parent(s): 2793604

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -34
app.py CHANGED
@@ -101,7 +101,42 @@ def enforce_s_u(text: str) -> str:
101
  return "u"
102
  return "s"
103
 
104
- def classify_text_stream(message, max_tokens, temperature, top_p):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  text = build_prompt(message)
106
  inputs = tokenizer([text], return_tensors="pt").to(model.device)
107
  do_sample = bool(temperature and temperature > 0.0)
@@ -114,6 +149,7 @@ def classify_text_stream(message, max_tokens, temperature, top_p):
114
  eos_token_id=tokenizer.eos_token_id,
115
  pad_token_id=tokenizer.eos_token_id
116
  )
 
117
  try:
118
  streamer = TextIteratorStreamer(tokenizer, skip_special_tokens=True, skip_prompt=True)
119
  except TypeError:
@@ -127,6 +163,9 @@ def classify_text_stream(message, max_tokens, temperature, top_p):
127
  partial_text = ""
128
  token_count = 0
129
  start_time = None
 
 
 
130
  with torch.inference_mode():
131
  thread.start()
132
  try:
@@ -135,7 +174,7 @@ def classify_text_stream(message, max_tokens, temperature, top_p):
135
  start_time = time.time()
136
  partial_text += chunk
137
  token_count += 1
138
- yield partial_text
139
  finally:
140
  thread.join()
141
 
@@ -143,48 +182,155 @@ def classify_text_stream(message, max_tokens, temperature, top_p):
143
  end_time = time.time() if start_time else time.time()
144
  duration = max(1e-6, end_time - start_time)
145
  tps = token_count / duration if duration > 0 else 0.0
146
- yield f"{final_label}\n\n⚡ Speed: {tps:.2f} tokens/s"
147
-
148
- with gr.Blocks() as demo:
149
- gr.Markdown("# Multilingual Content Moderation Classifier")
150
- gr.Markdown("Enter any text to classify it as safe ('s') or unsafe ('u').")
151
 
152
- with gr.Row():
153
- with gr.Column(scale=2):
154
- text_input = gr.Textbox(
155
- label="Text to Classify",
156
- lines=5,
157
- placeholder="Enter text in any language..."
158
- )
159
- submit_button = gr.Button("Classify", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
- with gr.Column(scale=1):
162
- text_output = gr.Textbox(label="Classification Result", interactive=False)
163
- with gr.Accordion("Advanced Settings", open=False):
164
  max_tokens_slider = gr.Slider(
165
- minimum=1, maximum=4, value=1, step=1, label="Max New Tokens"
 
 
166
  )
167
  temp_slider = gr.Slider(
168
- minimum=0.0, maximum=1.0, value=0.0, step=0.1, label="Temperature"
 
 
169
  )
170
  top_p_slider = gr.Slider(
171
- minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p"
 
 
172
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
- gr.Examples(
175
- examples=[
176
- ["Hello, how are you today?"],
177
- ["I will find you and hurt you."],
178
- ["C'est une belle journée pour apprendre le codage."],
179
- ["I want to die."],
180
- ],
181
- inputs=text_input
182
- )
183
-
184
- submit_button.click(
185
  fn=classify_text_stream,
186
  inputs=[text_input, max_tokens_slider, temp_slider, top_p_slider],
187
- outputs=text_output
 
 
 
 
 
 
188
  )
189
 
190
  if __name__ == "__main__":
@@ -193,4 +339,10 @@ if __name__ == "__main__":
193
  **tokenizer(["Hi"], return_tensors="pt").to(model.device),
194
  max_new_tokens=1, do_sample=False, use_cache=True
195
  )
196
- demo.queue(max_size=32).launch()
 
 
 
 
 
 
 
101
  return "u"
102
  return "s"
103
 
104
+ def format_classification_result(classification, tokens_per_second, processing_time):
105
+ if classification == "s":
106
+ status_emoji = "✅"
107
+ status_text = "SAFE"
108
+ status_color = "#22c55e"
109
+ description = "Content appears to be safe and appropriate."
110
+ else:
111
+ status_emoji = "🚫"
112
+ status_text = "UNSAFE"
113
+ status_color = "#ef4444"
114
+ description = "Content may contain inappropriate or harmful material."
115
+
116
+ result_html = f"""
117
+ <div style="text-align: center; padding: 20px; border-radius: 12px;
118
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
119
+ border: 2px solid {status_color}; margin: 10px 0;">
120
+ <div style="font-size: 48px; margin-bottom: 10px;">{status_emoji}</div>
121
+ <div style="font-size: 24px; font-weight: bold; color: {status_color}; margin-bottom: 8px;">
122
+ {status_text}
123
+ </div>
124
+ <div style="font-size: 16px; color: #64748b; margin-bottom: 15px;">
125
+ {description}
126
+ </div>
127
+ <div style="display: flex; justify-content: center; gap: 20px; font-size: 14px; color: #475569;">
128
+ <span>⚡ {tokens_per_second:.1f} tok/s</span>
129
+ <span>⏱️ {processing_time:.2f}s</span>
130
+ </div>
131
+ </div>
132
+ """
133
+ return result_html
134
+
135
+ def classify_text_stream(message, max_tokens, temperature, top_p, progress=gr.Progress()):
136
+ if not message.strip():
137
+ return format_classification_result("s", 0, 0)
138
+
139
+ progress(0, desc="Preparing classification...")
140
  text = build_prompt(message)
141
  inputs = tokenizer([text], return_tensors="pt").to(model.device)
142
  do_sample = bool(temperature and temperature > 0.0)
 
149
  eos_token_id=tokenizer.eos_token_id,
150
  pad_token_id=tokenizer.eos_token_id
151
  )
152
+
153
  try:
154
  streamer = TextIteratorStreamer(tokenizer, skip_special_tokens=True, skip_prompt=True)
155
  except TypeError:
 
163
  partial_text = ""
164
  token_count = 0
165
  start_time = None
166
+
167
+ progress(0.3, desc="Processing content...")
168
+
169
  with torch.inference_mode():
170
  thread.start()
171
  try:
 
174
  start_time = time.time()
175
  partial_text += chunk
176
  token_count += 1
177
+ progress(0.3 + (token_count / max_tokens) * 0.6, desc="Analyzing...")
178
  finally:
179
  thread.join()
180
 
 
182
  end_time = time.time() if start_time else time.time()
183
  duration = max(1e-6, end_time - start_time)
184
  tps = token_count / duration if duration > 0 else 0.0
 
 
 
 
 
185
 
186
+ progress(1.0, desc="Complete!")
187
+
188
+ return format_classification_result(final_label, tps, duration)
189
+
190
+ custom_css = """
191
+ .main-container {
192
+ max-width: 1200px !important;
193
+ margin: 0 auto !important;
194
+ }
195
+
196
+ .header-section {
197
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
198
+ padding: 2rem;
199
+ border-radius: 16px;
200
+ margin-bottom: 2rem;
201
+ color: white;
202
+ text-align: center;
203
+ }
204
+
205
+ .classification-panel {
206
+ background: white;
207
+ border-radius: 16px;
208
+ padding: 2rem;
209
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
210
+ border: 1px solid #e2e8f0;
211
+ }
212
+
213
+ .example-card {
214
+ transition: transform 0.2s ease;
215
+ }
216
+
217
+ .example-card:hover {
218
+ transform: translateY(-2px);
219
+ }
220
+
221
+ .gradio-container {
222
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
223
+ }
224
+
225
+ .input-section {
226
+ background: #f8fafc;
227
+ border-radius: 12px;
228
+ padding: 1.5rem;
229
+ border: 1px solid #e2e8f0;
230
+ }
231
+ """
232
+
233
+ with gr.Blocks(css=custom_css, title="AI Content Moderator", theme=gr.themes.Soft()) as demo:
234
+ with gr.Column(elem_classes="main-container"):
235
+ gr.HTML("""
236
+ <div class="header-section">
237
+ <h1 style="font-size: 2.5rem; margin-bottom: 0.5rem; font-weight: 700;">
238
+ 🛡️ AI Content Moderator
239
+ </h1>
240
+ <p style="font-size: 1.2rem; opacity: 0.9; margin: 0;">
241
+ Advanced multilingual content classification powered by AI
242
+ </p>
243
+ </div>
244
+ """)
245
+
246
+ with gr.Row():
247
+ with gr.Column(scale=3):
248
+ with gr.Group(elem_classes="input-section"):
249
+ gr.Markdown("### 📝 Content Analysis")
250
+ text_input = gr.Textbox(
251
+ label="Text to Analyze",
252
+ placeholder="Enter any text in any language for content moderation analysis...",
253
+ lines=6,
254
+ max_lines=10,
255
+ show_label=False
256
+ )
257
+
258
+ with gr.Row():
259
+ classify_btn = gr.Button(
260
+ "🔍 Analyze Content",
261
+ variant="primary",
262
+ size="lg",
263
+ scale=2
264
+ )
265
+ clear_btn = gr.Button(
266
+ "🗑️ Clear",
267
+ variant="secondary",
268
+ size="lg",
269
+ scale=1
270
+ )
271
+
272
+ with gr.Column(scale=2):
273
+ with gr.Group(elem_classes="classification-panel"):
274
+ gr.Markdown("### 📊 Classification Result")
275
+ result_display = gr.HTML(
276
+ value=format_classification_result("s", 0, 0),
277
+ label="Result"
278
+ )
279
 
280
+ with gr.Accordion("⚙️ Advanced Configuration", open=False):
281
+ with gr.Row():
 
282
  max_tokens_slider = gr.Slider(
283
+ minimum=1, maximum=10, value=3, step=1,
284
+ label="Max Tokens",
285
+ info="Maximum number of tokens to generate"
286
  )
287
  temp_slider = gr.Slider(
288
+ minimum=0.0, maximum=1.0, value=0.1, step=0.1,
289
+ label="Temperature",
290
+ info="Controls randomness in generation"
291
  )
292
  top_p_slider = gr.Slider(
293
+ minimum=0.1, maximum=1.0, value=0.95, step=0.05,
294
+ label="Top-p",
295
+ info="Nucleus sampling parameter"
296
  )
297
+
298
+ gr.Markdown("### 💡 Try These Examples")
299
+
300
+ example_data = [
301
+ ["Hello, how are you today? I hope you're having a wonderful time!"],
302
+ ["I hate you and I will find you and hurt you badly."],
303
+ ["C'est une belle journée pour apprendre la programmation et l'intelligence artificielle."],
304
+ ["I can't take this anymore. I want to end everything and disappear forever."],
305
+ ["¡Hola! Me encanta aprender nuevos idiomas y conocer diferentes culturas."],
306
+ ["You're absolutely worthless and nobody will ever love someone like you."]
307
+ ]
308
+
309
+ examples = gr.Examples(
310
+ examples=example_data,
311
+ inputs=text_input,
312
+ examples_per_page=6
313
+ )
314
+
315
+ gr.Markdown("""
316
+ ---
317
+ <div style="text-align: center; padding: 1rem; color: #64748b; font-size: 0.9rem;">
318
+ <p><strong>🌍 Multilingual Support:</strong> English, Spanish, French, German, and many more languages</p>
319
+ <p><strong>🚀 Real-time Analysis:</strong> Fast content classification with detailed feedback</p>
320
+ <p><strong>🔒 Privacy First:</strong> All processing happens locally on your machine</p>
321
+ </div>
322
+ """)
323
 
324
+ classify_btn.click(
 
 
 
 
 
 
 
 
 
 
325
  fn=classify_text_stream,
326
  inputs=[text_input, max_tokens_slider, temp_slider, top_p_slider],
327
+ outputs=result_display,
328
+ show_progress=True
329
+ )
330
+
331
+ clear_btn.click(
332
+ fn=lambda: ("", format_classification_result("s", 0, 0)),
333
+ outputs=[text_input, result_display]
334
  )
335
 
336
  if __name__ == "__main__":
 
339
  **tokenizer(["Hi"], return_tensors="pt").to(model.device),
340
  max_new_tokens=1, do_sample=False, use_cache=True
341
  )
342
+ print("🚀 Starting AI Content Moderator...")
343
+ demo.queue(max_size=64, concurrency_count=4).launch(
344
+ server_name="0.0.0.0",
345
+ server_port=7860,
346
+ share=False,
347
+ show_error=True
348
+ )