From c677919a58e4e6273d17b3c28e4213f9f10ac81a Mon Sep 17 00:00:00 2001 From: Javier Infante Date: Fri, 29 May 2026 11:43:13 +0200 Subject: [PATCH] doc ready --- practica_resueltos | 1 + slides/.nvmrc | 1 + slides/changes.md | 371 ----------------------------------- slides/public/nykk_black.png | Bin 0 -> 8638 bytes 4 files changed, 2 insertions(+), 371 deletions(-) create mode 160000 practica_resueltos create mode 100644 slides/.nvmrc delete mode 100644 slides/changes.md create mode 100644 slides/public/nykk_black.png diff --git a/practica_resueltos b/practica_resueltos new file mode 160000 index 0000000..fb0daba --- /dev/null +++ b/practica_resueltos @@ -0,0 +1 @@ +Subproject commit fb0daba4042a1d25a90ca7826500b1f2bb1c605b diff --git a/slides/.nvmrc b/slides/.nvmrc new file mode 100644 index 0000000..8ef0a52 --- /dev/null +++ b/slides/.nvmrc @@ -0,0 +1 @@ +v24.11.1 diff --git a/slides/changes.md b/slides/changes.md deleted file mode 100644 index 1d47186..0000000 --- a/slides/changes.md +++ /dev/null @@ -1,371 +0,0 @@ -# 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 diff --git a/slides/public/nykk_black.png b/slides/public/nykk_black.png new file mode 100644 index 0000000000000000000000000000000000000000..bd19fc6bc971b51bc8c8d40bd16bc9f896d98f6e GIT binary patch literal 8638 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