SamanthaStorm commited on
Commit
6aad389
·
verified ·
1 Parent(s): 96ba2c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +141 -62
app.py CHANGED
@@ -163,13 +163,73 @@ def format_summary_results(summary):
163
  else:
164
  sender_stats += "<p style='color: #1f2937;'>No sender statistics available.</p>"
165
 
166
- # Format primary abuser
167
- primary_abuser = "<h3 style='color: #1f2937;'>Primary Concern</h3>"
168
  if summary['primary_abuser']:
169
- primary_abuser += f"<p style='color: #1f2937;'>The analysis indicates that <strong style='color: #1f2937;'>{summary['primary_abuser']}</strong> "
170
- primary_abuser += "shows the highest percentage of concerning communication patterns.</p>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  else:
172
- primary_abuser += "<p style='color: #1f2937;'>No clear pattern of concerning communication from a specific sender.</p>"
173
 
174
  # Format escalation data
175
  escalation = "<h3 style='color: #1f2937;'>Escalation Analysis</h3>"
@@ -180,16 +240,25 @@ def format_summary_results(summary):
180
  future_prediction = summary['escalation_data'].get('future_prediction')
181
  cyclic_pattern = summary['escalation_data'].get('cyclic_pattern', False)
182
 
183
- escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Trend Direction:</strong> {trend.title()}</p>"
 
 
 
184
  escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Trend Strength:</strong> {trend_strength:.2f}</p>"
185
  escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Recent Average:</strong> {recent_avg:.1f}%</p>"
186
 
187
  if future_prediction is not None:
188
- escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>7-Day Prediction:</strong> {future_prediction:.1f}%</p>"
 
189
 
190
  if cyclic_pattern:
191
  cycle_period = summary['escalation_data'].get('cycle_period', 'unknown')
192
- escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Cyclic Pattern Detected:</strong> Yes (approximately {cycle_period} days)</p>"
 
 
 
 
 
193
  else:
194
  escalation += "<p style='color: #1f2937;'>No escalation data available.</p>"
195
 
@@ -198,14 +267,14 @@ def format_summary_results(summary):
198
  if summary['recommendations']:
199
  recommendations += "<div style='max-height: 300px; overflow-y: auto;'>"
200
  for rec in summary['recommendations']:
201
- recommendations += f"<div style='margin-bottom: 15px; padding: 10px; background: #f8f9fa; border-radius: 5px;'>"
202
- recommendations += f"<h4 style='color: #1f2937;'>{rec['title']}</h4>"
203
  recommendations += f"<p style='color: #1f2937;'>{rec['description']}</p>"
204
 
205
  if rec['actions']:
206
- recommendations += "<ul>"
207
  for action in rec['actions']:
208
- recommendations += f"<li style='color: #1f2937;'>{action}</li>"
209
  recommendations += "</ul>"
210
 
211
  recommendations += "</div>"
@@ -218,7 +287,7 @@ def format_summary_results(summary):
218
  <div style="padding: 20px; border: 1px solid #ddd; border-radius: 10px; background-color: #ffffff;">
219
  {basic_info}
220
  {sender_stats}
221
- {primary_abuser}
222
  {escalation}
223
  {recommendations}
224
  </div>
@@ -227,9 +296,11 @@ def format_summary_results(summary):
227
  return html
228
  except Exception as e:
229
  logger.error(f"Error formatting summary results: {e}")
 
230
  return f"<p style='color: #1f2937;'>Error formatting summary: {str(e)}</p>"
231
 
232
 
 
233
  def format_safety_plan(safety_plan):
234
  """Format safety plan for display"""
235
  try:
@@ -276,8 +347,8 @@ def create_interface():
276
  with gr.Column(scale=2):
277
  summary_output = gr.HTML(
278
  label="Analysis Summary",
279
- value="<p>Upload a file and click 'Analyze Chat History' to see results.</p>"
280
- )
281
 
282
  with gr.Row():
283
  with gr.Column():
@@ -341,54 +412,62 @@ def create_interface():
341
  </div>
342
  """)
343
 
344
- # Define event handlers
345
  def handle_file_analysis(file_path):
346
- if not file_path:
347
- return (
348
- "<p>Please upload a file first.</p>",
349
- None, None, None, None,
350
- "<p>Please upload a file first.</p>"
351
- )
352
-
353
- try:
354
- # Analyze file
355
- results_df, summary = analyze_file(file_path)
356
-
357
- if "error" in summary:
358
- return (
359
- f"<p>Error: {summary['error']}</p>",
360
- None, None, None, None,
361
- "<p>Error analyzing file.</p>"
362
- )
363
-
364
- # Format summary
365
- summary_html = format_summary_results(summary)
366
-
367
- # Generate plots
368
- timeline = generate_timeline_chart(results_df)
369
- pattern_freq = generate_pattern_frequency_chart(results_df)
370
- sender_comp = generate_sender_comparison_chart(results_df)
371
- time_heatmap = generate_time_of_day_heatmap(results_df)
372
-
373
- # Format safety plan
374
- safety_plan_html = format_safety_plan(summary['safety_plan'])
375
-
376
- return (
377
- summary_html,
378
- timeline,
379
- pattern_freq,
380
- sender_comp,
381
- time_heatmap,
382
- safety_plan_html
383
- )
384
- except Exception as e:
385
- logger.error(f"Error in handle_file_analysis: {e}")
386
- logger.error(traceback.format_exc())
387
- return (
388
- f"<p>Error analyzing file: {str(e)}</p>",
389
- None, None, None, None,
390
- "<p>Error analyzing file.</p>"
391
- )
 
 
 
 
 
 
 
 
 
392
 
393
  def handle_message_analysis(message):
394
  if not message.strip():
 
163
  else:
164
  sender_stats += "<p style='color: #1f2937;'>No sender statistics available.</p>"
165
 
166
+ # Format primary abuser section
167
+ primary_abuser_html = "<h3 style='color: #1f2937;'>Primary Concern</h3>"
168
  if summary['primary_abuser']:
169
+ primary_abuser_html += f"<p style='color: #1f2937;'>The analysis indicates that <strong style='color: #1f2937;'>{summary['primary_abuser']}</strong> "
170
+ primary_abuser_html += "shows the highest percentage of concerning communication patterns.</p>"
171
+
172
+ # Add detailed primary abuser analysis if available
173
+ if summary.get('primary_abuser_analysis'):
174
+ analysis = summary['primary_abuser_analysis']
175
+
176
+ # Add pattern section with collapsible details
177
+ primary_abuser_html += "<div style='margin-top: 20px; border: 1px solid #e5e7eb; border-radius: 8px; padding: 15px; background-color: #f9fafb;'>"
178
+ primary_abuser_html += "<h4 style='color: #1f2937; margin-top: 0;'>Most Common Patterns</h4>"
179
+
180
+ # Get patterns from sender stats
181
+ if summary['sender_stats'].get(summary['primary_abuser']):
182
+ abuser_stats = summary['sender_stats'][summary['primary_abuser']]
183
+ if abuser_stats.get('common_patterns'):
184
+ primary_abuser_html += "<ul style='color: #1f2937;'>"
185
+ for pattern, count in abuser_stats['common_patterns'][:5]: # Top 5 patterns
186
+ primary_abuser_html += f"<li style='color: #1f2937; margin-bottom: 8px;'><strong>{pattern}</strong> ({count} occurrences)</li>"
187
+ primary_abuser_html += "</ul>"
188
+ else:
189
+ primary_abuser_html += "<p style='color: #1f2937;'>No specific patterns detected.</p>"
190
+
191
+ # Add emotional tones section
192
+ primary_abuser_html += "<h4 style='color: #1f2937; margin-top: 20px;'>Emotional Tone Analysis</h4>"
193
+ if analysis.get('emotional_tones'):
194
+ primary_abuser_html += "<ul style='color: #1f2937;'>"
195
+ for tone, count in analysis['emotional_tones']:
196
+ if tone != "neutral":
197
+ primary_abuser_html += f"<li style='color: #1f2937;'><strong>{tone}</strong> ({count} messages)</li>"
198
+ primary_abuser_html += "</ul>"
199
+ else:
200
+ primary_abuser_html += "<p style='color: #1f2937;'>No significant emotional tones detected.</p>"
201
+
202
+ # Add DARVO score
203
+ darvo_level = "High" if analysis.get('darvo_score', 0) >= 0.65 else "Moderate" if analysis.get('darvo_score', 0) >= 0.25 else "Low"
204
+ darvo_color = "#ef4444" if darvo_level == "High" else "#f59e0b" if darvo_level == "Moderate" else "#10b981"
205
+
206
+ primary_abuser_html += f"""
207
+ <h4 style='color: #1f2937; margin-top: 20px;'>DARVO Analysis</h4>
208
+ <p style='color: #1f2937;'>DARVO Score: <strong style='color: {darvo_color};'>{analysis.get('darvo_score', 0):.3f}</strong> ({darvo_level})</p>
209
+ <p style='color: #1f2937; font-size: 0.9em;'>DARVO (Deny, Attack, Reverse Victim & Offender) indicates attempts to shift blame and manipulate the narrative.</p>
210
+ """
211
+
212
+ # Add time patterns section
213
+ primary_abuser_html += "<h4 style='color: #1f2937; margin-top: 20px;'>Communication Timing Patterns</h4>"
214
+
215
+ # Peak hours
216
+ primary_abuser_html += "<p style='color: #1f2937;'><strong>Peak Hours:</strong> "
217
+ if analysis.get('peak_hours'):
218
+ peak_hours_formatted = [f"{h}:00" for h in analysis['peak_hours']]
219
+ primary_abuser_html += f"{', '.join(peak_hours_formatted)}</p>"
220
+ else:
221
+ primary_abuser_html += "No clear pattern</p>"
222
+
223
+ # Peak days
224
+ primary_abuser_html += "<p style='color: #1f2937;'><strong>Peak Days:</strong> "
225
+ if analysis.get('peak_days'):
226
+ primary_abuser_html += f"{', '.join(analysis['peak_days'])}</p>"
227
+ else:
228
+ primary_abuser_html += "No clear pattern</p>"
229
+
230
+ primary_abuser_html += "</div>"
231
  else:
232
+ primary_abuser_html += "<p style='color: #1f2937;'>No clear pattern of concerning communication from a specific sender.</p>"
233
 
234
  # Format escalation data
235
  escalation = "<h3 style='color: #1f2937;'>Escalation Analysis</h3>"
 
240
  future_prediction = summary['escalation_data'].get('future_prediction')
241
  cyclic_pattern = summary['escalation_data'].get('cyclic_pattern', False)
242
 
243
+ # Add color coding for trend direction
244
+ trend_color = "#ef4444" if trend == "escalating" else "#10b981" if trend == "de-escalating" else "#6b7280"
245
+
246
+ escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Trend Direction:</strong> <span style='color: {trend_color};'>{trend.title()}</span></p>"
247
  escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Trend Strength:</strong> {trend_strength:.2f}</p>"
248
  escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>Recent Average:</strong> {recent_avg:.1f}%</p>"
249
 
250
  if future_prediction is not None:
251
+ future_color = "#ef4444" if future_prediction > 70 else "#f59e0b" if future_prediction > 50 else "#10b981"
252
+ escalation += f"<p style='color: #1f2937;'><strong style='color: #1f2937;'>7-Day Prediction:</strong> <span style='color: {future_color};'>{future_prediction:.1f}%</span></p>"
253
 
254
  if cyclic_pattern:
255
  cycle_period = summary['escalation_data'].get('cycle_period', 'unknown')
256
+ escalation += f"""
257
+ <div style='margin-top: 15px; padding: 10px; background-color: #fffbeb; border-left: 4px solid #f59e0b; border-radius: 4px;'>
258
+ <p style='color: #1f2937; margin: 0;'><strong style='color: #1f2937;'>⚠️ Cyclic Abuse Pattern Detected</strong></p>
259
+ <p style='color: #1f2937; margin-top: 5px;'>The analysis shows a repeating cycle of approximately {cycle_period} days. This is consistent with the cycle of abuse, where periods of tension and abuse are followed by reconciliation and calm before repeating.</p>
260
+ </div>
261
+ """
262
  else:
263
  escalation += "<p style='color: #1f2937;'>No escalation data available.</p>"
264
 
 
267
  if summary['recommendations']:
268
  recommendations += "<div style='max-height: 300px; overflow-y: auto;'>"
269
  for rec in summary['recommendations']:
270
+ recommendations += f"<div style='margin-bottom: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #3b82f6;'>"
271
+ recommendations += f"<h4 style='color: #1f2937; margin-top: 0;'>{rec['title']}</h4>"
272
  recommendations += f"<p style='color: #1f2937;'>{rec['description']}</p>"
273
 
274
  if rec['actions']:
275
+ recommendations += "<ul style='color: #1f2937;'>"
276
  for action in rec['actions']:
277
+ recommendations += f"<li style='color: #1f2937; margin-bottom: 5px;'>{action}</li>"
278
  recommendations += "</ul>"
279
 
280
  recommendations += "</div>"
 
287
  <div style="padding: 20px; border: 1px solid #ddd; border-radius: 10px; background-color: #ffffff;">
288
  {basic_info}
289
  {sender_stats}
290
+ {primary_abuser_html}
291
  {escalation}
292
  {recommendations}
293
  </div>
 
296
  return html
297
  except Exception as e:
298
  logger.error(f"Error formatting summary results: {e}")
299
+ logger.error(traceback.format_exc())
300
  return f"<p style='color: #1f2937;'>Error formatting summary: {str(e)}</p>"
301
 
302
 
303
+
304
  def format_safety_plan(safety_plan):
305
  """Format safety plan for display"""
306
  try:
 
347
  with gr.Column(scale=2):
348
  summary_output = gr.HTML(
349
  label="Analysis Summary",
350
+ value="<p style='color: #1f2937;'>Upload a file and click 'Analyze Chat History' to see results.</p>",
351
+ elem_id="summary_output" # Add an element ID for easier debugging
352
 
353
  with gr.Row():
354
  with gr.Column():
 
412
  </div>
413
  """)
414
 
 
415
  def handle_file_analysis(file_path):
416
+ if not file_path:
417
+ return (
418
+ "<p style='color: #1f2937;'>Please upload a file first.</p>",
419
+ None, None, None, None,
420
+ "<p style='color: #1f2937;'>Please upload a file first.</p>"
421
+ )
422
+
423
+ try:
424
+ # Analyze file
425
+ results_df, summary = analyze_file(file_path)
426
+
427
+ if "error" in summary:
428
+ return (
429
+ f"<p style='color: #1f2937;'>Error: {summary['error']}</p>",
430
+ None, None, None, None,
431
+ "<p style='color: #1f2937;'>Error analyzing file.</p>"
432
+ )
433
+
434
+ # Format summary
435
+ summary_html = format_summary_results(summary)
436
+
437
+ # Generate plots
438
+ timeline = generate_timeline_chart(results_df)
439
+ pattern_freq = generate_pattern_frequency_chart(results_df)
440
+ sender_comp = generate_sender_comparison_chart(results_df)
441
+ time_heatmap = generate_time_of_day_heatmap(results_df)
442
+
443
+ # Format safety plan
444
+ safety_plan_html = format_safety_plan(summary['safety_plan'])
445
+
446
+ # Debug output
447
+ logger.info(f"Summary HTML length: {len(summary_html)}")
448
+ logger.info(f"Generated {len(results_df)} results")
449
+ logger.info(f"Timeline chart generated: {timeline is not None}")
450
+ logger.info(f"Pattern frequency chart generated: {pattern_freq is not None}")
451
+ logger.info(f"Sender comparison chart generated: {sender_comp is not None}")
452
+ logger.info(f"Time heatmap generated: {time_heatmap is not None}")
453
+
454
+ return (
455
+ summary_html,
456
+ timeline,
457
+ pattern_freq,
458
+ sender_comp,
459
+ time_heatmap,
460
+ safety_plan_html
461
+ )
462
+ except Exception as e:
463
+ logger.error(f"Error in handle_file_analysis: {e}")
464
+ logger.error(traceback.format_exc())
465
+ return (
466
+ f"<p style='color: #1f2937;'>Error analyzing file: {str(e)}</p>",
467
+ None, None, None, None,
468
+ "<p style='color: #1f2937;'>Error analyzing file.</p>"
469
+ )
470
+
471
 
472
  def handle_message_analysis(message):
473
  if not message.strip():