← Todos los proyectos

2026

Mea culpa

Ajedrez con IA que repasa tu partida y te dice qué puedes mejorar

Jugar

Cómo funciona

Juegas una partida de ajedrez en el navegador contra el rival que elijas. Cuando termina, un motor de ajedrez repasa la partida, encuentra dónde se te escapó y una IA te lo cuenta en castellano, con una frase por error y un consejo para la próxima.

Lo hice porque yo mismo pierdo partidas que tenía ganadas. Te lo cuento en cinco pasos.

  1. Juegas en el navegador

    Abres la página, eliges contra quién quieres jugar y mueves las piezas como en cualquier tablero. Para jugar hay que entrar con tu cuenta de Google: así cada persona tiene su historial y sus límites del día, y nadie gasta la IA de los demás.

    Si solo quieres mirar el ranking o mis partidas, no hace falta entrar.

    Tu primera jugada: el peón de rey avanza dos casillas.
  2. Tu jugada viaja a Azure

    Cada jugada sale de tu navegador hacia un pequeño servidor que tengo en Azure, la nube de Microsoft. Ese servidor hace de árbitro: tiene el tablero de verdad y comprueba que la jugada es legal antes de aceptarla.

    No se fía de lo que dice el navegador. Así nadie puede colarle una jugada imposible o un resultado inventado al ranking.

    La jugada va a Azure y vuelve con la respuesta del rival.
  3. Responde tu rival

    Puedes jugar contra tres tipos de rival, de menos a más:

    • Algoritmos sencillos que escribí yo: uno que mueve al azar, uno que siempre come lo que puede y uno que calcula unas jugadas por delante.
    • Stockfish, uno de los motores de ajedrez más fuertes que existen, con un nivel de 0 a 20 para que se le pueda ganar.
    • Un modelo de IA de los que hay en Microsoft Foundry, como los de OpenAI, Meta, Mistral o DeepSeek.

    La IA no ve el tablero: solo lee la posición escrita y propone una jugada. A veces propone una imposible. Entonces el árbitro le dice por qué no vale y lo vuelve a intentar, hasta tres veces. Si aun así falla, el servidor juega por ella una jugada de respaldo y lo deja anotado.

    1. IAJuego Qxf7
    2. ÁrbitroNo vale: Qxf7 es ilegal en esta posición. Propón otra.
    3. IAEntonces Nf3
    4. ÁrbitroVale, se juega.
    Elige un tipo de rival. La jugada corregida es un ejemplo, en notación inglesa como en el juego: Q es la dama y N el caballo.
  4. Stockfish busca tus errores

    Al terminar, Stockfish repasa la partida posición por posición y calcula quién iba ganando y por cuánto, medido en peones. Donde tu ventaja se desploma de una jugada a la siguiente, ahí hay un error.

    Si pierdes más de tres peones de ventaja de golpe, es un error grave. Además, unas reglas fijas apuntan qué pasó: una pieza que se quedó sin defensa, un mate que no viste, el rey sin enrocar... Todo eso son hechos medidos, no opiniones.

    Partida de ejemplo. Arriba vas ganando; abajo, perdiendo.
  5. La IA te lo cuenta en castellano

    Un modelo de IA recibe esos hechos, junto con la partida y su resultado, y los convierte en frases que se entienden: qué jugaste, cuánto te costó y qué era mejor. Al final, un consejo para la próxima partida.

    La IA explica bien, pero a veces se inventa cosas. Por eso su respuesta se compara con los hechos del motor: si habla de un error que el motor no encontró, se descarta. Y solo te dice que un fallo se repite si de verdad aparece en tus partidas anteriores.

    Diagnóstico de ejemplo. Las jugadas van en notación inglesa, como en el juego: Q es la dama y B el alfil.

En Azure

Las piezas, y para qué sirve cada una

Todo vive en Azure salvo el inicio de sesión, que es de Google. La web y el almacén de imágenes del servidor tienen una cuota fija al mes; la API, los modelos y la base de datos se pagan por lo que se usan.

Tú

Tu navegador habla con danielalonso.dev, y con Google solo para entrar

Tu navegador

Pinta el tablero y manda cada jugada. No decide nada: solo enseña.

Inicio de sesión con Google

Google Identity Services

Entras con tu cuenta y la API comprueba que de verdad eres tú. No guardo ninguna contraseña.

danielalonso.dev

La web enseña las páginas y la API hace el resto

La web

Azure Static Web Apps

Páginas ya hechas, que se sirven al momento. Se publican solas cada vez que subo un cambio.

La API, el árbitro

Azure Container Apps

Lleva la partida, comprueba cada jugada y tiene Stockfish dentro. Se apaga sola tras unos minutos sin visitas.

  • Azure Container Registry guarda la imagen de la API, con Stockfish dentro.
  • Application Insights apunta los errores y lo que tarda cada petición.

Las dos van en el mismo dominio: la web le pasa a la API todo lo que empieza por /api. Para poder enlazarlas pagué el plan Standard de Static Web Apps.

Lo que usa la API

Solo la API habla con estas piezas, nunca tu navegador

Los modelos de IA

Microsoft Foundry, con los GPT por Azure OpenAI Logo de Azure OpenAI

27 modelos que saben jugar, de 8 fabricantes. Juegan contra ti y escriben el diagnóstico. Se pagan por uso.

La base de datos

Azure SQL Database, oferta gratuita

Usuarios, rankings, estadísticas y una copia de cada partida. Si se acaba lo gratis del mes, se pausa en vez de cobrar.

El almacén de ficheros

Azure Blob Storage

Cada partida y los contadores del día. Y una copia del ranking ya calculada, para que quien solo mira no despierte la base de datos.

Sin claves donde importa. Para hablar con los modelos, la base de datos y el almacén no hay ninguna clave: la API se identifica con una identidad administrada de Azure, así que no hay nada de eso que se pueda filtrar.

Con topes. Cada persona tiene un límite de partidas y de gasto en IA al día, la IA se corta al llegar a 0,50 $ diarios entre las dos demos y Azure me avisa por correo al acercarse a los presupuestos del mes: 10 y 15 € en el proyecto y 40 € en toda la suscripción.

Datos

En cifras

La demo

27
modelos de IA que saben jugar, de 8 fabricantes distintos
4
rivales clásicos, desde uno que mueve al azar hasta Stockfish con nivel de 0 a 20
3
oportunidades para que la IA corrija una jugada ilegal antes de que el servidor juegue por ella
0,50 $
de tope de gasto en IA al día entre las dos demos, y 0,20 $ por persona

Mis 71 partidas de blitz de octubre

30
victorias en 71 partidas de blitz a 3 minutos
78,5 %
de precisión media en las partidas que gané, según Stockfish
4,9
errores graves cada 100 jugadas en la apertura, mi fase más sólida. El margen de mejora estaba en el medio juego (12,8), y de ahí salió la idea de Mea culpa

Lecciones

Lo que aprendí haciéndolo

Casi nada salió a la primera. Esto es lo que más me enseñó, por si te sirve si montas algo parecido en Azure.

  1. La cuota manda más que el catálogo

    Con una suscripción de estudiante, los modelos más punteros, como GPT-6 o Claude, salen en el catálogo pero tienen cuota 0, y no se puede pedir más.

    Además, la cuota de un mismo modelo cambia según la zona y la forma en que lo pones en marcha: uno solo tenía cuota dentro de la Unión Europea, otros solo en una región concreta. Mirando solo la opción global parecía que no había nada, y tuve que revisarlo región por región. Algunos, además, ya están retirados y no se pueden usar.

    Las regiones también vienen limitadas: la web acabó en Estados Unidos, la API en Francia y uno de los modelos en Suecia.

  2. No todos los modelos saben jugar

    Antes de abrir un modelo al público le hice jugar una partida corta. Varios se quedaron fuera: Phi-4 proponía jugadas ilegales y sus versiones que razonan tardaban más de dos minutos por jugada (Phi-4-mini-reasoning propuso 18 jugadas ilegales en 6 jugadas, a unos 4 minutos cada una). Ministral 3B necesitó la jugada de respaldo en 4 de 6, y Grok 4.6 y Kimi K3.1 Pro fallaban en una de cada tres o cuatro llamadas.

    Antes había probado modelos pequeños en mi ordenador, con una tarjeta gráfica GTX 1060. LFM3 1.7B, Qwen 3.5 4B y Gemma 4 E4B perdieron las 60 partidas contra el rival que mueve al azar, todas por jugadas ilegales.

  3. La IA copia los ejemplos que le das

    En las instrucciones del diagnóstico puse de ejemplo «Otra vez has perdido por no enrocar a tiempo». El modelo lo copiaba aunque hubieras ganado o hecho tablas.

    La solución: decirle el resultado de forma explícita y, después, comprobar en el código que lo que escribe cuadra con él y que el «otra vez» tiene respaldo en tus partidas. Si no cuadra, se le pide de nuevo; si sigue mal, se usa un texto sin IA. Con un modelo de lenguaje no basta con pedirlo: hay que comprobarlo.

  4. Una base de datos gratis que no hay que despertar

    Al principio todo iba en ficheros. Para los rankings y las estadísticas añadí una base de datos de Azure en su oferta gratuita: se duerme cuando nadie la usa y, si se acaba lo gratis del mes, se queda en pausa en vez de cobrar.

    La pega es que despertarla tarda y gasta ese límite. Por eso la demo depende de ella lo menos posible: la partida se sigue guardando en ficheros, el ranking público se lee de una copia que se rehace al terminar cada partida y lo que va a la base de datos se apunta sin esperar. Si está dormida, la demo no se queda colgada: tira de lo último que sabía y sigue.

  5. Un presupuesto avisa, pero no corta

    Los presupuestos de Azure mandan un correo al acercarse a la cifra, pero no apagan nada. El corte lo pone la propia API: suma lo que cuesta de verdad cada llamada a la IA, según lo que ha escrito y leído, y deja de llamarla al llegar al tope del día. Así un modelo caro no se come el dinero de todos.

  6. Los detalles pequeños rompen cosas grandes

    Una línea de limpieza al preparar el servidor borraba piezas que necesitaba la conexión con la base de datos, y la API no arrancaba. La quité, y ahora se comprueba que no falta nada antes de publicarlo.

    El botón de Google va dentro de un marco, y con el tema oscuro el navegador le pintaba un recuadro blanco alrededor; se arregló pidiéndole a ese marco el tema claro. Y la web respondía «todo bien» en páginas que no existían, por una regla que mandaba cualquier dirección a la portada. Ahora dice que no existen.

¿Echamos una partida?

Elige rival, juega y mira qué te dice al final.

Con qué está hecho

Tecnologías utilizadas

Nube y despliegue

  • Azure Static Web AppsSirve la web, plan Standard con la API enlazada
  • Azure Container AppsLa API, que escala a cero sin visitas
  • Azure Container RegistryConstruye y guarda la imagen de la API
  • Identidad administrada de Microsoft EntraLa API entra en Foundry, Storage y SQL sin claves
  • Application InsightsTrazas, errores y tiempos de la API
  • GitHub ActionsPublica la web en cada push a main
  • DockerImagen de la API con Stockfish y ODBC Driver 18
  • Presupuestos de Microsoft Cost ManagementAvisos por correo de 40, 15 y 10 € al mes

IA

  • Microsoft FoundryModelos de Meta, Mistral, xAI, DeepSeek, Moonshot, Microsoft y Cohere
  • Azure OpenAILos modelos GPT, con salida estructurada

Ajedrez

  • StockfishJuega por nivel y encuentra los errores a profundidad 14
  • python-chessValida cada jugada y lleva la partida

Backend

  • Python
  • FastAPILa API de las dos demos
  • PydanticValida la salida estructurada de los modelos

Datos

  • Azure SQL Database (serverless, oferta gratuita)Usuarios, uso, rankings y una copia de cada partida
  • Azure Blob StoragePartidas y cuotas del día, con escrituras por ETag

Web

  • Nuxt 4La web, generada como páginas estáticas
  • Google Identity ServicesLogin con Google, con el ID token verificado en el servidor
Para los técnicosEl problema, cómo lo hice, el resultado y las herramientas

El problema

Analicé con Stockfish mis partidas de blitz de octubre y vi que mi margen de mejora estaba en el medio juego. Así que hice una demo: juegas contra Stockfish o contra un modelo de Microsoft Foundry y, al terminar, el motor encuentra tus errores y la IA te los explica en castellano.

Cómo lo hice

  1. API en FastAPI sobre Azure Container Apps, enlazada a esta web en /api/meaculpa: login con Google verificado en el servidor, partidas en Blob Storage con una copia en Azure SQL Database (oferta gratuita) para rankings y estadísticas, y cuotas diarias por persona.

  2. Rivales de menos a más: aleatorio, codicioso, minimax con poda alfa-beta, Stockfish por nivel y 27 modelos de Foundry a elegir, a los que se corrige si proponen una jugada ilegal.

  3. Stockfish encuentra los errores; el modelo solo los explica, y se descarta cualquier error que se invente.

  4. Antes de abrir un modelo al público, una partida corta de prueba: los que hacían jugadas ilegales, tardaban minutos o fallaban a ratos se quedaron fuera.

Despliegue

  • Web: Nuxt 4 estático en Azure Static Web Apps (plan Standard, Central US) con la Container App enlazada como backend. /api/* llega a la API desde el mismo dominio, sin CORS entre dominios. GitHub Actions publica en cada push a main.
  • API: FastAPI en Azure Container Apps (Francia Central), 0,5 vCPU y 1 GiB, de 0 a 1 réplica: tras 5 minutos sin peticiones escala a cero. Cualquier visita a la web la despierta, porque las estadísticas sin cookies avisan a /api/stats/visita.
  • Imagen construida en Azure Container Registry con az acr build a partir de un git archive del commit, con Stockfish del paquete de Debian y ODBC Driver 18. Al construir se comprueba con ldd que al driver no le falta ninguna librería.
  • Identidad administrada para Foundry, Blob Storage y Azure SQL, con la autenticación por clave desactivada en las dos cuentas de Foundry y en Storage, y solo login de Entra en SQL: para hablar con ellos no hay ninguna clave. Los únicos secretos de la Container App son la cadena de Application Insights y la clave de Google Maps del otro juego. El login de Google verifica el ID token en el servidor, sin client secret.
  • Coste fijo: el plan Standard de la Static Web App y el Container Registry Basic. Lo demás (la API, los modelos y la base de datos) es de pago por uso.

Rival IA

  • Los GPT de OpenAI van por el endpoint de Azure OpenAI (API v1, con salida estructurada) y gpt-oss y los de Meta, Mistral, xAI, DeepSeek, Moonshot, Microsoft y Cohere por el endpoint de inferencia de modelos de Foundry, con la jugada en texto. Todo con pago por uso: ningún despliegue de modelo tiene coste fijo.
  • python-chess valida cada propuesta. Si es ilegal, se le devuelve el error al modelo hasta 3 veces; después juega el rival codicioso y queda registrado como jugada de respaldo.
  • Por jugada se guardan intentos, jugadas ilegales, tokens, latencia y coste, que alimentan el tope de gasto.

Diagnóstico

  • Stockfish a profundidad 14 evalúa cada posición (hasta 200 plies). Una caída de 0,7, 1,5 o 3 peones es imprecisión, error o error grave.
  • Reglas deterministas etiquetan cada error: pieza colgada, mate permitido, mate no visto, cambio desfavorable, dama prematura, enroque tardío o rey en el centro.
  • El LLM recibe esos hechos, el PGN, el resultado y el historial de patrones (marcados como datos, no instrucciones) y responde en salida estructurada (pydantic). Se valida contra los hechos: los errores inventados se descartan y los patrones «recurrentes» solo se aceptan si aparecen en al menos 2 partidas contando esta, es decir, si ya salieron en alguna anterior.

Datos y coste

  • Cada partida es un JSON en Blob Storage con escrituras condicionadas por ETag, igual que los contadores de cuota del día, así que valen para varias réplicas y sobreviven al escalado a cero.
  • Azure SQL Database en la oferta gratuita (serverless) guarda usuarios, uso, configuración, rankings y una copia de cada partida: si se agota el límite gratis del mes se pausa en vez de cobrar. Solo admite login de Microsoft Entra.
  • Las escrituras van a una cola en segundo plano y las lecturas tienen un cortacircuitos de 30 s, así que una base de datos en pausa no tumba la demo. Cada operación abre y cierra su conexión para que pueda pausarse.
  • Los rankings públicos se leen de una copia en Blob que se rehace tras cada partida (más 60 s de caché en memoria): quien solo mira no despierta la base de datos.
  • Cuotas por persona y día (30 partidas, 200 jugadas de la IA, 20 análisis) y un tope de gasto en IA calculado con el coste real de cada llamada: 0,50 USD al día entre las dos demos y 0,20 USD por persona, ajustables desde el panel de administración. Además, presupuestos con alerta por correo: 40 € al mes en la suscripción y 15 € y 10 € en el grupo de recursos, que avisan desde el 50 %.

Lecciones, en detalle

  • Cuota por tipo de despliegue: gpt-5.4-mini solo tenía cuota en Data Zone (UE), gpt-4.1 y gpt-4o solo en Standard regional y gpt-5-mini en Global Standard. o4-mini y gpt-4o-mini ya no se pueden desplegar por estar retirados. Con Azure for Students, GPT-6 y Claude tienen cuota 0 y no se puede pedir más.
  • Regiones limitadas por política en la suscripción: la Static Web App en centralus, el resto en francecentral y gpt-4.1 en swedencentral.
  • En el Dockerfile, apt-get autoremove borraba librerías del ODBC Driver 18 y el contenedor no arrancaba. Se quitó y la imagen comprueba con ldd que no falta ninguna.
  • El botón de Google Identity Services va en un iframe: con color-scheme oscuro en la página, el navegador le pintaba un fondo blanco. Se arregló con color-scheme claro en ese iframe.
  • El navigationFallback de la Static Web App devolvía 200 con la portada en rutas inexistentes. Se quitó y ahora dan 404.

Resultado

Una demo que se juega en el navegador y mis propias partidas analizadas jugada a jugada.

Diagramas

Componentes

Componentes: la web Nuxt estática llega por la Static Web App al backend enlazado; la API FastAPI en Container Apps tiene rutas de partidas, análisis, barra, pista y deshacer, ranking y administración, los módulos de análisis, cuotas y login, los motores (jugador LLM, codicioso, aleatorio, minimax y Stockfish) y los proveedores de modelos hacia Microsoft Foundry; guarda en Azure SQL y Blob Storage y verifica el login con Google.
La web estática, las rutas y módulos de la API y los servicios con los que habla cada uno. Ver a tamaño real

Despliegue

Despliegue: GitHub Actions publica la web en la Static Web App de Central US, que enlaza /api con la Container App de Francia Central; la imagen se construye con az acr build en Container Registry; la identidad administrada entra en Container Registry, Blob Storage, Azure SQL serverless gratuita y las cuentas de Foundry de Francia Central y Suecia Central.
Dónde corre cada pieza, cómo llega el código y a qué entra la identidad administrada. Ver a tamaño real

Una jugada contra la IA

Secuencia: el navegador envía la jugada con el ID token, la API verifica el token de Google, lee la partida de Blob, comprueba turno, legalidad y cuota, aplica la jugada con python-chess, comprueba el tope de gasto, pide la jugada al modelo de Foundry hasta 1 + 3 veces devolviéndole el error si es ilegal, juega una de respaldo si hace falta, suma el coste real, guarda la partida y manda una copia a Azure SQL por la cola.
Login, validación, cuotas y tope de gasto, hasta 1 + 3 intentos del modelo y jugada de respaldo. Ver a tamaño real

Diagnóstico

Secuencia del análisis: Stockfish a profundidad 14 evalúa cada posición, se calculan caída, gravedad y etiquetas de cada jugada, el modelo recibe solo los hechos y el resultado, ground() descarta lo inventado, se comprueba que el texto cuadra con el resultado, con un reintento y textos de respaldo si no, y se guarda el diagnóstico.
Stockfish evalúa, reglas fijas etiquetan, el modelo explica y el código lo comprueba contra los hechos y contra el resultado. Ver a tamaño real

Clases

Clases: RandomOpponent, GreedyOpponent, MinimaxOpponent, StockfishOpponent y LLMOpponent implementan Opponent; OpenAIChatProvider, FoundryInferenceProvider, AzureOpenAIProvider, ClaudeFoundryProvider y MockProvider implementan LLMProvider; AlphaBetaAnalyzer y StockfishAnalyzer implementan Analyzer; GameStore, RankingStore, UsageLimiter y DataStore usan ObjectStore (Blob o ficheros) y Database.
Rivales detrás de Opponent, proveedores de modelos detrás de LLMProvider, analizadores y almacenes. Ver a tamaño real

Estados

Estados: una partida en curso alterna entre tu turno y el del rival, termina en victoria, tablas o derrota y deshacer la reabre con ayuda; aparte, la partida pasa de sin ayuda a con ayuda al pedir una pista o deshacer, y entonces no cuenta para el ranking; la base de datos serverless pasa de activa a pausa automática tras 60 minutos sin conexiones, o a pausa hasta el mes siguiente si se agota el límite gratuito, y se despierta con la primera conexión.
Estados de una partida, la marca de ayuda que la saca del ranking y la base de datos gratuita, que se pausa y se despierta. Ver a tamaño real