initial commit: slides + practica_resueltos + README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 11:50:55 +02:00
commit 0aff31e2d3
203 changed files with 23207 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
---
layout: cover
class: text-center
---
# Módulo 4: Mensajes y Prompts
Sistema de mensajes, templates y gestión de contexto
<div class="pt-12">
<span class="text-xl opacity-80">
Comunicándote efectivamente con los LLMs
</span>
</div>
+29
View File
@@ -0,0 +1,29 @@
---
layout: default
---
# Tipos de Mensajes
<div class="mt-4 text-sm">
Los **Chat Models** trabajan con mensajes tipados, no con texto plano. Cada tipo tiene una **carga semántica** que el modelo interpreta de forma diferente
<div class="mt-4 space-y-4">
<v-click>
<div class="border-l-4 border-blue-500 pl-3 bg-blue-50 dark:bg-blue-900/20 py-2 px-3">
<span class="font-bold text-base">💼 SystemMessage</span> <span class="text-xs opacity-70">(role: "system")</span>
<p class="text-sm mt-2 mb-0">Instrucciones iniciales que <b>condicionan todo el comportamiento</b> del modelo. Define persona, reglas, restricciones y formato de respuesta. Tiene la <b>mayor prioridad</b> en la atención del modelo.</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-3 bg-green-50 dark:bg-green-900/20 py-2 px-3">
<span class="font-bold text-base">👤 HumanMessage</span> <span class="text-xs opacity-70">(role: "user")</span>
<p class="text-sm mt-2 mb-0">Input del usuario. Es lo que el modelo debe <b>responder directamente</b>. Puede contener texto, imágenes, audio y archivos (multimodal).</p>
</div>
</v-click>
</div>
</div>
+33
View File
@@ -0,0 +1,33 @@
---
layout: default
---
# Tipos de Mensajes (cont.)
<div class="mt-4 text-sm">
<div class="mt-4 space-y-4">
<v-click>
<div class="border-l-4 border-purple-500 pl-3 bg-purple-50 dark:bg-purple-900/20 py-2 px-3">
<span class="font-bold text-base">🤖 AIMessage</span> <span class="text-xs opacity-70">(role: "assistant")</span>
<p class="text-sm mt-2 mb-0">Respuesta previa del modelo. Se usa para <b>historial de conversación</b> y para <b>few-shot learning</b>. Puede incluir <code>tool_calls</code>, <code>usage_metadata</code> y <code>response_metadata</code>.</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-orange-500 pl-3 bg-orange-50 dark:bg-orange-900/20 py-2 px-3">
<span class="font-bold text-base">🔧 ToolMessage</span> <span class="text-xs opacity-70">(role: "tool")</span>
<p class="text-sm mt-2 mb-0">Resultado de una herramienta ejecutada. Requiere <code>tool_call_id</code> que enlaza con el <code>AIMessage</code> que solicitó la herramienta. Cierra el <b>ciclo de tool-calling</b>.</p>
</div>
</v-click>
<v-click>
<div class="mt-4 text-xs bg-gray-100 dark:bg-gray-800 rounded p-3">
💡 También puedes usar la <b>notación abreviada</b> con tuplas: <code>["system", "..."]</code>, <code>["human", "..."]</code>, <code>["ai", "..."]</code> dentro de <code>ChatPromptTemplate</code>
</div>
</v-click>
</div>
</div>
+39
View File
@@ -0,0 +1,39 @@
---
layout: default
---
# Implicaciones: System vs Human
<div class="mt-6 text-sm">
El tipo de mensaje **no es solo una etiqueta**, cambia cómo el modelo procesa la información
<div class="mt-4 grid grid-cols-2 gap-4">
<v-click>
<div class="border rounded-lg p-4 bg-blue-50 dark:bg-blue-900/20">
<h3 class="text-base font-bold mb-2">💼 System vs Human</h3>
<p class="text-xs mb-2">Poner instrucciones en <code>SystemMessage</code> vs en <code>HumanMessage</code> <b>no es equivalente</b>:</p>
<ul class="text-xs list-disc pl-4 space-y-1">
<li>System tiene <b>mayor prioridad</b> — el modelo lo trata como "ley"</li>
<li>Human se trata como "petición" — puede ser ignorado si contradice al system</li>
<li>En Anthropic, system va en un <b>parámetro separado</b> de la API</li>
</ul>
</div>
</v-click>
<v-click>
<div class="border rounded-lg p-4 bg-purple-50 dark:bg-purple-900/20">
<h3 class="text-base font-bold mb-2">🤖 AIMessage manual</h3>
<p class="text-xs mb-2">Puedes <b>inyectar AIMessages falsos</b> en el historial:</p>
<ul class="text-xs list-disc pl-4 space-y-1">
<li>El modelo "cree" que él mismo dijo eso</li>
<li>Útil para <b>few-shot</b>: enseñar el patrón de respuesta deseado</li>
<li>Útil para <b>prefilling</b>: forzar el inicio de la respuesta</li>
</ul>
</div>
</v-click>
</div>
</div>
+39
View File
@@ -0,0 +1,39 @@
---
layout: default
---
# Implicaciones: Tool Calling y Orden
<div class="mt-6 text-sm">
<div class="mt-4 grid grid-cols-2 gap-4">
<v-click>
<div class="border rounded-lg p-4 bg-orange-50 dark:bg-orange-900/20">
<h3 class="text-base font-bold mb-2">🔧 Ciclo de Tool Calling</h3>
<p class="text-xs mb-2">El flujo completo requiere <b>3 mensajes</b>:</p>
<ol class="text-xs list-decimal pl-4 space-y-1">
<li><code>AIMessage</code> con <code>tool_calls</code> → modelo pide ejecutar</li>
<li><code>ToolMessage</code> con resultado → tu app ejecuta y devuelve</li>
<li><code>AIMessage</code> final → modelo interpreta el resultado</li>
</ol>
<p class="text-xs mt-2 opacity-70">Lo veremos en detalle en el módulo de <b>Agentes</b></p>
</div>
</v-click>
<v-click>
<div class="border rounded-lg p-4 bg-green-50 dark:bg-green-900/20">
<h3 class="text-base font-bold mb-2">📋 El orden importa</h3>
<p class="text-xs mb-2">La <b>secuencia</b> de mensajes define el contexto:</p>
<ul class="text-xs list-disc pl-4 space-y-1">
<li>Los mensajes recientes tienen <b>más peso</b> que los antiguos</li>
<li>El modelo espera alternancia <code>Human → AI → Human</code></li>
<li>Romper la alternancia puede causar comportamiento inesperado</li>
</ul>
<p class="text-xs mt-2 opacity-70">Por eso la <b>gestión del historial</b> es clave</p>
</div>
</v-click>
</div>
</div>
+29
View File
@@ -0,0 +1,29 @@
---
layout: default
---
# Ejemplo: Usando Mensajes
<div class="text-sm mt-6">
```typescript
import { ChatOpenAI } from "@langchain/openai";
import {
SystemMessage,
HumanMessage
} from "@langchain/core/messages";
const model = new ChatOpenAI({ model: "gpt-4.1-mini" });
const messages = [
new SystemMessage("Eres un experto en JavaScript y TypeScript"),
new HumanMessage("¿Qué es async/await?")
];
const response = await model.invoke(messages);
console.log(response.content);
// Respuesta contextualizada como experto en JS/TS
```
</div>
+47
View File
@@ -0,0 +1,47 @@
---
layout: default
---
# Prompt Templates
<div class="mt-4 text-sm">
<v-click>
<div class="mb-4">
**ChatPromptTemplate** permite reutilizar prompts con variables dinámicas y la notación abreviada de roles
</div>
</v-click>
<v-click>
```typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";
const template = ChatPromptTemplate.fromMessages([
["system", "Eres un experto en {topic}"], // ← shorthand de SystemMessage
["human", "{question}"] // ← shorthand de HumanMessage
]);
const prompt = await template.invoke({
topic: "JavaScript",
question: "¿Qué es async/await?"
});
const response = await model.invoke(prompt);
```
</v-click>
<v-click>
<div class="mt-3 text-xs bg-gray-100 dark:bg-gray-800 rounded p-2">
💡 Los templates son útiles para <b>reutilización</b>, <b>testing</b> y separar prompts de la lógica. Pero para casos simples, puedes usar mensajes directamente.
</div>
</v-click>
</div>
+37
View File
@@ -0,0 +1,37 @@
---
layout: default
---
# Ventajas de Templates
<div class="mt-6 text-sm space-y-3">
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 py-2 px-3">
<h3 class="text-base font-bold mb-1">✅ Reutilización</h3>
<p class="text-xs">El mismo template con diferentes variables</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 py-2 px-3">
<h3 class="text-base font-bold mb-1">✅ Mantenibilidad</h3>
<p class="text-xs">Cambiar el prompt en un solo lugar</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-purple-500 pl-4 bg-purple-50 dark:bg-purple-900/20 py-2 px-3">
<h3 class="text-base font-bold mb-1">✅ Testing</h3>
<p class="text-xs">Probar con múltiples combinaciones de variables</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-orange-500 pl-4 bg-orange-50 dark:bg-orange-900/20 py-2 px-3">
<h3 class="text-base font-bold mb-1">✅ Separación de Responsabilidades</h3>
<p class="text-xs">Prompts independientes de la lógica de negocio</p>
</div>
</v-click>
</div>
+41
View File
@@ -0,0 +1,41 @@
---
layout: default
---
# Few-Shot Prompting
<div class="mt-8 text-sm">
<v-click>
<div class="mb-6">
**Few-shot**: Dar ejemplos al LLM para que aprenda el patrón deseado
</div>
</v-click>
<v-click>
```typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";
const template = ChatPromptTemplate.fromMessages([
["system", "Clasifica el sentimiento de tweets"],
["human", "Me encanta este producto!"],
["ai", "positivo"],
["human", "No funciona bien :("],
["ai", "negativo"],
["human", "{tweet}"] // El tweet a clasificar
]);
const response = await model.invoke(
await template.invoke({ tweet: "Buena experiencia" })
);
// → "positivo"
```
</v-click>
</div>
+40
View File
@@ -0,0 +1,40 @@
---
layout: default
---
# Historial de Conversación
<div class="mt-8 text-sm">
<v-click>
<div class="mb-6">
Para mantener **contexto** entre mensajes, acumula el historial
</div>
</v-click>
<v-click>
```typescript
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage } from "@langchain/core/messages";
const model = new ChatOpenAI({ model: "gpt-4.1-mini" });
const history = [
new HumanMessage("Hola, me llamo Juan"),
new AIMessage("Hola Juan, ¿en qué puedo ayudarte?"),
new HumanMessage("¿Cuál es mi nombre?")
];
const response = await model.invoke(history);
console.log(response.content);
// → "Tu nombre es Juan"
```
</v-click>
</div>
+44
View File
@@ -0,0 +1,44 @@
---
layout: default
---
# Gestión de Historial
<div class="mt-10 text-sm">
<v-click>
<div class="mb-8">
**Problema**: El historial crece indefinidamente → Tokens infinitos → Costos altos
</div>
</v-click>
<div class="space-y-5">
<v-click>
<div class="border-l-4 border-orange-500 pl-4 bg-orange-50 dark:bg-orange-900/20 p-3">
<h3 class="text-base font-bold mb-2">📏 Limitar por cantidad</h3>
<p class="text-xs">Mantener solo los últimos N mensajes</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-3">
<h3 class="text-base font-bold mb-2">📊 Limitar por tokens</h3>
<p class="text-xs">Mantener solo los últimos N tokens</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-purple-500 pl-4 bg-purple-50 dark:bg-purple-900/20 p-3">
<h3 class="text-base font-bold mb-2">📝 Resumir</h3>
<p class="text-xs">Comprimir conversaciones antiguas en un resumen</p>
</div>
</v-click>
</div>
</div>
+34
View File
@@ -0,0 +1,34 @@
---
layout: default
---
# Ejemplo: Limitando Historial
<div class="text-sm mt-6">
```typescript
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage } from "@langchain/core/messages";
const model = new ChatOpenAI({ model: "gpt-4.1-mini" });
// Simular un historial largo
const fullHistory = [
new HumanMessage("Mensaje 1"),
new AIMessage("Respuesta 1"),
new HumanMessage("Mensaje 2"),
new AIMessage("Respuesta 2"),
new HumanMessage("Mensaje 3"),
new AIMessage("Respuesta 3"),
];
// Mantener solo los últimos 4 mensajes (2 turnos)
const recentHistory = fullHistory.slice(-4);
const response = await model.invoke([
...recentHistory,
new HumanMessage("Nueva pregunta")
]);
```
</div>
+51
View File
@@ -0,0 +1,51 @@
---
layout: default
---
# Placeholder Variables
<div class="mt-8 text-sm">
<v-click>
<div class="mb-6">
**MessagesPlaceholder**: Insertar arrays de mensajes dinámicamente en templates
</div>
</v-click>
<v-click>
```typescript
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
const template = ChatPromptTemplate.fromMessages([
["system", "Eres un asistente útil"],
new MessagesPlaceholder("history"), // Array de mensajes
["human", "{input}"]
]);
const response = await model.invoke(
await template.invoke({
history: [
new HumanMessage("Hola"),
new AIMessage("¡Hola! ¿En qué puedo ayudarte?")
],
input: "¿Qué tiempo hace?"
})
);
```
</v-click>
<v-click>
<div class="mt-2 text-xs text-gray-500">
💡 <code>["system", "..."]</code> y <code>["human", "..."]</code> son la forma abreviada de <code>SystemMessage</code> y <code>HumanMessage</code> en <code>ChatPromptTemplate</code>
</div>
</v-click>
</div>
+43
View File
@@ -0,0 +1,43 @@
---
layout: default
---
# Partial Templates
<div class="mt-8 text-sm">
<v-click>
<div class="mb-6">
**Partial**: Pre-rellenar algunas variables, completar otras después
</div>
</v-click>
<v-click>
```typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";
const template = ChatPromptTemplate.fromMessages([
["system", "Eres un experto en {topic} que habla {language}"],
["human", "{question}"]
]);
// Pre-configurar topic y language
const spanishJSTemplate = await template.partial({
topic: "JavaScript",
language: "español"
});
// Ahora solo necesitas la pregunta
const response = await model.invoke(
await spanishJSTemplate.invoke({ question: "¿Qué es async/await?" })
);
```
</v-click>
</div>