Volver a la wiki

Modelo AIInsight — insights de inteligencia artificial con clasificación estructurada

Modelo AIInsight

Archivo: monitoring/models_insight.py | DB: PostgreSQL (monitoring app) | Migration: 0020 (2026-06-05)

Propósito

Modelo que captura insights de inteligencia artificial generados por el Tutor (LLM) sobre anomalías detectadas en el monitoreo. Transforma datos de red (SNMP, SSH, syslog) en diagnósticos estructurados con recomendaciones de remediación.

Post-SA3: incluye campo category para clasificación estructurada (CONNECTIVITY / SECURITY / PERFORMANCE / OTHER), eliminando la necesidad de regex-matching en lógica de negocio.

Campos

Identidad

CampoTipoDescripción
idPKAutoincremento
organizationFK → core.OrganizationAlcance multi-tenant
targetFK → monitoring.MonitoringTargetDispositivo/host monitoreado

Anomalía original

CampoTipoDescripción
anomaly_triggerCharField(500)Nombre/tipo de la alerta que dispara el insight (p.ej. “Interface Down”, “DHCP Pool Exhaustion”)
snmp_dataJSONFieldRaw SNMP walk / MIB values (-- para missing)
ssh_logsJSONFieldRaw syslog / SSH logs (sanitizados para no exponer credenciales)
raw_snmp_dataTextFieldSNMP output, almacenado para auditabilidad
raw_ssh_logsTextFieldSSH/syslog output, almacenado para auditabilidad

Diagnóstico del Tutor

CampoTipoDescripción
diagnosis_textTextFieldDiagnóstico en lenguaje natural (Tutor)
summaryCharField(500)Resumen ejecutivo del problema
osi_layerIntegerField(1-7, nullable)Capa OSI (1=Physical, 2=DataLink, 3=Network, etc.)
confidence_scoreFloatField(0.0-1.0)Confianza del Tutor en su diagnosis
telemetry_insightTextFieldMeta-datos sobre el origen del insight (fuente de datos, timestamps, índices)

Recomendación de acción

CampoTipoDescripción
action_labelCharField(200)Acción recomendada (p.ej. “Check interface configuration”, “Restart DHCP service”)
action_descriptionTextFieldDescripción detallada de la acción
commandsJSONFieldArray de comandos sugeridos (CLI, API, manual steps)
rollback_commandsJSONFieldRollback en caso de que la acción cause problemas

Clasificación estructurada (Etapa 3 B18)

CampoTipoDescripción
categoryCharField(20, indexed)Enum: CONNECTIVITY | SECURITY | PERFORMANCE | OTHER

Enum AIInsight.Category:

class Category(models.TextChoices):
    CONNECTIVITY = "connectivity", "Connectivity"
    SECURITY = "security", "Security"
    PERFORMANCE = "performance", "Performance"
    OTHER = "other", "Other"

Asignación: En create_insight(), vía classify_insight_category(trigger_text + summary_text), que busca keywords hardcodeadas (idénticas a las de la migration 0020 para determinismo).

Control de estado

CampoTipoDescripción
statusCharField (Enum)PENDING | ACKNOWLEDGED | RESOLVED
ai_providerCharField(50)“anthropic”, “google”, “openai”, etc.
acknowledged_atDateTimeField(nullable)Timestamp de ACK por el usuario
acknowledged_notesTextField(blank)Notas del usuario
created_atDateTimeField(auto_now_add)Timestamp de creación
updated_atDateTimeField(auto_now)Timestamp de última edición

Índices

CampoUso
organizationScoping: filtrar por tenant
targetAnomalías de un dispositivo
statusEstados (PENDING, ACKNOWLEDGED, etc.)
created_atTimeseries / historial
categoryEtapa 3: auto_resolve_connectivity_insights() filtra category=CONNECTIVITY directamente

Flujo de creación

  1. Anomalía detectada: MonitoringAlert → spike o threshold violation.
  2. Recolectar contexto: SNMP walk, SSH log snapshot, syslog.
  3. Llamada al Tutor: create_insight(target, anomaly_description, snmp_data, ssh_logs, ...).
  4. Clasificación automática: classify_insight_category(f"{anomaly_description} {diagnosis_summary}") → asigna category.
  5. Almacenar en DB: AIInsight + AIInsightAuditLog.

Flujo de resolución automática (Etapa 3)

Antes (B18):

pending = AIInsight.objects.filter(target_id=target_id, status=PENDING)
for insight in pending:
    text = f"{insight.summary} {insight.anomaly_trigger}".lower()
    if any(kw in text for kw in ["total loss", "100%", ...]):  # Substring match ❌
        insight.status = ACKNOWLEDGED

Después (Etapa 3):

pending = AIInsight.objects.filter(
    target_id=target_id,
    status=PENDING,
    category=AIInsight.Category.CONNECTIVITY  # Estructurado, indexed ✓
)
for insight in pending:
    insight.status = ACKNOWLEDGED  # Sin regex

Ventajas:

Migración 0020

Fecha: 2026-06-05 | Status: RunPython autónomo

La migración:

  1. Añade campo category (CharField, choices, indexed, default=“other”).
  2. Backfill: itera todos los AIInsight existentes, aplica la función _classify (snapshot de keywords) a cada uno.
  3. Solo actualiza si category != "other" (optimización: evita touchdowns innecesarios).
  4. Bulk update en batches de 500 filas.
  5. Rollback: noop_reverse (no puede deshacer el backfill de forma limpia sin pérdida de info).

Snapshot de keywords en la migration:

_CONNECTIVITY = ["total loss", "unreachable", "100%", "device down", "link_down", "link down"]
_SECURITY = ["rogue", "deauth", "evil twin", "arp spoof", ..., "spoofing"]
_PERFORMANCE = ["latency", "packet loss", ..., "duplex"]

Idéntico a insight_service._CONNECTIVITY_KEYWORDS etc., asegurando determinismo histórico.

Relaciones

RelaciónModeloDescripción
organizationcore.OrganizationMulti-tenancy: un insight solo es visible a su org
targetMonitoringTargetFK: el insight está vinculado a un dispositivo/host
audit_logs (reverse)AIInsightAuditLogHistorial de cambios (creación, ACK, resolución)

Auditoría

Todo cambio de estado crea un AIInsightAuditLog:

AIInsightAuditLog.objects.create(
    insight=insight,
    action="created" | "acknowledged" | "auto_resolved",
    details={"reason": "...", "provider": "..."}
)

Véase también

Subir