Ir al contenido

Coherencia jerárquica en catalogación

Tras el scoring heurístico habitual, el clasificador aplica una capa de coherencia jerárquica: puede reordenar el ranking cuando el nodo líder y otro hermano (mismo parentId) compiten y se cumplen reglas explícitas alineadas con la desambiguación del vault. No suma ni resta score: solo intercambia posiciones en el top cuando las condiciones declaradas se cumplen.

Evita el sesgo symptom dominance: un síntoma muy lexicalizado (p. ej. puertas del ascensor) no debe ganar si el texto describe varios ejes y el vault indica un nodo más general bajo el mismo padre (p. ej. 1.4.2.5 frente a 1.4.2.2).

PiezaUbicación
Reglas versionadassrc/data/catalogacion-coherence-rules.v1.json (version + array rules)
Motor purosrc/lib/catalogacion-coherence.ts (applyCoherenceRules, loadCoherenceRulesVersion)
Hook en el clasificadorsrc/pages/api/catalogar-incidencia.ts — dentro de classifyIncident, después de ordenar por score y antes de tomar best / second para la confianza
Contrato v1src/pages/api/v1/catalogar-incidencia.ts — reexpone coherenceAdjustments y coherenceRules en el JSON minimal

Cada elemento de rules tiene esta forma (campos obligatorios salvo excludeNormalizedSubstrings):

CampoSignificado
idIdentificador estable para auditoría y trazabilidad en coherenceAdjustments.
parentIdPadre común: solo se comprueba coherencia si el líder en taxonomía tiene este parentId.
ifLeadingNodeIdLa regla solo se considera si el número 1 del ranking (tras reglas anteriores) es exactamente este nodo.
preferNodeIdHermano que debe pasar a la primera posición si el resto de condiciones se cumple.
maxLeaderMinusPreferredScoreTope de separación en score: leader.score − preferred.score debe ser este valor para aplicar el ajuste (evita saltos cuando el preferido va muy rezagado).
preferredMaxRankEl preferido debe estar ya entre las primeras posiciones 0…preferredMaxRank (índice en el ranking tras reglas previas).
when.allTokenGroupsHitLista de grupos de palabras clave. Debe cumplirse que cada grupo tenga al menos un acierto en el texto (ver siguiente apartado).
excludeNormalizedSubstringsOpcional. Si el texto normalizado contiene cualquiera de estas subcadenas (tras quitar acentos y minúsculas), la regla no se aplica.
reasonTexto breve que se devuelve en la API y sirve de explicación humana.

El motor usa el mismo texto normalizado (minúsculas, sin acentos) y el conjunto de tokens del mensaje que el resto del clasificador:

  • Palabra con espacios en la regla: se busca como substring en el texto normalizado.
  • Palabra sin espacios: debe aparecer como token en el mensaje, con longitud mínima 3 caracteres (tokens más cortos se ignoran para reducir ruido).
  1. Las reglas se evalúan en el orden del array; una promoción puede hacer que una regla posterior vea otro líder.
  2. Si una regla aplica, el nodo preferido pasa a la posición 1; el resto conserva el orden relativo (el antiguo líder queda detrás).
  3. Al nodo promovido se le añade una línea en evidence: Ajuste coherencia jerárquica: <ruleId> (visible en alternativas del modo full / en depuración).

La versión actual del fichero incluye la regla elev-142-multisymptom-prefer-225-over-222 bajo parentId 1.4.2: con señales de puertas/cabina y otro eje (vibración, paradas, garaje, recurrente, mantenimiento, etc.), sin exclusiones de parada total / fuera de servicio / atrapamiento, promueve 1.4.2.5 cuando el líder sería 1.4.2.2 y el gap de score no supera el umbral configurado.

  • coherenceAdjustments: array de { ruleId, fromNodeId, toNodeId, reason }; vacío si no hubo cambio.
  • model.coherenceRules (respuesta completa de classifyIncident): cadena de versión del fichero de reglas (p. ej. v1).
  • humanReadable.coherenceAdjustments: misma información para lectura junto al resto de campos amigables.

En POST /api/v1/catalogar-incidencia, el JSON minimal incluye coherenceAdjustments y coherenceRules en la raíz (la versión se toma de model.coherenceRules internamente). Los esquemas OpenAPI en public/openapi/ describen estos campos para integraciones externas.

  • Tras cambiar reglas o taxonomía, ejecutar npm run eval:catalogacion; los nodeId de las reglas deben existir en el dataset normalizado.
  • Añadir o ajustar entradas en scripts/catalogacion-gold-cases.json antes de endurecer una regla nueva.

Para listar padres con ≥2 hojas (candidatos a nuevas reglas), con metadatos de desambiguación del vault:

Ventana de terminal
npm run coherence:queue

Salida JSON en stdout (script scripts/list-coherence-sibling-queue.ts). Priorizar por familia (F01, F04, F10…) y añadir siempre un caso gold antes de activar una regla nueva.

  1. Completar reglas y gold para un parentId acotado (prototipo: 1.4.2).
  2. Ejecutar npm run eval:catalogacion.
  3. Repetir por familia usando la salida de coherence:queue.

La coherencia jerárquica es posterior al score descrito en Pesos y clasificación: primero se calculan y ordenan candidatos; después puede reordenarse el top entre hermanos; después se calcula la confianza con el primero y el segundo del ranking ya ajustado.