Makes ai rule generation content work good.
This commit is contained in:
@@ -1,8 +1,14 @@
|
||||
from flask import Blueprint, render_template, request, jsonify, make_response
|
||||
from flask_login import login_required, current_user
|
||||
from app import db
|
||||
from app.models import Folder
|
||||
from app.models import Folder, AIRuleCache
|
||||
from app.ai_service import AIService
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import json
|
||||
|
||||
# Initialize the AI service instance
|
||||
ai_service = AIService()
|
||||
|
||||
folders_bp = Blueprint('folders', __name__)
|
||||
|
||||
@@ -180,7 +186,10 @@ def edit_folder_modal(folder_id):
|
||||
return jsonify({'error': 'Folder not found'}), 404
|
||||
|
||||
# Return the edit folder modal with folder data
|
||||
response = make_response(render_template('partials/folder_modal.html', folder=folder))
|
||||
response = make_response(render_template('partials/folder_modal.html', folder=folder,
|
||||
folder_data={'rule_text': folder.rule_text,
|
||||
'show_ai_rules': True,
|
||||
'errors': None }))
|
||||
response.headers['HX-Trigger'] = 'open-modal'
|
||||
return response
|
||||
|
||||
@@ -313,4 +322,160 @@ def get_folders():
|
||||
|
||||
return response
|
||||
else:
|
||||
return render_template('partials/folders_list.html', folders=folders, show_hidden=show_hidden)
|
||||
return render_template('partials/folders_list.html', folders=folders, show_hidden=show_hidden)
|
||||
|
||||
@folders_bp.route('/api/folders/generate-rule', methods=['POST'])
|
||||
@login_required
|
||||
def generate_rule():
|
||||
"""Generate an email organization rule using AI."""
|
||||
try:
|
||||
# Get form data
|
||||
folder_name = request.form.get('name', '').strip()
|
||||
folder_type = request.form.get('folder_type', 'destination')
|
||||
rule_type = request.form.get('rule_type', 'single') # 'single' or 'multiple'
|
||||
rule_text = request.form.get('rule_text', '')
|
||||
|
||||
# Validate inputs
|
||||
if not folder_name:
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Folder name is required'})
|
||||
|
||||
if folder_type not in ['destination', 'tidy', 'ignore']:
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Invalid folder type'})
|
||||
|
||||
if rule_type not in ['single', 'multiple']:
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Invalid rule type'})
|
||||
|
||||
# Check cache first
|
||||
cache_key = AIRuleCache.generate_cache_key(folder_name, folder_type, rule_type, rule_text)
|
||||
cached_rule = AIRuleCache.query.filter_by(
|
||||
cache_key=cache_key,
|
||||
user_id=current_user.id,
|
||||
is_active=True
|
||||
).first()
|
||||
|
||||
if cached_rule and not cached_rule.is_expired():
|
||||
# Return cached result
|
||||
result = {
|
||||
'success': True,
|
||||
'cached': True,
|
||||
'rule': cached_rule.rule_text,
|
||||
'metadata': cached_rule.rule_metadata,
|
||||
'quality_score': cached_rule.rule_metadata.get('quality_score', 0) if cached_rule.rule_metadata else 0
|
||||
}
|
||||
return render_template('partials/ai_rule_result.html', result=result)
|
||||
|
||||
# Generate new rule using AI service
|
||||
if rule_type == 'single':
|
||||
rule_text, metadata = ai_service.generate_single_rule(folder_name, folder_type, rule_text)
|
||||
|
||||
if rule_text is None:
|
||||
# AI service failed, return fallback
|
||||
fallback_rule = ai_service.get_fallback_rule(folder_name, folder_type)
|
||||
result = {
|
||||
'success': True,
|
||||
'fallback': True,
|
||||
'rule': fallback_rule,
|
||||
'quality_score': 50,
|
||||
'message': 'AI service unavailable, using fallback rule'
|
||||
}
|
||||
return render_template('partials/ai_rule_result.html', result=result)
|
||||
|
||||
# Cache the result
|
||||
expires_at = datetime.utcnow() + timedelta(hours=1) # Cache for 1 hour
|
||||
cache_entry = AIRuleCache(
|
||||
user_id=current_user.id,
|
||||
folder_name=folder_name,
|
||||
folder_type=folder_type,
|
||||
rule_text=rule_text,
|
||||
rule_metadata=metadata,
|
||||
cache_key=cache_key,
|
||||
expires_at=expires_at
|
||||
)
|
||||
db.session.add(cache_entry)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
result = {
|
||||
'success': True,
|
||||
'rule': rule_text,
|
||||
'metadata': metadata,
|
||||
'quality_score': metadata.get('quality_score', 0)
|
||||
}
|
||||
return render_template('partials/ai_rule_result.html', result=result)
|
||||
|
||||
else: # multiple rules
|
||||
rules, metadata = ai_service.generate_multiple_rules(folder_name, folder_type, rule_text)
|
||||
|
||||
if rules is None:
|
||||
# AI service failed, return fallback
|
||||
fallback_rule = ai_service.get_fallback_rule(folder_name, folder_type)
|
||||
result = {
|
||||
'success': True,
|
||||
'fallback': True,
|
||||
'rules': [{'text': fallback_rule, 'quality_score': 50}],
|
||||
'message': 'AI service unavailable, using fallback rule'
|
||||
}
|
||||
return render_template('partials/ai_rule_result.html', result=result)
|
||||
|
||||
# Cache the first rule as representative
|
||||
expires_at = datetime.utcnow() + timedelta(hours=1)
|
||||
cache_entry = AIRuleCache(
|
||||
user_id=current_user.id,
|
||||
folder_name=folder_name,
|
||||
folder_type=folder_type,
|
||||
rule_text=rules[0]['text'] if rules else '',
|
||||
rule_metadata=metadata,
|
||||
cache_key=cache_key,
|
||||
expires_at=expires_at
|
||||
)
|
||||
db.session.add(cache_entry)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
result = {
|
||||
'success': True,
|
||||
'rules': rules,
|
||||
'metadata': metadata
|
||||
}
|
||||
return render_template('partials/ai_rule_result.html', result=result)
|
||||
|
||||
except Exception as e:
|
||||
# Print unhandled exceptions to the console as required
|
||||
logging.exception("Error generating rule: %s", e)
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'An unexpected error occurred'})
|
||||
|
||||
@folders_bp.route('/api/folders/assess-rule', methods=['POST'])
|
||||
@login_required
|
||||
def assess_rule():
|
||||
"""Assess the quality of an email organization rule."""
|
||||
try:
|
||||
# Get form data
|
||||
rule_text = request.form.get('rule_text', '').strip()
|
||||
folder_name = request.form.get('folder_name', '').strip()
|
||||
folder_type = request.form.get('folder_type', 'destination')
|
||||
|
||||
# Validate inputs
|
||||
if not rule_text:
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Rule text is required'})
|
||||
|
||||
if not folder_name:
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Folder name is required'})
|
||||
|
||||
if folder_type not in ['destination', 'tidy', 'ignore']:
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'Invalid folder type'})
|
||||
|
||||
# Assess rule quality
|
||||
quality_assessment = ai_service.assess_rule_quality(rule_text, folder_name, folder_type)
|
||||
|
||||
result = {
|
||||
'success': True,
|
||||
'assessment': quality_assessment,
|
||||
'rule': rule_text,
|
||||
'quality_score': quality_assessment['score']
|
||||
}
|
||||
return render_template('partials/ai_rule_result.html', result=result)
|
||||
|
||||
except Exception as e:
|
||||
# Print unhandled exceptions to the console as required
|
||||
logging.exception("Error assessing rule: %s", e)
|
||||
return render_template('partials/ai_rule_result.html', result={'success': False, 'error': 'An unexpected error occurred'})
|
||||
Reference in New Issue
Block a user