/**
* Full English names for the supported target languages. Prompting with a
* name instead of a bare ISO code makes the model translate reliably.
*/
private const LANGUAGE_NAMES = [
'en' => 'English',
'es' => 'Spanish',
'de' => 'German',
'it' => 'Italian',
'pt' => 'Portuguese',
];
Tu API acepta es; el prompt debería decir Spanish. Un código de dos letras es ambiguo y está poco especificado de una forma en que un nombre no lo está, y la diferencia se nota en la calidad de la salida.
La regla general: tus identificadores internos no son material de prompt. Casos de enum, claves foráneas, códigos de estado: tradúcelos a palabras antes de que lleguen al modelo. Razona sobre lenguaje; dale algo de lenguaje.
Fíjate además en que este mapa es la misma lista blanca contra la que valida el endpoint del capítulo 5. El conjunto de idiomas permitidos y el de nombres conocidos son una sola lista. Dos listas se separarían, y la separación sería un idioma validado sin nombre —que prompt-earía con un código ISO y degradaría en silencio.
Cuando el navegador tiene que llamar directamente
El trabajo largo choca con un límite de infraestructura que no tiene nada que ver con el modelo: los intermediarios tienen sus propios tiempos de espera, y uno que no controlas puede ser más corto que lo que dura el trabajo.
Nos pasó con un CDN delante de la aplicación, cuyo tiempo de espera al primer byte era más corto que una traducción de sitio completo. Todas las opciones arquitectónicamente pulcras —hacer de proxy, encolar y consultar— o chocaban con el mismo límite o eran desproporcionadas para algo que un usuario dispara de vez en cuando y espera.
La respuesta fue dejar que el navegador llamara a un endpoint que empieza a responder de inmediato, esquivando al intermediario que agotaba el tiempo.
Lo cual no viola el capítulo 5, y la distinción merece repetirse: el navegador llama a tu endpoint, que autentica, mide y compone el prompt. La credencial nunca sale del servidor. Lo que se movió fue el transporte, no las decisiones.
Sabe cuáles de tus límites son tuyos. Un tiempo de espera que no fijaste y no puedes cambiar es una restricción sobre la arquitectura, y fingir lo contrario produce un diseño que falla en producción y funciona en todas partes.
Limpia lo que queda rancio después
El contenido largo aterriza en algún sitio —un fichero, una configuración, una caché— y la capa que lo lee puede no enterarse.
Nuestro peor caso: una traducción se escribió correctamente en disco, y el proceso que servía el sitio siguió leyendo una copia cacheada de la versión anterior. El editor mostraba contenido rancio, el usuario lo «arreglaba», y guardar machacaba la traducción buena con la vieja. Escritura correcta, fichero correcto, cosa equivocada servida —y un fallo de pérdida de datos con aspecto de fallo de traducción.
Enumera qué cachea lo que acabas de escribir, e invalídalo todo en la misma operación. Cachés de bytecode, de configuración, de páginas estáticas, bordes de CDN. La escritura no ha terminado hasta que todos los lectores pueden verla.
Lo que sostiene este capítulo
- Fragmenta por estructura, nunca por desplazamiento de caracteres. Cada fragmento debe ser un subdocumento completo.
- Presupuesta instrucciones más entrada más expansión, y deja holgura: un fragmento demasiado grande se trunca, y el truncamiento parece éxito.
- Falla toda la operación si falla cualquier fragmento. Los resultados parciales con aspecto de completos se publican.
- Prompt-ea con nombres, no con identificadores internos. Mantén la lista blanca y el mapa de nombres como una sola lista.
- Algunos límites no son tuyos. El tiempo de espera de un intermediario es una restricción sobre el diseño.
- Mover el transporte no es mover las decisiones. El navegador puede llamar a tu endpoint; la credencial y el prompt se quedan en el servidor.
- Invalida todas las cachés de lo que acabas de escribir, en la misma operación.