SamanthaStorm commited on
Commit
aff25b6
·
verified ·
1 Parent(s): 9eb4f9e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -20
app.py CHANGED
@@ -6,48 +6,67 @@ import numpy as np
6
  from datetime import datetime
7
  import io
8
  import json
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  class CommunicationAnalyzer:
11
  def __init__(self):
 
12
  self.load_models()
13
 
14
  def load_models(self):
15
  """Load all the analysis models"""
16
  try:
17
- # DARVO Detection
18
  self.darvo_tokenizer = AutoTokenizer.from_pretrained("SamanthaStorm/tether-darvo-regressor-v1")
19
  self.darvo_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tether-darvo-regressor-v1")
20
 
21
- # Sentiment Analysis
22
  self.sentiment_pipeline = pipeline("text-classification", model="SamanthaStorm/tether-sentiment-v3")
23
 
24
- # Multilabel Classification
25
  self.multilabel_pipeline = pipeline("text-classification", model="SamanthaStorm/tether-multilabel-v6")
26
 
27
- # Healthy Boundary Detection
28
  self.boundary_pipeline = pipeline("text-classification", model="SamanthaStorm/healthy-boundary-predictor")
29
 
30
- # Fallacy Detection
31
  self.fallacy_tokenizer = AutoTokenizer.from_pretrained("SamanthaStorm/fallacyfinder")
32
  self.fallacy_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/fallacyfinder")
33
 
 
34
  except Exception as e:
35
- print(f"Error loading models: {e}")
36
 
37
  def analyze_darvo(self, text):
38
  """Analyze DARVO tactics in text"""
39
  try:
 
40
  inputs = self.darvo_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
41
  with torch.no_grad():
42
  outputs = self.darvo_model(**inputs)
43
  darvo_score = torch.sigmoid(outputs.logits).item()
 
44
  return darvo_score
45
- except:
 
46
  return 0.0
47
 
48
  def analyze_fallacy(self, text):
49
  """Detect logical fallacies in text"""
50
  try:
 
51
  inputs = self.fallacy_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
52
  with torch.no_grad():
53
  outputs = self.fallacy_model(**inputs)
@@ -57,18 +76,23 @@ class CommunicationAnalyzer:
57
 
58
  if hasattr(self.fallacy_model.config, 'id2label'):
59
  predicted_label = self.fallacy_model.config.id2label[predicted_class_id]
 
60
  else:
61
  predicted_label = f"Fallacy_Type_{predicted_class_id}"
 
62
 
63
  return predicted_label, confidence
64
- except:
 
65
  return "No Fallacy", 0.0
66
 
67
  def analyze_message(self, text):
68
  """Comprehensive analysis of a single message"""
69
  if not text or len(text.strip()) < 3:
 
70
  return {}
71
 
 
72
  analysis = {}
73
 
74
  # DARVO Analysis
@@ -79,7 +103,9 @@ class CommunicationAnalyzer:
79
  sentiment_result = self.sentiment_pipeline(text)
80
  analysis['sentiment'] = sentiment_result[0]['label']
81
  analysis['sentiment_confidence'] = sentiment_result[0]['score']
82
- except:
 
 
83
  analysis['sentiment'] = 'NEUTRAL'
84
  analysis['sentiment_confidence'] = 0.5
85
 
@@ -87,7 +113,9 @@ class CommunicationAnalyzer:
87
  try:
88
  multilabel_result = self.multilabel_pipeline(text)
89
  analysis['categories'] = multilabel_result
90
- except:
 
 
91
  analysis['categories'] = []
92
 
93
  # Boundary Analysis
@@ -95,7 +123,9 @@ class CommunicationAnalyzer:
95
  boundary_result = self.boundary_pipeline(text)
96
  analysis['boundary_type'] = boundary_result[0]['label']
97
  analysis['boundary_confidence'] = boundary_result[0]['score']
98
- except:
 
 
99
  analysis['boundary_type'] = 'UNCLEAR'
100
  analysis['boundary_confidence'] = 0.5
101
 
@@ -104,20 +134,42 @@ class CommunicationAnalyzer:
104
  analysis['fallacy_type'] = fallacy_type
105
  analysis['fallacy_confidence'] = fallacy_confidence
106
 
 
107
  return analysis
108
 
109
  def calculate_abuse_indicators(self, person_data):
110
  """Calculate abuse indicators for a person based on their messages"""
111
  if not person_data:
 
112
  return {}
113
 
 
 
 
114
  # Aggregate scores
115
  darvo_scores = [msg.get('darvo_score', 0) for msg in person_data]
116
- negative_sentiments = sum(1 for msg in person_data if msg.get('sentiment') == 'NEGATIVE')
117
- fallacy_count = sum(1 for msg in person_data if msg.get('fallacy_confidence', 0) > 0.7)
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  total_messages = len(person_data)
120
 
 
 
 
 
 
121
  indicators = {
122
  'avg_darvo_score': np.mean(darvo_scores) if darvo_scores else 0,
123
  'max_darvo_score': max(darvo_scores) if darvo_scores else 0,
@@ -127,28 +179,37 @@ class CommunicationAnalyzer:
127
  'high_darvo_messages': sum(1 for score in darvo_scores if score > 0.7)
128
  }
129
 
130
- # Calculate overall abuse likelihood
131
- abuse_score = (
132
- indicators['avg_darvo_score'] * 0.4 +
133
- indicators['negative_sentiment_ratio'] * 0.2 +
134
- indicators['fallacy_ratio'] * 0.2 +
135
- (indicators['high_darvo_messages'] / total_messages if total_messages > 0 else 0) * 0.2
136
- )
137
 
 
138
  indicators['abuse_likelihood'] = min(abuse_score, 1.0)
139
 
 
 
 
140
  return indicators
141
 
142
  def analyze_csv_file(file, message_col, sender_col, report_type):
143
  """Main function to analyze uploaded CSV file"""
144
  if file is None:
 
145
  return "Please upload a CSV file.", "", ""
146
 
147
  try:
 
 
148
  # Read CSV file
149
  df = pd.read_csv(file.name)
 
150
 
151
  if message_col not in df.columns or sender_col not in df.columns:
 
152
  return f"Columns '{message_col}' or '{sender_col}' not found in CSV.", "", ""
153
 
154
  # Initialize analyzer
@@ -158,10 +219,13 @@ def analyze_csv_file(file, message_col, sender_col, report_type):
158
  results = []
159
  person_analyses = {}
160
 
 
161
  for idx, row in df.iterrows():
162
  message = str(row[message_col])
163
  sender = str(row[sender_col])
164
 
 
 
165
  if sender not in person_analyses:
166
  person_analyses[sender] = []
167
 
@@ -174,25 +238,32 @@ def analyze_csv_file(file, message_col, sender_col, report_type):
174
  person_analyses[sender].append(analysis)
175
 
176
  # Calculate abuse indicators for each person
 
177
  person_indicators = {}
178
  for person, messages in person_analyses.items():
 
179
  person_indicators[person] = analyzer.calculate_abuse_indicators(messages)
180
 
181
  # Generate reports
 
182
  summary_report = generate_summary_report(person_indicators, results, report_type)
183
  detailed_report = generate_detailed_report(results, person_indicators, report_type)
184
  downloadable_report = generate_downloadable_report(results, person_indicators, report_type)
185
 
 
186
  return summary_report, detailed_report, downloadable_report
187
 
188
  except Exception as e:
 
189
  return f"Error processing file: {str(e)}", "", ""
190
 
191
  def generate_summary_report(person_indicators, results, report_type):
192
  """Generate summary report identifying potential abuser"""
 
193
 
194
  # Sort people by abuse likelihood
195
  sorted_people = sorted(person_indicators.items(), key=lambda x: x[1]['abuse_likelihood'], reverse=True)
 
196
 
197
  report = f"# Communication Analysis Summary Report\n"
198
  report += f"**Report Type:** {report_type}\n"
@@ -222,11 +293,13 @@ def generate_summary_report(person_indicators, results, report_type):
222
 
223
  def generate_detailed_report(results, person_indicators, report_type):
224
  """Generate detailed analysis report"""
 
225
 
226
  report = f"# Detailed Communication Analysis\n\n"
227
 
228
  # High-risk messages
229
  high_risk_messages = [r for r in results if r.get('darvo_score', 0) > 0.7]
 
230
 
231
  if high_risk_messages:
232
  report += "## High-Risk Messages (DARVO Score > 0.7)\n\n"
@@ -250,6 +323,7 @@ def generate_detailed_report(results, person_indicators, report_type):
250
 
251
  def generate_downloadable_report(results, person_indicators, report_type):
252
  """Generate downloadable comprehensive report"""
 
253
 
254
  report_data = {
255
  "analysis_metadata": {
@@ -321,15 +395,18 @@ def create_interface():
321
  download_output = gr.File(label="Download Complete Report (JSON)")
322
 
323
  def process_and_create_download(file, message_col, sender_col, report_type):
 
324
  summary, detailed, report_data = analyze_csv_file(file, message_col, sender_col, report_type)
325
 
326
  # Create downloadable file
327
  if report_data:
328
  filename = f"communication_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
 
329
  with open(filename, 'w') as f:
330
  f.write(report_data)
331
  return summary, detailed, filename
332
 
 
333
  return summary, detailed, None
334
 
335
  analyze_btn.click(
@@ -353,5 +430,6 @@ def create_interface():
353
  return interface
354
 
355
  if __name__ == "__main__":
 
356
  interface = create_interface()
357
  interface.launch()
 
6
  from datetime import datetime
7
  import io
8
  import json
9
+ import logging
10
+ import os
11
+
12
+ # Set up logging
13
+ logging.basicConfig(
14
+ level=logging.INFO,
15
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
16
+ handlers=[
17
+ logging.FileHandler("analysis_debug.log"),
18
+ logging.StreamHandler()
19
+ ]
20
+ )
21
+ logger = logging.getLogger("communication_analyzer")
22
 
23
  class CommunicationAnalyzer:
24
  def __init__(self):
25
+ logger.info("Initializing Communication Analyzer")
26
  self.load_models()
27
 
28
  def load_models(self):
29
  """Load all the analysis models"""
30
  try:
31
+ logger.info("Loading DARVO detection model")
32
  self.darvo_tokenizer = AutoTokenizer.from_pretrained("SamanthaStorm/tether-darvo-regressor-v1")
33
  self.darvo_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tether-darvo-regressor-v1")
34
 
35
+ logger.info("Loading sentiment analysis model")
36
  self.sentiment_pipeline = pipeline("text-classification", model="SamanthaStorm/tether-sentiment-v3")
37
 
38
+ logger.info("Loading multilabel classification model")
39
  self.multilabel_pipeline = pipeline("text-classification", model="SamanthaStorm/tether-multilabel-v6")
40
 
41
+ logger.info("Loading boundary detection model")
42
  self.boundary_pipeline = pipeline("text-classification", model="SamanthaStorm/healthy-boundary-predictor")
43
 
44
+ logger.info("Loading fallacy detection model")
45
  self.fallacy_tokenizer = AutoTokenizer.from_pretrained("SamanthaStorm/fallacyfinder")
46
  self.fallacy_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/fallacyfinder")
47
 
48
+ logger.info("All models loaded successfully")
49
  except Exception as e:
50
+ logger.error(f"Error loading models: {e}", exc_info=True)
51
 
52
  def analyze_darvo(self, text):
53
  """Analyze DARVO tactics in text"""
54
  try:
55
+ logger.debug(f"Analyzing DARVO for text: '{text[:50]}...'")
56
  inputs = self.darvo_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
57
  with torch.no_grad():
58
  outputs = self.darvo_model(**inputs)
59
  darvo_score = torch.sigmoid(outputs.logits).item()
60
+ logger.info(f"DARVO score: {darvo_score:.3f} for text: '{text[:50]}...'")
61
  return darvo_score
62
+ except Exception as e:
63
+ logger.error(f"Error in DARVO analysis: {e}", exc_info=True)
64
  return 0.0
65
 
66
  def analyze_fallacy(self, text):
67
  """Detect logical fallacies in text"""
68
  try:
69
+ logger.debug(f"Analyzing fallacies for text: '{text[:50]}...'")
70
  inputs = self.fallacy_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
71
  with torch.no_grad():
72
  outputs = self.fallacy_model(**inputs)
 
76
 
77
  if hasattr(self.fallacy_model.config, 'id2label'):
78
  predicted_label = self.fallacy_model.config.id2label[predicted_class_id]
79
+ logger.info(f"Fallacy detected: {predicted_label} with confidence {confidence:.3f} for text: '{text[:50]}...'")
80
  else:
81
  predicted_label = f"Fallacy_Type_{predicted_class_id}"
82
+ logger.info(f"Fallacy detected: {predicted_label} with confidence {confidence:.3f} for text: '{text[:50]}...'")
83
 
84
  return predicted_label, confidence
85
+ except Exception as e:
86
+ logger.error(f"Error in fallacy analysis: {e}", exc_info=True)
87
  return "No Fallacy", 0.0
88
 
89
  def analyze_message(self, text):
90
  """Comprehensive analysis of a single message"""
91
  if not text or len(text.strip()) < 3:
92
+ logger.debug(f"Skipping analysis for short/empty text: '{text}'")
93
  return {}
94
 
95
+ logger.info(f"Starting comprehensive analysis for message: '{text[:50]}...'")
96
  analysis = {}
97
 
98
  # DARVO Analysis
 
103
  sentiment_result = self.sentiment_pipeline(text)
104
  analysis['sentiment'] = sentiment_result[0]['label']
105
  analysis['sentiment_confidence'] = sentiment_result[0]['score']
106
+ logger.info(f"Sentiment: {analysis['sentiment']} with confidence {analysis['sentiment_confidence']:.3f}")
107
+ except Exception as e:
108
+ logger.error(f"Error in sentiment analysis: {e}", exc_info=True)
109
  analysis['sentiment'] = 'NEUTRAL'
110
  analysis['sentiment_confidence'] = 0.5
111
 
 
113
  try:
114
  multilabel_result = self.multilabel_pipeline(text)
115
  analysis['categories'] = multilabel_result
116
+ logger.info(f"Categories: {multilabel_result}")
117
+ except Exception as e:
118
+ logger.error(f"Error in multilabel analysis: {e}", exc_info=True)
119
  analysis['categories'] = []
120
 
121
  # Boundary Analysis
 
123
  boundary_result = self.boundary_pipeline(text)
124
  analysis['boundary_type'] = boundary_result[0]['label']
125
  analysis['boundary_confidence'] = boundary_result[0]['score']
126
+ logger.info(f"Boundary type: {analysis['boundary_type']} with confidence {analysis['boundary_confidence']:.3f}")
127
+ except Exception as e:
128
+ logger.error(f"Error in boundary analysis: {e}", exc_info=True)
129
  analysis['boundary_type'] = 'UNCLEAR'
130
  analysis['boundary_confidence'] = 0.5
131
 
 
134
  analysis['fallacy_type'] = fallacy_type
135
  analysis['fallacy_confidence'] = fallacy_confidence
136
 
137
+ logger.info(f"Completed analysis for message: '{text[:50]}...'")
138
  return analysis
139
 
140
  def calculate_abuse_indicators(self, person_data):
141
  """Calculate abuse indicators for a person based on their messages"""
142
  if not person_data:
143
+ logger.warning("No data provided for abuse indicators calculation")
144
  return {}
145
 
146
+ person_id = person_data[0].get('sender', 'unknown') if person_data else 'unknown'
147
+ logger.info(f"Calculating abuse indicators for {person_id} with {len(person_data)} messages")
148
+
149
  # Aggregate scores
150
  darvo_scores = [msg.get('darvo_score', 0) for msg in person_data]
151
+
152
+ # Count messages with negative sentiment
153
+ negative_sentiments = 0
154
+ for msg in person_data:
155
+ if msg.get('sentiment') == 'NEGATIVE':
156
+ negative_sentiments += 1
157
+ logger.debug(f"Negative sentiment detected in message: '{msg.get('message', '')[:50]}...'")
158
+
159
+ # Count messages with high fallacy confidence
160
+ fallacy_count = 0
161
+ for msg in person_data:
162
+ if msg.get('fallacy_confidence', 0) > 0.7:
163
+ fallacy_count += 1
164
+ logger.debug(f"High confidence fallacy detected in message: '{msg.get('message', '')[:50]}...' - {msg.get('fallacy_type')}")
165
 
166
  total_messages = len(person_data)
167
 
168
+ # Log raw scores for debugging
169
+ logger.info(f"Raw DARVO scores for {person_id}: {darvo_scores}")
170
+ logger.info(f"Negative sentiment count for {person_id}: {negative_sentiments}/{total_messages}")
171
+ logger.info(f"High confidence fallacy count for {person_id}: {fallacy_count}/{total_messages}")
172
+
173
  indicators = {
174
  'avg_darvo_score': np.mean(darvo_scores) if darvo_scores else 0,
175
  'max_darvo_score': max(darvo_scores) if darvo_scores else 0,
 
179
  'high_darvo_messages': sum(1 for score in darvo_scores if score > 0.7)
180
  }
181
 
182
+ # Calculate overall abuse likelihood with detailed logging
183
+ abuse_score_components = {
184
+ 'darvo_component': indicators['avg_darvo_score'] * 0.4,
185
+ 'sentiment_component': indicators['negative_sentiment_ratio'] * 0.2,
186
+ 'fallacy_component': indicators['fallacy_ratio'] * 0.2,
187
+ 'high_darvo_component': (indicators['high_darvo_messages'] / total_messages if total_messages > 0 else 0) * 0.2
188
+ }
189
 
190
+ abuse_score = sum(abuse_score_components.values())
191
  indicators['abuse_likelihood'] = min(abuse_score, 1.0)
192
 
193
+ logger.info(f"Abuse score components for {person_id}: {abuse_score_components}")
194
+ logger.info(f"Final abuse likelihood for {person_id}: {indicators['abuse_likelihood']:.3f}")
195
+
196
  return indicators
197
 
198
  def analyze_csv_file(file, message_col, sender_col, report_type):
199
  """Main function to analyze uploaded CSV file"""
200
  if file is None:
201
+ logger.warning("No file uploaded")
202
  return "Please upload a CSV file.", "", ""
203
 
204
  try:
205
+ logger.info(f"Processing file: {file.name}")
206
+
207
  # Read CSV file
208
  df = pd.read_csv(file.name)
209
+ logger.info(f"CSV loaded with {len(df)} rows and columns: {df.columns.tolist()}")
210
 
211
  if message_col not in df.columns or sender_col not in df.columns:
212
+ logger.error(f"Required columns not found. Available columns: {df.columns.tolist()}")
213
  return f"Columns '{message_col}' or '{sender_col}' not found in CSV.", "", ""
214
 
215
  # Initialize analyzer
 
219
  results = []
220
  person_analyses = {}
221
 
222
+ logger.info(f"Starting analysis of {len(df)} messages")
223
  for idx, row in df.iterrows():
224
  message = str(row[message_col])
225
  sender = str(row[sender_col])
226
 
227
+ logger.info(f"Analyzing message {idx} from {sender}: '{message[:50]}...'")
228
+
229
  if sender not in person_analyses:
230
  person_analyses[sender] = []
231
 
 
238
  person_analyses[sender].append(analysis)
239
 
240
  # Calculate abuse indicators for each person
241
+ logger.info("Calculating abuse indicators for each participant")
242
  person_indicators = {}
243
  for person, messages in person_analyses.items():
244
+ logger.info(f"Analyzing {len(messages)} messages from {person}")
245
  person_indicators[person] = analyzer.calculate_abuse_indicators(messages)
246
 
247
  # Generate reports
248
+ logger.info("Generating reports")
249
  summary_report = generate_summary_report(person_indicators, results, report_type)
250
  detailed_report = generate_detailed_report(results, person_indicators, report_type)
251
  downloadable_report = generate_downloadable_report(results, person_indicators, report_type)
252
 
253
+ logger.info("Analysis completed successfully")
254
  return summary_report, detailed_report, downloadable_report
255
 
256
  except Exception as e:
257
+ logger.error(f"Error processing file: {str(e)}", exc_info=True)
258
  return f"Error processing file: {str(e)}", "", ""
259
 
260
  def generate_summary_report(person_indicators, results, report_type):
261
  """Generate summary report identifying potential abuser"""
262
+ logger.info("Generating summary report")
263
 
264
  # Sort people by abuse likelihood
265
  sorted_people = sorted(person_indicators.items(), key=lambda x: x[1]['abuse_likelihood'], reverse=True)
266
+ logger.info(f"Sorted participants by abuse likelihood: {[(p[0], p[1]['abuse_likelihood']) for p in sorted_people]}")
267
 
268
  report = f"# Communication Analysis Summary Report\n"
269
  report += f"**Report Type:** {report_type}\n"
 
293
 
294
  def generate_detailed_report(results, person_indicators, report_type):
295
  """Generate detailed analysis report"""
296
+ logger.info("Generating detailed report")
297
 
298
  report = f"# Detailed Communication Analysis\n\n"
299
 
300
  # High-risk messages
301
  high_risk_messages = [r for r in results if r.get('darvo_score', 0) > 0.7]
302
+ logger.info(f"Found {len(high_risk_messages)} high-risk messages")
303
 
304
  if high_risk_messages:
305
  report += "## High-Risk Messages (DARVO Score > 0.7)\n\n"
 
323
 
324
  def generate_downloadable_report(results, person_indicators, report_type):
325
  """Generate downloadable comprehensive report"""
326
+ logger.info("Generating downloadable report")
327
 
328
  report_data = {
329
  "analysis_metadata": {
 
395
  download_output = gr.File(label="Download Complete Report (JSON)")
396
 
397
  def process_and_create_download(file, message_col, sender_col, report_type):
398
+ logger.info(f"Starting analysis with parameters: message_col={message_col}, sender_col={sender_col}, report_type={report_type}")
399
  summary, detailed, report_data = analyze_csv_file(file, message_col, sender_col, report_type)
400
 
401
  # Create downloadable file
402
  if report_data:
403
  filename = f"communication_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
404
+ logger.info(f"Creating downloadable report: {filename}")
405
  with open(filename, 'w') as f:
406
  f.write(report_data)
407
  return summary, detailed, filename
408
 
409
+ logger.warning("No report data generated")
410
  return summary, detailed, None
411
 
412
  analyze_btn.click(
 
430
  return interface
431
 
432
  if __name__ == "__main__":
433
+ logger.info("Starting Communication Analysis Tool")
434
  interface = create_interface()
435
  interface.launch()