Generación de imágenes por plantilla con Genviso y BetterToken

Cómo separar la exploración visual de la ejecución backend y convertir un prompt eficaz en una plantilla de producción versionada.

Una imagen acertada todavía no es un proceso de producción. Para una sola pieza se puede reescribir el prompt, revisar varios resultados y elegir uno a mano. Con cientos de SKU, ese hábito se convierte en una cadena de pruebas costosas: cada cambio de luz, ángulo o material provoca otra llamada y el motivo del buen resultado queda en la memoria de una persona.

Conviene separar el trabajo en dos circuitos. Primero, el equipo prueba la dirección visual y documenta las reglas repetibles. Después, el backend inserta los datos del negocio en la plantilla aprobada, envía solicitudes, guarda los resultados y trata los errores. La exploración creativa queda fuera de la cola de producción y una corrección de composición ya no obliga a modificar el servidor.

Por qué depurar prompts dentro del código se descontrola

Hay demasiadas variables relacionadas

El modelo responde al sujeto, el entorno, la iluminación, la cámara, el material, la profundidad de campo y la paleta al mismo tiempo. En una foto de un frasco de sérum cambian mucho el resultado:

  • una vista frontal o un plano cenital a 45 grados;
  • luz dura direccional o luz suave y difusa;
  • vidrio con reflejos marcados o acabado mate;
  • fondo de travertino, metal o papel liso;
  • aspecto macro de 85 mm o composición gran angular.

Si se cambian varios factores a la vez, nadie sabe qué frase mejoró la imagen. Si se cambia uno por uno, crece el número de solicitudes. Un backend que usa BetterToken puede ejecutar la plantilla mediante Image API, pero activar la cola demasiado pronto solo multiplica una hipótesis visual sin validar.

Cada tarea necesita su propia gramática visual

Una ficha de producto necesita una silueta legible, reflejos controlados y espacio para la maquetación. Una ilustración 3D exige otras reglas de forma y material. Un cartel social depende de la jerarquía, el contraste y las zonas seguras. Un prompt universal suele terminar lleno de adjetivos incompatibles.

Es más práctico mantener familias de plantillas:

skincare_product luxury_watch food_photography 3d_illustration social_poster

Cada familia define campos obligatorios y criterios de aceptación. La aplicación elige la plantilla según la categoría y rellena los valores del producto o de la campaña.

Explorar y producir requieren reglas distintas

La exploración admite muchas variantes y comparaciones subjetivas. La producción necesita un contrato predecible, versión de plantilla, reintentos limitados, identificador de trabajo y un resultado de aceptación explícito.

editar el prompt en el código → enviar una solicitud API → abrir la imagen → volver a editar el código → enviar otra solicitud

En ese ciclo no existe un punto de aprobación visual. Por eso cualquier conversación de diseño afecta al backend y a la cola de tareas.

Arquitectura: de la hipótesis visual al archivo del CMS

Durante la exploración, el equipo utiliza Genviso para comparar opciones en su galería visual de prompts, revisar composición, luz y estilo, y conservar la estructura que funciona. En la ejecución del servidor, la aplicación usa BetterToken con la Base URL compatible con OpenAI y la API Key propia del usuario, inserta los datos, llama a un modelo disponible y registra el resultado. Entre ambos pasos se entrega una versión del Prompt Template, no una imagen elegida ni instrucciones verbales.

Para comprobar esa frontera antes de conectar una cola, crea tu propia API Key, ejecuta una solicitud de control con la plantilla aprobada y concilia enseguida su modelo, estado y cargo real en el Dashboard. Así se valida la ruta del servidor sin convertir la exploración visual en solicitudes de producción.

exploración visual ↓ validación del Prompt Template ↓ variables y restricciones fijadas ↓ datos de PIM / CMS / SKU ↓ solicitud de Image API desde el backend ↓ archivo, estado y metadatos ↓ aceptación visual

Cada transición debe producir algo comprobable:

EtapaResultadoCondición de salida
Exploración visualVariantes válidas y descartadasSe conocen los parámetros que influyen
ValidaciónPrompt con variables nombradasFunciona con varios productos representativos
IntegraciónFunción de renderizado y esquemaLos campos obligatorios se validan antes de la API
PruebaUn archivo y un registroEl archivo abre y modelo/estado son correctos
ProducciónTarea con template_id, versión y job_idLos reintentos son finitos y el resultado corresponde al SKU

Etapa 1: convertir la decisión visual en plantilla

Una estructura inicial para fotografía de cosmética puede ser:

Commercial studio product photography of {subject}. Environment: {environment} Visual style: {visual_style} Lighting: {lighting} Composition: {composition} Color palette: {color_palette} Crisp reflections, premium material texture, high-end commercial editorial photography.

El orden y las dimensiones visuales permanecen estables; sus valores cambian por separado: subject, environment, visual_style, lighting, composition y color_palette.

Antes de entregar la plantilla a desarrollo, hay que fijar cuatro elementos:

  1. Campos obligatorios. Sin subject o composition, la solicitud no debe salir.
  2. Valores admitidos. Si solo hay tres ángulos aprobados, conviene usar un enum y no texto libre del CMS.
  3. Combinaciones prohibidas. Un envase transparente sobre un espejo puede necesitar otra plantilla.
  4. Criterios de aceptación. La silueta se entiende, el logotipo no se deforma, el producto no se recorta y el fondo sirve para la composición final.

Guarda el prompt junto a un contrato legible por la aplicación:

{ "template_id": "skincare_product_v3", "required_variables": [ "subject", "environment", "visual_style", "lighting", "composition", "color_palette" ], "output_size": "1024x1024" }

La versión de template_id aporta reproducibilidad. Si cambia la luz o la composición, las tareas nuevas reciben otra versión; los archivos existentes siguen vinculados a la anterior.

Etapa 2: conectar la plantilla al backend

Para una primera prueba necesitas el SDK oficial openai para Python, tu propia BetterToken API Key y un Model ID actual consultado en la documentación de Image API. Guarda ambos valores en el entorno:

python -m pip install openai export BETTERTOKEN_API_KEY="your_api_key_here" export BETTERTOKEN_IMAGE_MODEL="current_image_model_id"

No incluyas una clave real en el repositorio, el prompt, una captura o los logs. En producción, usa un gestor de secretos y claves separadas para cada aplicación o entorno.

Este ejemplo renderiza la plantilla, envía una solicitud y guarda un PNG desde b64_json:

import base64 import os from pathlib import Path from typing import Mapping from openai import OpenAI client = OpenAI( base_url="https://www.bettertoken.ai/v1", api_key=os.environ["BETTERTOKEN_API_KEY"], ) def render_product_prompt(variables: Mapping[str, str]) -> str: return f""" Commercial studio product photography of {variables['subject']}. Environment: {variables['environment']} Visual style: {variables['visual_style']} Lighting: {variables['lighting']} Composition: {variables['composition']} Color palette: {variables['color_palette']} Crisp reflections, premium material texture, high-end commercial editorial photography. """.strip() product = { "subject": "frosted amber glass serum bottle with a minimalist gold dropper", "environment": "organic travertine pedestal surrounded by subtle water ripples", "visual_style": "high-end botanical skincare editorial", "lighting": "warm directional morning rim light with soft diffused fill", "composition": "centered 85mm macro product photography with shallow depth of field", "color_palette": "earthy amber, warm beige and subtle gold", } response = client.images.generate( model=os.environ["BETTERTOKEN_IMAGE_MODEL"], prompt=render_product_prompt(product), size="1024x1024", n=1, ) image_base64 = response.data[0].b64_json if not image_base64: raise RuntimeError("Image API response does not contain b64_json") output_path = Path("serum-product.png") output_path.write_bytes(base64.b64decode(image_base64)) print(f"Saved: {output_path}")

La llamada client.images.generate(...) y la decodificación de b64_json siguen el contrato actual del SDK. El modelo se lee desde BETTERTOKEN_IMAGE_MODEL; así puede cambiar sin reescribir la plantilla ni la lógica del negocio.

Bucle mínimo de una tarea por lotes

El siguiente bloque es pseudocódigo explícito de integración. save_job, generate_image y ApiError representan adaptadores del almacenamiento y del cliente API; no son métodos adicionales del SDK.

MAX_ATTEMPTS = 3 RETRYABLE_STATUS = {429, 500, 502, 503, 504} for sku in sku_rows: variables = validate_variables(sku) # antes de llamar a la API prompt = render_product_prompt(variables) job_id = uuid4().hex prompt_hash = sha256(prompt.encode()).hexdigest() save_job(job_id=job_id, sku_id=sku["id"], template_id="skincare_product_v3", prompt_hash=prompt_hash, status="pending") for attempt in range(1, MAX_ATTEMPTS + 1): save_job(job_id=job_id, status="running", attempt=attempt) try: result = generate_image(prompt) except ApiError as error: if error.status_code in {400, 401}: save_job(job_id=job_id, status="failed", error_code=error.status_code) break if error.status_code not in RETRYABLE_STATUS or attempt == MAX_ATTEMPTS: save_job(job_id=job_id, status="failed", error_code=error.status_code) break sleep(min(2 ** attempt, 8)) continue except TimeoutError: save_job(job_id=job_id, status="unknown", error_code="timeout") break # revisar Dashboard y almacenamiento antes de reenviar if not result.b64_json: save_job(job_id=job_id, status="failed", error_code="empty_output") break output_path = persist_png(job_id, result.b64_json) save_job(job_id=job_id, status="succeeded", output_path=output_path, model=result.model, attempt=attempt) break

El job_id local relaciona SKU, plantilla y archivo, pero no vuelve idempotente la solicitud remota. Tras un timeout, conserva el estado unknown, busca por hora en el Dashboard y revisa el almacenamiento antes de decidir un único reenvío.

Orden de diagnóstico

SíntomaComprobar primeroCorrecciónRevalidación
400Variables obligatorias, Model ID actual y size admitidoCorregir datos o parámetro; no repetir automáticamenteEjecutar un SKU de control y abrir el PNG
401Variable de clave cargada, propiedad de la clave y protocoloSustituir o recrear la clave sin registrarlaEnviar la solicitud mínima y localizar el estado en Dashboard
429Concurrencia y ritmo de tareasDetener nuevas tareas, reducir concurrencia y aplicar backoff limitadoDejar pasar una solicitud y recuperar carga gradualmente
5xxHora y número de intentosRepetir solo hasta MAX_ATTEMPTS; guardar hora y estadoProbar una solicitud tras una pausa sin cambiar la plantilla
TimeoutDashboard y almacenamientoMantener unknown; no asumir falloSi no hay registro ni archivo, permitir un reenvío con el mismo job_id local
b64_json vacío o fallo de decodificaciónFormato de respuesta, modelo y parámetros actualesGuardar el error sin datos de la clave y corregir lectura o configuraciónRepetir un SKU y comprobar que el PNG abre

Qué añadir antes de generar por lotes

Validar los datos antes de la solicitud

Un material vacío, marcado inesperado en product_name o texto libre en vez de una paleta aprobada altera el prompt. Comprueba campos, longitud y valores permitidos. Guarda con la tarea el hash del prompt, template_id y el identificador del SKU.

Limitar los reintentos

Un reintento después de un timeout puede crear otra imagen aunque la aplicación no recibiera la primera respuesta. Define un máximo de intentos, aplica espera progresiva y asigna un job_id. No repitas indefinidamente errores 400, 401 o de configuración del modelo: corrige primero los datos, la clave o la configuración.

Separar aceptación técnica y visual

HTTP 200 y un PNG válido confirman el éxito técnico. La composición, las deformaciones y la adecuación a la marca se revisan aparte. La tarea automática guarda archivo y metadatos; el siguiente paso aplica los criterios visuales.

Conciliar la solicitud con el uso

Busca la generación de control en el Dashboard por hora y revisa modelo, estado y cargo. Los campos disponibles muestran tokens de entrada, salida y caché. El Dashboard guarda metadatos de uso y gasto, no el prompt o la respuesta completos. Usa la página actual de modelos y precios para presupuestar y el registro de la solicitud para conocer el gasto real de la prueba.

Flujo de ejemplo para un catálogo

PIM / base de SKU ↓ categoría → template_id ↓ nombre / material / color / fondo ↓ validación de campos ↓ render del Prompt Template ↓ tarea con job_id ↓ Image API ↓ almacenamiento de objetos ↓ aceptación visual ↓ CMS / biblioteca de medios

El prompt se convierte en un objeto de producción versionado. Es posible saber qué plantilla creó cada archivo, comparar rechazos por versión y revertir un cambio sin rehacer toda la integración.

Lista de control antes de activar la cola

  • La plantilla se probó con productos típicos y casos límite.
  • Están definidos template_id, variables obligatorias y criterios de aceptación.
  • La API Key queda fuera del código y de los logs.
  • El Model ID procede del entorno o de configuración.
  • Una solicitud de prueba crea un archivo válido del tamaño esperado.
  • Los errores 400/401 exigen corregir datos o configuración.
  • Los errores 429/5xx tienen reintentos limitados.
  • Cada tarea se vincula con SKU, job_id, versión y almacenamiento.
  • La comprobación técnica y la aceptación visual están separadas.
  • Modelo, estado y gasto de la prueba se comprobaron en el Dashboard.

Cómo mejora la colaboración al separar responsabilidades

Genviso se ocupa del circuito interactivo: encontrar una dirección visual, comparar prompts y validar la plantilla antes de entregarla a desarrollo. BetterToken se ocupa del circuito de servidor: API Key, conexión compatible con OpenAI, llamada a un modelo disponible y registro de uso. Los equipos comparten un único contrato: Prompt Template, variables, versión y criterios de aceptación.

Para llevar la plantilla aprobada a un backend real y comprobar el gasto con un SKU representativo, crea tu propia API Key, ejecuta la solicitud mínima de la referencia de Image API y revisa modelo, estado y cargo en el Dashboard antes de conectar la cola.

¿Quieres optimizar tu flujo de trabajo con LLM?

Conecta modelos mediante una API, gestiona claves y controla el gasto en IA.