thadillo commited on
Commit
316fc26
·
1 Parent(s): 71797a4

Phase 3 complete: Backend API for sentence-level analysis

Browse files

- Update /api/analyze to support sentence-level (use_sentences flag)
- Add /api/update-sentence-category endpoint
- Automatically create training examples from sentence corrections
- Recalculate submission primary category from sentences

Files changed (1) hide show
  1. app/routes/admin.py +89 -7
app/routes/admin.py CHANGED
@@ -1,5 +1,5 @@
1
  from flask import Blueprint, render_template, request, redirect, url_for, session, flash, jsonify, send_file
2
- from app.models.models import Token, Submission, Settings, TrainingExample, FineTuningRun
3
  from app import db
4
  from app.analyzer import get_analyzer
5
  from functools import wraps
@@ -277,6 +277,57 @@ def update_category(submission_id):
277
  print(f"Error updating category: {str(e)}")
278
  return jsonify({'success': False, 'error': str(e)}), 500
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  @bp.route('/api/toggle-flag/<int:submission_id>', methods=['POST'])
281
  @admin_required
282
  def toggle_flag(submission_id):
@@ -298,12 +349,17 @@ def delete_submission(submission_id):
298
  def analyze_submissions():
299
  data = request.json
300
  analyze_all = data.get('analyze_all', False)
 
301
 
302
  # Get submissions to analyze
303
  if analyze_all:
304
  to_analyze = Submission.query.all()
305
  else:
306
- to_analyze = Submission.query.filter_by(category=None).all()
 
 
 
 
307
 
308
  if not to_analyze:
309
  return jsonify({'success': False, 'error': 'No submissions to analyze'}), 400
@@ -316,13 +372,38 @@ def analyze_submissions():
316
 
317
  for submission in to_analyze:
318
  try:
319
- # Use the free Hugging Face model for classification
320
- category = analyzer.analyze(submission.message)
321
- submission.category = category
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  success_count += 1
323
 
324
  except Exception as e:
325
- print(f"Error analyzing submission {submission.id}: {e}")
326
  error_count += 1
327
  continue
328
 
@@ -331,7 +412,8 @@ def analyze_submissions():
331
  return jsonify({
332
  'success': True,
333
  'analyzed': success_count,
334
- 'errors': error_count
 
335
  })
336
 
337
  @bp.route('/export/json')
 
1
  from flask import Blueprint, render_template, request, redirect, url_for, session, flash, jsonify, send_file
2
+ from app.models.models import Token, Submission, Settings, TrainingExample, FineTuningRun, SubmissionSentence
3
  from app import db
4
  from app.analyzer import get_analyzer
5
  from functools import wraps
 
277
  print(f"Error updating category: {str(e)}")
278
  return jsonify({'success': False, 'error': str(e)}), 500
279
 
280
+ @bp.route('/api/update-sentence-category/<int:sentence_id>', methods=['POST'])
281
+ @admin_required
282
+ def update_sentence_category(sentence_id):
283
+ """Update category for a specific sentence"""
284
+ try:
285
+ sentence = SubmissionSentence.query.get_or_404(sentence_id)
286
+ data = request.json
287
+ new_category = data.get('category')
288
+
289
+ # Store original
290
+ original_category = sentence.category
291
+
292
+ # Validate category
293
+ if new_category and new_category not in CATEGORIES:
294
+ return jsonify({'success': False, 'error': f'Invalid category: {new_category}'}), 400
295
+
296
+ # Update sentence
297
+ sentence.category = new_category
298
+
299
+ # Create/update training example for this sentence
300
+ if new_category:
301
+ existing = TrainingExample.query.filter_by(sentence_id=sentence_id).first()
302
+
303
+ if existing:
304
+ existing.original_category = original_category
305
+ existing.corrected_category = new_category
306
+ existing.correction_timestamp = datetime.utcnow()
307
+ else:
308
+ training_example = TrainingExample(
309
+ sentence_id=sentence_id,
310
+ submission_id=sentence.submission_id,
311
+ message=sentence.text, # Just the sentence text
312
+ original_category=original_category,
313
+ corrected_category=new_category,
314
+ contributor_type=sentence.submission.contributor_type
315
+ )
316
+ db.session.add(training_example)
317
+
318
+ # Update parent submission's primary category (recalculate from sentences)
319
+ submission = sentence.submission
320
+ submission.category = submission.get_primary_category()
321
+
322
+ db.session.commit()
323
+
324
+ return jsonify({'success': True, 'category': new_category})
325
+
326
+ except Exception as e:
327
+ db.session.rollback()
328
+ logger.error(f"Error updating sentence category: {str(e)}")
329
+ return jsonify({'success': False, 'error': str(e)}), 500
330
+
331
  @bp.route('/api/toggle-flag/<int:submission_id>', methods=['POST'])
332
  @admin_required
333
  def toggle_flag(submission_id):
 
349
  def analyze_submissions():
350
  data = request.json
351
  analyze_all = data.get('analyze_all', False)
352
+ use_sentences = data.get('use_sentences', True) # NEW: sentence-level flag (default: True)
353
 
354
  # Get submissions to analyze
355
  if analyze_all:
356
  to_analyze = Submission.query.all()
357
  else:
358
+ # For sentence-level, look for submissions without sentence analysis
359
+ if use_sentences:
360
+ to_analyze = Submission.query.filter_by(sentence_analysis_done=False).all()
361
+ else:
362
+ to_analyze = Submission.query.filter_by(category=None).all()
363
 
364
  if not to_analyze:
365
  return jsonify({'success': False, 'error': 'No submissions to analyze'}), 400
 
372
 
373
  for submission in to_analyze:
374
  try:
375
+ if use_sentences:
376
+ # NEW: Sentence-level analysis
377
+ sentence_results = analyzer.analyze_with_sentences(submission.message)
378
+
379
+ # Clear old sentences for this submission
380
+ SubmissionSentence.query.filter_by(submission_id=submission.id).delete()
381
+
382
+ # Create new sentence records
383
+ for idx, result in enumerate(sentence_results):
384
+ sentence = SubmissionSentence(
385
+ submission_id=submission.id,
386
+ sentence_index=idx,
387
+ text=result['text'],
388
+ category=result['category'],
389
+ confidence=result.get('confidence')
390
+ )
391
+ db.session.add(sentence)
392
+
393
+ submission.sentence_analysis_done = True
394
+ # Set primary category for backward compatibility
395
+ submission.category = submission.get_primary_category()
396
+
397
+ logger.info(f"Analyzed submission {submission.id} into {len(sentence_results)} sentences")
398
+ else:
399
+ # OLD: Submission-level analysis (backward compatible)
400
+ category = analyzer.analyze(submission.message)
401
+ submission.category = category
402
+
403
  success_count += 1
404
 
405
  except Exception as e:
406
+ logger.error(f"Error analyzing submission {submission.id}: {e}")
407
  error_count += 1
408
  continue
409
 
 
412
  return jsonify({
413
  'success': True,
414
  'analyzed': success_count,
415
+ 'errors': error_count,
416
+ 'sentence_level': use_sentences
417
  })
418
 
419
  @bp.route('/export/json')