Shapefiles, OCR y 3G: construyendo una plataforma geopolítica para México con bajo ancho de banda

Descargo de responsabilidad: este proyecto fue desarrollado bajo NDA. No puedo compartir detalles de implementación específicos, información del cliente o arquitectura propietaria. Lo que puedo compartir son los desafíos generales de ingeniería y las lecciones que aprendí de ellos.

El resumen

Me contrataron para crear una aplicación web centrada en cartografía electoral y geodatos para una campaña política en México. La funcionalidad principal: visualizar distritos geográficos, superponer datos demográficos y electorales y procesar grandes volúmenes de documentos escaneados mediante OCR.

Bastante sencillo sobre el papel. En la práctica, se convirtió en el desafío de ingeniería de rendimiento más exigente al que me he enfrentado.

El despertar del Shapefile

Este fue mi primer encuentro con Shapefiles, el formato geoespacial de décadas de antigüedad que impulsa la mayoría de los sistemas SIG en todo el mundo.

Para los no iniciados: un Shapefile no es realmente un archivo. Es una colección de archivos (.shp, .shx, .dbf, .prj y, a veces, más) que en conjunto describen formas geométricas (polígonos para distritos, puntos para ubicaciones, líneas para límites) junto con sus datos asociados.

El desafío no fue analizarlos. Para eso existen bibliotecas. El desafío era representar miles de polígonos complejos en un navegador en hardware y conexiones que apenas podían soportar una inserción de Google Maps.

Los distritos electorales en México son complejos. No son rectángulos limpios: siguen ríos, calles, límites de vecindarios. El mapa de distrito de un solo estado puede contener cientos de miles de puntos de coordenadas. Cargar y renderizar todo ese lado del cliente en un teléfono de gama media a través de una conexión celular inestable es una receta para una pantalla en blanco y una pestaña bloqueada.

Bajar el nivel de rendimiento

La pila inicial era de un nivel demasiado alto. Estábamos renderizando datos geoespaciales con bibliotecas de mapas web estándar, y era inaceptablemente lento para los usuarios objetivo: trabajadores de campaña en el campo, a menudo en áreas rurales con mala conectividad.

Lo que siguió fue un proceso que describiría como descender la pila:

  1. Simplifique la geometría. Aplicamos la simplificación topológica (reduciendo la densidad de coordenadas y preservando la fidelidad de la forma) para reducir el tamaño de los archivos en órdenes de magnitud. Un distrito que tenía 2 MB de coordenadas se convirtió en 200 KB, visualmente idéntico en los niveles de zoom que los usuarios realmente necesitaban.

  2. Mosaicos y caché de forma agresiva. En lugar de enviar archivos de forma completos al cliente, renderizamos previamente mosaicos de mapas con niveles de zoom fijos. Esto convirtió un problema de SIG dinámico en un problema de servicio de activos estáticos, y los activos estáticos se pueden almacenar en caché en el borde, cerca de los usuarios.

  3. Mover el cálculo al lado del servidor. Todo lo que pudiera calcularse previamente se calculó previamente. Intersecciones, superposiciones, cálculos demográficos, todo realizado en el servidor y servido como JSON liviano. El cliente se convirtió en una fina capa de renderizado, no en un motor SIG.4. Optimizar para la primera pintura significativa. La aplicación necesitaba mostrar algo útil en segundos, incluso en 3G. Priorizamos cargar primero el contexto geográfico inmediato del usuario y luego cargar progresivamente las áreas circundantes. Si estabas en el Distrito 5, lo veías instantáneamente. Los distritos 1-4 cargados en segundo plano.

La lección fue universal: cuando el hardware y la conectividad de los usuarios son el cuello de botella, cada kilobyte es una decisión de diseño.

El sistema OCR: MLOps accidentales

El segundo componente importante fue un sistema de OCR para procesar documentos escaneados: miles de ellos, de diferente calidad, muchos de ellos fotografiados en ángulos o con poca iluminación.

Implementamos el modelo OCR de código abierto de Microsoft (adyacente a Tesseract, si no recuerdo mal) para manejar la extracción de texto. Este fue, sin que me diera cuenta en ese momento, mi primer proyecto real MLOps.

El oleoducto se parecía a esto:

  1. Ingestión: Documentos cargados a través de la aplicación web (optimizada para cargas de lotes grandes a través de conexiones lentas).
  2. Preprocesamiento: Normalización de imagen (corrección de rotación, ajuste de contraste, reducción de ruido) para mejorar la precisión del OCR.
  3. Servicio de modelo: El modelo de OCR que se ejecuta como un servicio, acepta entradas de imágenes y devuelve texto estructurado.
  4. Postprocesamiento: Analizar el texto extraído en campos de datos estructurados (nombres, números, ubicaciones) con reglas de validación.

Los desafíos de ingeniería eran problemas clásicos de MLOps, aunque todavía no tenía el vocabulario para ello:

  • Gestión de recursos: El modelo era pesado. Ejecutarlo en una infraestructura compartida junto con la aplicación web provocó una contención de recursos. Tuvimos que aislar el servicio OCR con su propia asignación informática.
  • Compensaciones entre rendimiento y latencia: El procesamiento de un solo documento debía ser rápido (para obtener comentarios en tiempo real). El procesamiento de miles debía ser eficiente (para trabajos por lotes). Estos son diferentes objetivos de optimización.
  • Monitoreo de precisión: El OCR no es binario: no “funciona” o “no funciona”. Funciona parcialmente, con diferentes puntuaciones de confianza. Necesitábamos señalar las extracciones de baja confianza para su revisión humana en lugar de ingerir silenciosamente datos basura.

Mirando hacia atrás, este fue el proyecto que plantó la semilla de mi trabajo posterior en infraestructura de IA. Los problemas (servir un modelo, administrar la computación, monitorear la calidad) eran los mismos problemas que enfrentaría años después a una escala mucho mayor. Simplemente no sabía el nombre todavía.

La colaboración .NET

Una dimensión inesperada de este proyecto fue la colaboración estrecha con un desarrollador .NET y C#. Viniendo del ecosistema JavaScript/Python, esta fue mi primera exposición real al mundo del desarrollo de Microsoft.

Lo que me llamó la atención fue lo diferentes que eran las convenciones: ni mejores ni peores, simplemente diferentes. Todo fuertemente escrito. Detallado pero explícito. Patrones empresariales que parecían pesados ​​al principio, pero que hacían que el código base fuera notablemente navegable para los recién llegados.

Reforzó algo que experimentaría más tarde en hackatones: trabajar con ingenieros de diferentes ecosistemas te enseña cosas que permanecer en tu propio ecosistema nunca te enseñará. No solo nuevas herramientas, sino nuevas formas de pensar sobre la estructura.## Lo que tomé de esto

  1. La optimización del rendimiento es una forma de empatía. Cada milisegundo que guardas es un usuario de una zona rural que no se rinde y cierra la pestaña.
  2. Los datos geográficos son una lección de humildad. El mundo real es un caos. Los ríos no siguen cuadrículas de píxeles. Los distritos tienen excepciones. Si su sistema puede manejar datos geográficos correctamente, puede manejar casi cualquier cosa.
  3. MLOps comienza antes de que sepas que es MLOps. La primera vez que implementas un modelo como servicio y te preocupas por el rendimiento, estás haciendo MLOps, ya sea que esté o no en tu puesto de trabajo.
  4. Los acuerdos de confidencialidad protegen el trabajo, pero las lecciones son portátiles. No puedo mostrarte el código. Pero los patrones (simplificar, almacenar en caché, precalcular, enviar el trabajo al servidor) se aplican en todas partes.

Diego Jiménez Vergara — Ingeniero de Infraestructura de IA y DevOps. Construyendo sistemas de alto rendimiento para los usuarios dondequiera que estén, incluso en 3G.