Noesis
Blog

El arte de decir no: constrained decoding

23 de junio3 min de lectura

Gastamos miles de millones entrenando máquinas para generar casi cualquier cosa. Después, en producción, dedicamos una enorme cantidad de esfuerzo a asegurarnos de que generen solo aquello que el sistema puede usar.

Gran parte de la conversación sobre los LLMs gira alrededor de la generación: más creatividad, más capacidad, más salida a partir de la misma entrada. El constrained decoding trata el problema contrario. Pertenece a la fase de producción de la integración de LLMs, donde la pregunta no es "¿puede el modelo producir algo?", sino "¿puede producir algo válido?".

Qué es el constrained decoding#

El constrained decoding obliga a que la salida de un LLM siga una estructura predefinida mientras se está generando.

Durante la inferencia, el modelo puntúa los posibles siguientes tokens. Esas puntuaciones se llaman logits: la preferencia bruta del modelo por cada token de su vocabulario. Un decodificador restringido filtra esas opciones antes de aceptar el siguiente token, bloqueando tokens que harían inválida la salida parcial.

Por ejemplo, imagina un agente text-to-SQL generando esta consulta parcial:

SELECT COUNT(*) FROM clients WHERE salary >

En ese punto, continuaciones válidas podrían ser:

8000
9000
10000

Continuaciones inválidas podrían ser:

FROM
DROP
hello

El modelo sigue generando, pero el decodificador estrecha el camino.

Aplicaciones#

Tomemos text-to-SQL. La promesa es que un usuario pueda hacer una pregunta sobre una base de datos en lenguaje natural y que el modelo escriba la consulta SQL. Pero SQL no es solo texto; es texto que otro sistema ejecutará. Si el modelo escribe SQL inválido, la consulta falla. Si escribe SQL válido con un join o un filtro incorrecto, la respuesta puede parecer correcta mientras es falsa.

Los autores de TeCoD señalan que text-to-SQL puede verse sólido en promedios de benchmark y aun así fallar mal en esquemas empresariales concretos. Reportan precisiones tan bajas como 20-30% en algunas bases de datos cuando los resultados se separan por esquema.

Ahí es exactamente donde ayuda el constrained decoding. En vez de dejar que el modelo invente toda la consulta desde cero, un sistema puede restringirlo a una plantilla SQL conocida y pedirle que rellene los huecos:

SELECT COUNT(T1.client_id)
FROM client AS T1
INNER JOIN district AS T2
  ON T1.district_id = T2.district_id
WHERE T1.gender = [gender]
  AND T2.A3 = [district_name]
  AND T2.A11 > [salary]

El modelo sigue haciendo trabajo útil, pero la parte más arriesgada del espacio de búsqueda ha sido eliminada.

La misma idea aparece en las salidas estructuradas. Cuando pedimos JSON a un modelo, el problema no es que el modelo nunca haya visto JSON. El problema es que "parece JSON" no es lo mismo que JSON que un parser pueda consumir siempre. JSONSchemaBench evalúa sistemas de constrained decoding sobre JSON Schemas reales, midiendo no solo validez, sino también eficiencia, cobertura y calidad de salida.

El coste#

Decir no tiene un coste. Al elegir el siguiente token más válido, el decodificador puede bloquear un camino que habría sido más creativo o semánticamente útil. El constrained decoding puede hacer que modelos grandes se comporten como sistemas más pequeños y especializados al reducir lo que se les permite hacer.

Los agentes suelen usar un patrón relacionado fuera del decodificador. Un agente de programación puede generar código libremente y después ejecutar bun lint, tsc o tests para rechazar salidas inválidas. Eso no es constrained decoding en sentido estricto, porque la restricción ocurre después de la generación, pero el instinto de producción es el mismo: generar, comprobar, rechazar, reparar.

Hoy, las restricciones pueden sentirse como ponerle un bozal a un poeta. Enfoques más nuevos, como backtracking o razonamiento antes de la generación estructurada, sugieren una dirección mejor: dejar que el modelo explore, pero asegurarse de que finalmente llegue a una salida en la que el sistema pueda confiar.

El constrained decoding es el arte de decir no durante la inferencia. No hace que el modelo sea correcto, pero puede detener clases enteras de salidas inválidas antes de que lleguen a producción.

Retícula del pie de Noesis