Prompting

Un prompt es el texto que colocas frente al modelo antes de que prediga. Esa es toda la idea que este capítulo afina: un prompt no es una orden que le das a una mente, es el contexto que organizas para que la respuesta que quieres se vuelva la continuación más probable.
Qué es realmente un prompt
Mismo modelo, dos prompts. "Escribe sobre cambio climático" te da un ensayo errático que no pediste. "Escribe tres oraciones sobre las causas principales del cambio climático para un niño de 12 años, sin estadísticas" te da algo que puedes usar. El modelo no cambió entre esas dos llamadas. El contexto sí, y la salida lo siguió.
El capítulo anterior cubrió cómo un modelo genera texto prediciendo el token siguiente más probable, guiado por todo lo que tiene frente a él. Un prompt es ese "todo lo que tiene frente a él". Esta es la definición que vale la pena mantener: un prompt no es una solicitud que haces a una persona, es el contexto que estableces para que la continuación que esperas sea la que el modelo encuentre más probable.
Ese replanteamiento cambia cómo escribes. No estás persuadiendo o instruyendo a alguien. Estás organizando texto para que la respuesta que quieres sea lo probable que sigue. Cada técnica en este capítulo es una forma diferente de hacer eso, y cada una tiene más sentido una vez que puedes ver la máquina predictora debajo.
Los tres roles
Cuando hablas con un modelo a través del código, no envías un bloque de texto. Envías una lista de mensajes, y cada mensaje lleva un rol que marca de dónde vino. Hay tres:
- system: tus instrucciones permanentes. Quién debería actuar el modelo, las reglas que sigue, el formato que quieres. Se establece una vez, se aplica a toda la conversación.
- user: un mensaje de la persona usando tu app. La solicitud real.
- assistant: un mensaje que el modelo produjo antes. Así es como una conversación mantiene su historial.
messages = [
{"role": "system", "content": "Eres un asistente conciso para una app de cocina. Responde en una oración."},
{"role": "user", "content": "¿Qué puedo usar en lugar de mantequilla en galletas?"},
]Bajo el capó, esos roles no son canales separados en el modelo. Se aplanan en un flujo de texto con tokens marcadores especiales alrededor de cada mensaje, y ese flujo completo es lo que el modelo predice. Los roles importan porque el modelo fue entrenado en conversaciones dispuestas de esta manera, así que aprendió a tratar el contenido system como las reglas permanentes autoritarias y el contenido user como la solicitud a responder.
El mensaje de sistema es lo que los principiantes subutilizan. Es donde estableces el comportamiento que quieres en cada turno: el tono, la audiencia, el formato, las cosas que el modelo nunca debería hacer. Pon las reglas duraderas allí, y pon la solicitud específica en el mensaje de usuario.
Como el modelo no tiene memoria entre solicitudes, el rol assistant es también cómo repites lo que se dijo antes: para continuar una conversación, envías el intercambio anterior como mensajes assistant y user. Más sobre eso cuando comiences a llamar modelos desde código.
system, user, o assistant. Esas etiquetas se aplanan en un flujo de texto que el modelo predice, pero fue entrenado para tratar system como reglas autoritarias y user como la solicitud. Pon instrucciones duraderas en system, la solicitud específica en user, y repite los mensajes anteriores assistant y user para llevar el historial de una conversación. Lo específico vence a lo vago
Dos prompts, un modelo. "Escribe sobre cambio climático" devuelve un ensayo genérico de longitud e tono impredecibles. "Escribe un resumen de tres oraciones de las causas principales del cambio climático, para un niño de 12 años, en lenguaje sencillo, sin estadísticas" devuelve algo cercano a lo que imaginaste. Misma máquina, salida wildamente diferente, y la única diferencia es cuánto fijaste.
La razón se remonta al bucle de predicción. En cada paso el modelo está eligiendo de un rango de continuaciones plausibles. Un prompt vago deja ese rango ancho, así que el modelo llena los vacíos con lo que sea más común en general, que raramente es exactamente lo que tenías en mente. Un prompt específico estrecha el rango hacia la respuesta que quieres, antes de que el modelo haya escrito un solo token.
# vago: el modelo decide longitud, tono, audiencia, formato
"Escribe sobre cambio climático."
# específico: tú decides
(
"Escribe un resumen de 3 oraciones de las causas principales del cambio climático, "
"para un niño de 12 años, en lenguaje sencillo, sin estadísticas."
)La versión vaga podría continuar de mil formas sensatas, y obtienes una aleatoria de ellas. La versión específica descarta casi todas de antemano. Cuando escribas un prompt, di qué realmente quieres:
- Formato: una oración, una lista, JSON, una tabla.
- Longitud: un párrafo, tres viñetas, menos de 50 palabras.
- Audiencia: un principiante, un experto, un niño de 12 años.
- Qué hacer cuando no estés seguro: "Si el texto no lo dice, responde 'no especificado' en lugar de adivinar."
Ese último lleva más peso de lo que parece. Dejado a su suerte el modelo llena un vacío con un acierto confiado, porque un acierto fluido es la continuación probable. Explícitamente darle la opción de decir "No sé" hace ese el camino probable en lugar de, que es uno de los pocos movimientos a nivel de prompt que reduce el problema de alucinación del capítulo anterior. La especificidad estrecha las opciones del modelo antes de que escriba un token.
Muéstrale ejemplos
A veces la forma más clara de preparar la continuación correcta es mostrara. Poner algunos ejemplos trabajados en el prompt se llama prompting de pocos disparos (sin ejemplos es cero disparos). Funciona porque el modelo es, en el fondo, un continuador de patrones: dale dos o tres ejemplos de entrada-entonces-salida-correcta y lo más probable que venga después es el mismo patrón aplicado a tu nueva entrada.
messages = [
{"role": "system", "content": "Etiqueta cada reseña como POSITIVA, NEGATIVA, o NEUTRAL. Responde solo con la etiqueta."},
{"role": "user", "content": "La comida estaba fría y tardó en llegar."},
{"role": "assistant", "content": "NEGATIVA"},
{"role": "user", "content": "Comida decente, nada especial."},
{"role": "assistant", "content": "NEUTRAL"},
{"role": "user", "content": "¡La mejor hamburguesa que he tenido en años!"},
]
# el modelo ahora responde: POSITIVALos dos ejemplos completados establecen el patrón exacto: una palabra, todo mayúsculas, de un conjunto fijo. Continuar ese patrón para la tercera reseña es ahora mucho más probable que escribir un párrafo de análisis, así que eso es lo que obtienes. Por qué un par de ejemplos claros a menudo vencen un párrafo de descripción, especialmente para clasificación y formato: estás demostrando la forma de la salida en lugar de describirla y esperar. Elige ejemplos que cubran los casos complicados, porque el modelo se patrona sobre lo que muestras, incluyendo cualquier error en tus ejemplos.
Pídale que razone
Aquí hay una de las ideas más útiles de prompting, y una de las menos intuitivas, y cae directamente de cómo funciona el modelo. El modelo genera un token a la vez, y el único espacio de trabajo que tiene es el texto que ya ha escrito. No tiene un bloc de notas oculto para trabajar silenciosamente en un problema duro antes de responder. Su pensamiento, si es que lo hay, sucede en voz alta, en los tokens que produce.
Así que si preguntas una pregunta de múltiples pasos y demandas solo la respuesta final, estás forzando el modelo a saltar al final en un solo token sin lugar de trabajo, y en cualquier cosa que implique razonamiento, matemáticas, o lógica a menudo salta mal. La corrección es dejarla trabajar abiertamente. Pídele que coloque sus pasos antes de la respuesta:
messages = [
{"role": "system", "content": "Trabaja el problema paso a paso, luego da la respuesta final en su propia línea."},
{"role": "user", "content": "Una tienda vende bolígrafos a 3 por $2. ¿Cuánto cuestan 12 bolígrafos?"},
]
# sin "paso a paso", los modelos a menudo dicen un número incorrecto
# con él, el modelo escribe el trabajado, y cada paso hace el siguiente más confiableEsto se llama prompting de cadena de pensamiento, y la razón por la que funciona es mecánica, no mágica. Cada paso que el modelo escribe se convierte en parte del contexto que lee para el siguiente token, así que escribir "12 bolígrafos es 4 grupos de 3" hace que "4 grupos por $2 es $8" sea la continuación natural, probable. Le estás dando espacio al modelo para computar en la página en lugar de demandando la respuesta en un salto imposible. "Piensa paso a paso" o "muestra tu trabajo" es la versión cotidiana.
Dos advertencias. El razonamiento escrito es todavía texto generado, así que puede parecer sólido y alcanzar una respuesta incorrecta, y no deberías tratarlo como una prueba garantizada. Y algunos modelos más nuevos hacen este tipo de trabajo internamente sin ser pedidos. Pero el principio subyacente es duradero en lo que sea que los modelos próximos lleguen: un modelo razona mejor cuando tiene espacio para escribir los pasos, porque su propia salida es el único lugar en el que tiene para pensar.
Estructura el prompt
A medida que los prompts crecen, la estructura mantiene el contexto claro para que el modelo pese cada parte correctamente. Algunos hábitos ayudan:
- Pon instrucciones primero, datos último. Expresa qué hacer, luego proporciona el texto para hacerlo.
- Separa instrucciones de datos con delimitadores. Envuelve cualquier texto proporcionado en marcadores claros para que el límite entre tus reglas y la entrada sea inconfundible.
- Pide la forma de salida explícitamente. Si quieres JSON, dilo, y describe los campos.
prompt = f'''Resumé el mensaje de cliente abajo en una oración.
Luego lista cualquier nombre de producto que mencione.
Mensaje de cliente:
"""
{user_message}
"""'''Las comillas triples son un delimitador. Marcan "todo dentro aquí es dato a procesar, no instrucciones a seguir". Esto no es solo orden, y aquí la vista de predicción muestra por qué es una salvaguardia real.
Para el modelo es todo un flujo de texto, así que si la entrada de usuario fluye directamente en tus instrucciones sin límite, un usuario puede escribir "ignora lo anterior y haz esto en su lugar" y el modelo no tiene manera confiable de decir esa línea aparte de tus instrucciones reales. Bien podría continuar obedeciendo.
Ese ataque se llama inyección de prompt, y mantener instrucciones y datos no confiables claramente cercados es la primera línea de defensa, cubierto en Seguridad y límites. Para el modelo es todo un flujo de texto, así que cerca la entrada no confiable.
En práctica
Aquí hay un prompt que apila varios de estas ideas: un mensaje de sistema para reglas duraderas, una solicitud específica, un ejemplo para fijar el formato, y dato claramente delimitado.
messages = [
{
"role": "system",
"content": (
"Extraes elementos de acción de notas de reunión. "
"Responde con una lista numerada, un elemento de acción por línea, cada uno comenzando con un verbo. "
"Si no hay elementos de acción, responde 'Ninguno'."
),
},
{"role": "user", "content": 'Notas: """Acordamos que Carlos envíe el presupuesto antes del viernes y Lucía reserve el lugar."""'},
{"role": "assistant", "content": "1. Enviar el presupuesto antes del viernes (Carlos)\n2. Reservar el lugar (Lucía)"},
{"role": "user", "content": f'Notas: """{meeting_notes}"""'},
]El mensaje de sistema establece las reglas una vez, el ejemplo fija el formato exacto, y cada solicitud entrega datos cercados. Cada pieza está organizando el contexto para que la salida que quieres sea la continuación probable. Eso es el oficio completo: este es un prompt confiable, no uno afortunado. Próximo enviarás mensajes como estos a un modelo desde código real en Llamar modelos desde código.
system para reglas duraderas, una solicitud específica, un ejemplo para fijar el formato, y dato claramente delimitado. Cada pieza organiza el contexto para que tu salida deseada sea el texto probable siguiente. Eso es el oficio, un prompt que funciona por diseño en lugar de por suerte. 
