Contenido del curso

Prompts dinámicos con LangChain y templates condicionales

Resumen

El prompting es el factor que separa a un agente mediocre de uno excepcional, incluso si usas los modelos más potentes del mundo o un orquestador como LangGraph. Si quieres que tus agentes respondan con precisión, necesitas dominar prompts dinámicos con LangChain y entender cómo inyectar variables en tiempo real. Aquí verás cómo lograrlo con PromptTemplate y Jinja2.

¿Por qué un buen prompt define el rendimiento de tu agente?

Un modelo poderoso con un prompt mediocre te dará resultados mediocres. Por eso el prompting no es opcional: es la habilidad que guía al modelo hacia el resultado que buscas.

Existen varias técnicas que puedes combinar según el modelo y el caso de uso:

  • Zero-shot: pides al modelo que resuelva sin ejemplos previos.
  • Few-shot: incluyes ejemplos dentro del prompt para guiar el estilo o formato.
  • Chain of thought: induces razonamiento paso a paso, ideal cuando usas etiquetas XML.

En ejemplos típicos de LangGraph verás prompts de una sola línea, pero eso responde a que el foco está en la orquestación, no en el prompt en sí. En producción, una línea no alcanza.

¿Qué es un PromptTemplate en LangChain? Es una clase que te permite definir un prompt con variables y rellenarlas después de forma diferida, sin tener que construir el string al momento de declararlo.

¿Cómo defino un PromptTemplate con variables dinámicas?

LangChain ofrece PromptTemplate para separar la definición del prompt del momento en que inyectas los datos. Esto es clave porque muchas variables, como el contexto o el estado de la conversación, solo existen más adelante en la ejecución.

La estructura básica funciona así:

  • Defines un string con marcadores entre llaves para cada variable.
  • Pasas ese string al PromptTemplate indicando el template.
  • Llamas al método format y envías los valores cuando ya los tengas.

python from langchain.prompts import PromptTemplate

template = """
Eres un experto en marketing. Fecha actual: {current_date} Texto del anuncio: {ad_text} """

prompt_template = PromptTemplate(template=template) prompt = prompt_template.format(current_date="2025-01-15", ad_text="...")

Fíjate en el detalle del backslash al inicio del string: escapa el primer salto de línea para que no entre como token extra. Cada espacio cuenta en prompt engineering.

¿Qué pasa si no envío todas las variables?

Si olvidas una variable al ejecutar format, LangChain lanza un error explícito diciéndote qué falta. Es un comportamiento útil porque evita que envíes prompts incompletos al modelo.

Pero hay casos donde quieres un valor por defecto, por ejemplo, la fecha actual. Para eso existen las partial_variables.

python from datetime import datetime

prompt_template = PromptTemplate( template=template, partial_variables={"current_date": lambda: datetime.now().isoformat()} )

Así, si no envías current_date, se calcula automáticamente. Si la envías, se usa la que pasaste.

¿Cómo hago condicionales dentro de un prompt con Jinja2?

Las variables dinámicas resuelven el 80% de los casos, pero a veces necesitas que un bloque entero del prompt aparezca solo bajo cierta condición. Aquí entra Jinja2, el mismo motor de plantillas que usa Django para server-side rendering, y que LangChain soporta de forma nativa.

Con Jinja2 puedes usar:

  • Iteraciones dentro del template para recorrer listas.
  • Expresiones de variables como en cualquier sistema de plantillas.
  • Bloques if para inyectar fragmentos solo cuando la variable existe.

Primero instala la dependencia con uv add jinja2 y reinicia tu notebook para que reconozca el paquete.

Luego declara el template indicando el formato:

python template = """
Eres un asistente muy útil que responde al mensaje de un usuario. {%- if name %} El nombre del cliente es {{ name }}. {%- endif %}

Mensaje: {{ user_message }} """

prompt_template = PromptTemplate( template=template, template_format="jinja2" )

Si no especificas template_format="jinja2", LangChain no entiende los bloques if y lanza un error.

¿Cuándo conviene usar Jinja2 en lugar de dos prompts distintos? Cuando la variación entre prompts es pequeña, una sola plantilla con condicionales es más mantenible. Si los prompts son radicalmente distintos, sepáralos en dos templates.

¿Por qué aparecen saltos de línea raros al usar if?

Cuando un bloque if no se cumple, Jinja2 puede dejar líneas en blanco que ensucian el prompt final. Recuerda que cada carácter influye en cómo el language model interpreta tu instrucción.

La solución es usar el guion en las etiquetas Jinja2: {%- if name %} y {%- endif %}. Ese guion le indica al motor que elimine los saltos de línea alrededor del bloque cuando no se renderiza.

python {%- if name -%} El nombre del cliente es {{ name }}. {%- endif %}

Con eso obtienes un prompt limpio, sin huecos ni espacios fantasma, listo para enviar al modelo.

¿Por qué centralizar la lógica del prompt en el template?

En LangGraph podrías resolver la variación con un nodo condicional: si tienes el nombre del cliente, inyectas un prompt; si no, inyectas otro. Funciona, pero te obliga a mantener dos versiones casi iguales.

Mover esa lógica al template tiene tres ventajas concretas:

  • Mantienes una sola fuente de verdad para el prompt base.
  • Reduces la duplicación cuando solo cambia un fragmento pequeño.
  • Haces explícito qué partes del prompt son condicionales y cuáles fijas.

Lo que es fijo vive en el template como texto plano. Lo que es dinámico se vuelve variable o bloque condicional. Esa distinción ordena el diseño de tus agentes y facilita iterar sobre el prompt sin tocar la orquestación.

¿Ya estás aplicando templates dinámicos en tus agentes? Cuéntame en los comentarios qué técnica de prompting te ha dado mejores resultados.