initial commit: slides ready + upgraded
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Slides LangChain.js
|
||||||
|
|
||||||
|
Presentación sobre LangChain.js - Desarrollo de aplicaciones con LLMs.
|
||||||
|
|
||||||
|
## Ver online
|
||||||
|
|
||||||
|
https://jabiinfante.github.io/slides-langchain.js/
|
||||||
|
|
||||||
|
## Desarrollo local
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run deploy
|
||||||
|
```
|
||||||
@@ -0,0 +1,371 @@
|
|||||||
|
# Cambios necesarios para actualizar el curso LangChain.js
|
||||||
|
|
||||||
|
> Fecha de revision: 2026-05-22
|
||||||
|
> Las slides fueron preparadas para Enero 2026 (v0.3.x). Desde entonces se ha lanzado **LangChain v1** y **LangGraph v1**, que traen cambios significativos.
|
||||||
|
> **Todos los cambios críticos e importantes han sido aplicados.** El documento se conserva como referencia histórica.
|
||||||
|
|
||||||
|
## Versiones actuales en npm (mayo 2026)
|
||||||
|
|
||||||
|
| Paquete | Slides | Actual | Cambio |
|
||||||
|
|---------|--------|--------|--------|
|
||||||
|
| `langchain` | v0.3.x | **v1.2.35** | MAJOR |
|
||||||
|
| `@langchain/core` | v0.3.x | **v1.1.34** | MAJOR |
|
||||||
|
| `@langchain/openai` | - | **v1.3.0** | MAJOR |
|
||||||
|
| `@langchain/anthropic` | - | **v1.3.25** | MAJOR |
|
||||||
|
| `@langchain/google-genai` | en uso | **v2.1.26** (DEPRECATED) | Ver punto 3 |
|
||||||
|
| `@langchain/google` | no mencionado | **v0.1.7** (NUEVO, reemplaza google-genai) | NUEVO |
|
||||||
|
| `@langchain/community` | en uso | **v1.1.24** | MAJOR |
|
||||||
|
| `@langchain/langgraph` | en uso | **v1.2.3** | MAJOR |
|
||||||
|
| `@langchain/classic` | no existe en slides | **v1.0.24** (NUEVO) | NUEVO |
|
||||||
|
| `@langchain/qdrant` | en uso | **v1.0.1** | MAJOR |
|
||||||
|
| `@langchain/pinecone` | - | **v1.0.1** | MAJOR |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. CRITICO: Versiones en slides/setup/03.md
|
||||||
|
|
||||||
|
**Fichero**: `pages/setup/03.md:52`
|
||||||
|
**Problema**: Dice `Versiones actuales (Enero 2026): langchain v0.3.x · @langchain/core v0.3.x`
|
||||||
|
**Correccion**: Cambiar a `Versiones actuales (Marzo 2026): langchain v1.x · @langchain/core v1.x`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. CRITICO: Nuevo paquete @langchain/classic
|
||||||
|
|
||||||
|
**Ficheros afectados**: `pages/setup/02.md`
|
||||||
|
**Problema**: La arquitectura de paquetes no menciona `@langchain/classic`, que es donde se ha movido la funcionalidad legacy en v1.
|
||||||
|
**Que se movio a @langchain/classic**:
|
||||||
|
- `MemoryVectorStore` (antes en `langchain/vectorstores/memory`)
|
||||||
|
- `DirectoryLoader` (antes en `langchain/document_loaders/fs/directory`)
|
||||||
|
- `TextLoader` (antes en `langchain/document_loaders/fs/text`)
|
||||||
|
- Legacy chains (`LLMChain`, `ConversationChain`, etc.)
|
||||||
|
- Retrievers legacy
|
||||||
|
- Hub module
|
||||||
|
- `ChatPromptTemplate` ahora se importa desde `@langchain/classic/prompts` en los ejemplos de proveedores (aunque sigue disponible en `@langchain/core/prompts`)
|
||||||
|
|
||||||
|
**Accion**: Anadir `@langchain/classic` al diagrama de arquitectura de paquetes en `setup/02.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. CRITICO: @langchain/google-genai DEPRECATED
|
||||||
|
|
||||||
|
**Ficheros afectados**:
|
||||||
|
- `pages/setup/02.md:54` - lista de proveedores
|
||||||
|
- `pages/setup/03.md:31` - instalacion
|
||||||
|
- `pages/setup/13.md` - ejemplo completo con Gemini
|
||||||
|
- `pages/models/08b.md` - ChatGoogleGenerativeAI
|
||||||
|
- `pages/models/10.md:38` - providers disponibles
|
||||||
|
- `pages/rag/06.md:22` - GoogleGenerativeAIEmbeddings
|
||||||
|
- `pages/rag/07.md` - no afectado directamente
|
||||||
|
|
||||||
|
**Problema**: La documentacion oficial dice textualmente:
|
||||||
|
> "This library is based on a deprecated library from Google and will be replaced by the ChatGoogle library. New implementations should use the ChatGoogle library instead."
|
||||||
|
|
||||||
|
**Correccion**:
|
||||||
|
```typescript
|
||||||
|
// ANTES (deprecated)
|
||||||
|
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
||||||
|
const model = new ChatGoogleGenerativeAI({ model: "gemini-2.0-flash-exp" });
|
||||||
|
|
||||||
|
// AHORA (recomendado)
|
||||||
|
import { ChatGoogle } from "@langchain/google";
|
||||||
|
const model = new ChatGoogle({ model: "gemini-2.5-flash" });
|
||||||
|
```
|
||||||
|
|
||||||
|
**Instalacion**: `npm install @langchain/google` en lugar de `npm install @langchain/google-genai`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. CRITICO: createReactAgent -> createAgent
|
||||||
|
|
||||||
|
**Ficheros afectados**:
|
||||||
|
- `pages/models/15.md` - ejemplo con Tavily usa `createReactAgent` de `@langchain/langgraph/prebuilt`
|
||||||
|
- `pages/models/16.md` - comparacion bindTools vs createReactAgent
|
||||||
|
|
||||||
|
**Problema**: `createReactAgent` de `@langchain/langgraph/prebuilt` ha sido reemplazado por `createAgent` de `langchain` en v1.
|
||||||
|
|
||||||
|
**Correccion para models/15.md**:
|
||||||
|
```typescript
|
||||||
|
// ANTES
|
||||||
|
import { ChatOpenAI } from "@langchain/openai";
|
||||||
|
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
|
||||||
|
import { createReactAgent } from "@langchain/langgraph/prebuilt";
|
||||||
|
|
||||||
|
const model = new ChatOpenAI({ model: "gpt-4o-mini" });
|
||||||
|
const agent = createReactAgent({ llm: model, tools: [searchTool] });
|
||||||
|
|
||||||
|
// AHORA
|
||||||
|
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],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Correccion para models/16.md**: Cambiar el titulo y contenido del panel derecho de `createReactAgent()` a `createAgent()`. La comparacion sigue siendo valida conceptualmente (bindTools para control manual vs createAgent para loop automatico).
|
||||||
|
|
||||||
|
> NOTA: La seccion de agentes (pages/agents/) ya usa `createAgent` correctamente. Solo models/15.md y models/16.md estan desactualizados.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. IMPORTANTE: Nombres de modelos desactualizados
|
||||||
|
|
||||||
|
### OpenAI
|
||||||
|
**Ficheros**: Multiples (models/, messages/, rag/, setup/, agents/)
|
||||||
|
- `gpt-4o-mini` -> `gpt-4.1-mini` (segun docs actuales de LangChain)
|
||||||
|
- `gpt-4o` -> `gpt-4.1` (segun docs actuales de LangChain)
|
||||||
|
- `gpt-4-turbo` en `models/10.md:18` -> `gpt-4.1` o posterior
|
||||||
|
|
||||||
|
**Nota**: Los modelos `gpt-4o` y `gpt-4o-mini` siguen funcionando pero ya no son los mas recientes. La documentacion oficial de LangChain ahora muestra `gpt-4.1-mini` y `gpt-5.2` como ejemplos.
|
||||||
|
|
||||||
|
### Anthropic
|
||||||
|
- `claude-sonnet-4-20250514` en `models/08.md:41` -> `claude-sonnet-4-6` (ultimo segun docs)
|
||||||
|
- `claude-sonnet-4-5-20250929` en `agents/05.md:17` -> mantener o actualizar a `claude-sonnet-4-6`
|
||||||
|
|
||||||
|
### Google Gemini
|
||||||
|
- `gemini-2.0-flash-exp` en `models/08b.md:19` -> `gemini-2.5-flash` (segun docs actuales)
|
||||||
|
- `gemini-pro` en `models/10.md:38` -> `gemini-2.5-flash-lite` (modelo recomendado actual)
|
||||||
|
- `gemini-2.5-flash` en `setup/13.md:16` -> OK, este esta correcto
|
||||||
|
|
||||||
|
### Embeddings
|
||||||
|
- `embedding-001` en `rag/06.md:25` -> verificar nombre actual del modelo de embeddings de Google
|
||||||
|
- `llama2` en `rag/07.md:32` (OllamaEmbeddings) -> `llama3.2` o modelo mas reciente
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. IMPORTANTE: MemoryVectorStore - import path cambiado
|
||||||
|
|
||||||
|
**Fichero**: `pages/rag/11.md:12`
|
||||||
|
**Problema**:
|
||||||
|
```typescript
|
||||||
|
// ANTES (v0.3.x)
|
||||||
|
import { MemoryVectorStore } from "langchain/vectorstores/memory";
|
||||||
|
|
||||||
|
// AHORA (v1.x)
|
||||||
|
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota**: En v1, `MemoryVectorStore` se ha movido a `@langchain/classic`. Requiere instalar: `npm install @langchain/classic`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. IMPORTANTE: initChatModel - import path cambiado
|
||||||
|
|
||||||
|
**Fichero**: `pages/models/09.md:22`
|
||||||
|
**Problema**:
|
||||||
|
```typescript
|
||||||
|
// ANTES (v0.3.x)
|
||||||
|
import { initChatModel } from "@langchain/core/chat_models/universal";
|
||||||
|
|
||||||
|
// AHORA (v1.x)
|
||||||
|
import { initChatModel } from "langchain";
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. IMPORTANTE: Document Loaders - import paths cambiados
|
||||||
|
|
||||||
|
**Fichero**: `pages/pending/06c.md`
|
||||||
|
**Problema**: Los loaders que estaban en `langchain/` se han movido a `@langchain/classic/`:
|
||||||
|
```typescript
|
||||||
|
// ANTES
|
||||||
|
import { DirectoryLoader } from "langchain/document_loaders/fs/directory";
|
||||||
|
import { TextLoader } from "langchain/document_loaders/fs/text";
|
||||||
|
|
||||||
|
// AHORA
|
||||||
|
import { DirectoryLoader } from "@langchain/classic/document_loaders/fs/directory";
|
||||||
|
import { TextLoader } from "@langchain/classic/document_loaders/fs/text";
|
||||||
|
```
|
||||||
|
Los loaders de community (`PDFLoader`, `CSVLoader`) mantienen su path en `@langchain/community/...`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. IMPORTANTE: OllamaEmbeddings - import path
|
||||||
|
|
||||||
|
**Fichero**: `pages/rag/07.md:29`
|
||||||
|
**Problema**:
|
||||||
|
```typescript
|
||||||
|
// ANTES
|
||||||
|
import { OllamaEmbeddings } from "@langchain/community/embeddings/ollama";
|
||||||
|
|
||||||
|
// AHORA (paquete dedicado)
|
||||||
|
import { OllamaEmbeddings } from "@langchain/ollama";
|
||||||
|
```
|
||||||
|
Requiere: `npm install @langchain/ollama`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. MENOR: favicon en slides.md
|
||||||
|
|
||||||
|
**Fichero**: `slides.md:10`
|
||||||
|
**Problema**: `favicon: https://js.langchain.com/v0.2/img/favicon.ico` - URL con referencia a v0.2
|
||||||
|
**Correccion**: Actualizar a la URL actual de la documentacion: `https://docs.langchain.com/...` o usar favicon local
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. NUEVO CONCEPTO: Standard Content Blocks (v1)
|
||||||
|
|
||||||
|
**No existe en las slides actualmente.**
|
||||||
|
**Relevancia**: Es una de las 3 mejoras principales de LangChain v1.
|
||||||
|
|
||||||
|
`contentBlocks` es una nueva propiedad en los mensajes que proporciona acceso unificado a features modernos de LLMs (reasoning tokens, imagenes, etc.) de forma estandarizada entre proveedores:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { AIMessage } from "@langchain/core/messages";
|
||||||
|
|
||||||
|
// Los mensajes ahora tienen .contentBlocks para acceso tipado
|
||||||
|
const reasoning = message.contentBlocks
|
||||||
|
.filter((b) => b.type === "reasoning")
|
||||||
|
.map((b) => b.reasoning);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sugerencia**: Considerar anadir una slide en la seccion de mensajes (messages/) o en la seccion de agentes explicando este nuevo concepto.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. NUEVO CONCEPTO: @langchain/classic
|
||||||
|
|
||||||
|
**No explicado en las slides.**
|
||||||
|
En v1, la funcionalidad legacy se ha movido a `@langchain/classic`:
|
||||||
|
- Legacy chains (LLMChain, ConversationChain)
|
||||||
|
- Retrievers legacy
|
||||||
|
- Hub module
|
||||||
|
- MemoryVectorStore
|
||||||
|
- Algunos document loaders
|
||||||
|
|
||||||
|
**Sugerencia**: Mencionar en la seccion de estructura/setup que en v1 existe este paquete para compatibilidad hacia atras.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. MENOR: Modelos disponibles en providers (models/10.md)
|
||||||
|
|
||||||
|
**Fichero**: `pages/models/10.md`
|
||||||
|
Los comentarios de modelos disponibles estan desactualizados:
|
||||||
|
- OpenAI: `gpt-4o, gpt-4o-mini, gpt-4-turbo` -> `gpt-4.1, gpt-4.1-mini, gpt-5.2`
|
||||||
|
- Google: `gemini-2.0-flash-exp, gemini-pro` -> `gemini-2.5-flash, gemini-2.5-flash-lite`
|
||||||
|
- Anthropic: `claude-sonnet-4, claude-opus-4` -> `claude-sonnet-4-6, claude-opus-4-6`
|
||||||
|
- Groq: `llama-3.1-70b, mixtral-8x7b` -> verificar disponibilidad actual
|
||||||
|
- Ollama: `llama3.1:7b` -> `llama3.2:7b` o posterior
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. MENOR: Structured Output con createAgent (v1 mejora)
|
||||||
|
|
||||||
|
**Ficheros**: Los slides de structured output ya cubren `withStructuredOutput()` correctamente.
|
||||||
|
**Novedad v1**: En `createAgent`, structured output ahora se genera en el loop principal (sin llamada LLM adicional) via `responseFormat`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createAgent } from "langchain";
|
||||||
|
import * as z from "zod";
|
||||||
|
|
||||||
|
const agent = createAgent({
|
||||||
|
model: "gpt-4.1-mini",
|
||||||
|
tools: [getWeather],
|
||||||
|
responseFormat: z.object({
|
||||||
|
temperature: z.number(),
|
||||||
|
condition: z.string(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const result = await agent.invoke({ messages: [...] });
|
||||||
|
console.log(result.structuredResponse);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sugerencia**: Verificar si esto ya esta cubierto en las slides de agents/structured output.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. MENOR: URLs de documentacion desactualizadas
|
||||||
|
|
||||||
|
**Ficheros afectados**:
|
||||||
|
- `pages/models/11.md` - enlace `js.langchain.com/docs/integrations/chat`
|
||||||
|
- `pages/models/13.md` - enlace `js.langchain.com/docs/integrations/tools`
|
||||||
|
- `pages/rag/29.md` - enlace `js.langchain.com/docs/tutorials/rag`
|
||||||
|
- `pages/pending/09.md` - enlace `js.langchain.com/docs`
|
||||||
|
|
||||||
|
**Problema**: Las URLs antiguas `js.langchain.com/docs/...` han cambiado a `docs.langchain.com/oss/javascript/...`
|
||||||
|
**Correccion**:
|
||||||
|
- `js.langchain.com/docs/integrations/chat` -> `docs.langchain.com/oss/javascript/integrations/chat`
|
||||||
|
- `js.langchain.com/docs/integrations/tools` -> `docs.langchain.com/oss/javascript/integrations/tools`
|
||||||
|
- `js.langchain.com/docs/tutorials/rag` -> `docs.langchain.com/oss/javascript/langchain/rag`
|
||||||
|
- `js.langchain.com/docs` -> `docs.langchain.com/oss/javascript`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. MENOR: Precios y modelos en setup/04.md
|
||||||
|
|
||||||
|
**Fichero**: `pages/setup/04.md`
|
||||||
|
**Problema**: La tabla de comparativa dice "Enero 2025" y lista modelos desactualizados:
|
||||||
|
- "GPT-4o" -> "GPT-4.1" (o posterior)
|
||||||
|
- "Gemini 2.0 Flash" -> "Gemini 2.5 Flash"
|
||||||
|
- "Claude 4 Sonnet" -> modelo actual
|
||||||
|
- Precios probablemente han cambiado
|
||||||
|
|
||||||
|
**Accion**: Actualizar la tabla con modelos y precios actuales (marzo 2026)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 17. MENOR: setup/07.md modelos recomendados para produccion
|
||||||
|
|
||||||
|
**Fichero**: `pages/setup/07.md`
|
||||||
|
**Problema**: Recomienda "Claude 4 Sonnet o GPT-4o" para produccion. Los nombres de modelo deberian reflejar los ultimos disponibles.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 18. MENOR: Modelos Ollama en setup/09.md
|
||||||
|
|
||||||
|
**Fichero**: `pages/setup/09.md`
|
||||||
|
**Problema**: Referencia a "Llama 3.1 7B/13B/70B" en la tabla de hardware. Llama 3.2 ya esta disponible y setup/14.md ya lo usa correctamente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 19. MENOR: Modelos en agents/ y alternatives/ desactualizados
|
||||||
|
|
||||||
|
**Ficheros afectados**:
|
||||||
|
- `pages/agents/05.md:17` y `pages/agents/06.md:31` - usan `claude-sonnet-4-5-20250929`
|
||||||
|
- `pages/alternatives/06.md:40` - usa `claude-sonnet-4-20250514` en ejemplo de Anthropic SDK nativo
|
||||||
|
- `pages/alternatives/06.md:22` - usa `gpt-4o` en ejemplo de OpenAI SDK nativo
|
||||||
|
- `pages/alternatives/07.md:15` - usa `gpt-4o` en Assistants API
|
||||||
|
- `pages/alternatives/07.md:32` - usa `gemini-2.0-flash` en Google GenAI SDK
|
||||||
|
|
||||||
|
**Correccion**: Actualizar nombres de modelos a los ultimos disponibles (ver punto 5)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## NOTA POSITIVA: Secciones ya actualizadas a v1
|
||||||
|
|
||||||
|
Las siguientes secciones **ya estan correctamente actualizadas** para LangChain v1:
|
||||||
|
- **agents/** (01-23): Usa `createAgent`, middleware, `humanInTheLoopMiddleware`, etc.
|
||||||
|
- **messages/** (01-11): `ChatPromptTemplate`, `MessagesPlaceholder`, `SystemMessage` siguen siendo validos
|
||||||
|
- **introduction/06.md**: Ya menciona "LangChain (v1)"
|
||||||
|
- **langsmith/05.md**: Ya usa `createAgent` de `"langchain"`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resumen de prioridades
|
||||||
|
|
||||||
|
### Criticos (el curso no funciona correctamente sin estos cambios)
|
||||||
|
1. Actualizar version numbers en setup/03.md (v0.3.x -> v1.x)
|
||||||
|
2. Actualizar `@langchain/google-genai` a `@langchain/google` en multiples ficheros
|
||||||
|
3. Reemplazar `createReactAgent` por `createAgent` en models/15.md y models/16.md
|
||||||
|
4. Actualizar import de `MemoryVectorStore` en rag/11.md
|
||||||
|
5. Actualizar import de `initChatModel` en models/09.md
|
||||||
|
6. Anadir `@langchain/classic` a la arquitectura de paquetes
|
||||||
|
|
||||||
|
### Importantes (el codigo funciona pero con warnings/deprecaciones)
|
||||||
|
7. Actualizar nombres de modelos (gpt-4o-mini -> gpt-4.1-mini, etc.)
|
||||||
|
8. Actualizar imports de document loaders en pending/06c.md
|
||||||
|
9. Actualizar OllamaEmbeddings import path en rag/07.md
|
||||||
|
|
||||||
|
### Menores / Mejoras
|
||||||
|
10. Actualizar favicon URL en slides.md
|
||||||
|
11. Considerar anadir slide sobre Standard Content Blocks
|
||||||
|
12. Actualizar lista de modelos en models/10.md
|
||||||
|
13. Mencionar @langchain/classic en el modulo de estructura
|
||||||
|
14. Documentar responseFormat en createAgent
|
||||||
|
15. Actualizar URLs de documentacion (js.langchain.com -> docs.langchain.com)
|
||||||
|
16. Actualizar tabla de precios/modelos en setup/04.md
|
||||||
|
17. Actualizar modelos recomendados en setup/07.mdhttps://docs.langchain.com/oss/javascript/langchain/messages
|
||||||
|
18. Actualizar modelos Ollama en setup/09.md
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<script setup>
|
||||||
|
import { useNav } from '@slidev/client'
|
||||||
|
const { currentPage } = useNav()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="currentPage > 1"
|
||||||
|
style="position:fixed;top:10px;left:0;right:0;display:flex;justify-content:space-between;align-items:center;padding:0 28px;z-index:100;pointer-events:none;opacity:0.22;"
|
||||||
|
>
|
||||||
|
<img src="/EITB.svg" style="height:14px;width:auto;object-fit:contain;" />
|
||||||
|
<img src="/nykk.png" style="height:8px;width:auto;object-fit:contain;" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
Generated
+9382
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "slides-langchain.js",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "slidev build",
|
||||||
|
"dev": "slidev --open --remote",
|
||||||
|
"export": "slidev export",
|
||||||
|
"preview": "slidev slides.md",
|
||||||
|
"deploy": "git push github main"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@slidev/cli": "^52.14.1",
|
||||||
|
"@slidev/theme-default": "latest",
|
||||||
|
"@slidev/theme-seriph": "latest",
|
||||||
|
"vue": "^3.5.30"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"playwright-chromium": "^1.58.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|
||||||
@@ -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 |
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user