Lector de pruebas de velocidad v2: valor, unidad e IP
La v2 del lector de pruebas de velocidad devuelve cada medida con su número y su unidad tal como aparecen, más la IP del cliente cuando la prueba la muestra. En la prueba automática pasó de 48,0% a 95,3% de casos completos; en la revisión visual, de 35,8% a 96,8%, con 78 de 78 casos normales correctos.
Experimento 02 · Lector de pruebas de velocidad · v2
La v1 leía bajada, subida y ping, y convertía todo a Mbps dentro del propio modelo. Ahí estaba su principal fallo: cuando fast.com mostraba la velocidad en Kbps, devolvía el número sin convertir. En la v2 el modelo ya no convierte nada: copia cada medida con su número y su unidad tal como aparecen en pantalla, y además devuelve la IP del cliente cuando la prueba la muestra. La conversión a Mbps la hace después el código, sin margen de error.
Formato de respuesta, con una IP de ejemplo reservada para documentación:
{"es_prueba_velocidad": true, "descarga": {"valor": 280, "unidad": "Kbps"}, "subida": {"valor": 31, "unidad": "Mbps"}, "ping": {"valor": 44, "unidad": "ms"}, "ip": "203.0.113.25"}
Si la imagen no es una prueba de velocidad, el modelo responde false y deja el resto vacío. Un campo cuenta como correcto solo si coinciden el número y la unidad; la IP debe coincidir exactamente.
¿Por qué un modelo de IA y no solo OCR? ¿Y por qué no un LLM grande?
OCR con reglas no alcanza. Lo comprobamos de primera mano, porque las etiquetas de este experimento salieron justamente de OCR con reglas escritas para cada diseño de pantalla:
- Cada app, y cada versión de la misma app, coloca los datos de otra forma: columnas, recuadros, diales, filas de latencia, tarjetas para compartir o fotos de otra pantalla. Cada rediseño obliga a escribir reglas nuevas.
- Hay trampas que un OCR no entiende: iconos leídos como dígitos, la velocidad de datos de la barra de estado del teléfono, anuncios con números grandes, el valor medio junto al principal, la latencia con carga junto al ping en reposo o el número identificador de la prueba junto a la IP.
- Saber si la imagen es o no una prueba de velocidad tampoco es trivial: un chat que menciona «500 Mbps», la caja de un router o la página de configuración del módem usan las mismas palabras.
- Aun con todo ese trabajo, las reglas dejaron como dudosas más de 2.200 de las 9.580 imágenes. En la revisión visual hubo 20 imágenes sin respuesta segura de las reglas: el modelo ajustado acertó todos los campos en 17 de ellas, y el modelo base en 8.
El modelo aprende qué significa cada número por su contexto visual, en lugar de depender de coordenadas y palabras clave.
¿Y un LLM grande, como GPT Luna o Claude Haiku? Podría leer muchas de estas capturas, pero elegimos un modelo pequeño propio por estas razones:
- Privacidad: las capturas son de clientes y muestran datos como su IP. El modelo corre en nuestro propio hardware, así que las imágenes no se envían a terceros para leerlas.
- Costo y escala: una API cobra por cada imagen; este modelo procesa una captura en uno o dos segundos en una sola GPU, sin costo por llamada ni límites de uso.
- Respuesta estable: siempre devuelve el mismo JSON con definiciones fijas (ping en reposo y no con carga, valor principal y no el medio, número y unidad tal como aparecen) sin depender de cómo se redacte el prompt.
- Precisión en los dígitos: contrastamos nuestras etiquetas con lecturas que un LLM general había hecho de las mismas conversaciones. En la mayoría de los desacuerdos que revisamos a ojo, o el LLM había leído mal (4,2 como 42, 27,92 como 2,92, 8,41 como 0,41) o se refería a otra imagen. En uno, el que se equivocaba era nuestro etiquetador, y lo corregimos.
No evaluamos GPT Luna ni Claude Haiku sobre este conjunto, así que no afirmamos que rindan peor: la decisión es de privacidad, costo y control. Además, ambos enfoques se complementan: un LLM puede conversar con el cliente y razonar sobre el problema usando como dato el JSON que devuelve este modelo.
Prueba automática
300 imágenes reservadas: 147 pruebas de velocidad y 153 imágenes que no lo son. Con todos los campos correctos: base 48,0% y ajustado 95,3%.
Las tasas por campo se miden sobre las 147 pruebas de velocidad. El modelo base cae mucho en bajada porque casi nunca devuelve el formato pedido: con frecuencia escribe decimales con coma, lo que produce un JSON inválido, u omite la unidad. Solo en 6 de esos casos se equivocó en el número en sí.
Revisión visual independiente
Las mismas 95 imágenes revisadas a ojo en la v1, a las que añadimos la unidad y la IP: 57 pruebas de velocidad, 26 de ellas con IP visible, y 17 casos difíciles.
El caso en Kbps que fallaba en la v1 ahora sale bien. Los 3 fallos que quedan son casos difíciles: una IP tapada a medias por la barra del navegador, la subida de una prueba hecha desde una consola de videojuegos y una página de prueba que todavía estaba cargando, que el modelo tomó por un resultado.
Qué cambió en los datos
- Las etiquetas guardan el número tal como se ve y su unidad normalizada (Kbps, Mbps, Gbps o ms), sin convertir.
- La IP solo cuenta si se lee entera como IPv4. Si aparece mal leída, en IPv6 o hay varias, la imagen sale del entrenamiento, para no enseñar al modelo a dejar vacía una IP que sí se ve.
- Las pocas capturas en Kbps se repitieron cuatro veces en el entrenamiento para que el modelo aprenda la unidad.
- Contra la revisión visual, las etiquetas automáticas coincidieron en todo, unidad e IP incluidas, en 48 de 49 pruebas de velocidad y en 26 de 26 imágenes que no lo son.
Datos y entrenamiento
Igual que en la v1: separación por conversación y huella SHA-256 entre entrenamiento y evaluación, parte visual congelada y ajuste solo de la parte que genera el texto.
0,75 s base / 2,18 s ajustado
Promedio por imagen en la prueba automática, procesando una imagen tras otra mientras la máquina atendía otros trabajos. La v2 tarda más que la v1 porque su respuesta es más larga: unidades e IP.
¿Qué PC hace falta para usarlo?
El modelo tiene unos 900 millones de parámetros: los pesos del modelo base ocupan 2,5 GB y el adaptador entrenado, 9 MB. No hace falta un centro de datos. Medimos el consumo procesando una captura a la vez:
* Medido en nuestro experimento de comprobantes de pago, que usa la misma base y un adaptador del mismo tamaño.
- Recomendado: una PC con una GPU NVIDIA de 6 GB o más (por ejemplo una RTX 3060), de 8 a 16 GB de RAM y unos 10 GB libres en disco para el modelo y el entorno de Python. A uno o dos segundos por captura, son del orden de 2.000 a 3.000 capturas por hora.
- Sin tarjeta gráfica: también funciona en una PC común con un procesador de 6 núcleos y 16 GB de RAM, a unos 30 segundos por captura (unas 120 por hora). Alcanza para volúmenes bajos.
- Para comparar: GPT Luna o Claude Haiku no se pueden instalar en un equipo propio; solo se usan a través de su API, pagando por cada imagen.
La prueba en CPU se hizo con capturas sintéticas del mismo tamaño que las reales, sin datos de clientes, y el modelo leyó bien las tres. Son mediciones de una imagen a la vez y no una prueba de carga: con varias peticiones simultáneas los números cambian.
Alcance y errores pendientes
- IP inventada: en capturas sin IP visible, el modelo a veces copia como IP el número identificador de la prueba. El script descarta todo lo que no sea una IPv4 bien formada, aplicando el mismo criterio al modelo base y al ajustado; aun así, puede colarse una IP inventada con formato válido.
- Tarjetas de resultado muy pequeñas dentro de una página: alguna vez confunde la unidad u omite subida o ping.
- Diseños poco frecuentes, como apps que muestran la latencia arriba: a veces omite el ping.
- Al revisar a ojo los 14 fallos de la prueba automática, al menos 3 eran errores de la etiqueta y el modelo había acertado.
- No se entrenó con pruebas en curso ni pantallas de error, y las métricas describen este histórico concreto. Nuevas apps o formatos requieren validarse de nuevo.