GenAINextVercel AI SDKLangchainGoogle Gemini

LangChain.js: El siguiente nivel de abstracción. Parte 1

Antonio Pérez
2025-09-11
8
LangChain.js: El siguiente nivel de abstracción. Parte 1

Introducción: La necesidad de un framework de composición

En el capítulo anterior, construimos un agente funcional. Si examinamos el código de nuestro backend, notaremos un patrón: una secuencia de llamadas asíncronas, condicionales y bucles que gestionan el flujo de información entre el usuario, el LLM y las herramientas. Esta lógica, aunque funciona, es imperativa. Describe cómo hacer algo, paso a paso.

typescript
// Patrón imperativo que hemos usado hasta ahora
async function handleRequest(messages) {
  const llmResponse = await callLlm(messages, tools);
  if (llmResponse.tool_calls) {
    const toolResults = await executeTools(llmResponse.tool_calls);
    const finalResponse = await callLlm(messages.concat(toolResults));
    return finalResponse;
  } else {
    return llmResponse;
  }
}

Este enfoque tiene sus límites. A medida que añadimos más herramientas, más pasos de razonamiento o más lógica condicional, este código se vuelve exponencialmente más complejo y difícil de mantener, testear y visualizar.

Aquí es donde entra en juego LangChain.js. LangChain no es solo una biblioteca de "prompts" o "envoltorios de API". En su núcleo, es un framework de composición declarativo. Nos permite definir qué queremos que haga nuestra aplicación de IA, no solo cómo. El "cómo" (la orquestación, los reintentos, el paralelismo) es gestionado por el framework.

En este capítulo, exploraremos dos conceptos clave de LangChain que nos permitirán refactorizar y elevar nuestra arquitectura:

  1. LCEL (LangChain Expression Language): Una sintaxis fluida y potente para componer cadenas de IA de forma declarativa.
  2. Agentes de LangChain: Abstracciones de alto nivel que encapsulan ciclos de razonamiento-acción complejos, como el que hemos estado construyendo manualmente.

Nuestro objetivo no es descartar el Vercel AI SDK. Al contrario, aprenderemos cómo combinar lo mejor de ambos mundos: la potencia de composición y las abstracciones de agentes de LangChain en el backend, con la eficiencia y la facilidad de uso del Vercel AI SDK (useChat, streamUI) en el frontend.

LCEL: Componiendo flujos de IA con "pipes"

LangChain Expression Language (LCEL) es la innovación central que hace que LangChain sea tan poderoso. Se basa en un concepto simple pero profundo: cualquier componente de una cadena de IA (un prompt, un modelo, un parser de salida, una herramienta) puede ser tratado como un Runnable. Los Runnables pueden ser "encadenados" juntos usando un método .pipe(), similar al operador | en los shells de Unix.

El Modelo mental: De funciones anidadas a tuberías lineales

Consideremos una operación simple: tomar una pregunta, formatearla en un prompt, enviarla a un modelo y parsear la salida.

Enfoque imperativo (Sin LCEL):

typescript
async function getAnswer(question: string): Promise<string> {
  const prompt = formatPrompt(question); // Función que crea el string del prompt
  const modelResponse = await model.invoke(prompt); // Llamada al modelo
  const parsedOutput = parseModelOutput(modelResponse); // Función que extrae el texto
  return parsedOutput;
}

Esto es anidamiento de funciones. Funciona, pero el flujo de datos está implícito.

Enfoque declarativo (Con LCEL):

typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";

const promptTemplate = ChatPromptTemplate.fromTemplate("Pregunta: {question}");
const outputParser = new StringOutputParser();

const chain = promptTemplate.pipe(model).pipe(outputParser);

const answer = await chain.invoke({ question: "..." });

Análisis de LCEL:

  1. Declarativo y legible: La cadena promptTemplate.pipe(model).pipe(outputParser) describe el qué (el flujo de datos) de forma explícita y lineal. Es mucho más fácil de leer y entender que el código imperativo.
  2. Componibilidad universal: Cualquier Runnable puede conectarse con cualquier otro Runnable, siempre que los tipos de salida de uno coincidan con los de entrada del siguiente. Esto crea un sistema de "legos" increíblemente flexible.
  3. Características "gratis": La verdadera potencia de LCEL es que cualquier cadena construida con .pipe() obtiene automáticamente una gran cantidad de funcionalidades de nivel de producción sin ningún esfuerzo adicional:
  • Streaming asíncrono: Todas las cadenas LCEL soportan .stream(). El framework se encarga de streamear la salida final a medida que se genera.
  • Ejecución en paralelo: Puedes usar RunnableSequence.from() y RunnableParallel para ejecutar múltiples cadenas en paralelo y combinar sus resultados.
  • Reintentos y fallbacks: Puedes añadir reintentos con backoff exponencial a cualquier parte de la cadena con .withRetry().
  • Trazabilidad automática: Cuando se usa con LangSmith, cada paso en la cadena (prompt, model, parser) se registra automáticamente como un "span" separado, lo que proporciona una visibilidad de depuración sin precedentes.

LCEL nos permite pasar de escribir código de orquestación a diseñar flujos de datos.

Agentes de LangChain: Encapsulando la complejidad del razonamiento

En el capítulo anterior, implementamos manualmente el ciclo de Razonamiento-Acción. Funcionó, pero nuestra lógica de backend tuvo que manejar explícitamente la decisión del LLM, la ejecución de la herramienta y el re-envío del resultado.

LangChain proporciona abstracciones de alto nivel, los Agentes, que encapsulan estos ciclos de razonamiento. Un Agente en LangChain no es una clase monolítica, sino la combinación de tres componentes clave:

  1. Herramientas (Tools): La lista de funciones que el agente puede usar. Es exactamente el mismo concepto que ya hemos manejado.
  2. Modelo (LLM): El modelo de lenguaje que toma las decisiones, "vinculado" a las herramientas para que sepa cómo llamarlas.
  3. Lógica del Agente (Agent Logic): El "cerebro" que orquesta la interacción. En lugar de un único tipo de agente, LangChain ofrece diferentes "constructores" para crear agentes con diferentes estilos de razonamiento (ej. ReAct, OpenAI Tools, etc.).

createOpenAIToolsAgent:

Este es uno de los constructores de agentes más modernos y potentes. Crea un agente diseñado para funcionar con la implementación de tool_calls de proveedores como OpenAI, Google y Anthropic.

El flujo interno de un agente de LangChain:

Cuando se invoca a un agente con una entrada, ocurre un flujo similar a nuestro ciclo manual, pero gestionado por el framework:

  1. Formateo del prompt: La entrada del usuario y el historial de la conversación se formatean usando una plantilla de prompt especializada.

2. Llamada al modelo: Se invoca al LLM con el prompt y las herramientas disponibles.ç

3. Parseo de la salida: La respuesta del LLM se parsea. LangChain determina si la respuesta es:

  • AgentAction: Una solicitud para llamar a una o más herramientas.
  • AgentFinish: Una respuesta final para el usuario.

4. Ejecución (si es AgentAction):

  • Se invoca la herramienta correspondiente con los argumentos proporcionados.
  • El resultado se formatea como un Observation (esencialmente, un mensaje de rol tool).
  • El ciclo vuelve al paso 1, ahora con la Observation añadida al historial.

5. Finalización (si es AgentFinish):

  • La respuesta final se devuelve al llamador.

Todo este bucle está encapsulado dentro de un AgentExecutor, que es en sí mismo un Runnable. Esto significa que todo nuestro agente, sin importar cuán complejo sea su razonamiento interno, puede ser invocado con un simple .invoke() o .stream(), y se integra perfectamente con el resto del ecosistema LCEL.

Sinergia: LangChain.js + Vercel AI SDK

LangChain y el Vercel AI SDK no son competidores; son herramientas complementarias que operan en diferentes niveles de abstracción y resuelven diferentes problemas.

  • LangChain.js (Backend): Es ideal para definir y orquestar la lógica de negocio de la IA. Su fortaleza es la composición de cadenas complejas y la encapsulación de patrones de agentes. Lo usaremos para construir el "cerebro" de nuestro agente en el servidor.
  • Vercel AI SDK (Frontend y Comunicación): Es ideal para conectar la lógica del backend con la interfaz de usuario. Sus hooks (useChat, streamUI) son abstracciones de frontend inigualables para consumir streams de datos y renderizar UIs conversacionales y generativas.

Arquitectura Combinada:

javascript
[Frontend (Next.js)]
      |
      +-- [Componente de Chat (con `useChat`)]
            |
            +-- `fetch('/api/chat')`
                  |
[Backend (Next.js Route Handler)]
      |
      +-- [1. Recibe la petición de `useChat`]
      |
      +-- [2. Invoca el `AgentExecutor` de LangChain]
            |
            +-- [3. LangChain orquesta el ciclo de razonamiento y herramientas]
            |
      +-- [4. LangChain's AgentExecutor devuelve un stream de salida]
      |
      +-- [5. **Adaptador:** Usamos `LangChainStream` del Vercel AI SDK]
      |      |
      |      +-- Convierte el stream de LangChain al formato que `useChat` entiende
      |
      +-- [6. Se devuelve la `StreamingTextResponse`]
            |
[Frontend]
      |
      +-- [`useChat` consume el stream y actualiza la UI]

El punto clave de integración es el adaptador (Paso 5). El Vercel AI SDK proporciona helpers (LangChainStream) que actúan como un puente, permitiendo que el stream generado por una cadena LCEL de LangChain sea consumido sin problemas por los hooks del SDK en el frontend.

Conclusión teórica

Hemos introducido una poderosa capa de abstracción en nuestra arquitectura de backend. Al adoptar LCEL, pasamos de escribir código de orquestación imperativo a diseñar flujos de IA declarativos, ganando en legibilidad, mantenibilidad y obteniendo de forma gratuita funcionalidades de nivel de producción.

Al utilizar los Agentes de LangChain, hemos encapsulado el complejo ciclo de Razonamiento-Acción detrás de una interfaz Runnable limpia.

Finalmente, hemos definido una arquitectura clara que aprovecha las fortalezas de ambas bibliotecas: LangChain para la lógica del agente en el servidor y el Vercel AI SDK para la gestión de la interfaz de usuario y la comunicación en el cliente.

En la sección práctica, refactorizaremos el agente de soporte técnico del capítulo anterior utilizando estos nuevos y potentes conceptos.