initial commit: slides ready + upgraded

This commit is contained in:
2026-05-24 10:37:53 +02:00
commit f6f46972c3
173 changed files with 16756 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
---
layout: cover
class: text-center
---
# Módulo 5: Agentes
Tools, Structured Output, Runtime y Human-in-the-Loop
<div class="pt-12">
<span class="text-xl opacity-80">
LLMs que pueden actuar en el mundo real
</span>
</div>
+41
View File
@@ -0,0 +1,41 @@
---
layout: default
---
# ¿Qué es un Agente?
<div class="mt-10 text-sm">
<v-click>
<div class="mb-8">
Un **agente** es un sistema que usa un LLM para decidir qué acciones tomar
</div>
</v-click>
<div class="grid grid-cols-2 gap-8">
<v-click>
<div class="border-l-4 border-red-500 pl-4 bg-red-50 dark:bg-red-900/20 p-4">
<h3 class="text-base font-bold mb-3">❌ Sin Agentes</h3>
<p class="text-xs mb-2">Flujo fijo y predecible</p>
<p class="text-xs mb-2">Usuario → LLM → Respuesta</p>
<p class="text-xs opacity-70">El LLM solo genera texto</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-4">
<h3 class="text-base font-bold mb-3">✅ Con Agentes</h3>
<p class="text-xs mb-2">Flujo dinámico y adaptativo</p>
<p class="text-xs mb-2">Usuario → LLM → Tool → LLM → Respuesta</p>
<p class="text-xs opacity-70">El LLM decide qué herramientas usar</p>
</div>
</v-click>
</div>
</div>
+37
View File
@@ -0,0 +1,37 @@
---
layout: default
---
# Casos de Uso de Agentes
<div class="mt-6 grid grid-cols-2 gap-4 text-xs">
<v-click>
<div class="border-l-4 border-blue-500 pl-3 bg-blue-50 dark:bg-blue-900/20 p-2">
<h3 class="text-sm font-bold mb-1">🔍 Búsqueda y análisis</h3>
<p>Buscar información en APIs, bases de datos o web</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-3 bg-green-50 dark:bg-green-900/20 p-2">
<h3 class="text-sm font-bold mb-1">🛠️ Automatización</h3>
<p>Enviar emails, crear tickets, actualizar sistemas</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-purple-500 pl-3 bg-purple-50 dark:bg-purple-900/20 p-2">
<h3 class="text-sm font-bold mb-1">💼 Asistentes empresariales</h3>
<p>Consultar CRM, generar reportes, analizar datos</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-orange-500 pl-3 bg-orange-50 dark:bg-orange-900/20 p-2">
<h3 class="text-sm font-bold mb-1">🤖 Agentes autónomos</h3>
<p>Tomar decisiones complejas con múltiples pasos</p>
</div>
</v-click>
</div>
+45
View File
@@ -0,0 +1,45 @@
---
layout: default
---
# createAgent: Creando el Agente
<div class="mt-6 text-xs">
<v-click>
<div class="mb-4">
**createAgent** es la forma estándar de crear agentes en LangChain v1
</div>
</v-click>
<v-click>
```typescript
import { createAgent } from "langchain";
const agent = createAgent({
model: "mistral:mistral-large-latest", // Modelo como string
tools: [weatherTool], // Array de tools
systemPrompt: "Eres un asistente útil.",
});
const result = await agent.invoke({
messages: [{ role: "user", content: "¿Qué tiempo hace en Madrid?" }]
});
```
</v-click>
<v-click>
<div class="mt-4 text-xs opacity-70">
El agente automatiza el ciclo: llamar al LLM -> ejecutar tools -> procesar resultados -> repetir
</div>
</v-click>
</div>
+42
View File
@@ -0,0 +1,42 @@
---
layout: default
---
# Configuración del Modelo
<div class="mt-4 text-xs">
<v-click>
**Opción 1: String con formato `provider:model`**
```typescript
const agent = createAgent({
model: "mistral:mistral-large-latest", // Mistral
// model: "openai:gpt-4.1", // OpenAI
// model: "anthropic:claude-sonnet-4-6", // Anthropic
tools: [],
});
```
</v-click>
<v-click>
**Opción 2: Instancia del modelo con configuración avanzada**
```typescript
import { ChatMistralAI } from "@langchain/mistralai";
const model = new ChatMistralAI({
model: "mistral-large-latest",
temperature: 0.1,
maxTokens: 1000,
});
const agent = createAgent({ model, tools: [] });
```
</v-click>
</div>
+43
View File
@@ -0,0 +1,43 @@
---
layout: default
---
# systemPrompt: Configurando el Comportamiento
<div class="mt-4 text-xs">
<v-click>
**String simple:**
```typescript
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [weatherTool],
systemPrompt: "Eres un asistente meteorológico. Sé conciso y preciso.",
});
```
</v-click>
<v-click>
**SystemMessage (para features avanzados como cache de Anthropic):**
```typescript
import { SystemMessage } from "langchain";
const agent = createAgent({
model: "anthropic:claude-sonnet-4-6",
tools: [weatherTool],
systemPrompt: new SystemMessage({
content: [
{ type: "text", text: "Eres un experto en clima...", cache_control: { type: "ephemeral" } }
],
}),
});
```
</v-click>
</div>
+44
View File
@@ -0,0 +1,44 @@
---
layout: default
---
# Tools: Definiendo Herramientas
<div class="mt-6 text-xs">
<v-click>
```typescript
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const weatherTool = tool(
async ({ location }) => {
// Llamar a API del tiempo
return `El tiempo en ${location} es soleado, 22°C`;
},
{
name: "get_weather",
description: "Obtiene el tiempo actual de una ubicación",
schema: z.object({
location: z.string().describe("Ciudad o ubicación"),
}),
}
);
```
</v-click>
<v-click>
```typescript
// El agente decide automáticamente cuándo usar cada tool
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [weatherTool, calculatorTool, searchTool],
});
```
</v-click>
</div>
+42
View File
@@ -0,0 +1,42 @@
---
layout: default
---
# Streaming: Modos de Transmisión
<div class="mt-4 text-xs">
<v-click>
**`updates`**: Emite evento después de cada paso del agente
```typescript
for await (const chunk of await agent.stream(
{ messages: [{ role: "user", content: "¿Tiempo en Madrid?" }] },
{ streamMode: "updates" }
)) {
console.log(chunk);
// { model: { messages: [AIMessage con tool_call] } }
// { tools: { messages: [ToolMessage con resultado] } }
// { model: { messages: [AIMessage respuesta final] } }
}
```
</v-click>
<v-click>
**`values`**: Emite el estado completo después de cada paso
```typescript
for await (const chunk of await agent.stream(
{ messages: [{ role: "user", content: "¿Tiempo en Madrid?" }] },
{ streamMode: "values" }
)) {
console.log(chunk.messages); // Array completo de mensajes hasta ese punto
}
```
</v-click>
</div>
+40
View File
@@ -0,0 +1,40 @@
---
layout: default
---
# Streaming: Tokens y Mensajes
<div class="mt-4 text-xs">
<v-click>
**`messages`**: Stream de tokens del LLM + metadata
```typescript
for await (const [mode, chunk] of await agent.stream(
{ messages: [{ role: "user", content: "Explica qué es TypeScript" }] },
{ streamMode: ["updates", "messages"] }
)) {
if (mode === "messages") {
const [token, metadata] = chunk;
if (token.content) {
process.stdout.write(token.content); // Token a token
}
} else if (mode === "updates") {
// Paso completo del agente
console.log("\n[Paso completado]", Object.keys(chunk));
}
}
```
</v-click>
<v-click>
<div class="mt-4 text-xs opacity-80">
Combina múltiples modos: `streamMode: ["updates", "messages"]`
</div>
</v-click>
</div>
+39
View File
@@ -0,0 +1,39 @@
---
layout: default
---
# Checkpointer: MemorySaver
<div class="mt-4 text-xs">
<v-click>
**MemorySaver**: Persistencia en memoria (desarrollo/testing)
```typescript
import { createAgent } from "langchain";
import { MemorySaver } from "@langchain/langgraph";
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [weatherTool],
checkpointer: new MemorySaver(), // En memoria RAM
});
const config = { configurable: { thread_id: "conv-1" } };
// Primera conversación
await agent.invoke(
{ messages: [{ role: "user", content: "Hola, soy María" }] }, config
);
// Segunda conversación - recuerda el contexto
await agent.invoke(
{ messages: [{ role: "user", content: "¿Cómo me llamo?" }] }, config
);
// "Tu nombre es María"
```
</v-click>
</div>
+47
View File
@@ -0,0 +1,47 @@
---
layout: default
---
# Checkpointer: SqliteSaver
<div class="mt-4 text-xs">
<v-click>
**SqliteSaver**: Persistencia en SQLite (local)
```bash
npm install @langchain/langgraph-checkpoint-sqlite
```
</v-click>
<v-click>
```typescript
import { createAgent } from "langchain";
import { SqliteSaver } from "@langchain/langgraph-checkpoint-sqlite";
const checkpointer = SqliteSaver.fromConnString("./agent_memory.db");
await checkpointer.setup(); // Crear tablas
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [weatherTool],
checkpointer,
});
// El estado persiste aunque reinicies la aplicación
```
</v-click>
<v-click>
<div class="mt-4 text-xs opacity-80">
Ideal para desarrollo local y aplicaciones de usuario único
</div>
</v-click>
</div>
+47
View File
@@ -0,0 +1,47 @@
---
layout: default
---
# Checkpointer: PostgresSaver
<div class="mt-4 text-xs">
<v-click>
**PostgresSaver**: Persistencia en PostgreSQL (producción)
```bash
npm install @langchain/langgraph-checkpoint-postgres
```
</v-click>
<v-click>
```typescript
import { createAgent } from "langchain";
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
const DB_URI = "postgresql://user:pass@localhost:5432/mydb";
const checkpointer = PostgresSaver.fromConnString(DB_URI);
await checkpointer.setup();
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [weatherTool],
checkpointer,
});
```
</v-click>
<v-click>
<div class="mt-4 text-xs opacity-80">
También disponibles: **MongoDB** (`@langchain/langgraph-checkpoint-mongodb`),
**Redis** (`@langchain/langgraph-checkpoint-redis`), y **Custom** (implementar `BaseCheckpointSaver`)
</div>
</v-click>
</div>
+51
View File
@@ -0,0 +1,51 @@
---
layout: default
---
# Middleware: Arquitectura
<div class="mt-6 text-xs">
<v-click>
<div class="mb-4">
**Middleware**: Hooks que interceptan el flujo del agente en puntos clave
</div>
</v-click>
<v-click>
<div class="space-y-3 text-xs">
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-2">
<code class="font-bold">beforeAgent</code> - Antes de iniciar el agente
</div>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-2">
<code class="font-bold">beforeModel</code> - Antes de cada llamada al LLM
</div>
<div class="border-l-4 border-purple-500 pl-4 bg-purple-50 dark:bg-purple-900/20 p-2">
<code class="font-bold">wrapModelCall</code> - Envuelve la llamada al LLM (interceptar/modificar)
</div>
<div class="border-l-4 border-orange-500 pl-4 bg-orange-50 dark:bg-orange-900/20 p-2">
<code class="font-bold">wrapToolCall</code> - Envuelve la ejecución de tools
</div>
<div class="border-l-4 border-red-500 pl-4 bg-red-50 dark:bg-red-900/20 p-2">
<code class="font-bold">afterModel</code> - Después de cada respuesta del LLM
</div>
<div class="border-l-4 border-cyan-500 pl-4 bg-cyan-50 dark:bg-cyan-900/20 p-2">
<code class="font-bold">afterAgent</code> - Después de completar el agente
</div>
</div>
</v-click>
</div>
+36
View File
@@ -0,0 +1,36 @@
---
layout: default
---
# Middleware Custom
<div class="mt-4 text-xs">
<v-click>
```typescript
import { createAgent, createMiddleware } from "langchain";
const loggingMiddleware = createMiddleware({
name: "LoggingMiddleware",
beforeModel: (state) => {
console.log(`Llamando modelo con ${state.messages.length} mensajes`);
return; // No modificar estado
},
afterModel: (state) => {
const lastMsg = state.messages[state.messages.length - 1];
console.log(`Modelo respondió: ${lastMsg.content?.slice(0, 50)}...`);
return;
},
});
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [weatherTool],
middleware: [loggingMiddleware],
});
```
</v-click>
</div>
+46
View File
@@ -0,0 +1,46 @@
---
layout: default
---
# dynamicSystemPromptMiddleware
<div class="mt-4 text-xs">
<v-click>
```typescript
import * as z from "zod";
import { createAgent, dynamicSystemPromptMiddleware } from "langchain";
const contextSchema = z.object({
userRole: z.enum(["expert", "beginner"]),
});
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [searchTool],
contextSchema,
middleware: [
dynamicSystemPromptMiddleware<z.infer<typeof contextSchema>>((state, runtime) => {
const userRole = runtime.context.userRole;
let prompt = "Eres un asistente útil.";
if (userRole === "expert") {
prompt += " Proporciona respuestas técnicas detalladas.";
} else {
prompt += " Explica conceptos de forma simple, sin jerga técnica.";
}
return prompt;
}),
],
});
await agent.invoke(
{ messages: [{ role: "user", content: "Explica machine learning" }] },
{ context: { userRole: "beginner" } }
);
```
</v-click>
</div>
+48
View File
@@ -0,0 +1,48 @@
---
layout: default
---
# toolCallLimitMiddleware: Limitar Tools
<div class="mt-4 text-xs">
<v-click>
```typescript
import { createAgent, toolCallLimitMiddleware } from "langchain";
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [searchTool, databaseTool, scraperTool],
middleware: [
// Límite global: máx 20 por thread, 10 por run
toolCallLimitMiddleware({ threadLimit: 20, runLimit: 10 }),
// Límite específico para búsquedas
toolCallLimitMiddleware({
toolName: "search",
threadLimit: 5,
runLimit: 3,
}),
// Límite estricto para scraping (lanza error si excede)
toolCallLimitMiddleware({
toolName: "scrape_webpage",
runLimit: 2,
exitBehavior: "error", // "continue" | "error" | "end"
}),
],
});
```
</v-click>
<v-click>
<div class="mt-3 text-xs opacity-80">
Requiere checkpointer para `threadLimit`. `runLimit` se resetea en cada invocación.
</div>
</v-click>
</div>
+44
View File
@@ -0,0 +1,44 @@
---
layout: default
---
# summarizationMiddleware: Resumir Historial
<div class="mt-4 text-xs">
<v-click>
```typescript
import { createAgent, summarizationMiddleware } from "langchain";
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [searchTool, calculatorTool],
middleware: [
summarizationMiddleware({
model: "mistral:mistral-small-latest", // Modelo para resumir (más barato)
trigger: { tokens: 4000 }, // Resumir cuando supere 4000 tokens
keep: { messages: 20 }, // Mantener los últimos 20 mensajes
}),
],
});
```
</v-click>
<v-click>
<div class="mt-4 text-xs opacity-80">
**Funcionamiento automático:**
1. Detecta cuando el historial supera el límite de tokens
2. Resume los mensajes antiguos usando el modelo especificado
3. Reemplaza permanentemente los mensajes antiguos por el resumen
4. Mantiene los mensajes recientes intactos para contexto
</div>
</v-click>
</div>
+46
View File
@@ -0,0 +1,46 @@
---
layout: default
---
# Middleware: Limitar Historial (Trim)
<div class="mt-4 text-xs">
<v-click>
```typescript
import { RemoveMessage } from "@langchain/core/messages";
import { createAgent, createMiddleware } from "langchain";
import { MemorySaver, REMOVE_ALL_MESSAGES } from "@langchain/langgraph";
const trimMessages = createMiddleware({
name: "TrimMessages",
beforeModel: (state) => {
const messages = state.messages;
if (messages.length <= 5) return; // No recortar si hay pocos
// Mantener primer mensaje + últimos 4
const firstMsg = messages[0];
const recentMsgs = messages.slice(-4);
const newMessages = [firstMsg, ...recentMsgs];
return {
messages: [
new RemoveMessage({ id: REMOVE_ALL_MESSAGES }),
...newMessages,
],
};
},
});
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [],
middleware: [trimMessages],
checkpointer: new MemorySaver(),
});
```
</v-click>
</div>
+40
View File
@@ -0,0 +1,40 @@
---
layout: default
---
# Middleware: wrapModelCall
<div class="mt-4 text-xs">
<v-click>
Permite interceptar y modificar la llamada al modelo:
```typescript
import { ChatMistralAI } from "@langchain/mistralai";
import { createAgent, createMiddleware } from "langchain";
const basicModel = new ChatMistralAI({ model: "mistral-small-latest" });
const advancedModel = new ChatMistralAI({ model: "mistral-large-latest" });
const dynamicModelSelection = createMiddleware({
name: "DynamicModelSelection",
wrapModelCall: (request, handler) => {
// Elegir modelo según complejidad de la conversación
const messageCount = request.messages.length;
const model = messageCount > 10 ? advancedModel : basicModel;
return handler({ ...request, model });
},
});
const agent = createAgent({
model: basicModel,
tools: [searchTool],
middleware: [dynamicModelSelection],
});
```
</v-click>
</div>
+40
View File
@@ -0,0 +1,40 @@
---
layout: default
---
# Middleware: wrapToolCall
<div class="mt-4 text-xs">
<v-click>
Intercepta la ejecución de tools para manejo de errores:
```typescript
import { createAgent, createMiddleware, ToolMessage } from "langchain";
const handleToolErrors = createMiddleware({
name: "HandleToolErrors",
wrapToolCall: async (request, handler) => {
try {
return await handler(request);
} catch (error) {
// Devolver mensaje de error al modelo para que reintente
return new ToolMessage({
content: `Error en tool: ${error}. Por favor revisa los parámetros.`,
tool_call_id: request.toolCall.id!,
});
}
},
});
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [databaseTool, apiTool],
middleware: [handleToolErrors],
});
```
</v-click>
</div>
+51
View File
@@ -0,0 +1,51 @@
---
layout: default
---
# Middleware Built-in: Resumen
<div class="mt-6 text-xs space-y-3">
<v-click>
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-2">
<code class="font-bold">summarizationMiddleware</code> - Resumir historial cuando supera tokens
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-2">
<code class="font-bold">humanInTheLoopMiddleware</code> - Pausar para aprobación humana
</div>
</v-click>
<v-click>
<div class="border-l-4 border-purple-500 pl-4 bg-purple-50 dark:bg-purple-900/20 p-2">
<code class="font-bold">toolCallLimitMiddleware</code> - Limitar llamadas a tools
</div>
</v-click>
<v-click>
<div class="border-l-4 border-orange-500 pl-4 bg-orange-50 dark:bg-orange-900/20 p-2">
<code class="font-bold">modelCallLimitMiddleware</code> - Limitar llamadas al modelo
</div>
</v-click>
<v-click>
<div class="border-l-4 border-red-500 pl-4 bg-red-50 dark:bg-red-900/20 p-2">
<code class="font-bold">modelFallbackMiddleware</code> - Fallback a modelos alternativos
</div>
</v-click>
<v-click>
<div class="border-l-4 border-cyan-500 pl-4 bg-cyan-50 dark:bg-cyan-900/20 p-2">
<code class="font-bold">modelRetryMiddleware</code> - Reintentar con backoff exponencial
</div>
</v-click>
<v-click>
<div class="border-l-4 border-yellow-500 pl-4 bg-yellow-50 dark:bg-yellow-900/20 p-2">
<code class="font-bold">piiRedactionMiddleware</code> - Redactar información personal
</div>
</v-click>
</div>
+46
View File
@@ -0,0 +1,46 @@
---
layout: default
---
# Combinando Middleware
<div class="mt-4 text-xs">
<v-click>
```typescript
import {
createAgent,
summarizationMiddleware,
humanInTheLoopMiddleware,
toolCallLimitMiddleware,
modelRetryMiddleware,
} from "langchain";
import { MemorySaver } from "@langchain/langgraph";
const agent = createAgent({
model: "mistral:mistral-large-latest",
tools: [searchTool, sendEmailTool, databaseTool],
checkpointer: new MemorySaver(),
middleware: [
modelRetryMiddleware({ maxRetries: 3, backoffFactor: 2 }),
summarizationMiddleware({ model: "mistral:mistral-small-latest", trigger: { tokens: 4000 } }),
toolCallLimitMiddleware({ toolName: "search", runLimit: 5 }),
humanInTheLoopMiddleware({
interruptOn: { send_email: { allowedDecisions: ["approve", "reject"] } },
}),
],
});
```
</v-click>
<v-click>
<div class="mt-3 text-xs opacity-80">
El orden de los middleware importa: se ejecutan en secuencia
</div>
</v-click>
</div>
+49
View File
@@ -0,0 +1,49 @@
---
layout: default
---
<h1 class="!text-2xl">Human-in-the-Loop</h1>
<div class="mt-1">
<v-click>
````md magic-move
```typescript
import { createAgent, humanInTheLoopMiddleware } from "langchain";
import { Command, MemorySaver } from "@langchain/langgraph";
const agent = createAgent({
model: "gpt-4.1",
tools: [sendEmailTool, deleteRecordTool],
checkpointer: new MemorySaver(),
middleware: [
humanInTheLoopMiddleware({
interruptOn: {
send_email: { allowedDecisions: ["approve", "edit", "reject"] },
delete_record: { allowedDecisions: ["approve", "reject"] },
},
}),
],
});
```
```typescript
const config = { configurable: { thread_id: "thread-1" } };
// Se pausa antes de ejecutar tools sensibles
let result = await agent.invoke({ messages: [...] }, config);
// Aprobar y continuar
result = await agent.invoke(
new Command({ resume: { decisions: [{ type: "approve" }] } }),
config
);
```
````
</v-click>
</div>
---
+51
View File
@@ -0,0 +1,51 @@
---
layout: default
---
# Resumen: Agentes LangChain v1
<div class="mt-6 text-xs space-y-3">
<v-click>
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-2">
<code class="font-bold">createAgent</code> - Punto de entrada principal
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-2">
<code class="font-bold">model</code> - String ("mistral:mistral-large-latest") o instancia ChatModel
</div>
</v-click>
<v-click>
<div class="border-l-4 border-purple-500 pl-4 bg-purple-50 dark:bg-purple-900/20 p-2">
<code class="font-bold">systemPrompt</code> - String o SystemMessage
</div>
</v-click>
<v-click>
<div class="border-l-4 border-orange-500 pl-4 bg-orange-50 dark:bg-orange-900/20 p-2">
<code class="font-bold">tools</code> - Array de tools definidas con Zod
</div>
</v-click>
<v-click>
<div class="border-l-4 border-red-500 pl-4 bg-red-50 dark:bg-red-900/20 p-2">
<code class="font-bold">checkpointer</code> - MemorySaver | SqliteSaver | PostgresSaver
</div>
</v-click>
<v-click>
<div class="border-l-4 border-cyan-500 pl-4 bg-cyan-50 dark:bg-cyan-900/20 p-2">
<code class="font-bold">middleware</code> - Array para customización (prompts, límites, HITL)
</div>
</v-click>
<v-click>
<div class="border-l-4 border-yellow-500 pl-4 bg-yellow-50 dark:bg-yellow-900/20 p-2">
<code class="font-bold">stream()</code> - updates | values | messages
</div>
</v-click>
</div>
+20
View File
@@ -0,0 +1,20 @@
---
layout: cover
class: text-center
---
# Alternativas en el Ecosistema JS/TS
Frameworks y SDKs para aplicaciones LLM en TypeScript
<div class="pt-12">
<span class="text-xl opacity-80">
Pinceladas rápidas del mercado actual (Mayo 2026)
</span>
</div>
<div class="mt-8 text-sm opacity-60">
Nota: Nos centramos exclusivamente en opciones JavaScript/TypeScript
</div>
+31
View File
@@ -0,0 +1,31 @@
---
layout: default
---
# El Panorama JS/TS para LLMs
<v-clicks>
### Tres niveles de abstracción
```
┌─────────────────────────────────────────────────────┐
│ Frameworks (LangChain, LlamaIndex) │ ← Mayor abstracción
├─────────────────────────────────────────────────────┤
│ SDKs unificados (Vercel AI SDK) │ ← Abstracción media
├─────────────────────────────────────────────────────┤
│ APIs nativas (OpenAI SDK, Anthropic SDK, etc.) │ ← Control total
└─────────────────────────────────────────────────────┘
```
### La pregunta no es "cuál es mejor"
Es: **¿qué nivel de abstracción necesito?**
- **Prototipo rápido** → API nativa o Vercel AI
- **RAG complejo** → LlamaIndex o LangChain
- **Agentes sofisticados** → LangGraph / DeepAgents o Vercel AI SDK 6
- **UI streaming en React** → Vercel AI SDK
</v-clicks>
+50
View File
@@ -0,0 +1,50 @@
---
layout: default
---
# LlamaIndex.TS
El "hermano pequeño" de LlamaIndex (Python)
<v-clicks>
### Realidad del ecosistema TS
<div class="grid grid-cols-2 gap-4">
<div>
**Lo bueno**
- Especializado en RAG
- API similar a la versión Python
- Conectores de datos incluidos
- Activamente desarrollado
</div>
<div>
**La realidad**
- Mejorando rápido (agentes, LiteParse)
- Documentación aún por detrás de Python
- Comunidad más pequeña
- Features llegan después
</div>
</div>
### Ejemplo básico
```typescript
import { Document, VectorStoreIndex } from "llamaindex";
const doc = new Document({ text: "Contenido..." });
const index = await VectorStoreIndex.fromDocuments([doc]);
const response = await index.asQueryEngine().query({ query: "Mi pregunta" });
```
<div class="p-3 bg-yellow-500/10 rounded text-sm">
⚠️ Ha mejorado mucho, pero si tu proyecto permite Python, LlamaIndex Python sigue siendo más completo.
</div>
</v-clicks>
+36
View File
@@ -0,0 +1,36 @@
---
layout: default
---
# Vercel AI SDK
El SDK moderno para aplicaciones AI en JS/TS
<v-clicks>
### Por qué destaca
- **Provider-agnostic**: OpenAI, Anthropic, Google, Mistral, Groq...
- **Streaming nativo**: Pensado para UIs reactivas
- **React-first**: Hooks listos para usar (`useChat`, `useCompletion`)
- **Edge-ready**: Funciona en Vercel, Cloudflare Workers, etc.
- **Ligero**: Pocas abstracciones, código directo
### Ya en v6 — El SDK que más ha crecido
```typescript
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
const { text } = await generateText({
model: openai('gpt-4.1'),
prompt: 'Explica qué es RAG',
});
```
<div class="mt-4 p-3 bg-green-500/10 rounded">
✅ Excelente para: Apps Next.js/React, APIs serverless, prototipos rápidos
</div>
</v-clicks>
+40
View File
@@ -0,0 +1,40 @@
---
layout: default
---
# Vercel AI SDK 6 - Agentes
<v-clicks>
### Agent class (nuevo en v6)
```typescript
import { openai } from '@ai-sdk/openai';
import { Agent, tool } from 'ai';
import { z } from 'zod';
const agent = new Agent({
model: openai('gpt-4.1'),
tools: {
weather: tool({
description: 'Obtiene el clima',
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => ({ temp: 22, condition: 'Soleado' }),
}),
},
maxSteps: 5,
});
```
### ¿Agentes completos?
| Tiene ✅ | No tiene ❌ |
|----------|-------------|
| Agent class reutilizable | Persistencia de estado (threads) |
| Human-in-the-loop (`needsApproval`) | Tools built-in (code interpreter) |
| Tools custom + Streaming | Orquestación multi-agente nativa |
</v-clicks>
+52
View File
@@ -0,0 +1,52 @@
---
layout: default
---
# APIs Nativas de los Providers
Cada provider tiene su SDK oficial para Node.js/TS
<v-clicks>
<div class="grid grid-cols-2 gap-6 mt-4">
<div>
### OpenAI SDK
```typescript
import OpenAI from "openai";
const openai = new OpenAI();
// Function calling nativo
const response = await openai.chat.completions.create({
model: "gpt-4.1",
messages: [...],
tools: [{ type: "function", function: {...} }],
});
```
- Assistants API (agentes con estado)
- File search, code interpreter built-in
</div>
<div>
### Anthropic SDK + Agent SDK
```typescript
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
const message = await anthropic.messages.create({
model: "claude-sonnet-4-6",
messages: [...],
tools: [{ name: "...", input_schema: {...} }],
});
```
- Tool use muy potente
- **Claude Agent SDK** (`@anthropic-ai/claude-agent-sdk`)
</div>
</div>
</v-clicks>
+42
View File
@@ -0,0 +1,42 @@
---
layout: default
---
# ¿Agentes con APIs Nativas?
Cada provider tiene su propio enfoque
<v-clicks>
### OpenAI: Assistants API
```typescript
const assistant = await openai.beta.assistants.create({
name: "Analyst", tools: [{ type: "code_interpreter" }], model: "gpt-4.1",
});
const thread = await openai.beta.threads.create();
const run = await openai.beta.threads.runs.create(thread.id, { assistant_id: assistant.id });
```
- Agentes con estado, tools built-in (code interpreter, file search)
### Anthropic: Claude Agent SDK
- Agent SDK con tools built-in (Bash, Read, Edit, Web...)
- O tool use manual si prefieres control total
### Google (Gemini): @google/genai SDK
```typescript
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: "gemini-2.5-flash", contents: "Explica RAG",
});
```
- Function calling similar a OpenAI
- Vertex AI Agents Builder para low-code enterprise
</v-clicks>
+16
View File
@@ -0,0 +1,16 @@
---
layout: default
---
# Comparativa Rápida: Ecosistema JS/TS
| | LangChain.js | LlamaIndex.TS | Vercel AI | APIs Nativas |
|---|:---:|:---:|:---:|:---:|
| **Madurez TS** | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| **RAG** | ✅ Completo | ✅ Especializado | ⚠️ Básico | 🔧 Manual |
| **Agentes** | ✅ LangGraph | ⚠️ Básico | ✅ Agent class | 🔧 Varía |
| **Streaming UI** | ✅ | ⚠️ | ✅✅ | ✅ |
| **Curva aprendizaje** | Media-Alta | Media | Baja | Baja |
| **Vendor lock-in** | Bajo | Bajo | Bajo | Alto |
+25
View File
@@ -0,0 +1,25 @@
---
layout: default
---
# Recomendación Pragmática
<v-clicks>
| Caso de uso | Recomendación |
|-------------|---------------|
| **Prototipo/MVP** | Vercel AI SDK o API nativa |
| **RAG** | LangChain.js (o Python si puedes) |
| **Agentes complejos** | LangGraph / DeepAgents |
| **App React con chat** | Vercel AI SDK |
| **Control total** | APIs nativas del provider |
<div class="p-3 bg-blue-500/10 rounded mt-2 text-sm">
1. **Empieza simple** → API nativa o Vercel AI
2. **Añade complejidad cuando la necesites** → LangChain/LangGraph
3. **No sobre-ingenierices** → La herramienta mínima que resuelva el problema
</div>
</v-clicks>
+31
View File
@@ -0,0 +1,31 @@
---
layout: default
---
# Reflexión Final
<v-clicks>
### El ecosistema JS/TS para LLMs está madurando
- **2023**: LangChain dominaba, pocas alternativas
- **2024**: Explosión de opciones, Vercel AI despega
- **2025**: Vercel AI SDK 5/6, Claude Agent SDK, DeepAgents
- **2026**: Ecosistema TS ya compite seriamente con Python
### Pero seamos honestos...
<div class="p-4 bg-yellow-500/10 rounded mt-4">
**Python sigue adelante** en el ecosistema LLM:
- Más ejemplos, tutoriales, comunidad
- Features nuevas llegan antes
- Mejor soporte de ML/embeddings locales
Si tu stack lo permite, Python puede ser más productivo para AI.
</div>
</v-clicks>
+38
View File
@@ -0,0 +1,38 @@
---
layout: default
---
# ¿Cuándo JS/TS es viable para AI?
<v-clicks>
### Casos donde tiene sentido
- Tu equipo es **JS/TS puro** y no quieres añadir Python
- Necesitas **edge computing** (Cloudflare Workers, Vercel Edge)
- Tu aplicación es **web-first** con mucho frontend
- Quieres un **stack unificado** (mismo lenguaje front y back)
### El ecosistema está mejorando
<div class="grid grid-cols-2 gap-4 mt-4">
<div class="p-3 bg-green-500/10 rounded">
**Vercel AI SDK** está muy maduro y bien mantenido
</div>
<div class="p-3 bg-green-500/10 rounded">
**LangChain.js** sigue de cerca a Python
</div>
</div>
<div class="mt-6 p-4 bg-blue-500/10 rounded">
**Conclusión**: JS/TS ya es una opción seria para aplicaciones LLM en producción, especialmente si tu contexto lo favorece.
</div>
</v-clicks>
+30
View File
@@ -0,0 +1,30 @@
---
layout: center
class: text-center
---
# Eskerrik asko! 🎉
<div class="mt-12 text-xl">
Gracias por vuestra atención
</div>
<div class="mt-10 text-base opacity-80">
¿Dudas o consultas?
</div>
<div class="mt-4 text-lg">
📧 **jabi@nykk.io**
</div>
<div class="mt-10 text-sm opacity-60">
LangChain.js: De cero a producción
</div>
+15
View File
@@ -0,0 +1,15 @@
---
layout: cover
class: text-center
---
# ¿Qué es LangChain?
Framework para desarrollar aplicaciones con Modelos de Lenguaje (LLMs)
<div class="pt-12">
<span class="px-2 py-1 rounded cursor-pointer opacity-80">
Conectando LLMs con el mundo real
</span>
</div>
+33
View File
@@ -0,0 +1,33 @@
---
layout: default
---
# Historia de LangChain
<div class="text-sm">
<v-clicks>
<div class="mb-3">
<p><strong>Octubre 2022</strong>: Nace LangChain en <strong>Python</strong> 🐍</p>
<p class="text-xs opacity-80 ml-4">Creado por Harrison Chase • Enfoque inicial: encadenar prompts y LLMs</p>
</div>
<div class="mb-3">
<p><strong>Diciembre 2022</strong>: Lanzamiento de <strong>LangChain.js</strong> ⚡</p>
<p class="text-xs opacity-80 ml-4">Apenas 2 meses después • Port oficial • Para desarrolladores web</p>
</div>
<div class="mb-3">
<p><strong>2023</strong>: Explosión de adopción en ambos ecosistemas</p>
<p class="text-xs opacity-80 ml-4">Múltiples proveedores de LLMs • 110K+ stars en GitHub</p>
</div>
<div class="mb-3">
<p><strong>2024-2025</strong>: Maduración hacia producción</p>
<p class="text-xs opacity-80 ml-4"><strong>LangGraph</strong>: Control de bajo nivel • <strong>LangSmith</strong>: Observabilidad y testing</p>
</div>
</v-clicks>
</div>
+34
View File
@@ -0,0 +1,34 @@
---
layout: center
class: text-center
---
# Filosofía de LangChain
<div class="grid grid-cols-2 gap-4 mt-8">
<div v-click class="border border-main rounded p-4">
<div class="text-2xl mb-2">🔌</div>
<div class="font-bold">Flexibilidad</div>
<div class="text-sm opacity-80">Sin vendor lock-in</div>
</div>
<div v-click class="border border-main rounded p-4">
<div class="text-2xl mb-2">🔗</div>
<div class="font-bold">Integración</div>
<div class="text-sm opacity-80">LLMs + Datos externos</div>
</div>
<div v-click class="border border-main rounded p-4">
<div class="text-2xl mb-2">🤖</div>
<div class="font-bold">Agentes</div>
<div class="text-sm opacity-80">Decisiones autónomas</div>
</div>
<div v-click class="border border-main rounded p-4">
<div class="text-2xl mb-2">🏗️</div>
<div class="font-bold">Producción</div>
<div class="text-sm opacity-80">Del prototipo a la realidad</div>
</div>
</div>
+33
View File
@@ -0,0 +1,33 @@
---
layout: default
---
# Principios Fundamentales
<div class="grid grid-cols-1 gap-6 mt-8">
<div class="border-l-4 border-blue-500 pl-4">
<h3 class="text-xl font-bold">1. Flexibilidad de Modelos</h3>
<p class="opacity-80">
Estandarización de inputs/outputs entre proveedores de LLMs.
Cambia fácilmente entre OpenAI, Anthropic, Google, etc.
</p>
</div>
<div class="border-l-4 border-green-500 pl-4">
<h3 class="text-xl font-bold">2. Orquestación Compleja</h3>
<p class="opacity-80">
Los modelos coordinan flujos de trabajo con datos externos y herramientas.
Más allá de la simple generación de texto.
</p>
</div>
<div class="border-l-4 border-purple-500 pl-4">
<h3 class="text-xl font-bold">3. Fiabilidad en Producción</h3>
<p class="opacity-80">
Observabilidad, testing y debugging para aplicaciones reales.
El prototipo es fácil, producción es el reto.
</p>
</div>
</div>
+38
View File
@@ -0,0 +1,38 @@
---
layout: default
---
# Creencias Fundamentales
<div class="text-sm">
<v-clicks>
<div class="mb-4">
<h3 class="text-lg">🚀 Los LLMs son tecnología poderosa</h3>
<p class="opacity-80">Una innovación que vale la pena construir sobre ella</p>
</div>
<div class="mb-4">
<h3 class="text-lg">🔗 Los LLMs son mejores con datos externos</h3>
<p class="opacity-80">Combinar LLMs con fuentes de datos externas potencia sus capacidades</p>
</div>
<div class="mb-4">
<h3 class="text-lg">🤖 El futuro es agéntico</h3>
<p class="opacity-80">Las aplicaciones exhibirán capacidades autónomas y de toma de decisiones</p>
</div>
<div class="mb-4">
<h3 class="text-lg">🌱 Estamos en una etapa temprana</h3>
<p class="opacity-80">El campo está en constante evolución con espacio sustancial para crecer</p>
</div>
<div class="mb-4">
<h3 class="text-lg">💪 Producción es difícil</h3>
<p class="opacity-80">Prototipar es fácil, lograr fiabilidad en producción es el verdadero desafío</p>
</div>
</v-clicks>
</div>
+31
View File
@@ -0,0 +1,31 @@
---
layout: center
class: text-center
---
# Ecosistema LangChain
<div class="grid grid-cols-3 gap-8 mt-12">
<div v-click>
<div class="text-4xl mb-4">⛓️</div>
<div class="font-bold text-xl">LangChain (v1)</div>
<div class="text-sm opacity-70 mt-2">Interfaz productiva para agentes</div>
<div class="text-sm opacity-70">createAgent + Middleware</div>
</div>
<div v-click>
<div class="text-4xl mb-4">🕸️</div>
<div class="font-bold text-xl">LangGraph</div>
<div class="text-sm opacity-70 mt-2">Motor de runtime confiable</div>
<div class="text-sm opacity-70">Persistencia, streaming, control granular</div>
</div>
<div v-click>
<div class="text-4xl mb-4">🔍</div>
<div class="font-bold text-xl">LangSmith</div>
<div class="text-sm opacity-70 mt-2">Observabilidad + Evaluación</div>
<div class="text-sm opacity-70">Tracing automático, debugging visual</div>
</div>
</div>
+42
View File
@@ -0,0 +1,42 @@
---
layout: default
---
# ¿Quién usa LangChain?
<div class="grid grid-cols-2 gap-6 mt-6">
<div>
## 🏢 Empresas en Producción
- **LinkedIn** - Agentes con LangGraph
- **Uber** - Sistemas agénticos
- **Replit** - Asistentes de código
- **Klarna** - Chatbots de atención
- **Snowflake** - Integración de datos
- **J.P. Morgan** - Aplicaciones financieras
- **BCG** - Consultoría con IA
</div>
<div>
## 📊 Números de Adopción
- **1,306** empresas verificadas
- **132K+** aplicaciones LLM construidas
- **130M+** descargas totales
- **51%** usando agentes en producción
- **78%** planean usar agentes pronto
### 💼 Casos de Uso Comunes
- Chat sobre documentos
- Atención al cliente
- Asistentes personalizados
- Análisis de datos
</div>
</div>
+52
View File
@@ -0,0 +1,52 @@
---
layout: default
---
# Modelo de Negocio de LangChain
<div class="grid grid-cols-2 gap-6 mt-4 text-sm">
<div>
## 🏢 La Empresa
- **Fundadores**: Harrison Chase y Ankush Gola
- **Fundación**: Octubre 2022
- **Sede**: San Francisco, CA
- **CEO**: Harrison Chase
- **Equipo**: ~136 empleados (2025)
### 💰 Financiación
- **$260M** levantados en total
- **$1.25B** de valoración (Oct 2025)
- **Inversores**: Sequoia, Benchmark, IVP, CapitalG
</div>
<div>
## 💼 Modelo de Negocio
**Freemium B2B**
- Framework open-source (gratis)
- Monetización vía LangSmith
**Revenue 2025**: $16M ARR
- Crecimiento: $8.5M → $16M en 1 año
- **1,000+** clientes empresariales
### 💎 LangSmith Pricing
- **Developer**: Gratis (5k traces/mes)
- **Plus**: $39/usuario/mes (10k traces)
- **Enterprise**: Personalizado + self-hosted
</div>
</div>
+27
View File
@@ -0,0 +1,27 @@
---
layout: two-cols
---
# LangChain.js
La implementación JavaScript/TypeScript del framework LangChain
::right::
<v-clicks>
## ¿Por qué LangChain.js?
- **Desarrollo web nativo**
- Frontend y backend con la misma tecnología
- **Ecosistema JavaScript**
- NPM, TypeScript, Node.js
- **Paridad con Python**
- Mismos conceptos y APIs
- **Comunidad activa**
- Mantenido oficialmente
</v-clicks>
+54
View File
@@ -0,0 +1,54 @@
---
layout: default
---
# LangChain.js: Entornos de Ejecución
<div class="grid grid-cols-2 gap-6 mt-6">
<div>
## 🖥️ Runtimes Soportados
<v-clicks>
- **Node.js** (20.x, 22.x, 24.x)
- ESM y CommonJS
- **Deno** - Runtime seguro
- **Bun** - Runtime ultra-rápido
- **Navegadores** - Client-side
</v-clicks>
</div>
<div>
## ☁️ Edge & Serverless
<v-clicks>
- **Cloudflare Workers**
- **Vercel Edge Functions**
- **Next.js** (Server, Edge, Browser)
- **Supabase Edge Functions**
</v-clicks>
<v-click>
### 💪 Ventaja Clave
**Una sola codebase** para frontend, backend, edge y serverless
</v-click>
</div>
</div>
+59
View File
@@ -0,0 +1,59 @@
---
layout: default
---
# Arquitectura de Componentes
<p class="text-sm opacity-80 -mt-2">Los componentes trabajan juntos para crear aplicaciones AI sofisticadas</p>
<div class="mt-4">
## 🧩 Seis Categorías Principales
<div class="grid grid-cols-3 gap-3 mt-4 text-sm">
<v-click>
<div class="border-l-4 border-blue-500 pl-3 py-1">
<h3 class="font-bold text-base">📝 Models</h3>
<p class="text-xs opacity-80">Chat, LLMs, embeddings</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-3 py-1">
<h3 class="font-bold text-base">🔧 Tools</h3>
<p class="text-xs opacity-80">APIs, búsquedas, DBs</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-purple-500 pl-3 py-1">
<h3 class="font-bold text-base">🤖 Agents</h3>
<p class="text-xs opacity-80">Orquestación y razonamiento</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-yellow-500 pl-3 py-1">
<h3 class="font-bold text-base">💾 Memory</h3>
<p class="text-xs opacity-80">Historia y estado</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-red-500 pl-3 py-1">
<h3 class="font-bold text-base">🔍 Retrievers</h3>
<p class="text-xs opacity-80">Búsqueda vectorial y web</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-orange-500 pl-3 py-1">
<h3 class="font-bold text-base">📄 Documents</h3>
<p class="text-xs opacity-80">Loaders, splitters</p>
</div>
</v-click>
</div>
</div>
+14
View File
@@ -0,0 +1,14 @@
---
layout: cover
class: text-center
---
# Módulo 6: LangSmith
Observabilidad, debugging y evaluación
<div class="pt-12">
<span class="text-xl opacity-80">
Llevando tu aplicación a producción
</span>
</div>
+44
View File
@@ -0,0 +1,44 @@
---
layout: default
---
# ¿Qué es LangSmith?
<div class="mt-10 text-sm">
<v-click>
<div class="mb-8">
**LangSmith**: Plataforma de observabilidad y testing para aplicaciones LLM
</div>
</v-click>
<div class="space-y-4 text-xs">
<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-sm font-bold mb-2">🔍 Observabilidad</h3>
<p>Ver cada paso del agente: prompts, respuestas, tools ejecutadas</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-3">
<h3 class="text-sm font-bold mb-2">🐛 Debugging</h3>
<p>Identificar errores, latencias y costos en producción</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-sm font-bold mb-2">✅ Evaluación</h3>
<p>Datasets de prueba y métricas de calidad</p>
</div>
</v-click>
</div>
</div>
+29
View File
@@ -0,0 +1,29 @@
---
layout: default
---
# ¿Por qué LangSmith?
<div class="mt-10 text-xs space-y-4">
<v-click>
<div class="border-l-4 border-red-500 pl-4 bg-red-50 dark:bg-red-900/20 p-3">
<h3 class="text-sm font-bold mb-2">❌ Sin LangSmith</h3>
<p>• No sabes qué prompts se enviaron exactamente</p>
<p>• Difícil reproducir errores</p>
<p>• Imposible saber el costo real por usuario</p>
<p>• Testing manual y tedioso</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-3">
<h3 class="text-sm font-bold mb-2">✅ Con LangSmith</h3>
<p>• Trazas completas de cada ejecución</p>
<p>• Replay de conversaciones problemáticas</p>
<p>• Dashboard de costos y latencias</p>
<p>• Datasets y evaluaciones automáticas</p>
</div>
</v-click>
</div>
+42
View File
@@ -0,0 +1,42 @@
---
layout: default
---
# Configuración de LangSmith
<div class="mt-8 text-sm">
<v-click>
**Paso 1:** Crear cuenta gratuita en [smith.langchain.com](https://smith.langchain.com)
</v-click>
<v-click>
**Paso 2:** Obtener API Key desde Settings → API Keys
</v-click>
<v-click>
**Paso 3:** Configurar variables de entorno
```bash
# .env
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_pt_...
LANGCHAIN_PROJECT=mi-proyecto
```
</v-click>
<v-click>
<div class="mt-6 text-xs opacity-80">
✨ Automático: LangChain detecta las variables y envía trazas a LangSmith
</div>
</v-click>
</div>
+33
View File
@@ -0,0 +1,33 @@
---
layout: default
---
# Ejemplo con LangSmith
<div class="text-xs mt-6">
```typescript
import { createAgent } from "langchain";
// Con las variables de entorno configuradas,
// las trazas se envían automáticamente a LangSmith
const agent = createAgent({
model: "openai:gpt-4.1-mini",
tools: [weatherTool],
});
const result = await agent.invoke({
messages: [{ role: "user", content: "¿Qué tiempo hace en Madrid?" }]
});
// ✅ Ve la traza completa en https://smith.langchain.com
// - Input del usuario
// - Decisión del LLM de usar la tool
// - Ejecución de la tool
// - Respuesta final
// - Tokens consumidos
// - Latencia de cada paso
```
</div>
+37
View File
@@ -0,0 +1,37 @@
---
layout: default
---
# Plan Gratuito
<div class="mt-10 text-sm">
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-4 mb-6">
<h3 class="text-base font-bold mb-3">🎁 Developer (Gratis)</h3>
<p class="text-xs mb-2">• 5,000 traces/mes</p>
<p class="text-xs mb-2">• Retención de 14 días</p>
<p class="text-xs mb-2">• 1 usuario</p>
<p class="text-xs">• Perfecto para desarrollo y testing</p>
</div>
</v-click>
<v-click>
<div class="text-xs opacity-70">
📚 Planes de pago desde $39/mes (Plus) para equipos y producción
</div>
</v-click>
<v-click>
<div class="mt-6 text-center text-sm">
[smith.langchain.com/pricing](https://smith.langchain.com/pricing)
</div>
</v-click>
</div>
+30
View File
@@ -0,0 +1,30 @@
---
layout: default
---
# Próximos Pasos
<div class="mt-10 text-sm space-y-5">
<v-click>
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-4">
<h3 class="text-base font-bold mb-2">🚀 En producción</h3>
<p class="text-xs">Activa LangSmith para monitorear tu aplicación en real-time</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-4">
<h3 class="text-base font-bold mb-2">📚 Explora datasets</h3>
<p class="text-xs">Crea casos de prueba y evalúa mejoras en tus prompts</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-4">
<h3 class="text-base font-bold mb-2">📖 Documentación</h3>
<p class="text-xs">[docs.smith.langchain.com](https://docs.smith.langchain.com)</p>
</div>
</v-click>
</div>
+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>
+14
View File
@@ -0,0 +1,14 @@
---
layout: cover
class: text-center
---
# Módulo 3: Modelos
Trabajando con LLMs y Chat Models en LangChain.js
<div class="pt-12">
<span class="text-xl opacity-80">
La base de cualquier aplicación con IA
</span>
</div>
+43
View File
@@ -0,0 +1,43 @@
---
layout: default
---
# Chat Models
<div class="mt-8">
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-4 mb-6">
<h3 class="text-lg font-bold mb-3">💬 La interfaz estándar en LangChain</h3>
<p class="text-sm mb-2">Todos los modelos en LangChain se usan como <strong>Chat Models</strong></p>
<p class="text-xs opacity-80 mb-2">📥 <strong>Entrada:</strong> Lista de mensajes (System, Human, AI)</p>
<p class="text-xs opacity-80 mb-2">📤 <strong>Salida:</strong> Mensaje estructurado (AIMessage)</p>
</div>
<div class="grid grid-cols-3 gap-4">
<div class="text-center p-3 rounded bg-yellow-50 dark:bg-yellow-900/20">
<p class="text-sm font-bold">Mistral</p>
<p class="text-xs opacity-80">Mistral Large, Small</p>
</div>
<div class="text-center p-3 rounded bg-orange-50 dark:bg-orange-900/20">
<p class="text-sm font-bold">Anthropic</p>
<p class="text-xs opacity-80">Claude Sonnet, Haiku</p>
</div>
<div class="text-center p-3 rounded bg-blue-50 dark:bg-blue-900/20">
<p class="text-sm font-bold">Google</p>
<p class="text-xs opacity-80">Gemini Pro, Flash</p>
</div>
</div>
<v-click>
<div class="mt-6 text-center text-sm border-t pt-4">
✅ Misma interfaz para todos → fácil cambiar de proveedor
</div>
</v-click>
</div>
+44
View File
@@ -0,0 +1,44 @@
---
layout: default
---
# ¿Qué es un Token?
<div class="mt-10 text-sm">
<v-click>
<div class="mb-8">
**Token** = Unidad básica de texto que procesa un LLM
No es exactamente una palabra, ni un carácter
</div>
</v-click>
<v-click>
<div class="grid grid-cols-2 gap-8 text-xs">
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-4">
<h3 class="text-sm font-bold mb-3">Ejemplos de Tokenización</h3>
<p class="mb-2"><code>"Hola mundo"</code> → <strong>2 tokens</strong></p>
<p class="mb-2"><code>"LangChain"</code> → <strong>2 tokens</strong> (Lang + Chain)</p>
<p class="mb-2"><code>"desarrollador"</code> → <strong>3 tokens</strong></p>
<p class="mb-2"><code>"🚀"</code> → <strong>1-2 tokens</strong></p>
</div>
<div class="border-l-4 border-orange-500 pl-4 bg-orange-50 dark:bg-orange-900/20 p-4">
<h3 class="text-sm font-bold mb-3">Regla General</h3>
<p class="mb-2">1 token ≈ <strong>4 caracteres</strong> en inglés</p>
<p class="mb-2">1 token ≈ <strong>¾ de palabra</strong> en inglés</p>
<p class="mb-2">100 tokens ≈ <strong>75 palabras</strong></p>
</div>
</div>
</v-click>
</div>
+41
View File
@@ -0,0 +1,41 @@
---
layout: default
---
# ¿Cómo se Cuentan los Tokens?
<div class="mt-4 text-sm">
<v-click>
<div class="mb-4">
Los tokens se cuentan en **entrada (input)** y **salida (output)** por separado
</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 mb-4 text-xs">
<h3 class="text-sm font-bold mb-2">💰 Costos</h3>
<p class="mb-2">Los LLMs cobran por tokens procesados</p>
<p class="mb-2">Output suele ser <strong>más caro</strong> que input (3-5x)</p>
<p class="mb-2">Ejemplo: GPT-4o → $2.50/1M tokens input, $10/1M tokens output</p>
<p>📊 <a href="https://raw.githubusercontent.com/BerriAI/litellm/refs/heads/main/model_prices_and_context_window.json" target="_blank">Precios actualizados por modelo (JSON)</a></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 text-xs">
<h3 class="text-sm font-bold mb-2">🔧 Herramienta para Contar Tokens</h3>
<p class="mb-2">OpenAI Tokenizer (funciona para la mayoría de modelos):</p>
<p><a href="https://platform.openai.com/tokenizer" target="_blank">platform.openai.com/tokenizer</a></p>
</div>
</v-click>
</div>
+25
View File
@@ -0,0 +1,25 @@
---
layout: default
---
# Parámetros Principales
<div class="mt-10 space-y-5 text-sm">
<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">🌡️ temperature</h3>
<p class="text-xs mb-1">Controla la aleatoriedad de las respuestas</p>
<p class="text-xs opacity-80">0.0 = Determinista | 1.0 = Creativo | 2.0 = Muy aleatorio</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">📏 maxTokens</h3>
<p class="text-xs mb-1">Límite máximo de tokens en la respuesta</p>
<p class="text-xs opacity-80">Ejemplo: 500 (aprox. 375 palabras)</p>
</div>
</v-click>
</div>
+31
View File
@@ -0,0 +1,31 @@
---
layout: default
---
# Parámetros Principales
<div class="mt-10 space-y-5 text-sm">
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-3">
<h3 class="text-base font-bold mb-2">🎯 topP</h3>
<p class="text-xs mb-1">Nucleus sampling (alternativa a temperature)</p>
<p class="text-xs opacity-80">0.1 = Conservador | 0.9 = Diverso</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">🔁 n</h3>
<p class="text-xs mb-1">Número de respuestas a generar</p>
<p class="text-xs opacity-80">Útil para comparar variaciones</p>
</div>
</v-click>
<v-click>
<div class="mt-4 text-xs opacity-70 italic text-center">
⚠️ Estos parámetros dependen de cada modelo y pueden no estar disponibles en todos los proveedores.
</div>
</v-click>
</div>
+34
View File
@@ -0,0 +1,34 @@
---
layout: default
---
# Ejemplo: Configurando Parámetros
<div class="text-sm mt-6">
```typescript
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-4.1-mini",
temperature: 0.7, // Balance entre creatividad y coherencia
maxTokens: 500, // Limitar longitud de respuesta
topP: 0.9, // Nucleus sampling
});
const response = await model.invoke(
"Explica qué es un agente en LangChain"
);
console.log(response.content);
```
<v-click>
<div class="mt-4 text-xs opacity-80 text-center">
💡 <strong>Tip:</strong> Usa <code>temperature: 0</code> para respuestas deterministas (útil en tests)
</div>
</v-click>
</div>
+42
View File
@@ -0,0 +1,42 @@
---
layout: default
---
# Streaming: Respuestas en Tiempo Real
<div class="mt-8">
<v-click>
<div class="text-sm mb-6">
**¿Por qué streaming?**
- ✅ Experiencia de usuario mejorada (como ChatGPT)
- ✅ Feedback inmediato (no esperar 10-20 segundos)
- ✅ Procesar mientras se genera
</div>
</v-click>
<v-click>
```typescript
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-4.1-mini",
streaming: true,
});
const stream = await model.stream("Explica qué es LangChain");
for await (const chunk of stream) {
console.log(chunk.content); // Imprime palabra por palabra
}
```
</v-click>
</div>
+45
View File
@@ -0,0 +1,45 @@
---
layout: default
---
# Batch: Procesamiento en Lote
<div class="mt-8">
<v-click>
<div class="text-sm mb-6">
**¿Cuándo usar batch?**
- ✅ Procesar múltiples inputs a la vez
- ✅ Optimización de costos (algunos proveedores ofrecen descuentos)
- ✅ Mejor throughput que llamadas individuales
</div>
</v-click>
<v-click>
```typescript
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({ model: "gpt-4.1-mini" });
const inputs = [
"¿Qué es un agente?",
"¿Qué es RAG?",
"¿Qué es LangSmith?"
];
const responses = await model.batch(inputs);
responses.forEach((response, i) => {
console.log(`Pregunta ${i + 1}:`, response.content);
});
```
</v-click>
</div>
+43
View File
@@ -0,0 +1,43 @@
---
layout: default
---
# Structured Output
<div class="text-sm mt-6">
<v-click>
<div class="mb-4">
**Problema:** Las respuestas de LLMs son texto plano, difíciles de procesar
**Solución:** Forzar al modelo a responder con JSON estructurado
</div>
</v-click>
<v-click>
```typescript
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
// Definir el esquema con Zod
const schema = z.object({
sentiment: z.enum(["positive", "negative", "neutral"]),
score: z.number().min(0).max(1),
keywords: z.array(z.string()),
});
const model = new ChatOpenAI({ model: "gpt-4.1-mini" })
.withStructuredOutput(schema);
const result = await model.invoke("Me encanta LangChain!");
// { sentiment: "positive", score: 0.95, keywords: ["encanta", "langchain"] }
```
</v-click>
</div>
+49
View File
@@ -0,0 +1,49 @@
---
layout: default
---
# Intercambiabilidad de Modelos
<div class="mt-10 text-sm">
<v-click>
<div class="mb-8">
**Ventaja clave de LangChain:** Cambiar de proveedor sin reescribir código
</div>
</v-click>
<div class="grid grid-cols-2 gap-8">
<v-click>
```typescript
// OpenAI
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-4.1-mini"
});
```
</v-click>
<v-click>
```typescript
// Anthropic Claude
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
model: "claude-sonnet-4-6"
});
```
</v-click>
</div>
</div>
+47
View File
@@ -0,0 +1,47 @@
---
layout: default
---
# Intercambiabilidad de Modelos
<div class="mt-10 text-sm">
<div class="grid grid-cols-2 gap-8">
<v-click>
```typescript
// Google Gemini
import { ChatGoogle } from "@langchain/google";
const model = new ChatGoogle({
model: "gemini-2.5-flash"
});
```
</v-click>
<v-click>
```typescript
// Ollama (Local)
import { ChatOllama } from "@langchain/ollama";
const model = new ChatOllama({
model: "llama3.2"
});
```
</v-click>
</div>
<v-click>
<div class="mt-8 text-center text-sm opacity-80">
⚡ Todos usan la misma interfaz: <code>.invoke()</code>, <code>.stream()</code>, <code>.batch()</code>
</div>
</v-click>
</div>
+51
View File
@@ -0,0 +1,51 @@
---
layout: default
---
# initChatModel: Configuración Universal
<div class="mt-8 text-sm">
<v-click>
<div class="mb-6">
**Forma simplificada** de inicializar modelos sin imports específicos
</div>
</v-click>
<v-click>
```typescript
import { initChatModel } from "langchain";
// En lugar de importar ChatOpenAI, ChatAnthropic, etc.
const model = await initChatModel("gpt-4.1-mini", {
modelProvider: "openai",
temperature: 0.7,
});
const response = await model.invoke("Hola!");
```
</v-click>
<v-click>
<div class="mt-6 text-xs opacity-80">
✅ Ventaja: Cambiar de proveedor modificando solo el string
</div>
</v-click>
<v-click>
<div class="mt-4 p-3 bg-amber-500/10 border border-amber-500/30 rounded text-xs">
⚠️ <strong>No es magia:</strong> aunque no veas el <code>import</code>, el paquete del proveedor (<code>@langchain/openai</code>, <code>@langchain/mistralai</code>, etc.) <strong>debe estar instalado</strong> en tu proyecto. <code>initChatModel</code> lo resuelve internamente (<em>under the hood</em>).
</div>
</v-click>
</div>
+100
View File
@@ -0,0 +1,100 @@
---
layout: default
---
# Providers Disponibles
<div class="text-xs mt-8">
<div class="grid grid-cols-2 gap-6">
<div>
<v-click>
**OpenAI**
```typescript
modelProvider: "openai"
// gpt-4.1, gpt-4.1-mini, gpt-5.2
```
</v-click>
<v-click>
**Anthropic**
```typescript
modelProvider: "anthropic"
// claude-sonnet-4-6, claude-opus-4-6
```
</v-click>
<v-click>
**Google**
```typescript
modelProvider: "google"
// gemini-2.5-flash, gemini-2.5-flash-lite
```
</v-click>
<v-click>
**Azure OpenAI**
```typescript
modelProvider: "azure_openai"
```
</v-click>
</div>
<div>
<v-click>
**Mistral**
```typescript
modelProvider: "mistral"
// mistral-large, mistral-small
```
</v-click>
<v-click>
**Groq**
```typescript
modelProvider: "groq"
// llama-3.3-70b, mixtral-8x7b
```
</v-click>
<v-click>
**Ollama**
```typescript
modelProvider: "ollama"
// llama3.2:7b, mistral:7b
```
</v-click>
<v-click>
**Cohere**
```typescript
modelProvider: "cohere"
// command-r, command-r-plus
```
</v-click>
</div>
</div>
</div>
+78
View File
@@ -0,0 +1,78 @@
---
layout: default
---
# Más Providers
<div class="text-xs mt-8">
<div class="grid grid-cols-2 gap-6">
<div>
<v-click>
**Fireworks**
```typescript
modelProvider: "fireworks"
```
</v-click>
<v-click>
**Together AI**
```typescript
modelProvider: "together_ai"
```
</v-click>
<v-click>
**Bedrock (AWS)**
```typescript
modelProvider: "bedrock"
```
</v-click>
</div>
<div>
<v-click>
**Vertex AI (Google Cloud)**
```typescript
modelProvider: "google-vertexai"
```
</v-click>
<v-click>
**Cloudflare**
```typescript
modelProvider: "cloudflare"
```
</v-click>
</div>
</div>
<v-click>
<div class="mt-8 text-center text-sm">
📚 Lista completa de providers
[docs.langchain.com/integrations/chat](https://docs.langchain.com/oss/javascript/integrations/chat)
</div>
</v-click>
</div>
+44
View File
@@ -0,0 +1,44 @@
---
layout: default
---
# Binding Tools al Modelo
<div class="text-sm mt-8">
<v-click>
<div class="mb-6">
Puedes vincular tools directamente al modelo con `.bindTools()`
</div>
</v-click>
<v-click>
```typescript
import { ChatOpenAI } from "@langchain/openai";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const weatherTool = tool(
async ({ location }) => `El tiempo en ${location} es soleado`,
{
name: "get_weather",
description: "Obtiene el tiempo de una ubicación",
schema: z.object({ location: z.string() }),
}
);
const model = new ChatOpenAI({ model: "gpt-4.1-mini" });
const modelWithTools = model.bindTools([weatherTool]);
const response = await modelWithTools.invoke("¿Qué tiempo hace en Madrid?");
console.log(response.tool_calls); // Tool que el LLM decidió usar
```
</v-click>
</div>
+75
View File
@@ -0,0 +1,75 @@
---
layout: default
---
# Tools Integradas en LangChain.js
<div class="text-sm mt-6">
<v-click>
LangChain.js incluye numerosas **herramientas pre-construidas** listas para usar con agentes
</v-click>
<div class="grid grid-cols-2 gap-4 mt-6 text-xs">
<div>
<v-click>
**Busqueda Web**
- `TavilySearchResults` - Busqueda optimizada para LLMs
- `DuckDuckGoSearch` - Busqueda gratuita
- `SerpAPI` / `SearchApi` - Google Search
- `ExaSearchResults` - Busqueda semantica
</v-click>
<v-click>
**Conocimiento**
- `WikipediaQueryRun` - Consultas a Wikipedia
- `WolframAlphaTool` - Calculos y datos
- `GoogleScholar` - Articulos academicos
</v-click>
</div>
<div>
<v-click>
**Productividad**
- `GmailTools` - Leer/enviar emails
- `GoogleCalendarTools` - Gestionar eventos
- `DiscordTool` - Integracion Discord
</v-click>
<v-click>
**Desarrollo**
- `StackExchangeTool` - Q&A tecnico
- `PythonInterpreter` - Ejecutar codigo
- `WebBrowserTool` - Navegar paginas
</v-click>
</div>
</div>
<v-click>
<div class="mt-4 text-xs text-center opacity-70">
Ver listado completo: [docs.langchain.com/integrations/tools](https://docs.langchain.com/oss/javascript/integrations/tools)
</div>
</v-click>
</div>
+50
View File
@@ -0,0 +1,50 @@
---
layout: default
---
# Usando Tools Integradas
<div class="text-sm mt-6">
<v-click>
```typescript
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
import { WikipediaQueryRun } from "@langchain/community/tools/wikipedia_query_run";
import { Calculator } from "@langchain/community/tools/calculator";
// Crear instancias de las tools
const tavilySearch = new TavilySearchResults({
apiKey: process.env.TAVILY_API_KEY,
maxResults: 3,
});
const wikipedia = new WikipediaQueryRun({
topKResults: 2,
maxDocContentLength: 4000,
});
const calculator = new Calculator();
// Usar con un agente
const tools = [tavilySearch, wikipedia, calculator];
```
</v-click>
<v-click>
<div class="mt-4 text-xs bg-yellow-50 dark:bg-yellow-900/20 p-3 rounded">
**Paquete:** La mayoria de tools integradas estan en `@langchain/community`
```bash
npm install @langchain/community
```
</div>
</v-click>
</div>
+41
View File
@@ -0,0 +1,41 @@
---
layout: default
---
# Ejemplo: Agente con Tavily Search
<div class="text-xs mt-2">
```typescript
import { createAgent } from "langchain";
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
const searchTool = new TavilySearchResults({ apiKey: process.env.TAVILY_API_KEY, maxResults: 5 });
const agent = createAgent({
model: "openai:gpt-4.1-mini",
tools: [searchTool],
});
const result = await agent.invoke({
messages: [{ role: "user", content: "¿Cuales son las ultimas noticias sobre IA?" }],
});
```
<div class="mt-2 grid grid-cols-2 gap-3">
<div class="bg-blue-50 dark:bg-blue-900/20 p-2 rounded">
**Tavily** - Optimizado para LLMs: extrae contenido relevante, filtra anuncios/ruido, API key gratuita limitada
</div>
<div class="bg-green-50 dark:bg-green-900/20 p-2 rounded">
**Docs**: [langchain.com/integrations/tools](https://docs.langchain.com/oss/javascript/integrations/tools)
</div>
</div>
</div>
+43
View File
@@ -0,0 +1,43 @@
---
layout: default
---
# Diferencia: bindTools vs createAgent
<div class="mt-10 text-xs">
<div class="grid grid-cols-2 gap-6">
<v-click>
<div class="border-l-4 border-blue-500 pl-4 bg-blue-50 dark:bg-blue-900/20 p-4">
<h3 class="text-sm font-bold mb-3">🔧 .bindTools()</h3>
<p class="mb-2">• El LLM decide si usar la tool</p>
<p class="mb-2">• Devuelve <code>tool_calls</code></p>
<p class="mb-2">• Tú ejecutas la tool manualmente</p>
<p class="mb-2">• Control total del flujo</p>
<p class="text-xs opacity-70 mt-3">Ideal para flujos personalizados</p>
</div>
</v-click>
<v-click>
<div class="border-l-4 border-green-500 pl-4 bg-green-50 dark:bg-green-900/20 p-4">
<h3 class="text-sm font-bold mb-3">🤖 createAgent() <span class="text-xs opacity-60">(LangChain v1)</span></h3>
<p class="mb-2">• El agente decide y ejecuta</p>
<p class="mb-2">• Loop automático</p>
<p class="mb-2">• Ejecuta tools automáticamente</p>
<p class="mb-2">• Estado persistente incluido</p>
<p class="text-xs opacity-70 mt-3">Ideal para agentes autónomos</p>
</div>
</v-click>
</div>
<v-click>
<div class="mt-6 text-center text-xs opacity-70">
💡 Usa <code>bindTools()</code> para control, <code>createAgent()</code> (LangChain v1) para simplicidad
</div>
</v-click>
</div>
+14
View File
@@ -0,0 +1,14 @@
---
layout: cover
class: text-center
---
# Temas Pendientes
Lo que nos dejamos en el tintero
<div class="pt-12">
<span class="text-xl opacity-80">
Hay mucho más por explorar en el ecosistema LangChain...
</span>
</div>
+22
View File
@@ -0,0 +1,22 @@
---
layout: default
---
# Sistemas Multi-Agente (Subagentes)
<v-clicks>
### Patrones principales en LangChain/LangGraph
| Patrón | Descripción |
|--------|-------------|
| **Subagents** | Un agente supervisor coordina subagentes como tools |
| **Handoffs** | El comportamiento cambia dinámicamente según el estado |
| **Skills** | Prompts y conocimiento especializado cargado bajo demanda |
| **Router** | Clasifica input y lo dirige a agentes especializados |
| **Custom Workflow** | Flujos con LangGraph mezclando lógica determinista y agéntica |
[Docs: Multi-agent](https://docs.langchain.com/oss/javascript/langchain/multi-agent/index)
</v-clicks>
+37
View File
@@ -0,0 +1,37 @@
---
layout: default
---
# Deep Agents
<v-clicks>
### Librería standalone para agentes complejos
Inspirada en Claude Code, Deep Research y Manus.
### Características principales
- **Planificación**: Capacidad de planificar tareas multi-paso
- **File systems**: Sistema de archivos virtual para gestión de contexto
- **Subagentes**: Spawn de agentes especializados para subtareas
- **Long-term memory**: Integración con almacenamiento persistente
### Ejemplo básico
```typescript
import { createDeepAgent } from "@langchain/deepagents";
const agent = createDeepAgent({
model: "gpt-4.1",
filesystem: true,
planning: true,
});
await agent.invoke("Research and write a report about AI trends");
```
[Docs: Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview)
</v-clicks>
+32
View File
@@ -0,0 +1,32 @@
---
layout: default
---
# Long-term Memory con Semantic Search
<v-clicks>
### InMemoryStore con embeddings
```typescript
import { InMemoryStore } from "@langchain/langgraph";
import { OpenAIEmbeddings } from "@langchain/openai";
const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const store = new InMemoryStore({
index: { embeddings, dims: 1536 }
});
// Guardar memorias
await store.put(["user_123", "memories"], "1", { text: "I love pizza" });
// Buscar por similitud semántica
const items = await store.search(
["user_123", "memories"],
{ query: "I'm hungry", limit: 2 }
);
```
</v-clicks>
+30
View File
@@ -0,0 +1,30 @@
---
layout: default
---
# Integración MCP (Model Context Protocol)
<v-clicks>
### MCP en LangChain.js
Protocolo abierto que estandariza cómo las aplicaciones proporcionan tools y contexto a LLMs.
```typescript
import { ChatOpenAI, tools } from "@langchain/openai";
const model = new ChatOpenAI({ model: "gpt-4.1" });
const response = await model.invoke("Roll 2d4+1", {
tools: [
tools.mcp({
serverLabel: "dmcp",
serverDescription: "A D&D MCP server for dice rolling",
serverUrl: "https://dmcp-server.deno.dev/sse",
requireApproval: "never",
}),
],
});
```
</v-clicks>
+38
View File
@@ -0,0 +1,38 @@
---
layout: default
---
# Context Engineering
<v-clicks>
### Inyección de dependencias en runtime
```typescript
const contextSchema = z.object({
userId: z.string(),
apiKey: z.string(),
});
const fetchUserData = tool(
async ({ query }, runtime: ToolRuntime<any, typeof contextSchema>) => {
const { userId, apiKey } = runtime.context;
return await performQuery(query, apiKey, userId);
},
{ name: "fetch_user_data", schema: z.object({ query: z.string() }) }
);
const agent = createAgent({
model: "gpt-4.1",
tools: [fetchUserData],
contextSchema
});
// Cada usuario tiene su propio contexto
await agent.invoke(messages, {
context: { userId: "user_123", apiKey: "sk-..." }
});
```
</v-clicks>
+26
View File
@@ -0,0 +1,26 @@
---
layout: default
---
# Tipos de Contexto en LangGraph
<v-clicks>
### Tres dimensiones de contexto
| Tipo | Mutabilidad | Alcance | Uso |
|------|-------------|---------|-----|
| **Static (config)** | Inmutable | Single run | user ID, API keys, DB connections |
| **Dynamic (state)** | Mutable | Single run | historial, resultados intermedios |
| **Store** | Mutable | Cross-conversation | memorias persistentes, preferencias |
### Casos de uso
- **Autenticación por usuario**: Inyectar API keys específicas por tenant
- **Permisos dinámicos**: Ajustar herramientas disponibles según rol
- **Personalización**: Cargar preferencias del usuario desde el store
- **Multi-tenancy**: Aislar datos entre organizaciones
[Docs: Context Engineering](https://docs.langchain.com/oss/javascript/langchain/context-engineering)
</v-clicks>
+32
View File
@@ -0,0 +1,32 @@
---
layout: default
---
# Testing de Aplicaciones LLM
<v-clicks>
### Dos enfoques complementarios
**Unit tests**: Componentes aislados con mocks, validaciones rápidas y predecibles.
**Integration tests**: Llamadas reales para confirmar que todo funciona junto.
### AgentEvals
```typescript
import { createTrajectoryMatchEvaluator } from "agentevals";
// Trajectory Match: compara contra trayectoria de referencia
const evaluator = createTrajectoryMatchEvaluator({ matchMode: "subset" });
// LLM-as-Judge: validación cualitativa con un modelo
const llmEvaluator = createLLMJudgeEvaluator({ model: "gpt-4.1" });
```
### Integración con LangSmith
Configura `LANGSMITH_API_KEY` y `LANGSMITH_TRACING` para registrar experimentos automáticamente con Vitest/Jest.
[Docs: Testing](https://docs.langchain.com/oss/javascript/langchain/test)
</v-clicks>
+27
View File
@@ -0,0 +1,27 @@
---
layout: default
---
# Recursos para continuar aprendiendo
<v-clicks>
### Documentación oficial
- **LangChain.js Docs**: [docs.langchain.com](https://docs.langchain.com/oss/javascript)
- **LangGraph.js**: [docs.langchain.com/langgraph](https://docs.langchain.com/langgraph)
- **LangSmith**: [docs.smith.langchain.com](https://docs.smith.langchain.com)
### Cursos y tutoriales
- **LangChain Academy**: Cursos oficiales gratuitos
- **DeepLearning.AI**: Cursos sobre LLMs y LangChain
- **YouTube**: Canal oficial de LangChain
### Comunidad
- **Discord**: Comunidad activa de LangChain
- **GitHub Discussions**: Preguntas y respuestas
- **Twitter/X**: @LangChainAI para novedades
### Chat de LangChain
- **Chat**: [chat.langchain.com](https://chat.langchain.com) - Asistente IA entrenado con la documentación oficial
</v-clicks>
+14
View File
@@ -0,0 +1,14 @@
---
layout: cover
class: text-center
---
# Módulo 7: RAG
Retrieval Augmented Generation
<div class="pt-12">
<span class="text-xl opacity-80">
Extendiendo el conocimiento de los LLMs con tus datos
</span>
</div>
+25
View File
@@ -0,0 +1,25 @@
---
layout: default
---
# ¿Qué es RAG?
<v-clicks>
**Retrieval Augmented Generation** combina búsqueda de información con generación de texto
- **Problema**: Los LLMs tienen conocimiento limitado
- Datos de entrenamiento hasta cierta fecha
- No conocen información específica de tu empresa
- No pueden acceder a bases de datos en tiempo real
- **Solución RAG**:
- Buscar información relevante en tus documentos
- Proporcionar ese contexto al LLM
- Generar respuestas basadas en tus datos
<div class="mt-8 p-4 bg-blue-500/10 rounded">
💡 <b>En resumen</b>: Dale al LLM la información que necesita para responder correctamente
</div>
</v-clicks>
+28
View File
@@ -0,0 +1,28 @@
---
layout: default
---
# Flujo típico de RAG
<div class="mt-8">
```mermaid
graph LR
A[Pregunta del usuario] --> B[Convertir a embedding]
B --> C[Buscar en BD vectorial]
C --> D[Recuperar documentos relevantes]
D --> E[Construir prompt con contexto]
E --> F[LLM genera respuesta]
F --> G[Respuesta al usuario]
```
</div>
<v-clicks>
### Dos fases principales
1. **Indexación** (una vez): Convertir documentos a embeddings y almacenarlos
2. **Recuperación** (cada consulta): Buscar documentos relevantes y generar respuesta
</v-clicks>

Some files were not shown because too many files have changed in this diff Show More