Files
breakpilot-lehrer/backend-lehrer/alerts_agent/processing/rule_engine.py
Benjamin Admin bd4b956e3c [split-required] Split final 43 files (500-668 LOC) to complete refactoring
klausur-service (11 files):
- cv_gutter_repair, ocr_pipeline_regression, upload_api
- ocr_pipeline_sessions, smart_spell, nru_worksheet_generator
- ocr_pipeline_overlays, mail/aggregator, zeugnis_api
- cv_syllable_detect, self_rag

backend-lehrer (17 files):
- classroom_engine/suggestions, generators/quiz_generator
- worksheets_api, llm_gateway/comparison, state_engine_api
- classroom/models (→ 4 submodules), services/file_processor
- alerts_agent/api/wizard+digests+routes, content_generators/pdf
- classroom/routes/sessions, llm_gateway/inference
- classroom_engine/analytics, auth/keycloak_auth
- alerts_agent/processing/rule_engine, ai_processor/print_versions

agent-core (5 files):
- brain/memory_store, brain/knowledge_graph, brain/context_manager
- orchestrator/supervisor, sessions/session_manager

admin-lehrer (5 components):
- GridOverlay, StepGridReview, DevOpsPipelineSidebar
- DataFlowDiagram, sbom/wizard/page

website (2 files):
- DependencyMap, lehrer/abitur-archiv

Other: nibis_ingestion, grid_detection_service, export-doclayout-onnx

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 09:41:42 +02:00

139 lines
4.4 KiB
Python

"""
Rule Engine für Alerts Agent.
Evaluiert Regeln gegen Alert-Items und führt Aktionen aus.
Batch-Verarbeitung und Action-Anwendung.
"""
import logging
from typing import List, Dict, Any, Optional
from alerts_agent.db.models import AlertItemDB, AlertRuleDB, RuleActionEnum
from .rule_models import (
ConditionOperator,
RuleCondition,
RuleMatch,
get_field_value,
evaluate_condition,
evaluate_rule,
evaluate_rules_for_alert,
create_keyword_rule,
create_exclusion_rule,
create_score_threshold_rule,
)
logger = logging.getLogger(__name__)
# Re-export for backward compatibility
__all__ = [
"ConditionOperator",
"RuleCondition",
"RuleMatch",
"get_field_value",
"evaluate_condition",
"evaluate_rule",
"evaluate_rules_for_alert",
"RuleEngine",
"create_keyword_rule",
"create_exclusion_rule",
"create_score_threshold_rule",
]
class RuleEngine:
"""Rule Engine für Batch-Verarbeitung von Alerts."""
def __init__(self, db_session):
self.db = db_session
self._rules_cache: Optional[List[AlertRuleDB]] = None
def _get_active_rules(self) -> List[AlertRuleDB]:
"""Lädt aktive Regeln aus der Datenbank (cached)."""
if self._rules_cache is None:
from alerts_agent.db.repository import RuleRepository
repo = RuleRepository(self.db)
self._rules_cache = repo.get_active()
return self._rules_cache
def clear_cache(self) -> None:
"""Leert den Regel-Cache."""
self._rules_cache = None
def process_alert(self, alert: AlertItemDB) -> Optional[RuleMatch]:
"""Verarbeitet einen Alert mit allen aktiven Regeln."""
rules = self._get_active_rules()
return evaluate_rules_for_alert(alert, rules)
def process_alerts(self, alerts: List[AlertItemDB]) -> Dict[str, RuleMatch]:
"""Verarbeitet mehrere Alerts mit allen aktiven Regeln."""
rules = self._get_active_rules()
results = {}
for alert in alerts:
match = evaluate_rules_for_alert(alert, rules)
if match:
results[alert.id] = match
return results
def apply_rule_actions(self, alert: AlertItemDB, match: RuleMatch) -> Dict[str, Any]:
"""Wendet die Regel-Aktion auf einen Alert an."""
from alerts_agent.db.repository import AlertItemRepository, RuleRepository
alert_repo = AlertItemRepository(self.db)
rule_repo = RuleRepository(self.db)
action = match.action
config = match.action_config
result = {"action": action.value, "success": False}
try:
if action == RuleActionEnum.KEEP:
alert_repo.update_scoring(
alert_id=alert.id, score=1.0, decision="KEEP",
reasons=["rule_match"], summary=f"Matched rule: {match.rule_name}",
model="rule_engine",
)
result["success"] = True
elif action == RuleActionEnum.DROP:
alert_repo.update_scoring(
alert_id=alert.id, score=0.0, decision="DROP",
reasons=["rule_match"], summary=f"Dropped by rule: {match.rule_name}",
model="rule_engine",
)
result["success"] = True
elif action == RuleActionEnum.TAG:
tags = config.get("tags", [])
if tags:
existing_tags = alert.user_tags or []
new_tags = list(set(existing_tags + tags))
alert_repo.update(alert.id, user_tags=new_tags)
result["tags_added"] = tags
result["success"] = True
elif action == RuleActionEnum.EMAIL:
result["email_config"] = config
result["success"] = True
result["deferred"] = True
elif action == RuleActionEnum.WEBHOOK:
result["webhook_config"] = config
result["success"] = True
result["deferred"] = True
elif action == RuleActionEnum.SLACK:
result["slack_config"] = config
result["success"] = True
result["deferred"] = True
rule_repo.increment_match_count(match.rule_id)
except Exception as e:
logger.error(f"Error applying rule action: {e}")
result["error"] = str(e)
return result