Publicado el / 6 min
UI generativa con IA: interfaces útiles, no HTML improvisado
Cómo transformar respuestas de un modelo en componentes React seguros: datos estructurados, estados, límites y un ejemplo práctico.
Una persona pregunta «¿cómo evolucionaron mis ventas?» y recibe cinco párrafos que describen una gráfica que no puede ver. La UI generativa intenta resolver esa fricción: según la intención, la aplicación presenta un componente adecuado —una gráfica, un resumen, una tarjeta— en lugar de limitarse a texto. La clave no es que el modelo escriba cualquier HTML, sino que tu aplicación controle qué piezas puede mostrar.
De la respuesta a la interfaz
En un chat tradicional la salida es texto. En UI generativa el servidor puede obtener datos mediante una herramienta y devolver un resultado estructurado que el frontend asigna a componentes conocidos. Por ejemplo:
- La persona pide un resumen de ventas de septiembre.
- El modelo decide utilizar una herramienta autorizada
consultar_ventas. - El servidor obtiene datos, comprueba permisos y devuelve un resultado con esquema conocido.
- React elige
MetricCardoSummaryCard; el modelo no recibe permiso para inyectar JSX arbitrario.
Así lo plantea también la guía de generative UI de Vercel AI SDK: herramientas producen datos y la interfaz renderiza componentes correspondientes. Puedes aplicar el mismo patrón sin esa biblioteca si tu producto tiene otro stack.
¿Para qué sirve de verdad?
Tiene sentido cuando el formato de la respuesta depende de la consulta: una previsión meteorológica pide una tarjeta de clima; un pedido pide un estado y un enlace; una comparación pide una tabla. Una pantalla de ajustes con estructura fija no necesita IA para decidir su layout. Tampoco reemplaza un buen diseño: si todas las tarjetas son ilegibles, generarlas dinámicamente solo multiplica el problema.
Consejo: primero diseña tres respuestas excelentes sin IA. Después deja que el modelo escoja entre ellas mediante datos estructurados. No comiences por «el modelo puede dibujar cualquier cosa».
Un contrato sencillo entre backend y React
Supongamos que la API, tras consultar datos autorizados, devuelve una de estas dos formas. El ejemplo no llama a un modelo: enseña el límite seguro que cualquier modelo o tool debe respetar antes del render:
type Result =
| { type: "metric"; label: string; value: number; unit: string }
| { type: "summary"; text: string };
function parseResult(value: unknown): Result | null {
if (!value || typeof value !== "object") return null;
const item = value as Record<string, unknown>;
if (item.type === "metric" && typeof item.label === "string" &&
typeof item.value === "number" && Number.isFinite(item.value) &&
typeof item.unit === "string") {
return { type: "metric", label: item.label, value: item.value, unit: item.unit };
}
if (item.type === "summary" && typeof item.text === "string") {
return { type: "summary", text: item.text };
}
return null;
}
La validación se repite en el servidor con un esquema o validador real antes de enviar datos; la comprobación en el cliente protege además el borde del render. Para producción limita longitudes de texto, unidades permitidas y valores fuera de rango.
function GeneratedResult({ value }: { value: unknown }) {
const result = parseResult(value);
if (!result) return <p>No se pudo mostrar esta respuesta.</p>;
switch (result.type) {
case "metric":
return <MetricCard label={result.label} value={result.value} unit={result.unit} />;
case "summary":
return <p>{result.text}</p>;
}
}
MetricCard es un componente tuyo, diseñado, probado y accesible. React escapa el texto por defecto; evita convertir la respuesta del modelo en HTML mediante dangerouslySetInnerHTML. Un esquema de respuesta cambia más fácil que una interfaz improvisada por cada prompt.
El streaming no elimina los estados
Si los datos llegan en fragmentos, enseña loading, resultado parcial cuando sea válido, error recuperable y resultado final. No dibujes un objeto incompleto como si fuera definitivo. Puedes reservar el espacio de la tarjeta para evitar saltos de layout; si la herramienta tarda, muestra su estado, no una tarjeta vacía. Cuando el modelo falle, la aplicación necesita una salida comprensible y un botón para volver a intentar.
En aplicaciones sensibles añade límites: el modelo propone, tu código valida y la persona confirma acciones que cambian dinero, datos o permisos. Un gráfico equivocado desinforma; un botón de «confirmar pago» generado sin revisión puede hacer daño.
Consejos y errores comunes
- Separa contenido y presentación. Haz que el servidor devuelva datos y un
type, no una cadena HTML. - Instrumenta el flujo. Mide cuándo la tool falla, qué variante se muestra y si la persona entiende el resultado; no midas solo tokens.
- Diseña accesibilidad desde el inicio. Títulos, etiquetas, tabla alternativa para gráficas y foco visible también aplican a contenido generado.
- Evita componentes ilimitados. Un registro pequeño de variantes es más comprobable que cientos de widgets elegidos por prompt.
- No confíes en la instrucción del modelo como autorización. La API valida acceso antes de devolver cualquier dato.
Para llevar a tu proyecto
Prueba con una sola pregunta que hoy respondes con demasiado texto. Diseña una tarjeta que la responda mejor; define un tipo de datos verificable, contempla los cuatro estados (cargando, listo, vacío, error) y luego conecta la herramienta o el modelo. UI generativa no significa renunciar al diseño: significa hacer que un buen diseño aparezca en el momento correcto.