Fundamentos de langgraph
Langgraph emplea un grafo de estados donde los nodos ejecutan funciones que modifican el estado de la generación, y los bordes establecen el orden de ejecución. El componente central es StateGraph, que coordina el proceso, con nodos de inicio y fin para definir límites claros del flujo.
FastAPI como caso práctico
FastAPI es un framework de Python para APIs, caracterizado por su rendimiento y tipado estático. Se elige como ejemplo por su amplia adopción en desarrollo web y su estructura modular, lo que permite a los ingenieros de pruebas simular entornos de backend de menera rápida y controlada.
Ejemplo de generación con langgraph
El siguiente código demuestra cómo configurar langgraph para producir código FastAPI, con variables y lógica reestructuradas:
from typing import List
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
from langchain_core.messages import SystemMessage, HumanMessage
from llm import DeepSeek
model = DeepSeek()
system_prompt = """
Eres un desarrollador de Python enfocado en FastAPI. Genera código para aplicaciones web con este framework.
Entrega solo el código, sin comentarios adicionales ni formateo Markdown.
"""
class AppState(TypedDict):
primary_code: str
endpoints: list[str]
handlers: list[str]
def split_sections(content: str) -> List[str]:
segments = content.split('|||')
if len(segments) != 2:
raise ValueError("Formato inválido en el contenido")
return segments
def generate_api_routes(state):
user_prompt = """
Crea rutas y funciones de manejo para FastAPI, separadas por '|||'
ruta_saludo:
@app.get("/saludo")
manejador_saludo:
Retorna el mensaje "hola" en la respuesta
"""
response = model.invoke([SystemMessage(content=system_prompt), HumanMessage(content=user_prompt)])
sections = split_sections(response.content)
state["endpoints"].append(sections[0])
state["handlers"].append(sections[1])
return state
def assemble_fastapi_app(state):
template = """
1. Inicializar FastAPI
2. Incluir código de rutas
{rutas}
Las funciones de manejo están listas.
3. Ejecutar servidor en el puerto 8000
"""
filled_template = template.format(rutas=state["endpoints"][-1])
response = model.invoke([SystemMessage(content=system_prompt), HumanMessage(content=filled_template)])
state["primary_code"] += response.content
return state
if __name__ == "__main__":
graph = StateGraph(AppState)
graph.add_node("route_generator", generate_api_routes)
graph.add_node("app_constructor", assemble_fastapi_app)
graph.add_edge(START, "route_generator")
graph.add_edge("route_generator", "app_constructor")
graph.add_edge("app_constructor", END)
compiled = graph.compile()
output = compiled.invoke({"primary_code": "", "endpoints": [], "handlers": []})
print(output["primary_code"])
for h in output["handlers"]:
print(h)
Este ejemplo utiliza un delimitador diferente y nombres de funciones más descriptivos, manteniendo la funcionalidad original.
Variante con separación de componentes
Para mayor modularidad, se pueden definir nodos independientes para rutas y manejadores:
from typing import List
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
from langchain_core.messages import SystemMessage, HumanMessage
from llm import DeepSeek
model = DeepSeek()
system_prompt = """
Eres un desarrollador de Python especializado en FastAPI. Produce código para aplicaciones web.
Solo genera código, sin explicaciones ni formato especial.
"""
class AppState(TypedDict):
app_code: str
route_code: list[str]
handler_code: list[str]
def create_routes(state):
prompt = """
Genera código de rutas para FastAPI
ruta_saludo:
@app.get("/saludo")
"""
result = model.invoke([SystemMessage(content=system_prompt), HumanMessage(content=prompt)])
state["route_code"].append(result.content)
return state
def create_handlers(state):
prompt = """
Genera funciones de manejo para FastAPI
manejador_saludo:
Entrega una respuesta con el texto "hola"
"""
result = model.invoke([SystemMessage(content=system_prompt), HumanMessage(content=prompt)])
state["handler_code"].append(result.content)
return state
def build_final_app(state):
template = """
1. Crear instancia de FastAPI
2. Agregar rutas
{rutas}
3. Agregar manejadores
{manejadores}
4. Iniciar servidor en puerto 8000
"""
rendered = template.format(rutas=state["route_code"][-1], manejadores=state["handler_code"][-1])
result = model.invoke([SystemMessage(content=system_prompt), HumanMessage(content=rendered)])
state["app_code"] += result.content
return state
if __name__ == "__main__":
sg = StateGraph(AppState)
sg.add_node("route_node", create_routes)
sg.add_node("handler_node", create_handlers)
sg.add_node("app_node", build_final_app)
sg.add_edge(START, "route_node")
sg.add_edge("route_node", "handler_node")
sg.add_edge("handler_node", "app_node")
sg.add_edge("app_node", END)
graph = sg.compile()
result = graph.invoke({"app_code": "", "route_code": [], "handler_code": []})
print(result["app_code"])
for hc in result["handler_code"]:
print(hc)
for rc in result["route_code"]:
print(rc)
Esta estructura facilita la reutilización y el mantenimiento del código generado.
Impacto en pruebas de software
Los ingenieros de pruebas pueden usar langgraph para automatizar la creación de stubs de API, escenarios de prueba y herramientas de validación, lo que reduce el tiempo de configuración y permite centrarse en el diseño de casos de prueba complejos.
Arquitectura recomendada para proyectos
Un proyecto maduro basado en FastAPI y langgraph debería organizar el código en módulos separados: una aplicación principal, definiciones de rutas, lógica de negocio, archivos de configuración y conectores de base de datos, asegurando escalabilidad y claridad.
Aplicaciones en automatización avanzada
Langgraph puede integrarse en pipelines de CI/CD para generar automáticamente pruebas unitarias, de carga y de regresión, lo que promueve una cultura de calidad continua en equipos de desarrollo.
Gestión de prompts en langgraph
Los prompts del sistema establecen el contexto y reglas generales, como el framework y formato de salida, mientras que los prompts del usuario especifican requisitos detallados, permitiendo una generación de código adaptada a necesidades particulares.