En la lección anterior fijamos el system prompt v1 de DocuBot y aprendimos a estructurar un prompt en partes bien delimitadas. Con eso cubrimos las tareas directas: preguntar, resumir, responder con contexto. Pero DocuBot tiene por delante tareas más finas — por ejemplo, clasificar cada pregunta de soporte de Nubelia para dirigirla al equipo adecuado — donde una buena instrucción no basta: el modelo necesita ver ejemplos, o necesita espacio para razonar antes de responder, o la tarea es sencillamente demasiado grande para un solo prompt. Esta lección presenta las tres técnicas fundamentales del prompting — few-shot, cadena de razonamiento y descomposición en pasos — y termina convirtiendo nuestros prompts en plantillas Python reutilizables, el formato en el que viajarán al módulo 3 cuando empecemos a llamar a la API desde código. Seguimos sin tocar ninguna API: Python aparece solo para construir el texto de los prompts.

Contenido

  1. Zero-shot: la técnica por defecto
  2. Few-shot: enseñar con ejemplos
  3. Cadena de razonamiento: dar espacio para pensar
  4. Descomposición de tareas: prompt chaining conceptual
  5. Plantillas de prompts en Python
  6. Tabla comparativa: qué técnica usar en cada caso

Zero-shot: la técnica por defecto

Zero-shot significa pedir la tarea sin mostrar ningún ejemplo resuelto: solo instrucciones. Todo lo que hicimos en 02-01 era zero-shot. Gracias al fine-tuning con instrucciones que vimos en 01-02, los modelos actuales resuelven así una cantidad enorme de tareas: resumir, traducir, responder con contexto, extraer datos evidentes.

Tomemos la nueva tarea de DocuBot: clasificar preguntas de soporte de Nubelia en categorías para enrutarlas. Versión zero-shot:

Clasifica la siguiente pregunta de soporte de Nubelia en UNA de estas
categorías: facturacion, permisos, integraciones, api, incidencias, otros.
Responde únicamente con el nombre de la categoría.

<pregunta>
No consigo que mi compañera vea el tablero del proyecto Atlas aunque le
envié la invitación.
</pregunta>

Respuesta esperada: permisos. Y para muchos casos funcionará. El problema aparece en las fronteras entre categorías, que las instrucciones no pueden definir del todo con palabras:

  • "¿Por qué me habéis cobrado dos veces este mes?" → ¿facturacion o incidencias? (Es un posible fallo, pero de cobro.)
  • "El webhook de Slack dejó de llegar ayer" → ¿integraciones, api o incidencias?

Podrías intentar cubrir cada frontera con más reglas escritas ("si es un fallo relacionado con cobros, usa facturacion; si…"), pero las reglas se multiplican, se contradicen y nunca cubren todo. Cuando notes que estás escribiendo el párrafo número cinco de matices, es la señal de cambiar de técnica.

Few-shot: enseñar con ejemplos

Few-shot consiste en incluir en el prompt varios ejemplos resueltos (típicamente de 2 a 8) antes de la entrada real. El modelo, que como vimos en 01-02 es una máquina de continuar patrones, capta de los ejemplos matices que costaría verbalizar: dónde están las fronteras, qué formato exacto quieres, qué tono. Es la misma tarea de clasificación, ahora con ejemplos elegidos precisamente en las fronteras difíciles:

Clasifica la pregunta de soporte de Nubelia en UNA de estas categorías:
facturacion, permisos, integraciones, api, incidencias, otros.
Responde únicamente con el nombre de la categoría.

Ejemplos:

Pregunta: ¿Cómo descargo la factura de marzo?
Categoría: facturacion

Pregunta: ¿Por qué me habéis cobrado dos veces este mes?
Categoría: facturacion

Pregunta: La página de tableros tarda más de un minuto en cargar desde ayer.
Categoría: incidencias

Pregunta: El webhook que configuré hacia Slack dejó de enviar mensajes.
Categoría: integraciones

Pregunta: ¿Qué límite de peticiones por minuto tiene el endpoint de tareas?
Categoría: api

Pregunta: ¿Tenéis descuentos para ONGs?
Categoría: otros

Pregunta: {pregunta_del_usuario}
Categoría:

Fíjate en las decisiones de diseño, porque elegir los ejemplos es el 90 % del few-shot:

  • Los ejemplos definen las fronteras, no el centro. "¿Cómo descargo la factura?" sola no aporta casi nada (zero-shot ya la acierta); el ejemplo valioso es "me habéis cobrado dos veces" → facturacion, que resuelve por demostración la ambigüedad facturación/incidencia. Igual que el webhook de Slack → integraciones (y no api ni incidencias).
  • Cubre todas las categorías si puedes, o al menos las conflictivas. Un few-shot donde 5 de 6 ejemplos son facturacion sesga al modelo hacia esa etiqueta (los modelos son sensibles a la distribución e incluso al orden de los ejemplos; conviene mezclarlos).
  • El formato de los ejemplos ES el formato de la salida. Como cada ejemplo termina en Categoría: <etiqueta> y nada más, el modelo continuará el patrón con la etiqueta a secas. Few-shot es también la forma más eficaz de fijar formato — idea que reaparecerá con los JSON de la lección 02-03.
  • Los ejemplos deben ser correctos y ficticios pero realistas. Un ejemplo mal etiquetado enseña el error con la misma eficacia que uno bueno enseña el acierto.
  • Cada ejemplo cuesta tokens en cada llamada (recuerda los costes de 01-04). Seis ejemplos cortos son ~150 tokens: irrelevante. Cincuenta ejemplos largos en cada clasificación, no. Empieza con 3-5 y añade solo los que corrijan errores observados.

¿Cuándo usar few-shot frente a zero-shot? Regla práctica:

Situación Técnica
Tarea común y bien definida (resumir, traducir, responder con contexto) Zero-shot
Categorías o criterios con fronteras difusas Few-shot
Formato de salida muy específico o inusual Few-shot
Tono/estilo difícil de describir con adjetivos Few-shot (muestras del estilo)
El prompt zero-shot falla en casos concretos identificables Few-shot con esos casos como ejemplos

Cadena de razonamiento: dar espacio para pensar

Recuerda la mecánica de 01-02: el modelo genera token a token, y cada token se apoya en los anteriores. Si obligas a DocuBot a responder facturacion como primer y único token, toda la "deliberación" debe caber en una sola predicción. La técnica de cadena de razonamiento (chain-of-thought, CoT) consiste en pedirle que razone por escrito antes de dar la respuesta final: cada paso de razonamiento generado pasa a formar parte del contexto del siguiente, y la conclusión se apoya en ellos. Es, literalmente, darle espacio para pensar.

Ejemplo con un caso ambiguo de Nubelia:

Clasifica la pregunta de soporte en UNA categoría: facturacion, permisos,
integraciones, api, incidencias, otros.

Primero, en una sección "Análisis:", razona brevemente: qué pide el
usuario, qué categorías podrían aplicar y por qué eliges una.
Después, en una línea final "Categoría:", escribe solo la etiqueta.

<pregunta>
Desde que conectamos Nubelia con nuestro SSO corporativo, los usuarios
nuevos entran como Lectores y no puedo subirlos a Editores.
</pregunta>

Respuesta esperada:

Análisis: el usuario menciona la integración con SSO, pero su problema
real es que no puede cambiar el rol de los usuarios nuevos: es una
cuestión de gestión de roles. La integración funciona (los usuarios
entran); lo que falla o se desconoce es la asignación de permisos.
Dudo entre integraciones y permisos; el problema accionable es de
permisos.

Categoría: permisos

Puntos clave para usar bien CoT:

  • El orden importa: razonamiento primero, respuesta después. Si pides "la categoría y luego una justificación", el modelo decide primero (sin espacio para pensar) y luego racionaliza su elección — la justificación no habrá influido en la respuesta. CoT solo funciona si la conclusión va al final.
  • Estructura el razonamiento. "Razona paso a paso" funciona; funciona mejor decirle qué pasos: "qué pide el usuario, qué categorías podrían aplicar, por qué eliges una". Y delimita la respuesta final con un marcador fijo (Categoría:) para poder extraerla de forma fiable.
  • CoT tiene coste. Más tokens de salida = más latencia y más gasto (01-04). Resérvalo para tareas con razonamiento real: casos ambiguos, decisiones con varios factores, aritmética, análisis de errores. Para "¿cómo descargo la factura?" es tirar dinero.
  • Nota de contexto: los modelos más recientes incorporan modos de razonamiento nativos que hacen esto internamente. La técnica sigue siendo válida y necesaria como herramienta de prompting — y entenderla te explica por qué esos modos existen.
  • CoT y few-shot se combinan bien: ejemplos que incluyen el razonamiento escrito enseñan a la vez el criterio y el proceso.

Descomposición de tareas: prompt chaining conceptual

Hay peticiones que ningún prompt único resuelve bien. Piensa en el flujo completo que Nubelia quiere para DocuBot en la web de soporte:

  1. Clasificar la pregunta del usuario (¿de qué va?).
  2. Con la categoría, seleccionar la documentación relevante.
  3. Redactar la respuesta basada en esa documentación.
  4. Comprobar que la respuesta cumple las reglas (cita fuente, no inventa).

Meterlo todo en un mega-prompt ("clasifica, y según la categoría busca en estos 12 documentos, y redacta, y revisa que…") produce resultados mediocres: demasiadas instrucciones compitiendo (el problema de sobre-restricción de 02-01), contexto enorme con riesgo de "lost in the middle" (01-04), y un fallo en cualquier paso arruina el conjunto sin que sepas cuál falló.

La alternativa es el encadenamiento de prompts (prompt chaining): dividir la tarea en pasos, cada uno con su propio prompt enfocado, donde la salida de un paso es la entrada del siguiente:

flowchart LR
    A[Pregunta del usuario] --> B[Prompt 1:\nclasificar]
    B -->|categoria| C[Seleccionar docs\nde esa categoría]
    C -->|contexto| D[Prompt 2:\nredactar respuesta]
    D -->|borrador| E[Prompt 3:\nverificar reglas]
    E --> F[Respuesta final]

Ventajas para el desarrollador — y nota que son las mismas que las de descomponer funciones en código:

  • Cada prompt es simple y hace una cosa: el de clasificar no necesita saber redactar; el de verificar solo comprueba reglas.
  • Depurable: si la respuesta final es mala, inspeccionas las salidas intermedias y localizas el paso culpable.
  • Testeable por partes: puedes evaluar el clasificador por separado del redactor — esto será oro en la lección 02-04.
  • Optimizable por partes: el paso de clasificar puede usar un modelo más barato y rápido que el de redactar (criterios de 01-03).

El coste: más llamadas = más latencia total y más complejidad de orquestación. Por ahora nos quedamos en el nivel conceptual y en el diseño de los prompts de cada paso; el "pegamento" (código que ejecuta la cadena, maneja errores y pasa salidas a entradas) es materia del módulo 3, y su evolución — que el propio modelo decida qué paso ejecutar — son los agentes del módulo 5.

Plantillas de prompts en Python

Hasta ahora escribimos los prompts como texto acabado. Pero fíjate en el few-shot del clasificador: terminaba en {pregunta_del_usuario} — un hueco. Un prompt de producción es siempre una plantilla: parte fija (instrucciones, ejemplos) + huecos para lo variable (datos de cada petición). Formalizar esto en Python es el puente hacia el módulo 3. Sin llamadas HTTP ni SDKs: funciones que devuelven texto.

# prompts.py — plantillas de prompts de DocuBot (v1)

SYSTEM_DOCUBOT = """Eres DocuBot, el asistente interno de documentación \
y soporte de Nubelia, una plataforma SaaS de gestión de proyectos.
...
(el system prompt v1 completo de la lección 02-01)
"""

def prompt_respuesta(documentacion: str, pregunta: str) -> str:
    """Construye el mensaje de usuario para responder una pregunta
    a partir de documentación seleccionada."""
    return f"""<documentacion>
{documentacion}
</documentacion>

<pregunta>
{pregunta}
</pregunta>

Recuerda: si la respuesta no está en <documentacion>, di exactamente
"No encuentro esa información en la documentación disponible."."""


CATEGORIAS = ["facturacion", "permisos", "integraciones",
              "api", "incidencias", "otros"]

EJEMPLOS_CLASIFICACION = [
    ("¿Cómo descargo la factura de marzo?", "facturacion"),
    ("¿Por qué me habéis cobrado dos veces este mes?", "facturacion"),
    ("La página de tableros tarda más de un minuto en cargar.", "incidencias"),
    ("El webhook hacia Slack dejó de enviar mensajes.", "integraciones"),
    ("¿Qué límite de peticiones tiene el endpoint de tareas?", "api"),
    ("¿Tenéis descuentos para ONGs?", "otros"),
]

def prompt_clasificacion(pregunta: str) -> str:
    """Construye el prompt few-shot de clasificación de preguntas."""
    ejemplos = "\n\n".join(
        f"Pregunta: {p}\nCategoría: {c}" for p, c in EJEMPLOS_CLASIFICACION
    )
    return f"""Clasifica la pregunta de soporte de Nubelia en UNA de estas
categorías: {", ".join(CATEGORIAS)}.
Responde únicamente con el nombre de la categoría.

Ejemplos:

{ejemplos}

Pregunta: {pregunta}
Categoría:"""

Desglose para quien empieza con Python:

  • SYSTEM_DOCUBOT es una constante: el system prompt es estable (lección 02-01: en system lo estable), así que vive como constante de módulo, no se reconstruye cada vez.
  • Las f-strings (f"""...""") interpolan variables dentro del texto: {pregunta} se sustituye por el valor real. Es la forma más simple de plantilla en Python.
  • Los ejemplos viven en una lista de tuplas, no incrustados en el texto. Ventaja enorme: añadir o corregir un ejemplo es tocar un dato, no editar un bloque de texto frágil; y en 02-04 podremos probar variantes con distintos conjuntos de ejemplos sin duplicar la plantilla.
  • Separación instrucciones-datos, ahora en código: la plantilla (instrucciones, del desarrollador) y los argumentos (pregunta, documentacion, del usuario) entran por caminos distintos y los datos quedan siempre dentro de delimitadores. Nunca construyas prompts concatenando texto de usuario fuera de sus etiquetas.
  • Funciones puras: reciben datos, devuelven un str. Fáciles de testear (assert "¿Cómo archivo" in prompt_respuesta(doc, "¿Cómo archivo...?")), de versionar en git como cualquier código, y listas para enchufar a la API en 03-01.

Un uso ilustrativo:

print(prompt_clasificacion("No puedo invitar a un usuario externo"))
# → imprime el prompt completo con los 6 ejemplos y la pregunta al final,
#   listo para enviarse al modelo (módulo 3).

Tabla comparativa: qué técnica usar en cada caso

Técnica Qué es Cuándo usarla Coste extra Ejemplo en DocuBot
Zero-shot Solo instrucciones Tareas comunes y bien definidas Ninguno Responder preguntas con documentación en el contexto
Few-shot Instrucciones + 2-8 ejemplos resueltos Fronteras difusas, formato exacto, estilo difícil de describir Tokens de entrada por llamada Clasificar preguntas de soporte en 6 categorías
Cadena de razonamiento Razonar por escrito antes de responder Ambigüedad real, varios factores, análisis, aritmética Tokens de salida y latencia Decidir la categoría de un caso frontera SSO/permisos
Descomposición (chaining) Varios prompts encadenados, salida → entrada La tarea tiene fases distintas o un prompt único falla/es indepurable Varias llamadas, orquestación Clasificar → seleccionar docs → redactar → verificar

Y se combinan: la cadena de DocuBot usará few-shot en el paso de clasificar y zero-shot en el de redactar; el paso de verificar puede usar CoT. Elegir técnica es una decisión por paso, no por sistema.

Errores Comunes y Consejos

  • Ejemplos few-shot "de libro" que no enseñan nada. Si todos tus ejemplos son casos obvios que zero-shot ya acierta, pagas tokens sin ganar precisión. Los ejemplos valiosos son los que a ti mismo te costaría clasificar a la primera.
  • Ejemplos con formato inconsistente entre sí. Si un ejemplo termina en Categoría: permisos y otro en Respuesta: la categoría es permisos., el modelo no sabe qué patrón continuar. Formato idéntico en todos.
  • Pedir la justificación después de la respuesta creyendo que es CoT. Conclusión primero = racionalización, no razonamiento. La respuesta final siempre al final.
  • Aplicar CoT a todo por defecto. En tareas triviales solo añade coste y latencia, y a veces hasta empeora: el modelo se inventa complejidad donde no la hay.
  • El mega-prompt que lo hace todo. Si tu prompt tiene tres tareas distintas ("clasifica y además redacta y además comprueba"), casi siempre saldrás ganando al partirlo en una cadena.
  • Construir prompts concatenando strings sin delimitadores ("Resume: " + texto_usuario). Reintroduce el problema instrucción/dato que resolvimos en 02-01. Los datos, siempre dentro de sus etiquetas y a través de los parámetros de la plantilla.
  • Consejo: guarda tus plantillas en un módulo propio (prompts.py) desde el primer día. Los prompts son código: se revisan, se versionan y — como veremos en 02-04 — se testean.

Ejercicios

Ejercicio 1. El clasificador few-shot de DocuBot confunde sistemáticamente estas dos preguntas: "La API devuelve 500 desde esta mañana en /v1/tareas" (debería ser incidencias: algo está roto) y "¿Qué códigos de error puede devolver /v1/tareas?" (debería ser api: duda de uso). Escribe los dos ejemplos few-shot que añadirías al prompt para corregirlo y justifica por qué esos.

Ejercicio 2. Escribe un prompt con cadena de razonamiento para este caso de soporte de Nubelia: "Quiero que los clientes externos vean el avance del proyecto pero sin que puedan ver los costes." El prompt debe estructurar el razonamiento (qué necesita el usuario, qué opciones da la documentación, cuál encaja) y terminar con una recomendación delimitada por el marcador Recomendación:. Incluye un bloque <documentacion> inventado con dos opciones plausibles del producto (por ejemplo, "invitados con rol Lector" y "página de estado pública del proyecto").

Ejercicio 3. Escribe en Python una función prompt_resumen(titulo: str, texto: str, max_puntos: int = 5) -> str que genere un prompt para resumir un documento de la wiki de Nubelia en como máximo max_puntos puntos, orientado a agentes de soporte, con el texto delimitado en <documento> y la instrucción crítica repetida al final (recuerda "lost in the middle").

Soluciones

Solución 1. Ejemplos a añadir:

Pregunta: La API devuelve error 500 desde esta mañana en /v1/tareas.
Categoría: incidencias

Pregunta: ¿Qué códigos de error puede devolver el endpoint /v1/tareas?
Categoría: api

Justificación: son un par mínimo contrastivo — casi idénticos en superficie (ambos mencionan la API y errores) pero con etiquetas distintas. Colocados juntos enseñan exactamente la frontera que el modelo confunde: algo funcionaba y se ha rotoincidencias; duda sobre el comportamiento documentadoapi. Es la estrategia general: convertir cada error observado en el ejemplo que lo corrige.

Solución 2. Una solución posible:

Eres DocuBot. Un empleado de Nubelia plantea una necesidad de un cliente.
Analiza la situación usando SOLO la documentación proporcionada.

Estructura tu respuesta así:
Análisis: (1) qué necesita exactamente el usuario, (2) qué opciones de la
documentación podrían servir, (3) qué ofrece y qué no cubre cada una.
Recomendación: la opción elegida y su limitación principal, en 2 frases.

<documentacion>
## Invitados externos
Puedes invitar a usuarios externos con rol Lector: ven tableros, tareas
y avance, incluidos los campos de presupuesto si el proyecto los tiene
visibles.

## Página de estado del proyecto
Cada proyecto puede publicar una página de estado de solo lectura con
hitos y porcentaje de avance. No muestra tareas, comentarios ni campos
de presupuesto.
</documentacion>

<pregunta>
Quiero que los clientes externos vean el avance del proyecto pero sin
que puedan ver los costes.
</pregunta>

Respuesta esperada (abreviada): el análisis debería detectar que el rol Lector expone los campos de presupuesto (no cumple el requisito de ocultar costes) y que la página de estado muestra avance sin presupuesto, y concluir Recomendación: usar la página de estado del proyecto; limitación: los clientes no verán el detalle de tareas. El valor del CoT aquí es que obliga a contrastar cada opción con el requisito "sin costes" antes de elegir.

Solución 3.

def prompt_resumen(titulo: str, texto: str, max_puntos: int = 5) -> str:
    """Prompt para resumir un documento de la wiki de Nubelia."""
    return f"""Resume el documento de la wiki de Nubelia titulado
"{titulo}" en un máximo de {max_puntos} puntos, orientado a un agente
de soporte que necesita responder tickets. Prioriza pasos accionables
y limitaciones del producto; omite historia y agradecimientos.

<documento>
{texto}
</documento>

Recuerda: máximo {max_puntos} puntos y solo información presente en
<documento>."""

Claves: max_puntos con valor por defecto se interpola dos veces (instrucción inicial y recordatorio final), el texto va delimitado, y la función es pura — recibe datos y devuelve el prompt como str.

Conclusión

Tu caja de herramientas de prompting ya tiene fondo: zero-shot como opción por defecto, few-shot para enseñar fronteras y formatos mediante ejemplos bien elegidos (los del clasificador de soporte de Nubelia quedan fijados en EJEMPLOS_CLASIFICACION), cadena de razonamiento para darle al modelo espacio de deliberación antes de la respuesta, y descomposición en pasos cuando la tarea desborda un solo prompt — el diseño en cadena de DocuBot (clasificar → seleccionar → redactar → verificar) que iremos materializando en los próximos módulos. Y todo ello vive ya como plantillas Python en prompts.py: funciones puras que devuelven texto, listas para conectarse a una API real. Pero hay un cabo suelto: el clasificador devuelve una etiqueta en texto libre, y la web de soporte de Nubelia necesitará bastante más — categoría, respuesta, fuentes y nivel de confianza — en un formato que el código pueda parsear sin sorpresas. Ese es el tema de la próxima lección: salidas estructuradas, o cómo conseguir que un modelo probabilístico devuelva JSON en el que puedas confiar.

© Copyright 2026. Todos los derechos reservados