Ir al contenido principal
Laravel, thinking fast.

Capitulo 16

Contenido largo

Julian Beaujardin

Todo lo anterior ha asumido que el trabajo cabe en una llamada.

Tarde o temprano algo no cabe: el texto de un sitio entero para traducir, un documento largo para resumir, un lote de registros para clasificar. Hay un tope de entrada, un tope de salida y un tiempo de espera, y tu trabajo supera al menos uno.

El arreglo ingenuo es pedir un tope mayor. El arreglo real es dejar de enviar una cosa grande.

Fragmenta por estructura, no por caracteres

La implementación obvia parte por número de caracteres. Es también la que produce salida corrupta, porque corta por la mitad lo que sea que esté partiendo: media frase, media clave, medio objeto JSON.

Parte por la estructura que ya tienes:

/**
 * api-ai caps a single prompt at services.ai.prompt.max_length chars with a
 * bounded output. A whole site's messages file is routinely larger than that,
 * so we translate in chunks — grouping top-level keys so each call stays
 * comfortably under the cap — and reassemble.
 */

Las claves de primer nivel son la costura. Cada fragmento es un subdocumento completo y válido: claves enteras con valores enteros, nada seccionado. El modelo ve algo coherente, y reensamblar es una fusión y no una reparación.

Encuentra la costura natural de tus datos. Secciones de un documento, registros de un lote, claves de una configuración. Si estás partiendo en un desplazamiento de caracteres, estás partiendo en el sitio equivocado.

Deja sitio para las instrucciones

/**
 * Max chars of content per call. Kept well under the 4000-char prompt cap
 * (leaving room for the ~700-char instruction preamble) and its output-token
 * ceiling.
 */
private const CHUNK_CHAR_LIMIT = 2500;

El tope se aplica al prompt entero, no a tu contenido. Tus instrucciones viajan en cada fragmento, y no son pequeñas.

2500 frente a un tope de 4000, con un preámbulo de unos 700 caracteres. Eso deja unos 800 de margen —deliberadamente generoso, porque la salida también tiene techo y el texto traducido suele ser más largo que el original. Un fragmento dimensionado para que la entrada quepa justo producirá una salida que no cabe.

Presupuesta instrucciones más entrada más expansión, y deja holgura. El modo de fallo de un fragmento demasiado grande es una respuesta truncada, que el capítulo 4 estableció como el fallo que parece un éxito.

Falla del todo antes que reensamblar una mentira

foreach ($this->chunk($content) as $chunk) {
    $translated = $this->translateChunk($token, $chunk, $language);

    if ($translated === null) {
        return null;
    }

    foreach ($translated as $key => $value) {
        $result[$key] = $value;
    }
}

Si un fragmento falla, toda la operación devuelve null.

La alternativa tentadora —conserva lo que funcionó, salta lo que no— produce un sitio mitad en español y mitad en inglés, sin registro de qué mitad es cuál. Un éxito parcial que no se distingue de uno completo es peor que un fallo limpio, porque el fallo limpio se reintenta y el parcial se publica.

Haz que los resultados parciales sean imposibles u obvios. Aquí, imposibles sale más barato.