Qué construimos en esta entrada

El resultado del primer paso no es un modelo espectacular, sino una hoja de diseño de una sola página. Una IA de go necesita que funcionen juntos un modelo que recomienda jugadas, un motor que juzga las reglas, un servidor que guarda las partidas y una pantalla donde el usuario coloca las piedras. Si entrenas el modelo sin fijar antes estos límites, es fácil confundir las jugadas ilegales y los errores de guardado con problemas de rendimiento del modelo.

  1. Se usa un tablero reglamentario de 19×19.
  2. El humano juega con negras y la IA con blancas.
  3. No hay límite de tiempo para las jugadas del humano.
  4. El motor de reglas vuelve a comprobar la respuesta del modelo.
  5. El tablero y la secuencia de jugadas se guardan en el servidor tras cada jugada.

Paso 1: Separar el modelo del motor de reglas

La responsabilidad del modelo termina en mirar el tablero actual y proponer una coordenada candidata para la siguiente jugada. Si ese punto está vacío, si es un suicidio o si es un ko que repite el tablero anterior lo decide el motor de reglas. Si el modelo responde con un punto que ya tiene una piedra, se rechaza el candidato y se le vuelve a pedir. Si el reintento también falla, no se sustituye por una jugada aleatoria, sino que se registra el error.

Esta separación es importante por la reproducibilidad. Cuando surge un problema en un tablero concreto, se puede comprobar por separado si el modelo eligió mal o si el código de reglas estaba equivocado. Las reglas se fijan con pruebas y el modelo queda como una pieza reemplazable.

Paso 2: Definir el estado de la partida como un solo objeto

El estado mínimo incluye el tablero de 19×19, a quién le toca jugar, el número de piedras capturadas, la coordenada prohibida por ko, la secuencia completa de jugadas y la hora del último guardado. No intentes reconstruir el estado a partir de la pantalla: el servidor debe conservar el original. Para continuar la misma partida aunque se vuelva a abrir el navegador, también hacen falta un código de partida y una clave de acceso.

Paso 3: Escribir las condiciones de finalización

La condición de finalización de la primera versión no es "una IA fuerte". Basta con que el humano pueda hacer jugadas legales, que se rechacen las respuestas ilegales de la IA, que la secuencia de jugadas sobreviva a una recarga y que dos pases seguidos terminen la partida. Solo después de superar este criterio conviene mejorar los datos de entrenamiento y la fuerza de juego, para poder rastrear la causa de cada problema de uno en uno.

En la siguiente entrada explico cómo dividir una partida en SGF en entradas de entrenamiento y coordenadas objetivo.

El código real de este paso

La partida web de MariaGO guarda en el servidor el "estado de la partida como un solo objeto" del paso 2 con el tipo GameRow que aparece abajo. En una misma fila van el tablero, el siguiente jugador, la coordenada de ko, las piedras capturadas, el número de pases consecutivos y la secuencia completa de jugadas, junto con una clave de acceso para continuar en otro dispositivo.

mariago-web/lib/gameTypes.tstypescript · 32 líneas
export type MoveRec = {
  ply: number;
  color: 1 | 2;
  pass?: boolean;
  r?: number;
  c?: number;
};

export type GameWinner = "black" | "white" | "draw";

export type GameRow = {
  code: string;
  guest_id: string;
  /** 비공개 키 — 다른 기기 이어두기용. 남에게 코드만 공유하면 안 됨 */
  access_key: string;
  board: number[];
  to_play: number;
  ko: { r: number; c: number } | null;
  last_move: { r: number; c: number } | null;
  move_no: number;
  cap_b: number;
  cap_w: number;
  pass_streak: number;
  epoch: number;
  started: boolean;
  status: "playing" | "ended";
  end_text: string | null;
  winner: GameWinner | null;
  moves: MoveRec[];
  created_at: string;
  updated_at: string;
};

Modelo utilizado: Qwen3-VL-8B-Instruct + adaptador LoRA (lora_mix_qwen_r5). El código fuente completo y la descripción del modelo están en la entrada "8. El código fuente completo y los modelos utilizados".