Files
ETB/ETB-API/knowledge_learning/management/commands/generate_recommendations.py
Iliyan Angelov 6b247e5b9f Updates
2025-09-19 11:58:53 +03:00

139 lines
4.9 KiB
Python

from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from datetime import timedelta
from incident_intelligence.models import Incident
from knowledge_learning.services.recommendation_engine import RecommendationEngine
from knowledge_learning.models import IncidentRecommendation
class Command(BaseCommand):
help = 'Generate recommendations for incidents'
def add_arguments(self, parser):
parser.add_argument(
'--days',
type=int,
default=1,
help='Number of days back to look for incidents (default: 1)'
)
parser.add_argument(
'--status',
type=str,
choices=['OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'],
default='OPEN',
help='Only generate recommendations for incidents with specific status (default: OPEN)'
)
parser.add_argument(
'--severity',
type=str,
choices=['LOW', 'MEDIUM', 'HIGH', 'CRITICAL', 'EMERGENCY'],
help='Only generate recommendations for incidents with specific severity'
)
parser.add_argument(
'--force',
action='store_true',
help='Force generation even if recommendations already exist'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='Show what would be generated without actually creating recommendations'
)
parser.add_argument(
'--max-recommendations',
type=int,
default=5,
help='Maximum number of recommendations per incident (default: 5)'
)
def handle(self, *args, **options):
days = options['days']
status = options['status']
severity = options['severity']
force = options['force']
dry_run = options['dry_run']
max_recommendations = options['max_recommendations']
# Calculate date range
end_date = timezone.now()
start_date = end_date - timedelta(days=days)
self.stdout.write(
self.style.SUCCESS(f'Looking for {status} incidents from {start_date.date()} to {end_date.date()}')
)
# Build queryset for incidents
queryset = Incident.objects.filter(
status=status,
created_at__gte=start_date,
created_at__lte=end_date
)
if severity:
queryset = queryset.filter(severity=severity)
# Filter out incidents that already have recommendations (unless force is used)
if not force:
existing_recommendation_incidents = IncidentRecommendation.objects.values_list('incident_id', flat=True)
queryset = queryset.exclude(id__in=existing_recommendation_incidents)
incidents = list(queryset)
if not incidents:
self.stdout.write(
self.style.WARNING('No incidents found matching criteria')
)
return
self.stdout.write(
self.style.SUCCESS(f'Found {len(incidents)} incidents to process')
)
if dry_run:
self.stdout.write(self.style.WARNING('DRY RUN - No recommendations will be created'))
for incident in incidents:
self.stdout.write(f' - {incident.title} ({incident.severity}) - {incident.created_at}')
return
# Initialize recommendation engine
recommendation_engine = RecommendationEngine()
success_count = 0
error_count = 0
total_recommendations = 0
for incident in incidents:
try:
self.stdout.write(f'Generating recommendations for: {incident.title}')
recommendations = recommendation_engine.generate_recommendations(
incident_id=str(incident.id),
max_recommendations=max_recommendations,
min_confidence=0.5
)
self.stdout.write(
self.style.SUCCESS(f' ✓ Generated {len(recommendations)} recommendations')
)
success_count += 1
total_recommendations += len(recommendations)
except Exception as e:
self.stdout.write(
self.style.ERROR(f' ✗ Failed to generate recommendations: {str(e)}')
)
error_count += 1
# Summary
self.stdout.write('\n' + '='*50)
self.stdout.write(
self.style.SUCCESS(f'Recommendation generation completed:')
)
self.stdout.write(f' Incidents processed: {success_count}')
self.stdout.write(f' Total recommendations generated: {total_recommendations}')
if error_count > 0:
self.stdout.write(
self.style.ERROR(f' Failed: {error_count}')
)
self.stdout.write('='*50)