Creación de flujos de trabajo de agentes con LangGraph y Granite

Autor

Vrunda Gadesha

AI Advocate | Technical Content Author

Los sistemas modernos de IA están evolucionando más allá de las simples interacciones de instrucción-respuesta. Los agentes de IA de hoy en día pueden realizar un razonamiento estructurado de varios pasos, la toma de decisiones y coordinar tareas complejas de forma autónoma. Esta capacidad emergente se conoce como un flujo de trabajo—un poderoso cambio en el machine learning donde los agentes operan a través de una serie de pasos lógicos para resolver problemas de manera más efectiva.

En este tutorial, exploraremos cómo crear tales flujos de trabajo de agentes de IA mediante dos herramientas clave: LangGraph, un marco para construir rutas de razonamiento basadas en gráficos y modelos IBM® Granite, un modelo robusto que complementa esta estructura. Cada paso del flujo de trabajo, llamado "nodo", es manejado por un agente, generalmente impulsado por modelos de lenguaje de gran tamaño. Estos agentes se mueven entre estados en función de los resultados del modelo o la lógica condicional, formando un gráfico dinámico basado en decisiones.

Para dar vida a estos flujos de trabajo de agentes, analizaremos más de cerca dos componentes esenciales: LangGraph y el modelo Granite.

Entendiendo LangGraph

Un marco para flujos de trabajo escalables impulsados por IA

LangGraph es una infraestructura potente diseñada para agilizar el desarrollo de flujos de trabajo impulsados por IA mediante la representación de modelos de IA como agentes con estado dentro de un gráfico computacional. Permite a los desarrolladores crear sistemas modulares escalables en los que cada comportamiento o punto de decisión se define como un nodo en el gráfico.

Con LangGraph, puede:

  • Definir el comportamiento de cada agente como un nodo distinto
  • Utilice algoritmos o resultados de modelos para determinar el siguiente paso
  • Pase el estado entre nodos para preservar la memoria y el contexto
  • Visualice, depure y controle el flujo de razonamiento con facilidad

Sistemas multiagente y marcos como LangGraph, cuando se aplican a tareas de IA generativa (IA gen), suelen estructurar la ejecución de tareas como flujos de trabajo secuenciales o condicionales. Ya sea que esté trabajando con LangChain, modelos IBM Granite, modelos GPT de OpenAI u otras herramientas de inteligencia artificial, LangGraph ayuda a optimizar su flujo de trabajo para una mejor escalabilidad y rendimiento.

Componentes clave de LangGraph para automatizar flujos de trabajo complejos

LangGraph introduce un enfoque moderno para orquestar tecnologías de IA mediante el desglose de flujos de trabajo complejos en componentes modulares e inteligentes. A diferencia de la automatización tradicional o la automatización robótica de procesos (RPA), LangGraph permite la ejecución dinámica de tareas conscientes del contexto mediante el uso de lógica y memoria en tiempo real. Estos son los cuatro componentes clave que impulsan esta infraestructura:

  • Nodos: los nodos representan unidades individuales de lógica o acción, como llamar a una herramienta de IA, consultar fuentes de datos o realizar una tarea específica. Son ideales para automatizar tareas repetitivas dentro de procesos comerciales más grandes.
  • Bordes: los bordes definen el flujo entre nodos, guiando cómo se conectan y ejecutan las tareas. Esta estructura respalda procesos flexibles de toma de decisiones y permite que los flujos de trabajo se adapten en función de los resultados.
  • Bordes condicionales (gráficos cíclicos): los gráficos cíclicos permiten bucles y ramificaciones condicionales, lo que permite que el sistema vuelva a visitar los nodos en función de la lógica o los resultados del modelo. Esta capacidad es crucial para manejar tareas iterativas y tomar decisiones informadas en entornos dinámicos.
  • Estado (gráficos con estado): el estado actúa como memoria compartida, preservando el contexto y permitiendo el uso de datos en tiempo real en todos los nodos. Esta capacidad permite a LangGraph ir más allá de los flujos estáticos y admitir avances adaptativos e inteligentes en la automatización del flujo de trabajo.

Juntos, estos componentes permiten a LangGraph transformar la forma en que las organizaciones diseñan y ejecutan flujos de trabajo impulsados por IA, cerrando la brecha entre las herramientas de IA y los procesos empresariales del mundo real.

Componentes clave de LangGraph para automatizar flujos de trabajo complejos Figura 1 Componentes clave de LangGraph para automatizar flujos de trabajo complejos

Modelo Granite: LLM ligero para la resolución de problemas del mundo real

Granite-4.0-Tiny-Preview, desarrollado por IBM Research, es un modelo de lenguaje de código abierto ligero pero capaz, diseñado para resolver problemas complejos y tareas prácticas de procesamiento de lenguaje natural (PLN). Si bien es más pequeño que los modelos comerciales como GPT-4, Granite es rápido, eficiente y totalmente compatible con Hugging Face, lo que lo convierte en una excelente opción para los desarrolladores que buscan eficiencia operativa sin sacrificar el rendimiento.

Granite se destaca en:

  • Clasificación de intenciones: identificación de los objetivos del usuario en chatbots o sistemas basados en tareas
  • Generación creativa: producción de resúmenes, diálogos o contenido breve
  • Razonamiento y resumen: ideal para flujos de trabajo que involucran RAG o análisis de datos

En este tutorial, el modelo Granite desempeña un papel clave en varias etapas del flujo de trabajo agentivo, apoyando tanto la resolución de problemas como la generación de contenido. Su diseño liviano lo hace adecuado para aplicaciones del mundo real donde la intervención humana puede ser limitada y donde los patrones de diseño escalables son esenciales para crear soluciones de IA sólidas en diversos conjuntos de datos y proveedores.

Caso de uso

En este tutorial, crearemos un flujo de trabajo de agente que actúa como asistente creativo para escribir guiones cortos animados.

Objetivo

Dada una idea de historia del usuario, el agente:

  • Identificar el género y el tono adecuados para la historia
  • Generar un breve esquema de la trama
  • Ampliarlo a una escena clave (por ejemplo, clímax o punto de inflexión)
  • Escriba un diálogo para esa escena en formato de guión

Este caso de uso está diseñado para mostrar tanto el razonamiento como las capacidades generativas de un modelo de lenguaje, estructurado a través del flujo de trabajo compositivo de LangGraph.

Cómo funciona el flujo de trabajo

Cada uno de los siguientes pasos se implementa como un nodo LangGraph:

  • Entrada del usuario: el usuario proporciona una idea de historia de alto nivel para iniciar el flujo de trabajo.
  • Detección de género (node_name - select_genre): un LLM analiza la entrada para inferir el género y el tono adecuados para la historia.
  • Generación de esquemas (node_name -generate_outline): el LLM genera un breve resumen de la trama basado en el género seleccionado.
  • Escritura de escenas (node_name - generar_escena):  el LLM escribe una escena fundamental en prosa, dando vida a la historia.
  • Escritura de diálogos (node_name - write_dialogue): el LLM reescribe la escena como un diálogo de guión formateado, adecuado para producción o edición posterior.

Estos nodos se conectan secuencialmente en un LangGraph, y el modelo se mueve a través de ellos mientras lleva adelante un diccionario de estado mutable.

Este flujo de trabajo logra un equilibrio entre la generación creativa y la planificación estructural. Demuestra:

  • Coordinación de LLM a través de LangGraph
  • Narración de varios pasos con una intervención manual mínima
  • Automatización creativa en un ámbito donde la imaginación humana es esencial

También se escala bien, puede ampliarlo fácilmente agregando pasos de revisión, múltiples generadores de escenas o incluso ramificación basada en caracteres.

Requisitos previos

Necesita una cuenta de IBM Cloud para crear un proyecto en watsonx.ai .

Pasos

Paso 1: Configuración del entorno

Si bien puede elegir entre varias herramientas, este tutorial lo guiará a través de cómo configurar una cuenta de IBM para usar un Jupyter Notebook.

  1. Inicie sesión en watsonx.ai mediante su cuenta de IBM Cloud.
  2. Cree un proyecto watsonx.ai. Puede obtener su ID de proyecto desde dentro de su proyecto. Haga clic en la pestaña Manage . Luego, copie el ID del proyecto de la sección Details de la página General. Necesita este ID para este tutorial.
  3. Cree un Jupyter Notebook.

Este paso abre un entorno de notebook donde puede copiar el código de este tutorial. También puede descargar este Notebook en su sistema local y cargarlo en su proyecto watsonx.ai como activo. Para ver más tutoriales de Granite, consulte la comunidad de IBM Granite. Este tutorial también está disponible en GitHub

Paso 2. Configuración del servicio watsonx.ai Runtime y la clave de API

  1. Cree una instancia de servicio watsonx.ai Runtime (elija el plan Lite, que es una instancia gratuita).
  2. Genere una clave de interfaz de programación de aplicaciones (clave API).
  3. Asocie el servicio de watsonx.ai Runtime al proyecto que creó en watsonx.ai.

Paso 3. Instalación de las bibliotecas necesarias

Esta celda instala las bibliotecas principales necesarias para utilizar el modelo IBM Granite alojado en Hugging Face:

  • transformers: Esta es la biblioteca principal para cargar e interactuar con modelos de lenguaje previamente entrenados, que incluyengranite-4.0-tiny-preview .
  • accelerate:  Ayuda con la carga eficiente de modelos y la colocación de dispositivos, especialmente útil para usar GPU de manera fluida.

Hay-q flag ejecuta la instalación silenciosamente, suprimiendo la salida detallada para una interfaz de notebook más limpia. Estas bibliotecas son esenciales para descargar el modelo y manejar la inferencia de manera eficiente en este tutorial.

Nota: Si está ejecutando este tutorial en un entorno virtual y no tiene langgrapg preinstalado, use pip install langgraph para instalarlo en su entorno local.

!pip install -q transformers accelerate
Schreenshot de una terminal que notifica una nueva versión de PiP Fragmento de salida: Cree un flujo de trabajo de agentes: instalación de las bibliotecas

Paso 4. Importación de las bibliotecas necesarias

Esta celda importa todas las bibliotecas principales necesarias para crear y ejecutar el flujo de trabajo de los agentes:

AutoTokenizer YAutoModelForCausalLM detransformers : se utiliza para cargar el modelo Granite y tokenizar las instrucciones de entrada para su generación.

torch : proporciona aceleración de GPU y operaciones de tensor necesarias para la inferencia de modelos.

time: Permite el seguimiento opcional del tiempo y la supervisión del rendimiento.

StateGraph YEND delanggraph.graph : se utilizan para definir y compilar el gráfico de flujo de trabajo agentivo.

IPython.display ,base64: Se utiliza para representar los resultados de forma ordenada y habilitar características de descarga opcionales para el contenido generado en Jupyter Notebooks.

En conjunto, estas importaciones preparan el entorno para la interacción del modelo, la estructuración del flujo de trabajo y la presentación de resultados.

# Import libraries
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import time
from langgraph.graph import StateGraph, END
from IPython.display import display, HTML
import base64

Paso 5. Carga del modelo Granite y el tokenizador

Esta celda carga IBMgranite-4.0-tiny-preview modelo y su tokenizador correspondiente de Hugging Face:

model_id: Especifica el identificador del modelo previamente entrenado alojado en Hugging Face.

AutoTokenizer.from_pretrained(model_id): Carga el tokenizador asociado al modelo Granite. El tokenizador es responsable de convertir el texto legible por humanos en tokens de entrada para el modelo.

AutoModelForCausalLM.from_pretrained(...): Carga el modelo de lenguaje real para el modelado de lenguaje causal (es decir, generativo). Este modelo puede predecir y generar salidas de texto basadas en la entrada.

Haytorch_dtype=torch.float32 establece explícitamente el tipo de datos en float32, que es más eficiente en términos de memoria y ampliamente compatible, especialmente útil en entornos con restricciones de GPU.

Este paso inicializa eficazmente el modelo Granite como el "motor de razonamiento" detrás de nuestro flujo de trabajo de agentes.

#Load Granite-4.0-Tiny-Preview model and tokenizer from Hugging Face
model_id = "ibm-granite/granite-4.0-tiny-preview"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.float32)
Fragmento de salida que dice que la ruta rápida no está disponible Fragmento de salida: Cree un flujo de trabajo agente: cargando el modelo Granite

Paso 6. Función de empresa de servicios públicos para generar texto con Granite

Esta función,generate_with_granite , envuelve el proceso de generación de texto mediante el modelo Granite. Acepta la instrucción que es el texto de entrada para guiar la respuesta del modelo.

max_tokens : el número máximo de tokens que se generarán en los resultados (predeterminado: 200).

use_gpu : una marca que indica si se debe ejecutar la inferencia en la GPU (si está disponible).

Detalles clave:

device = torch.device(...): Selecciona dinámicamente GPU (cuda) si se solicita y está disponible; de lo contrario, el valor predeterminado es CPU.

model.to(device): Carga el modelo en el dispositivo adecuado justo a tiempo, lo que ayuda a conservar la memoria.

tokenizer(prompt, return_tensors="pt"): Convierte la cadena de entrada en tensores de token para el procesamiento del modelo.

model.generate(...): Comienza la generación de texto con estrategias de muestreo que incluyen:

  • do_sample=True: Permite la aleatoriedad para obtener resultados más creativos.

  • temperature=0.7 Ytop_p=0.9: Controle la diversidad del texto generado.

tokenizer.decode(...): Convierte los tokens generados en texto legible, eliminando cualquier token especial.

Esta función se reutilizará en todo el flujo de trabajo agentivo para invocar el modelo Granite en varios nodos de decisión o generación.

def generate_with_granite(prompt: str, max_tokens: int = 200, use_gpu: bool = False) -> str:
    device = torch.device("cuda" if use_gpu and torch.cuda.is_available() else "cpu")

    # Move model to device only at generation time
    model.to(device)
    inputs = tokenizer(prompt, return_tensors="pt").to(device)

    outputs = model.generate(
        **inputs,
        max_new_tokens=max_tokens,
        do_sample=True,
        temperature=0.7,
        top_p=0.9,
        pad_token_id=tokenizer.eos_token_id
    )

    return tokenizer.decode(outputs[0], skip_special_tokens=True).strip()

 

Paso 7. Crear nodo para seleccionar género y tono (nodo-1)

Esta función,select_genre_node , define el primer nodo en nuestro flujo de trabajo de generación de guiones de agentes. Utiliza el modelo Granite para determinar el género y el tono de la historia en función de la entrada del usuario.

Entrada:state , un diccionario que incluye"user_input" (por ejemplo, "Quiero escribir una historia de fantasía caprichosa para niños").

Construcción de instrucciones: la instrucción pide al modelo que:

  • Actuar como asistente creativo.
  • Analice la entrada del usuario.
  • Recomiende un género y tono utilizando un formato de salida específico:Genre: <genre> YTone: <tone>

Generación de texto: la instrucción se pasa algenerate_with_granite() función de Empresa de servicios públicos para generar una respuesta creativa.

Análisis de salida: un bucle simple extrae el género y el tono de la respuesta del modelo en función de los prefijos de línea ("Genre:" Y"Tone:" ).

Actualización de estado: la información extraídagenre Ytone los valores se insertan nuevamente en el diccionario de estado que se pasará al siguiente nodo.

Este nodo actúa como clasificador creativo, lo que permite que los nodos posteriores generen esquemas, estructuras y escenas alineados contextualmente mediante el uso del género y el tono como parámetros fundacionales.

def select_genre_node(state: dict) -> dict:
    prompt = f"""
You are a creative assistant. The user wants to write a short animated story.
Based on the following input, suggest a suitable genre and tone for the story.
User Input: {state['user_input']}

Respond in this format:
Genre: <genre>
Tone: <tone>
""".strip()

    response = generate_with_granite(prompt)

    # Basic parsing of output
    genre, tone = None, None
    for line in response.splitlines():
        if "Genre:" in line:
            genre = line.split("Genre:")[1].strip()
        elif "Tone:" in line:
            tone = line.split("Tone:")[1].strip()

    # Update state
    state["genre"] = genre
    state["tone"] = tone
    return state

Paso 8. Crear un nodo para generar el esquema de la trama (nodo - 2)

Haygenerate_outline_node define el segundo nodo en el flujo de trabajo de generación de guiones. Se basa en el género y el tono seleccionados para generar un esquema conciso de la trama de la historia.

Entrada: la función recibe el diccionario de estado que contiene:

  • user_input: la idea original de la historia.
  • género: seleccionado en el nodo anterior.
  • tono: seleccionado en el nodo anterior.

Construcción de instrucciones: se instruye al modelo para que:

  • Actuar como asistente de escritura creativa.
  • Considere la idea, el género y el tono del usuario.
  • Genere un breve esquema de la trama (3 a 5 oraciones) adecuado para un guión animado corto.

Generación de texto: la instrucción se envía agenerate_with_granite() con un mayortoken limit (max_tokens=250) para dejar espacio para un esquema de varias oraciones.

Actualización de estado: el contorno del gráfico generado se agrega al estado bajo la clave"outline" , listo para su uso en la siguiente fase de expansión de la estructura.

Este nodo traduce la intención creativa abstracta en un esbozo narrativo, proporcionando un andamio para la estructura detallada de tres actos que sigue. Garantiza que los nodos descendentes funcionen desde una línea de base coherente e imaginativa.

def generate_outline_node(state: dict) -> dict:
    prompt = f"""
You are a creative writing assistant helping to write a short animated screenplay.
The user wants to write a story with the following details:
Genre: {state.get('genre')}
Tone: {state.get('tone')}
Idea: {state.get('user_input')}

Write a brief plot outline (3–5 sentences) for the story.
""".strip()

    response = generate_with_granite(prompt, max_tokens=250)
    state["outline"] = response
    return state

Paso 9. Cree un nodo para generar una escena clave a partir del esquema (nodo - 3)

Haygenerate_scene_node define el tercer paso en el flujo de trabajo donde el esquema de la trama se transforma en una rica escena narrativa. Esta escena sirve como una dramatización vívida de un punto de inflexión en la historia, trasladando la idea del resumen a la narración.

Entrada: el nodo toma el diccionario de estado, que ahora incluye:

  • genre Ytone
  • Hayplot outline del nodo anterior

Construcción de instrucciones: se instruye al modelo para que:

  • Actuar como guionista
  • Genere un punto de inflexión o una escena clímax utilizando losgenre ,tone Youtline
  • Escriba en formato prosa para preservar la legibilidad y la descripción amigable con las animaciones

Requisitos de la escena:

  • Vívido y descriptivo (adecuado para la animación)
  • Central para el arco emocional o narrativo (por ejemplo, descubrimiento, conflicto o resolución)

Generación de texto:generate_with_granite se llama conmax_tokens=300 , lo que permite suficiente espacio para la creación de escenas inmersivas.

Actualización de estado: la escena generada se agrega al diccionario de estado bajo el"scene" clave.

Introduce la inmersión narrativa y la narración visual en el flujo de trabajo. En lugar de simplemente resumir la historia, este nodo le da vida con detalles sensoriales y emocionales, esenciales para escribir guiones de cortos animados.

def generate_scene_node(state: dict) -> dict:
    prompt = f"""
You are a screenwriter.
Based on the following plot outline, write a key scene from the story.
Focus on a turning point or climax moment. Make the scene vivid, descriptive, and suitable for an animated short film.

Genre: {state.get('genre')}
Tone: {state.get('tone')}
Outline: {state.get('outline')}

Write the scene in prose format (not screenplay format).
""".strip()

    response = generate_with_granite(prompt, max_tokens=300)
    state["scene"] = response
    return state

Paso 10. Crear un nodo para escribir diálogos de personajes en formato de guión (nodo - 4)

Haywrite_dialogue_node define el cuarto paso creativo en el flujo de trabajo de la narración: convertir una escena narrativa en un diálogo de personaje formateado. Este paso cierra la brecha entre la prosa y la escritura de guiones listos para la pantalla, dando voz a los personajes.

Entrada: el nodo espera el estadoscene para contener un momento vívido de la historia (normalmente un punto de inflexión o clímax).

Construcción de instrucción: el modelo se guía para:

  • Actuar como escritor de diálogos
  • Extraiga y adapte el diálogo de la escena
  • Formatee la salida en estilo de guión usando:CHARACTER: Dialogue line

Pautas para el diálogo:

  • Sea breve y expresivo
  • Asegúrese de que sea apropiado para la animación (visual, emocional, conciso)
  • Inventa nombres si es necesario para mayor claridad

Generación: Lagenerate_with_granite() usos de llamadasmax_tokens=300 , que equilibra la expresividad con la brevedad, ideal para guiones cortos animados.

Actualización de estado: el cuadro de diálogo se guarda en el estado bajo eldialogue clave para pasos futuros (por ejemplo, visualización o edición).

def write_dialogue_node(state: dict) -> dict:
    prompt = f"""
You are a dialogue writer for an animated screenplay.

Below is a scene from the story:
{state.get('scene')}

Write the dialogue between the characters in screenplay format.
Keep it short, expressive, and suitable for a short animated film.

Use character names (you may invent them if needed), and format as:

CHARACTER:
Dialogue line

CHARACTER:
Dialogue line
""".strip()

    response = generate_with_granite(prompt, max_tokens=300)
    state["dialogue"] = response
    return state

Paso 11. Agregar informes de progreso a cada nodo

Esta función auxiliarwith_progress está diseñado para envolver cada nodo de flujo de trabajo con indicadores de progreso en tiempo real. No altera la lógica de la función original: simplemente rastrea e imprime el estado de ejecución y el tiempo para hacer que los flujos de trabajo largos sean más transparentes.

Propósito de la función: envolver un nodo (por ejemplo, generar_nodo_escena) con un decorador que registre:

  • Qué paso se está ejecutando
  • Índice de pasos y recuento total
  • Cuánto tarda el paso

Parámetros:

  • fn : la función de nodo real (por ejemplo, write_dialogue_node)
  • label : una etiqueta legible por humanos para esa función
  • index : número de paso en la secuencia (por ejemplo, 2)
  • total : Número total de pasos en el flujo de trabajo

Envoltura interna:

  • Imprime un mensaje inicial
  • Registra la hora de inicio
  • Llama a la función original
  • Imprime un mensaje de finalización con la duración transcurrida

Devoluciones: una versión modificada de la función que agrega mensajes de progreso pero que, por lo demás, se comporta de manera idéntica.

A medida que crecen los flujos de trabajo, es importante realizar un seguimiento de qué paso se está ejecutando, especialmente si algunos pasos (como la generación o la edición) tardan más o pueden causar problemas, como sobrecarga de memoria. Este contenedor de progreso garantiza la transparencia y es útil para la depuración y el diagnóstico del tiempo de ejecución.

# Wrap with progress reporting

def with_progress(fn, label, index, total):
    def wrapper(state):
        print(f"\n[{index}/{total}] Starting: {label}")
        start = time.time()
        result = fn(state)
        duration = time.time() - start
        print(f"[{index}/{total}] Completed: {label} in {duration:.2f} seconds")
        return result
    return wrapper

Paso 12. Definición del flujo de trabajo de LangGraph

Esta celda define la lógica del flujo de trabajo para generar una historia corta animada mediante LangGraph, un marco de programación basado en gráficos compositivos diseñado para flujos de trabajo LLM. Cada paso del gráfico representa una tarea creativa y se ejecutan en una secuencia específica para producir el guión final.

Componentes del flujo de trabajo:StateGraph(dict)  - Inicializa el flujo de trabajo con un estado basado en diccionario (es decir, la memoria de trabajo es un dictado pasado de nodo a nodo).

Registro de nodos con seguimiento de progreso: cada paso (selección de género, generación de esquemas, escritura de escenas, escritura de diálogos) se agrega como un nodo con el contenedor with_progress() - 

graph.add_node("select_genre", with_progress(select_genre_node, "Select Genre", 1, 4)) 

Este enfoque garantiza que cada nodo registre su tiempo de ejecución y progreso cuando se ejecute.

Perímetros del flujo de trabajo (secuenciación de nodos): la secuencia del pipeline creativo está claramente definida:

select_genre → generate_outline → generate_scene → write_dialogue

 

set_entry_point() Yset_finish_point(): Estos definen los nodos de inicio y finalización del flujo de trabajo.

graph.compile(): Compila el flujo de trabajo en un formulario ejecutable (flujo de trabajo) que ahora se puede invocar con un estado inicial.

Esta estructura permite un flujo de trabajoLLM modular, legible y depurable. Cada etapa de su proceso creativo está aislada, se puede perfilar por separado y luego se puede intercambiar o ampliar (por ejemplo, agregando un paso de "revisar escena" o un nodo de "resumir resultado"). Elworkflow ahora está listo para ejecutarse con una instrucción y ejecutará su pipeline creativo paso a paso, mostrando el progreso en vivo.

# Define LangGraph

graph = StateGraph(dict)
graph.add_node("select_genre", with_progress(select_genre_node, "Select Genre", 1, 4))
graph.add_node("generate_outline", with_progress(generate_outline_node, "Generate Outline", 2, 4))
graph.add_node("generate_scene", with_progress(generate_scene_node, "Generate Scene", 3, 4))
graph.add_node("write_dialogue", with_progress(write_dialogue_node, "Write Dialogue", 4, 4))

graph.set_entry_point("select_genre")
graph.add_edge("select_genre", "generate_outline")
graph.add_edge("generate_outline", "generate_scene")
graph.add_edge("generate_scene", "write_dialogue")
graph.set_finish_point("write_dialogue")

workflow = graph.compile()

 

Paso 13. Ejecutar el flujo de trabajo de LangGraph y mostrar el resultado

Esta celda de código final es donde se ejecuta el flujo de trabajo creativo completo y se muestran los resultados de cada etapa de la generación de la historia.

initial_state: Este comando es el punto de partida del flujo de trabajo, donde el usuario proporciona una idea o tema creativo. El user_input sirve como semilla para el pipeline de la historia.

final_state: Este comando activa la canalización completa de LangGraph. La entrada se pasa a través de cada nodo registrado (select_genre, generar_outline, generar_escena y escribir_diálogo) en secuencia.

Visualización de resultados: el diccionario de estado final ahora contiene claves pobladas por varios nodos:

  • "genre": El género identificado basado en la entrada del usuario.
  • "tone": La calidad tonal de la historia.
  • "outline": un resumen de la trama de 3 a 5 oraciones.
  • "scene": Una vívida escena decisiva escrita en prosa.
  • "dialogue": Diálogo de personajes con formato de guión.

Esta sección demuestra cómo la intención del usuario se transforma en un miniscript completo a través de un flujo de trabajo LLM modular y paso a paso. Es un pipeline creativo de extremo a extremo que es interactivo, interpretable y personalizable.

Nota: El código tardará aproximadamente entre 15 y 17 minutos en ejecutarse si utiliza GPU o TPU. Se tardará entre 65 y 70 minutos en un entorno virtual local para ejecutar y generar el resultado basado en la infraestructura utilizada para ejecutar el cede.

# Run workflow
initial_state = {
    "user_input": "I want to write a whimsical fantasy story for children about a lost dragon finding its home."
}
final_state = workflow.invoke(initial_state)

# Display Results
print("\n=== Final Output ===")
print("Genre:", final_state.get("genre"))
print("Tone:", final_state.get("tone"))
print("\nPlot Outline:\n", final_state.get("outline"))
print("\nKey Scene:\n", final_state.get("scene"))
print("\nDialogue:\n", final_state.get("dialogue"))
Fragmento de resultados que registra cuánto tiempo tardó cada paso (90 a 260 segundos)
Resultado del esquema de la trama y escenas clave de una historia de fantasía
Fragmentos de salida de una historia de fantasía
Fragmentos de salida de una historia de fantasía
Fragmentos de salida de una historia de fantasía

Comprendamos cómo el sistema transforma la instrucción del usuario: "Quiero escribir una historia de fantasía caprichosa para niños sobre un dragón perdido que encuentra su hogar", en una historia animada completa. Cada paso se basa en el anterior, guiado por los nodos creativos del flujo de trabajo e impulsado por el modelo Granite.

1. Género y tono. El flujo de trabajo comienza interpretando la instrucción original del usuario: Quiero escribir una historia de fantasía caprichosa para niños sobre un dragón perdido que encuentra su hogar. Con base en esta entrada, select_genre_node clasifica correctamente la narrativa como fantasía caprichosa e identifica el tono encantador y conmovedor apropiado. Este resultado es preciso y está alineado con el contexto, ya que el uso de frases como “caprichoso”, “para niños” y “dragón perdido encontrando su hogar” indica claramente un estilo narrativo mágico pero amable. El género y el tono actúan como parámetros fundacionales que dan forma a cada paso de generación posterior en el flujo de trabajo.

2. Esquema de la trama y descripciones de los personajes. En el siguiente paso, se le pide al modelo que cree un esquema de trama basado en el género identificado, el tono y la idea original del usuario. El resultado no solo incluye un resumen de la historia de 3 a 5 oraciones, sino que también incluye descripciones de personajes adicionales, probablemente debido a la fuga de instrucciones o al formato de instrucciones retenido de iteraciones anteriores.

El esquema de la trama se centra en una niña llamada Lily que descubre un dragón herido y lo ayuda a regresar al bosque encantado con la guía de un viejo herbolario. Esta historia refleja exactamente la intención del usuario: centrarse en un viaje mágico apto para niños con matices emocionales sobre la curación, la pertenencia y la amistad. Los bocetos de personajes del dragón, Lily y el herbolario agregan profundidad, transformando una idea vaga en un concepto estructurado con roles definidos, personalidades y responsabilidades narrativas. Este paso garantiza que la historia pase de la intención abstracta a una estructura tangible adecuada para la adaptación cinematográfica.

3. Escena clave. Dado el esquema completo de la trama, elgenerate_scene_node escribe una escena vívida en formato de prosa que captura un punto de inflexión en la historia, otro elemento solicitado explícitamente en la intención original del usuario de desarrollar un guión de animación corto.

El momento elegido es cuando Lily atiende al dragón herido en el bosque encantado, estableciendo una relación emocional y un entendimiento mutuo entre los personajes. Este momento es crítico, ya que gira la historia hacia el regreso a casa del dragón. La escena es rica en imágenes y emociones, y se adhiere a las restricciones "caprichosas" y "conmovedoras", a la vez que es visualmente expresiva, perfectamente adecuada para un formato animado corto.

La capacidad del modelo para mantener la consistencia del tono y el género en todas las etapas demuestra el valor del flujo de trabajo de paso de estado de LangGraph y las capacidades de razonamiento del modelo Granite.

4. Diálogo en formato de guión. Finalmente, elwrite_dialogue_node convierte la escena en prosa en un diálogo estructurado en formato de guión. La instrucción del usuario, centrada en la creación de una historia parala animación, exige implícitamente que la narrativa se presente en un formato listo para la producción o visualización. Este nodo cumple ese objetivo al ofrecer un diálogo bien formateado entre Lily, Drago (el dragón) y el viejo herbolario en dos escenas distintas: la cabaña y el bosque encantado. El diálogo conserva las señales emocionales y la intención del personaje, y está formateado para que coincida con las convenciones de escritura de guiones de animación (por ejemplo, nombres de personajes en mayúsculas, encabezados de escena como[INT. LILY’S COTTAGE - DAY]) El resultado sigue siendo breve, expresivo y emocionalmente resonante, lo cual es esencial para atraer a la audiencia joven en un entorno animado.

Cada etapa del flujo de trabajo traduce la instrucción original — "una historia de fantasía caprichosa para niños sobre un dragón perdido que encuentra su hogar" — en un resultado estructurado, creativo y expresivo. Desde la selección del género hasta el formato de los diálogos, el sistema crea de forma incremental un arco narrativo coherente. El marco LangGraph garantiza que las transiciones entre tareas estén conectadas lógicamente, y el modelo IBM Granite® permite la generación de texto sensible al contexto con un tono coherente. El resultado es una historia corta de animación compacta y lista para la pantalla que surge completamente de una sola línea de entrada de usuario, lo que demuestra el poder práctico de los flujos de trabajo en aplicaciones creativas de IA.

Para que la experiencia de contar historias sea aún más atractiva, aquí hay una visualización simple basada en HTML que da un formato hermoso a los elementos de la historia generados: género, tono, trama, escena y diálogo. Además, con un solo clic, puede descargar el script completo como archivo de texto para usarlo o compartirlo en el futuro. ¡Demos vida a la historia en la pantalla!

# Beautification and Downloadable option creation for user

def display_output_with_download(final_state):
    genre = final_state.get("genre", "")
    tone = final_state.get("tone", "")
    outline = final_state.get("outline", "")
    scene = final_state.get("scene", "")
    dialogue = final_state.get("dialogue", "")

    # Combine scene and dialogue into a full script
    script = f"""Genre: {genre}
Tone: {tone}
Outline:
{outline}
Scene:
{scene}
Dialogue:
{dialogue}
"""

    # Encode to base64
    b64_script = base64.b64encode(script.encode()).decode()

    # Create downloadable HTML content
    html = f"""
    <h2>Genre & Tone</h2>
    <p><strong>Genre:</strong> {genre}</p>
    <p><strong>Tone:</strong> {tone}</p>

    <h2>Outline</h2>
    <pre>{outline}</pre>

    <h2>Scene</h2>
    <pre>{scene}</pre>

    <h2>Dialogue</h2>
    <pre>{dialogue}</pre>

    <a download="screenplay_script.txt" href="data:text/plain;base64,{b64_script}">
        <button style="margin-top: 20px; padding: 10px 20px; font-size: 16px;">Download Script as .txt</button>
    </a>
    """
    display(HTML(html))

# Run this after workflow.invoke()
display_output_with_download(final_state)

Notas de infraestructura y uso de GPU

Este tutorial utiliza Granite-4.0-Tiny-Preview modelo para la generación de texto. Si bien es uno de los modelos más pequeños de la familia Granite, aún requiere un entorno habilitado para GPU para funcionar de manera eficiente, especialmente cuando se ejecutan múltiples nodos en un flujo de trabajo de LangGraph.

Configuración recomendada:

  • Al menos una GPU NVIDIA V100 o A100
  • 16 GB de memoria GPU o más para un rendimiento estable
  • Python 3.8+ con torch, transformers y langgraph instalados

Notas de rendimiento:

  • Es posible que encuentre errores de memoria insuficiente de CUDA si ejecuta todos los nodos secuencialmente sin borrar la memoria de la GPU.
  • Para minimizar los problemas de memoria:
    • Mueva el modelo a GPU solo durante la generación y vuelva a CPU después.
    • Mantenga los tokens de generación modestos (max_tokens=200–300).
    • Opcionalmente, elimine o simplifique nodos, como la revisión o la expansión detallada de la escena.

Si está ejecutando este tutorial en un entorno de notebook alojado (por ejemplo, IBM watsonx.ai o Google Colab Pro), asegúrese de que la GPU esté habilitada en la configuración de tiempo de ejecución.

Para entornos de bajos recursos, considere:

  • Descarga de la inferencia del modelo a la API Hugging Face Inference.
  • Reducir la complejidad del flujo de trabajo.
  • Uso de CPU (con tiempos de generación más largos).

Resumen

En este tutorial, creamos un flujo de trabajo de narración modular y agentivo mediante LangGraph y Granite-4.0-Tiny-Preview de IBM modelo de lenguaje. A partir de una simple instrucción creativa, construimos un pipeline paso a paso que clasifica el género y el tono, genera un esquema de la trama, escribe una escena clave y termina con un diálogo al estilo de un guión. En el camino, demostramos cómo:

  • Estructure flujos de trabajo dinámicos con LangGraph
  • Integre LLM ligeros como Granite para un razonamiento creativo
  • Maneje las limitaciones de memoria de la GPU con la carga de modelos ad hoc
  • Muestre y exporte la salida de la historia en un formato fácil de usar

Este marco no solo es potente para la escritura de pantallas, sino que puede extenderse a una amplia gama de casos de uso creativos o de enrutamiento de tareas. Con solo unos pocos nodos, ha creado un asistente de escritura en miniatura capaz de convertir una idea caprichosa en una historia lista para el guión.

Ya sea desarrollador, narrador o investigador, este tutorial le brinda una base práctica para explorar la ingeniería de flujo de trabajo basada en LLM en dominios creativos.

¿Listo para crear sus propios agentes? Deje que la creatividad fluya con los modelos IBM Granite e IBM watsonx Orchestrate.

Soluciones relacionadas
Agentes de IA para empresas

Cree, implemente y gestione poderosos asistentes y agentes de IA que automaticen flujos de trabajo y procesos con IA generativa.

    Explore watsonx Orchestrate
    Soluciones de agentes de IA de IBM

    Construya el futuro de su empresa con soluciones de IA en las que pueda confiar.

    Explorar las soluciones de agentes de IA
    Servicios de IA de IBM Consulting

    Los servicios de IA de IBM Consulting ayudan a reinventar la forma en que las empresas trabajan con IA para la transformación.

    Explorar los servicios de inteligencia artificial
    Dé el siguiente paso

    Ya sea que elija personalizar aplicaciones y habilidades predefinidas o crear y desplegar servicios agénticos personalizados utilizando un estudio de IA, la plataforma IBM watsonx responde a sus necesidades.

    Explore watsonx Orchestrate Explore watsonx.ai
    Notas de pie de página

    1 Lang Cao. 2024. GraphReason: Mejora de las capacidades de razonamiento de los modelos lingüísticos de gran tamaño mediante un Approach de verificación basado en grafos. En Proceedings of the 2nd Workshop on Natural Language Reasoning and Structured Explanations (@ACL 2024), páginas 1–12, Bangkok, Tailandia. Association for Computational Linguistics.