SamanthaStorm commited on
Commit
3458c10
Β·
verified Β·
1 Parent(s): 2bbd07b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +370 -0
app.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
4
+ import numpy as np
5
+
6
+ class FallacyFinder:
7
+ def __init__(self):
8
+ # Fallacy labels mapping
9
+ self.fallacy_labels = {
10
+ 'ad_hominem': 'Ad Hominem (Personal Attack)',
11
+ 'strawman': 'Strawman (Misrepresenting Argument)',
12
+ 'whataboutism': 'Whataboutism (Deflecting with Counter-Accusations)',
13
+ 'gaslighting': 'Gaslighting (Making Someone Question Reality)',
14
+ 'false_dichotomy': 'False Dichotomy (Only Two Options When More Exist)',
15
+ 'appeal_to_emotion': 'Appeal to Emotion (Using Emotions Instead of Logic)',
16
+ 'darvo': 'DARVO (Deny, Attack, Reverse Victim/Offender)',
17
+ 'moving_goalposts': 'Moving Goalposts (Changing Criteria When Challenged)',
18
+ 'cherry_picking': 'Cherry Picking (Selecting Only Supporting Evidence)',
19
+ 'appeal_to_authority': 'Appeal to Authority (Inappropriate Use of Authority)',
20
+ 'slippery_slope': 'Slippery Slope (One Thing Leads to Extreme Consequences)',
21
+ 'motte_and_bailey': 'Motte and Bailey (Defending Weak Position with Stronger One)',
22
+ 'gish_gallop': 'Gish Gallop (Overwhelming with Many Weak Arguments)',
23
+ 'kafkatrapping': 'Kafkatrapping (Denial Proves Guilt)',
24
+ 'sealioning': 'Sealioning (Persistent Bad-Faith Requests for Evidence)',
25
+ 'no_fallacy': 'No Fallacy (Clean, Logical Statement)'
26
+ }
27
+
28
+ # Fallacy descriptions
29
+ self.fallacy_descriptions = {
30
+ 'ad_hominem': "Attacking the person making the argument rather than addressing the argument itself.",
31
+ 'strawman': "Misrepresenting someone's argument to make it easier to attack.",
32
+ 'whataboutism': "Deflecting criticism by pointing out similar issues elsewhere instead of addressing the original concern.",
33
+ 'gaslighting': "Making someone question their own memory, perception, or sanity.",
34
+ 'false_dichotomy': "Presenting only two options when more alternatives exist.",
35
+ 'appeal_to_emotion': "Using emotional manipulation instead of logical reasoning to persuade.",
36
+ 'darvo': "A manipulation tactic: Deny the abuse, Attack the victim, Reverse Victim and Offender roles.",
37
+ 'moving_goalposts': "Changing the criteria for evidence or success when the original criteria are met.",
38
+ 'cherry_picking': "Selecting only data or examples that support your position while ignoring contradictory evidence.",
39
+ 'appeal_to_authority': "Citing an authority figure inappropriately to support an argument.",
40
+ 'slippery_slope': "Arguing that one small step will lead to a chain of negative consequences.",
41
+ 'motte_and_bailey': "Switching between a defensible position (motte) and a controversial one (bailey).",
42
+ 'gish_gallop': "Overwhelming an opponent with many rapid-fire arguments, regardless of their quality.",
43
+ 'kafkatrapping': "A logical trap where denial of guilt is taken as evidence of guilt.",
44
+ 'sealioning': "Persistently requesting evidence or debate in a way that appears reasonable but is actually harassment.",
45
+ 'no_fallacy': "The statement appears to be logically sound and free of common fallacies."
46
+ }
47
+
48
+ # Try to load model, fallback to rule-based if not available
49
+ self.model = None
50
+ self.tokenizer = None
51
+ self.use_model = False
52
+
53
+ try:
54
+ # This would be your trained model path
55
+ # For now, we'll use a rule-based approach
56
+ # self.tokenizer = AutoTokenizer.from_pretrained("your-model-path")
57
+ # self.model = AutoModelForSequenceClassification.from_pretrained("your-model-path")
58
+ # self.use_model = True
59
+ pass
60
+ except:
61
+ print("Model not found, using rule-based approach")
62
+
63
+ def predict_with_rules(self, text):
64
+ """Rule-based fallacy detection for when model isn't available"""
65
+ text_lower = text.lower().strip()
66
+
67
+ # Ad Hominem patterns
68
+ ad_hominem_patterns = [
69
+ 'you\'re', 'you are', 'stupid', 'idiot', 'moron', 'dumb', 'ignorant',
70
+ 'loser', 'pathetic', 'crazy', 'insane', 'nuts'
71
+ ]
72
+ if any(pattern in text_lower for pattern in ad_hominem_patterns) and ('you' in text_lower):
73
+ return 'ad_hominem', 0.85
74
+
75
+ # Strawman patterns
76
+ strawman_patterns = [
77
+ 'so you\'re saying', 'so you think', 'so you believe', 'so you want',
78
+ 'according to you', 'you\'re advocating', 'you want to destroy'
79
+ ]
80
+ if any(pattern in text_lower for pattern in strawman_patterns):
81
+ return 'strawman', 0.82
82
+
83
+ # Whataboutism patterns
84
+ whataboutism_patterns = [
85
+ 'what about', 'but what about', 'how about when', 'what about when you',
86
+ 'but you', 'but when you'
87
+ ]
88
+ if any(pattern in text_lower for pattern in whataboutism_patterns):
89
+ return 'whataboutism', 0.88
90
+
91
+ # Gaslighting patterns
92
+ gaslighting_patterns = [
93
+ 'that never happened', 'you\'re imagining', 'you\'re being too sensitive',
94
+ 'you\'re overreacting', 'that\'s not what i said', 'you\'re remembering wrong',
95
+ 'you\'re being paranoid', 'you\'re being dramatic'
96
+ ]
97
+ if any(pattern in text_lower for pattern in gaslighting_patterns):
98
+ return 'gaslighting', 0.80
99
+
100
+ # False Dichotomy patterns
101
+ false_dichotomy_patterns = [
102
+ 'either you\'re', 'either we', 'you\'re either', 'it\'s either',
103
+ 'with us or against us', 'love it or leave it'
104
+ ]
105
+ if any(pattern in text_lower for pattern in false_dichotomy_patterns):
106
+ return 'false_dichotomy', 0.78
107
+
108
+ # Appeal to Emotion patterns
109
+ emotion_patterns = [
110
+ 'think of the children', 'innocent people will', 'if you have any heart',
111
+ 'how can you sleep', 'break the hearts', 'suffer needlessly'
112
+ ]
113
+ if any(pattern in text_lower for pattern in emotion_patterns):
114
+ return 'appeal_to_emotion', 0.83
115
+
116
+ # DARVO patterns
117
+ darvo_patterns = [
118
+ 'i never did that', 'you\'re the one who', 'i\'m the victim here',
119
+ 'you\'re attacking me', 'i\'m innocent', 'you started this'
120
+ ]
121
+ if any(pattern in text_lower for pattern in darvo_patterns) and len([p for p in darvo_patterns if p in text_lower]) >= 2:
122
+ return 'darvo', 0.75
123
+
124
+ # Moving Goalposts patterns
125
+ goalpost_patterns = [
126
+ 'that doesn\'t count because', 'you need better sources', 'that\'s not enough evidence',
127
+ 'those statistics don\'t count', 'that\'s different because'
128
+ ]
129
+ if any(pattern in text_lower for pattern in goalpost_patterns):
130
+ return 'moving_goalposts', 0.77
131
+
132
+ # Appeal to Authority patterns
133
+ authority_patterns = [
134
+ 'my doctor said', 'the expert said', 'the ceo thinks', 'einstein believed',
135
+ 'my professor told me', 'the government says'
136
+ ]
137
+ if any(pattern in text_lower for pattern in authority_patterns):
138
+ return 'appeal_to_authority', 0.72
139
+
140
+ # Slippery Slope patterns
141
+ slope_patterns = [
142
+ 'if we allow this', 'this will lead to', 'give them an inch',
143
+ 'this is just the beginning', 'where will it end', 'slippery slope'
144
+ ]
145
+ if any(pattern in text_lower for pattern in slope_patterns):
146
+ return 'slippery_slope', 0.74
147
+
148
+ # Check for healthy communication (No Fallacy)
149
+ healthy_patterns = [
150
+ 'i understand your perspective', 'i disagree because', 'based on the evidence',
151
+ 'i appreciate your input', 'let\'s examine', 'i think we need more information',
152
+ 'i see the merit', 'thank you for sharing'
153
+ ]
154
+ if any(pattern in text_lower for pattern in healthy_patterns):
155
+ return 'no_fallacy', 0.90
156
+
157
+ # Default to no fallacy if nothing detected
158
+ return 'no_fallacy', 0.60
159
+
160
+ def predict_fallacy(self, text):
161
+ """Main prediction function"""
162
+ if not text.strip():
163
+ return None, 0, "Please enter a message to analyze."
164
+
165
+ if self.use_model and self.model is not None:
166
+ # Use trained model
167
+ inputs = self.tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
168
+
169
+ with torch.no_grad():
170
+ outputs = self.model(**inputs)
171
+ predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
172
+ predicted_class_id = predictions.argmax().item()
173
+ confidence = predictions.max().item()
174
+
175
+ # Map to fallacy label
176
+ label_keys = list(self.fallacy_labels.keys())
177
+ predicted_label = label_keys[predicted_class_id]
178
+
179
+ else:
180
+ # Use rule-based approach
181
+ predicted_label, confidence = self.predict_with_rules(text)
182
+
183
+ fallacy_name = self.fallacy_labels[predicted_label]
184
+ description = self.fallacy_descriptions[predicted_label]
185
+
186
+ return predicted_label, confidence, fallacy_name, description
187
+
188
+ def analyze_message(self, message):
189
+ """Analyze a message and return formatted results"""
190
+ if not message.strip():
191
+ return "Please enter a message to analyze.", "", ""
192
+
193
+ predicted_label, confidence, fallacy_name, description = self.predict_fallacy(message)
194
+
195
+ # Format confidence as percentage
196
+ confidence_percent = f"{confidence * 100:.1f}%"
197
+
198
+ # Determine confidence level
199
+ if confidence >= 0.8:
200
+ confidence_level = "πŸ”΄ High Confidence"
201
+ confidence_color = "high"
202
+ elif confidence >= 0.6:
203
+ confidence_level = "🟑 Medium Confidence"
204
+ confidence_color = "medium"
205
+ else:
206
+ confidence_level = "🟒 Low Confidence"
207
+ confidence_color = "low"
208
+
209
+ # Format the main result
210
+ if predicted_label == 'no_fallacy':
211
+ result = f"βœ… **No Fallacy Detected**\n\n{confidence_level} ({confidence_percent})"
212
+ icon = "βœ…"
213
+ else:
214
+ result = f"⚠️ **{fallacy_name}**\n\n{confidence_level} ({confidence_percent})"
215
+ icon = "⚠️"
216
+
217
+ # Format the explanation
218
+ explanation = f"**What this means:**\n{description}"
219
+
220
+ # Add examples or tips based on fallacy type
221
+ if predicted_label == 'ad_hominem':
222
+ explanation += "\n\n**Better approach:** Focus on the argument itself rather than the person making it."
223
+ elif predicted_label == 'strawman':
224
+ explanation += "\n\n**Better approach:** Address the actual argument being made, not a distorted version of it."
225
+ elif predicted_label == 'whataboutism':
226
+ explanation += "\n\n**Better approach:** Address the original concern directly before discussing other issues."
227
+ elif predicted_label == 'gaslighting':
228
+ explanation += "\n\n**Better approach:** Acknowledge the other person's experience and work toward understanding."
229
+ elif predicted_label == 'no_fallacy':
230
+ explanation = "**Great communication!** This message appears to use logical reasoning and respectful language."
231
+
232
+ return result, explanation, confidence_color
233
+
234
+ # Initialize the fallacy finder
235
+ finder = FallacyFinder()
236
+
237
+ def analyze_fallacy(message):
238
+ return finder.analyze_message(message)
239
+
240
+ # Create the Gradio interface
241
+ with gr.Blocks(
242
+ theme=gr.themes.Soft(primary_hue="red", secondary_hue="orange"),
243
+ title="Fallacy Finder",
244
+ css="""
245
+ .gradio-container {
246
+ max-width: 900px !important;
247
+ }
248
+ .high-confidence {
249
+ border-left: 4px solid #ef4444;
250
+ }
251
+ .medium-confidence {
252
+ border-left: 4px solid #eab308;
253
+ }
254
+ .low-confidence {
255
+ border-left: 4px solid #22c55e;
256
+ }
257
+ """
258
+ ) as demo:
259
+
260
+ gr.Markdown(
261
+ """
262
+ # πŸ” Fallacy Finder
263
+
264
+ Analyze messages for logical fallacies and argumentative patterns. Enter any statement, argument, or message to identify potential fallacies and get suggestions for better communication.
265
+
266
+ **Detects 15+ types of fallacies** including ad hominem, strawman, whataboutism, gaslighting, and more.
267
+ """
268
+ )
269
+
270
+ with gr.Row():
271
+ with gr.Column(scale=2):
272
+ message_input = gr.Textbox(
273
+ label="Enter a message to analyze",
274
+ placeholder="e.g., 'You're just saying that because you're too young to understand politics'",
275
+ lines=4,
276
+ info="Paste any statement, argument, or message you want to check for logical fallacies"
277
+ )
278
+
279
+ analyze_btn = gr.Button("πŸ” Analyze for Fallacies", variant="primary", size="lg")
280
+
281
+ with gr.Column(scale=1):
282
+ gr.Markdown(
283
+ """
284
+ ### Quick Examples:
285
+
286
+ **Ad Hominem:**
287
+ *"You're too stupid to understand"*
288
+
289
+ **Strawman:**
290
+ *"So you want to destroy the economy?"*
291
+
292
+ **Whataboutism:**
293
+ *"What about when you did the same thing?"*
294
+
295
+ **No Fallacy:**
296
+ *"I disagree because the evidence shows..."*
297
+ """
298
+ )
299
+
300
+ with gr.Row():
301
+ with gr.Column():
302
+ result_output = gr.Textbox(
303
+ label="Analysis Result",
304
+ lines=4,
305
+ interactive=False
306
+ )
307
+
308
+ explanation_output = gr.Textbox(
309
+ label="Explanation & Suggestions",
310
+ lines=6,
311
+ interactive=False
312
+ )
313
+
314
+ # Examples section
315
+ gr.Markdown("## πŸ“‹ Try These Examples")
316
+
317
+ example_messages = [
318
+ "You're clearly too young and inexperienced to have a valid opinion on this topic",
319
+ "So you're saying we should just let criminals run free and destroy society?",
320
+ "What about when you lied to me last year? Why should I trust you now?",
321
+ "That never happened, you're just being overly emotional and dramatic about nothing",
322
+ "Either you support the troops or you hate America - there's no middle ground",
323
+ "I understand your concerns, but based on the research I've seen, I think we should consider other options"
324
+ ]
325
+
326
+ examples = gr.Examples(
327
+ examples=[[msg] for msg in example_messages],
328
+ inputs=[message_input],
329
+ outputs=[result_output, explanation_output],
330
+ fn=analyze_fallacy,
331
+ cache_examples=False
332
+ )
333
+
334
+ # Information section
335
+ gr.Markdown(
336
+ """
337
+ ## 🎯 How It Works
338
+
339
+ This tool analyzes text for common logical fallacies and argumentative patterns that can harm productive communication. It looks for:
340
+
341
+ - **Personal attacks** instead of addressing arguments
342
+ - **Misrepresentations** of opposing viewpoints
343
+ - **Emotional manipulation** instead of logical reasoning
344
+ - **Deflection tactics** that avoid the main issue
345
+ - **False choices** that ignore other options
346
+
347
+ ### πŸ’‘ Tips for Better Arguments
348
+
349
+ βœ… **Focus on the argument, not the person**
350
+ βœ… **Address the actual position being argued**
351
+ βœ… **Use evidence and logical reasoning**
352
+ βœ… **Acknowledge valid points from the other side**
353
+ βœ… **Stay on topic and address concerns directly**
354
+ """
355
+ )
356
+
357
+ # Connect the function
358
+ analyze_btn.click(
359
+ fn=analyze_fallacy,
360
+ inputs=[message_input],
361
+ outputs=[result_output, explanation_output]
362
+ )
363
+
364
+ # Launch the app
365
+ if __name__ == "__main__":
366
+ demo.launch(
367
+ share=True,
368
+ server_name="0.0.0.0",
369
+ server_port=7860
370
+ )