Pesos y clasificación
Este manual distingue tres cosas distintas que a veces se confunden:
- Puntuación interna (score) que el clasificador suma por cada nodo candidato.
- Confianza que se muestra al usuario (derivada del mejor score frente al segundo).
- Peso de completitud del vault en el script de auditoría
audit_vault_signals.py(calidad documental del nodo, no el score en tiempo real).
La fuente de verdad operativa del API es src/pages/api/catalogar-incidencia.ts (funciones classifyIncident y scoreCandidate). El explorador web usa una versión simplificada en src/components/explorer/ExplorerApp.tsx (scoreNodeForIncident): los números no coinciden al 100 % con el API, pero la idea es la misma.
El atributo fm_type (hard | soft | mixto) en cada hoja no entra en la fórmula de score del clasificador; solo describe el tipo de FM asociado al nodo. Definición y criterios: Ontología y taxonomía → Campo fm_type.
El campo ai.disambiguation del dataset normalizado procede del vault: bloque > **Desambiguación:** en la ficha (si existe) o, si no, la primera línea > del cuerpo (breadcrumb). Ese texto se incluye en searchText al generar scripts/generate-normalized-taxonomy.js, de modo que la cobertura semántica y coincidencias por tokens pueden usar también esas frases. Sigue existiendo la pista disambiguationHint en la respuesta del API para la mejor hoja (no es una bonificación numérica separada).
1. Flujo general del clasificador (API)
Sección titulada «1. Flujo general del clasificador (API)»- Se normaliza el texto (minúsculas, sin acentos, tokenización).
- Si el mensaje trae el patrón
Texto canónico: … Texto original: …, solo el tramo canónico entra en la clasificación (el original queda para trazabilidad). - Para cada nodo del dataset normalizado se calcula un score sumando contribuciones (tokens, frases, reglas contextuales).
- Se descartan candidatos con score ≤
SCORE_MIN(actualmente0.0001). - Se ordenan por score descendente.
- Coherencia jerárquica (reglas declarativas): puede reordenar el top entre hojas hermanas con el mismo
parentIdsin modificar los scores numéricos. Detalle de campos, API y flujo de trabajo: Coherencia jerárquica (catalogación). - El primero del ranking tras ese paso es la mejor hoja (o el mejor candidato según reglas de hoja).
- La confianza se obtiene con
computeConfidence(mejorScore, segundoScore)y se compara conminConfidence(por defecto 0,55 si el cliente no envía el parámetro), posiblemente relajado porgetEffectiveMinConfidencesegún el tipo de evidencia (ver §4).
2. Pesos base por tipo de coincidencia (API)
Sección titulada «2. Pesos base por tipo de coincidencia (API)»Estos valores son aditivos: cuantas más evidencias encajen, mayor es el score del nodo.
| Concepto | Efecto típico | Notas |
|---|---|---|
| Tokens del nombre del nodo | +1,8 por token del nombre que aparezca en el mensaje | Intersección de tokens. |
ID del nodo en el texto (p. ej. 1.2.1.4.1) | +8 | Refuerzo fuerte si el usuario o un sistema citan el código. |
| Slug del nodo en el texto | +5 | Similar al ID, con umbral de longitud para evitar ruido. |
Keywords (ai.kw en taxonomía) | +3,2 por keyword que coincide | Frases completas: substring en texto normalizado; palabra suelta: token presente. |
| Señales (frase completa en texto) | +4,5 por señal | Función phraseListScore. |
| Señales (solo solapamiento de tokens ≥ 0,45) | + overlap × 3,4 | overlap = tokens comunes / tokens de la frase. |
| Ejemplos | Igual criterio que señales | Misma función phraseListScore. |
Cobertura semántica (searchText del nodo) | Si la proporción de tokens del mensaje presentes en el nodo es ≥ 0,34: + proporción × (8,5 si hoja, × 4,2 si no) | Prioriza hojas cuando el vocabulario encaja. |
| Cobertura jerárquica (breadcrumb) | Si ≥ 0,4: + proporción × (2,2 hoja / 1,1 resto) | |
| Nombre de tramo de breadcrumb (≥ 8 caracteres) en el texto | +1,6 por coincidencia | Hasta las que apliquen. |
Además existen muchas reglas contextuales (biohazard/limpieza, tipo declarado en el formulario, domiciliación bancaria, juntas, actas, contratos, seguridad, filtraciones vs fugas, etc.) que suman o restan bonos o penalizaciones fijas a ramas concretas de la taxonomía. Están implementadas en el mismo scoreCandidate: al cambiar el comportamiento hay que revisar también los casos de prueba en scripts/eval-catalogacion.ts y scripts/catalogacion-gold-cases.json.
Un inventario orientativo de reglas añadidas o reforzadas recientemente (garaje, humedades, portal, CCTV, etc.) está en §9; los valores exactos siguen en código.
3. De score a “probabilidad” (confianza)
Sección titulada «3. De score a “probabilidad” (confianza)»El score no es una probabilidad entre 0 y 1. La confianza se calcula así (computeConfidence):
margen = max(mejorScore − segundoScore, 0)confianza = 0,35 + margen / (mejorScore + segundoScore + 6)- Resultado acotado entre 0 y
0,99y redondeado a 4 decimales.
Intuición: si el segundo clasificado queda muy cerca del primero, el margen es pequeño y la confianza baja aunque el score absoluto sea alto.
4. Umbrales: minConfidence y relajación automática
Sección titulada «4. Umbrales: minConfidence y relajación automática»minConfidence(query/body JSON): umbral mínimo para marcarreviewRequired = false. Por defecto 0,55 si no se envía (tanto el endpoint legacy comoPOST /api/v1/catalogar-incidencia).getEffectiveMinConfidencepuede bajar el umbral efectivo cuando hay evidencias fuertes o combinaciones previstas (contratos con dominio alineado, domiciliación bancaria, tipo declarado con rama preferida, heurísticas de biohazard/limpieza, varias líneas de evidencia semántica, etc.). Así se evita pedir revisión humana en escenarios donde el modelo ya es explícito en el código.- Strict vs relajado (importante): en
catalogar-incidencia.ts(rutasGET/POSTsin versión), si el cliente envíaminConfidence, se pasastrictMinConfidence: truey no se aplica la relajación: el umbral aplicado es exactamente el pedido. En cambioPOST /api/v1/catalogar-incidenciallama aclassifyIncidentsin esa opción (sigue el valor por defectostrictMinConfidence: false), así que sí puede aplicarsegetEffectiveMinConfidenceaunque el cuerpo traigaminConfidence.
Para afinar política de revisión humana se tocan estas funciones y, si aplica, el valor por defecto de minConfidence en cada endpoint.
5. Explorador (UI) frente al API
Sección titulada «5. Explorador (UI) frente al API»scoreNodeForIncident en el explorador usa coeficientes parecidos pero distintos (p. ej. keywords ×3 frente a ×3,2, señales/ejemplos con pasos ligeramente diferentes, base +0,35 en hojas). No uses el explorador como referencia numérica exacta del API; úsalo como orientación visual.
6. Auditoría del vault: pesos de completitud (no son el clasificador)
Sección titulada «6. Auditoría del vault: pesos de completitud (no son el clasificador)»El script analisis/audit_vault_signals.py calcula un score 0–10 de “¿el nodo está bien documentado?”, no de clasificación:
| Componente | Peso en el score de completitud |
|---|---|
| Keywords (objetivo ≥ 6) | 0,30 |
| Señales de alarma (objetivo ≥ 4) | 0,40 |
| Ejemplos reales (objetivo ≥ 2) | 0,30 |
Cada componente se normaliza a 0–1 según cuántos ítems hay frente al objetivo y se combina en una nota 0–10. Sirve para priorizar mejoras editoriales en el vault, no para decidir el nodo ganador en runtime.
7. Cómo gestionar o cambiar los pesos (checklist)
Sección titulada «7. Cómo gestionar o cambiar los pesos (checklist)»- Clasificación en producción (API): editar constantes y reglas en
scoreCandidate,phraseListScore,overlapRatioy listas de frases ensrc/pages/api/catalogar-incidencia.ts. - Documentación: tras cambiar bonificaciones o criterios de desambiguación, actualizar §9 de esta página (intento + nodos ±) para que producto y mantenimiento compartan la misma referencia.
- Coherencia UI: si quieres paridad explorador/API, alinear manualmente
ExplorerApp.tsx(no está automatizado). - Regresión: ejecutar
npm run eval:catalogacion(evalúa contra casos oro). - Dataset: los keywords/señales/ejemplos vienen del vault →
vault_to_taxonomy.py→taxonomy.js→ generación detaxonomy.normalized.json. Mejorar datos suele importar más que retocar un+0,2en el código. - Completitud documental: ajustar
W_KEYWORDS,W_SENALES,W_EJEMPLOSo los objetivosTARGET_*enaudit_vault_signals.pysi cambias el estándar de calidad del vault.
8. Lectura recomendada
Sección titulada «8. Lectura recomendada»- Ontología y taxonomía: qué modela el árbol y qué papel juegan señales y keywords a nivel conceptual.
- analisis/CLAUDE.md: flujo vault →
taxonomy.js→ generación de documentación.
Si añades reglas nuevas al clasificador, documenta en §9 el intento (qué conflicto resuelven), los nodos afectados y los órdenes de magnitud (+/−); enlaza al bloque de código (comentarios // ── … ── en scoreCandidate) y amplía scripts/catalogacion-gold-cases.json cuando el caso sea estable.
9. Reglas contextuales relevantes (inventario)
Sección titulada «9. Reglas contextuales relevantes (inventario)»Tabla de referencia de desambiguaciones con bonificaciones/penalizaciones aditivas sobre el score base. Condiciones exactas (substrings tras normalizar el texto) en catalogar-incidencia.ts, función scoreCandidate. Las cifras son las vigentes en código a 2026-04-05; si difieren, prevalece el archivo TS.
| Tema | Condición resumida | Penaliza (Δ) | Refuerza (Δ) |
|---|---|---|---|
| Ruido en garaje/parking | ruido + zona garaje/parking/sótano; sin ventilación/extractor/CO; sin puerta de garaje en foco | 1.5.3.1: −9,5 | 4.1.3.4: +8,2 |
| Portal abierto vs garaje | portal o “entrada al edificio” + “queda abierta/oberta” | 1.9.1.2: −12 | 6.3.1.1: +9 |
| CCTV / grabación | camara + graba / grabacion / funcionamiento | 1.1.2.3.1: −10 | 6.3.2.1: +9,5 |
| Timbre | presencia de timbre | 11.1.5: −9 | 1.6.2.1: +8 |
| Puerta comunitaria (seguimiento) | puerta + comunitaria + continuidad/fallo; sin caldera/calefacción | 1.2.2.1.1: −12 | 6.3.1.1: +8 |
| Cableado visible | cable/cableado + visible/visto/techo | 1.2.1.4.4: −9 | 9.2.2: +8,5 |
| Corriente de aire | entra aire / corriente de aire / cerramiento no estanco | 1.1.2.2.2: −9 | 6.3.1.1: +7,5 |
| Bomba / grupo de presión | (bomba o grupo+presion) + (ruido/urgente/revisar/revision/tarda) + agua | 1.2.1.3.2: −11; 3.4.3.2: −10 | 1.2.1.2.3: +11 |
| Agua recurrente en garaje | garaje + agua + recurrente/“otra vez”/“sigue”; sin atasco/bajante/fecales… | 1.2.3.1.2: −9 | 1.2.1.4.5: +8,5 |
| Humedad en techo sin lluvia | techo/sostre + humedad/mancha; sin lluvia/gotera/cuando llueve | 1.1.2.2.2: −7 | 1.2.1.4.4: +6,5 |
| Mancha en pared sin lluvia | pared + mancha/taca; sin lluvia/gotera | 1.1.2.2.2: −6,5 | 1.2.1.4.4: +6 |
| Fuga pequeña | fuga + pequeña/petita/tuberia | — | 1.2.1.4.1: +10 |
| Grieta parking/garaje | grieta + parking/garaje + pared/paramento/muro | — | 1.1.1.1.2: +9 |
| Pintura techo portal | portal + techo + pintura/pelando/desconchado/deterioro | 1.2.1.4.4: −6 | 9.8.2: +10 |
| Olor en ascensor | ascensor + olor/huele/olia | — | 10.1.6: +7 |
| Pitido sin caldera | pitido y sin caldera | 1.2.2.1.1: −10 | 4.1.3.4: +7,5 |
| Luz en rellano/patio/escalera (no ascensor) | luz/iluminacion/alumbrado/llum + rellano/patio/pati/… + apagado/fuera de servicio/…; sin ascensor/elevador/montacargas | 1.4.2.1: −14 | 1.3.2.3: +11,5 |
| Alumbrado de emergencia | emergencia + luz/alumbrado/luminaria + fallo; sin ascensor | 1.4.2.1: −14 | 1.3.3.1: +11,5 |
| Trámite / alcance de seguro | seguro/aseguradora/poliza + incidencia/alcance/siniestro/…; sin caldera/calefaccion | 1.2.2.2.1: −13 | 3.1.4.1: +10,5 |
| Puerta ascensor rápida o puertas (ajuste) | ascensor + puerta + rapido/demasiado/…; refuerzo existente para 1.4.2.2 | 1.4.1.2: −11 | 1.4.2.2: +9 (y −5,5 a 1.4.2.1) |
| Ascensor solo lentitud / espera | ascensor + tiempo de espera / espera excesiva / tarda+mucho; sin parada/avería/fuera de servicio | 1.4.2.1: −9 | 11.1.3: +8,5 |
Nodos nuevos en taxonomía (vault) que entran en el juego de puntuación por keywords y por las filas anteriores: 1.2.1.4.5 (agua en garaje/sótano origen indeterminado), 1.2.1.2.3 (grupo de presión / bomba de impulsión AFS), 4.1.3.4 (ruido en zona común sin origen identificado). Flujo de datos: analisis/vault/ → vault_to_taxonomy.py → taxonomy.js → npm run generate.
Informes de caja negra: el script scripts/report-124.ts clasifica los textos canónicos de analisis/clasificaciones_124_incidencias.md y escribe analisis/informe-124.md; no sustituye eval:catalogacion pero sirve para regresión rápida tras tocar reglas o el vault.
Última actualización (UTC): 2026-04-05 12:00:00 UTC