El encargo era pequeño: un formulario de alta de clientes que rechazara DNI y NIE mal escritos antes de llegar al servidor. Empecé por lo obvio, una regex: ocho cifras y una letra mayúscula.
/^\d{8}[A-Z]$/
Pasaba todas mis pruebas, y el fallo estaba justo ahí: 12345678A también pasaba. Una regex sabe cómo se escribe un DNI, pero no sabe si ese DNI existe. La letra no es decorativa, es un dígito de control.
Qué hice con la IA local
Abrí Elffuss Code, pegué la regex y los casos que fallaban y le pregunté al modelo qué se me estaba escapando. Me explicó el mecanismo: se divide el número entre 23 y el resto indexa la cadena TRWAGMYFPDXBNJZSQVHLCKE. Para 12345678 el resto es 14 y la letra es la Z. Con eso reescribimos la función y le pedí tests con casos límite.
Salieron tres cosas que yo no había pensado:
- El NIE. Empieza por X, Y o Z, que se sustituyen por 0, 1 y 2 antes de calcular. X1234567L es válido; con la letra cambiada, no.
- Lo que llega pegado desde fuera. Minúsculas, espacios, guiones: «12.345.678-z». Normalizar primero, validar después.
- Las letras imposibles. Un DNI nunca lleva I, Ñ, O ni U. Con la tabla de 23 letras ese rechazo sale solo, sin una regla aparte.
No me fié del modelo a ciegas. Calculé a mano un par de letras para comprobar los tests, porque una tabla con una letra cambiada habría dado por buenos DNI falsos con mucha seguridad. Aun así, dejarle escribir la primera versión y los casos de prueba me ahorró la tarde.
Por qué importaba que fuera en local
Para probar un validador de DNI se acaba pegando DNI de verdad. Los míos eran un extracto de la base de datos del cliente, con nombres al lado, porque los casos raros solo aparecen en datos reales. Eso no lo mando a un servicio externo ni por comodidad. Aquí el modelo corre en el navegador, sobre mi propia GPU: el código, el prompt y esas filas se quedaron en mi equipo. Funcionó incluso con la conexión cortada.
Es la misma razón por la que uno no pega un volcado de clientes en un chat cualquiera. Con la IA en local no hace falta decidir qué es «lo bastante anónimo» para compartir: no sale nada.
Lo que me quedo
La función final son unas veinte líneas y nueve tests. El formato y el control van por separado: la regex descarta lo que ni parece un DNI y el módulo 23 decide si es válido. Si tu validador solo tiene la regex, prueba 12345678A. Si te lo da por bueno, tienes el mismo fallo que yo.
Abre Elffuss Code y prueba tu propio validador con datos reales: corre en el navegador, sobre tu GPU, y ni el código ni lo que pegues se suben a ningún sitio.
Abrir Code →