Creación de flujos de trabajo agénticos 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 actuales pueden realizar razonamientos estructurados de varios pasos, tomar 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 estos flujos de trabajo agénticos de IA utilizando dos herramientas clave: LangGraph, un marco para construir rutas de razonamiento basadas en gráficos y modelos IBM® Granite, un modelo sólido que complementa esta estructura. Cada paso del flujo de trabajo, denominado "nodo", lo gestiona un agente, normalmente impulsado por modelos de lenguaje de gran tamaño. Estos agentes se mueven entre estados en función de los outputs del modelo o la lógica condicional, formando un gráfico dinámico basado en decisiones.

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

Entender LangGraph

Un marco para flujos de trabajo escalables e impulsados por IA

LangGraph es un potente marco diseñado 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 escalables y modulares 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 u outputs de modelos para determinar los próximos pasos
  • Pasar el estado entre nodos para conservar 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, suelen estructurar la ejecución de tareas como flujos de trabajo secuenciales o condicionales. Tanto si trabaja con LangChain, modelos IBM Granite, modelos GPT de OpenAI u otras herramientas de inteligencia artificial, LangGraph le ayuda a optimizar su flujo de trabajo para mejorar la escalabilidad y el rendimiento.

Componentes clave de LangGraph para automatizar flujos de trabajo complejos

LangGraph presenta un enfoque moderno para orquestar las tecnologías de IA al descomponer 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 alimentan este marco:

  • 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 empresariales más grandes.
  • Edges: los edges definen el flujo entre los nodos, guiando la forma en que 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.
  • Edges condicionales (gráficos cíclicos): los gráficos cíclicos permiten bucles y ramificaciones condicionales, lo que permite al sistema volver a visitar los nodos en función de la lógica o los outputs 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, preserva el contexto y permite 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 del lenguaje natural (PLN). Aunque es más pequeño que 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 destaca en:

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

En este tutorial, el modelo Granite desempeña un papel clave en varias etapas del flujo de trabajo agéntico, y respalda tanto la resolución de problemas como la generación de contenido. Su diseño ligero lo hace adecuado para aplicaciones del mundo real en las que la intervención humana puede ser limitada y en las que 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 agencia que actúe como asistente creativo para escribir guiones cortos animados.

Objetivo

Dada una idea de historia del usuario, el agente:

  • Identifique el género y el tono adecuados para la historia
  • Generará un breve esquema de la trama
  • Lo ampliará hasta convertirlo en una escena clave (por ejemplo, el clímax o el punto de inflexión)
  • Escribirá un diálogo para esa escena en formato guion

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 -generate_scene):  el LLM escribe una escena fundamental en prosa, y da 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 la producción o la 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 estados 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 en el que la imaginación humana es esencial

También se escala bien, puede ampliarlo fácilmente añadiendo 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 watsonx.ai .

Pasos

Paso 1. Configure su entorno

Aunque puede elegir entre varias herramientas, este tutorial le muestra cómo configurar una cuenta de IBM para utilizar un Jupyter Notebook.

  1. Inicie sesión en watsonx.ai utilizando su cuenta de IBM Cloud.
  2. Cree un proyecto watsonx.ai. Puede obtener el ID de su proyecto desde dentro del propio proyecto. Haga clic en la pestaña Gestionar. A continuación, copie el ID del proyecto de la sección Detalles 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 cuaderno 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. Configure el 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 sin coste).
  2. Genere una clave de interfaz de programación de aplicaciones (clave API).
  3. Asocie el servicio watsonx.ai Runtime al proyecto que ha creado 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 preentrenados, incluidosgranite-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.

El-q flag ejecuta la instalación silenciosamente, suprimiendo la salida 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á siguiendo este tutorial en un entorno virtual y no tiene Langgraph preinstalado, utilice pip install langgraph para instalarlo en tu entorno local.

!pip install -q transformers accelerate
Captura de pantalla de un terminal que notifica una nueva versión de PiP Fragmento de output: crear un flujo de trabajo de agencia; 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 agencia:

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

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

time: Permite el seguimiento temporal y la monitorización del rendimiento opcionales.

StateGraph yEND delanggraph.graph : se utilizan para definir y compilar el gráfico de flujo de trabajo agéntico.

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

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

# 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 el modelo de IBMgranite-4.0-tiny-preview y su tokenizador correspondiente de Hugging Face.

model_id: Especifica el identificador del modelo preentrenado 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 outputs basadas en la entrada.

Eltorch_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 agéntico.

#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 output que dice que la ruta rápida no está disponible Fragmento de output: crear un flujo de trabajo agéntico: cargar el modelo Granite

Paso 6. Función de servicios para generar texto con Granite

Esta función,generate_with_granite , envuelve el proceso de generación de texto utilizando 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 el output (por defecto: 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 la GPU (CUDA) si se solicita y está disponible; de lo contrario, se establece la CPU de forma predeterminada.

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(...): Inicia la generación de texto con estrategias de muestreo que incluyen:

  • do_sample=True: Permitir la aleatoriedad para obtener outputs más creativos.

  • temperature=0.7 ytop_p=0.9: Controlar la diversidad del texto generado.

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

Esta función se reutilizará en todo el flujo de trabajo de agencia 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 de nuestro flujo de trabajo de generación de guiones de agencia. 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 divertida para niños").

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

  • Actúe como asistente creativo.
  • Analice la entrada del usuario.
  • Recomiende un género y un tono utilizando un formato de output específico:Genre: <genre> yTone: <tone>

Generación de texto: la instrucción se transfiere a la función degenerate_with_granite() utilidad para generar una respuesta creativa.

Análisis de output: 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 del estado: los valoresgenre ytone extraídos se vuelven a insertar en el diccionario de estado que se pasará al siguiente nodo.

Este nodo actúa como un clasificador creativo que permite que los nodos posteriores generen esquemas, estructuras y escenas alineados contextualmente utilizando el género y el tono como parámetros fundamentales.

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 nodo para generar el contorno de la trama (nodo - 2)

Elgenerate_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 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:

  • Actúe como asistente de escritura creativa.
  • Tenga en cuenta la idea, el género y el tono del usuario.
  • Genere un breve esquema argumental (de 3 a 5 frases) 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 frases.

Actualización de estado: el contorno del gráfico generado se añade 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 boceto narrativo, proporcionando un andamiaje para la estructura detallada en tres actos que sigue a continuación. Garantiza que los nodos posteriores funcionen a partir de 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. Crear un nodo para generar una escena clave a partir del esquema (nodo - 3)

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

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

  • genre ytone
  • Elplot outline del nodo anterior

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

  • Actúe como guionista
  • Genera un punto de inflexión o una escena culminante utilizando lagenre ,tone youtline
  • Escriba en formato prosa para preservar la legibilidad y la descripción compatible con 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 , dejando suficiente espacio para la creación de escenas inmersivas.

Actualización del estado: La escena generada se añade al diccionario de estados bajo la"scene" clave.

Introduce la inmersión narrativa y la narración visual en el flujo de trabajo. En lugar de limitarse a resumir la historia, este nodo le da vida con detalles sensoriales y emocionales, esenciales para la creación de 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 nodo para escribir diálogos de personajes en formato de guión (nodo - 4)

Elwrite_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 personajes formateado. Este paso sirve de puente entre la prosa y la escritura de guiones listos para la pantalla, y da voz a los personajes.

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

Construcción de instrucciones: el modelo se orienta hacia:

  • La escritura de diálogos
  • La extracción y adaptación de diálogos de la escena
  • El formateo del output en estilo de guión utilizando:CHARACTER: Dialogue line

Directrices para el diálogo:

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

Generación: lagenerate_with_granite() llamada usamax_tokens=300 , que equilibra la expresividad con la brevedad, ideal para guiones cortos de animación.

Actualización del estado: El diálogo se guarda en el estado bajo ladialogue 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ñada 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, generate_scene_node) con un decorador que registra:

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

Parámetros:

  • fn : la función de nodo real (por ejemplo, write_dialogue_node)
  • label : una etiqueta legible 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

Envoltorio interno:

  • 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

Devuelve: una versión modificada de la función que añade mensajes de progreso pero que, por lo demás, se comporta de forma 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 la sobrecarga de memoria. Este contenedor de progreso garantiza la transparencia y es útil para la depuración y el diagnóstico en 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 breve historia animada mediante LangGraph, un marco de programación composicional basado en grafos diseñado para flujos de trabajo LLM. Cada paso del diagrama representa una tarea creativa que se ejecuta en una secuencia específica para producir el guion 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 del 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 su progreso cuando se ejecute.

Fases del flujo de trabajo (secuenciación de nodos): la secuencia del proceso creativo está claramente definida:

select_genre → generate_outline → generate_scene → write_dialogue

 

set_entry_point() yset_finish_point(): Definen los nodos de inicio y final 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 trabajo LLM modular, legible y depurable. Cada etapa del proceso creativo se puede aislar, perfilar por separado y, posteriormente, intercambiar o ampliar (por ejemplo, añadiendo un paso de "revisar escena" o un nodo de "resumir resultado"). Elworkflow ahora está listo para ejecutarse con una instrucción y ejecutará su canalización creativa 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. Ejecución del flujo de trabajo de LangGraph y visualización del output de datos

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 la canalización de la historia.

final_state: Este comando activa la canalización completa de LangGraph. La entrada se transmite a través de cada nodo registrado (select_genre, generate_outline, generate_scene y write_dialogue) 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 frases.
  • "scene": Una vívida escena crucial 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 una canalización creativa integral que es interactiva, interpretable y personalizable.

Nota: el código tardará aproximadamente entre 15 y 17 minutos en ejecutarse si utiliza GPU o TPU. En un entorno virtual local, se tardará entre 65 y 70 minutos en ejecutarse y generar el output en función de la infraestructura utilizada para ejecutar la cesión.

# 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 output que registra cuánto tiempo tardó cada paso (entre 90 y 260 segundos)
Output de la trama y escenas clave de una historia fantástica
Fragmentos de output de una historia fantástica
Fragmentos de output de una historia fantástica
Fragmentos de output de una historia fantástica

Entendamos cómo el sistema transforma la instrucción del usuario: "quiero escribir una historia de fantasía divertida 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 del usuario: quiero escribir una historia de fantasía divertida para niños sobre un dragón perdido que encuentra su hogar. Basándose en esta entrada, select_genre_node clasifica correctamente la narrativa como fantasía divertida e identifica el tono encantador y conmovedor apropiado. Este resultado es preciso y contextual, ya que el uso de frases como "divertida", "para niños" y "dragón perdido que encuentra 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 próximo paso, se pide al modelo que cree un esquema argumental basado en el género identificado, el tono y la idea original del usuario. El output no solo incluye un resumen de la historia de 3 a 5 frases, sino que también incluye descripciones de caracteres adicionales, probablemente debido a la fuga de la instrucción o al formato de instrucciones retenido de iteraciones anteriores.

El argumento gira en torno a una niña llamada Lily que descubre a un dragón herido y le ayuda a regresar al bosque encantado con la ayuda de un viejo herborista. Esta historia refleja exactamente la intención del usuario: centrarse en un viaje mágico para niños con matices emocionales sobre la curación, la pertenencia y la amistad. Los bocetos de los personajes del dragón, Lily y el herborista añaden profundidad, y transforman una idea vaga en un concepto estructurado con roles, personalidades y responsabilidades narrativas definidos. 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, y establece una relación emocional y un entendimiento mutuo entre los personajes. Este momento es crítico, ya que marca un punto de inflexión en la historia hacia el regreso del dragón a casa. 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 coherencia de tono y 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. Por último, 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 crear una historia para la 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 herborista en dos escenas distintas: la cabaña y el bosque encantado. El diálogo conserva las señales emocionales y la intención de los personajes, 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 escenas como[INT. LILY’S COTTAGE - DAY]) El output sigue siendo breve, expresivo y emocionalmente resonante, lo que es esencial para atraer a la audiencia joven en un entorno animado.

Cada etapa del flujo de trabajo traduce la instrucción original ("una extravagante historia de fantasía para niños sobre un dragón perdido que encuentra su hogar") en un output estructurado, creativo y expresivo. Desde la selección del género hasta el formato de los diálogos, el sistema construye 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 entrada de usuario de una sola línea, lo que demuestra el poder práctico de los flujos de trabajo de agencia en aplicaciones creativas de IA.

Para que la experiencia de contar historias sea aún más atractiva, he aquí una sencilla visualización basada en HTML que formatea a la perfección los elementos generados de la historia: género, tono, trama, escena y diálogo. Además, con un solo clic, puede descargar todo el script 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 sobre el uso y la infraestructura de la GPU

Este tutorial utiliza el modelo Granite-4.0-Tiny-Preview para generar texto. Aunque es uno de los modelos más pequeños de la familia Granite, sigue necesitando un entorno con GPU para funcionar de manera eficiente, sobre todo cuando se ejecutan varios nodos en un flujo de trabajo 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 se produzcan errores de memoria insuficiente de CUDA si se ejecutan todos los nodos secuencialmente sin borrar la memoria de la GPU.
  • Para minimizar los problemas de memoria:
    • Mueva el modelo a la GPU solo durante la generación y vuelva a la 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 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, hemos creado un flujo de trabajo modular y agentivo para la narración de historias utilizando LangGraph y el modelo lingüístico Granite-4.0-Tiny-Preview de IBM. Partiendo de una simple instrucción creativa, construimos un proceso 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 guion cinematográfico. En el camino, demostramos cómo:

  • Estructurar flujos de trabajo dinámicos utilizando LangGraph
  • Integrar LLM ligeros como Granite para el razonamiento creativo
  • Gestionar las limitaciones de memoria de la GPU con la carga de modelos ad hoc
  • Muestre y exporte el output de la historia en un formato fácil de usar

Este marco de trabajo no solo es muy útil para escribir guiones, sino también para un montón de casos creativos o para organizar tareas. Con solo unos pocos nodos, puedes crear un asistente de escritura en miniatura capaz de convertir una idea descabellada en una historia lista para ser un guion.

Ya sea desarrollador, narrador o investigador, este tutorial le ofrece una base práctica para explorar la ingeniería de flujos de trabajo con LLM en ámbitos creativos.

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

Soluciones relacionadas
Agentes de IA para empresas

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

    Explore watsonx Orchestrate
    Soluciones de agente de IA de IBM

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

    Explore las soluciones de los agentes de IA
    Servicios de IA de IBM Consulting

    Los servicios de IA de IBM Consulting ayudan a reinventar la forma de trabajar de las empresas usando IA para la transformación.

    Explore los servicios de inteligencia artificial
    Dé el siguiente paso

    Tanto si opta por personalizar las aplicaciones y habilidades prediseñadas como si prefiere crear e implementar servicios agentivos personalizados mediante un estudio de IA, la plataforma IBM watsonx le ofrece todo lo que necesita.

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

    1 Lang Cao. 2024. GraphReason: Enhancing Reasoning Capabilities of Large Language Models through A Graph-Based Verification Approach. En Actas del 2.º taller sobre razonamiento en lenguaje natural y explicaciones estructuradas (@ACL 2024), páginas 1–12, Bangkok, Tailandia. Asociación de Lingüística Computacional.