La respuesta que rompió la aplicación
Pedir JSON a un modelo de lenguaje es decirle, en la instrucción, la forma exacta de la respuesta que quieres. Importa porque un programa solo puede usar una respuesta que sabe leer.
La aplicación de una cafetería le pide a un modelo que invente un bocadillo y su precio. Un día la respuesta empieza con «Claro, aquí tienes» y el programa se detiene. El modelo respondió, pero no en una forma legible.
Al final de esta lección
Nota
Puedo pedir una respuesta con una forma que mi programa sepa leer.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Instrucción | el texto que envías a un modelo | |
| JSON | un formato de texto para datos, hecho de claves y valores | |
| Clave | el nombre de un campo en un objeto JSON | price |
| Bloque de código | tres acentos graves que rodean código en una respuesta | |
| Analizar | leer un texto para convertirlo en datos que un programa usa | |
| Límite de tokens | la longitud máxima de una respuesta |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Di la forma en la instrucción
Un modelo adivina lo que quieres a partir de tus palabras. Por eso, di la forma. Nombra las claves, indica el tipo de cada valor y di qué debe quedar fuera.
Termina con una regla sencilla: responde solo con el JSON. Cuanto más dejes al azar, más distintas serán las respuestas.
Ejemplo resuelto: tres instrucciones para un bocadillo
| La instrucción dice | Lo que puede volver |
|---|---|
| Dame un bocadillo y un precio | Frases sueltas, quizá una lista, sin claves fijas |
| Dame un bocadillo en JSON | Probablemente JSON, con claves que tú no elegiste |
| Responde con un objeto JSON con las claves name (texto) y price (un número). Responde solo con el JSON. | Más probable que tenga la forma que pediste |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Muestra una respuesta de ejemplo
Un ejemplo vale más que un párrafo de reglas. Pon en la instrucción una respuesta completa, con valores inventados, y di que la respuesta real debe tener las mismas claves.
Los modelos tienden a copiar la forma de un ejemplo. Usa valores que nadie confunda con reales, o un ejemplo copiado pasará por una respuesta verdadera.
Escribir la ayuda del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"estado \" + res.status);' ' return (await res.json()).choices[0].message.content;' > model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir la ayuda del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' const list = [].concat(sample);' ' const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' ' return list[Math.min(turn, list.length - 1)];' ' }' '}' 'module.exports = { ask };' >> model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el primer script, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' 'const messages = [' ' { role: \"system\", content: \"Respondes solo con JSON.\" },' ' { role: \"user\", content: \"Inventa un bocadillo para la cafetería de una facultad. Responde con un objeto JSON con las claves name (texto) y price (un número en euros). Responde solo con el JSON.\" },' '];' 'const fence = \"\x60\x60\x60\";' '// Muestra grabada, usada solo si ningún modelo responde. Es desordenada a propósito.' 'const sample = \"Claro, aquí tienes tu bocadillo:\n\" + fence + \"json\n\" + JSON.stringify({ name: \"Bocadillo de tortilla\", price: 3.5 }) + \"\n\" + fence + \"\nEspero que te sirva.\";' > ask1.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribir el primer script, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function pullJson(text) {' ' try { return JSON.parse(text); } catch (error) { }' ' const start = text.indexOf(\"{\");' ' const end = text.lastIndexOf(\"}\");' ' if (start === -1 || end < start) return null;' ' try { return JSON.parse(text.slice(start, end + 1)); } catch (error) { return null; }' '}' '' 'async function main() {' ' const reply = await ask(messages, sample, 100);' ' console.log(\"Respuesta en bruto:\");' ' console.log(reply);' ' let whole = true;' ' try { JSON.parse(reply); } catch (error) { whole = false; }' ' console.log(\"Toda la respuesta es JSON:\", whole ? \"sí\" : \"no\");' ' console.log(\"Extraído:\", JSON.stringify(pullJson(reply)));' '}' 'main();' >> ask1.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecutar y leer la respuesta
docker exec -w /home/node/project agent node ask1.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Una salida posible
| Línea | Lo que puede mostrar |
|---|---|
| Respuesta en bruto | Una frase, luego el JSON en un bloque de código, luego otra frase |
| Toda la respuesta es JSON | no |
| Extraído | {"name":"Bocadillo de tortilla","price":3.5} |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Por qué una buena instrucción puede fallar
Incluso una instrucción clara puede fallar. El modelo puede añadir un saludo, rodear el JSON con un bloque de código o cambiar el nombre de una clave. También puede parar pronto si el límite de tokens es muy bajo, y el JSON queda cortado a medias.
Por eso siempre se analiza y se comprueba. Pedir bien hace que una mala respuesta sea más rara. Nunca la hace imposible.
Un error frecuente
Advertencia
Mucha gente cree que una instrucción bastante clara permite saltarse la comprobación. Una instrucción solo baja la probabilidad de una mala respuesta. Mantén la comprobación aunque las últimas cien respuestas fueran buenas.