Generacion con IA
Documento tecnico que describe el sistema de generacion de invitaciones con Inteligencia Artificial en Nvito: proveedores, flujo de generacion, analisis de vision, cuotas por plan, tracking de uso y cache.
| Campo | Valor |
|---|---|
| Version | 1.0 |
| Fecha | Febrero 2026 |
| Estado | En revision |
| Audiencia | Equipo de desarrollo, arquitectos, stakeholders |
1. Proveedores de IA
Nvito implementa un sistema multi-proveedor con seleccion automatica y fallback. Ambos proveedores se gestionan a traves de la interfaz comun AIProvider y estan protegidos por circuit breakers individuales (libreria opossum).
1.1 Proveedores Disponibles
| Proveedor | Modelo por defecto | SDK | Timeout | Uso principal |
|---|---|---|---|---|
| OpenAI | gpt-4o | openai | 30s | Generacion de textos, extraccion de colores (Vision) |
| Anthropic | claude-sonnet-4-5-20250929 | @anthropic-ai/sdk | 120s | Generacion de textos, analisis de diseno (Vision) |
1.2 Interfaz Comun (AIProvider)
Ambos proveedores implementan la interfaz AIProvider definida en providers/ai-provider.interface.ts:
interface AIProvider {
generate(options: GenerationOptions): Promise<GenerationResult>;
extractColors(imageUrl: string): Promise<ColorExtractionResult>;
getModelName(): string;
getProviderName(): string;
isAvailable(): boolean;
}
El resultado de cada generacion (GenerationResult) incluye:
| Campo | Tipo | Descripcion |
|---|---|---|
content | string | JSON con los textos generados |
tokensUsed | number | Total de tokens consumidos (input + output) |
model | string | Modelo exacto utilizado |
latencyMs | number | Tiempo de respuesta en milisegundos |
1.3 Sistema de Fallback
La seleccion de proveedor sigue esta logica implementada en selectProvider():
- Si el usuario elige
openaiy esta disponible, se usa OpenAI. - Si el usuario elige
claudey esta disponible, se usa Claude. - Si el modo es
auto(por defecto), se prefiere OpenAI; si no esta disponible, se usa Claude. - Si ningun proveedor esta disponible, se lanza
BadRequestException.
La disponibilidad se verifica con isAvailable(), que comprueba la existencia del API key configurado.
1.4 Circuit Breaker
Cada proveedor implementa un circuit breaker con la siguiente configuracion:
| Parametro | OpenAI | Claude |
|---|---|---|
| Timeout | 30,000 ms | 120,000 ms |
| Error Threshold | 50% | 50% |
| Reset Timeout | 60,000 ms | 60,000 ms |
| Volume Threshold | 5 requests | 5 requests |
Cuando el circuit breaker se abre (mas del 50% de errores en las ultimas 5 peticiones), todas las llamadas fallan inmediatamente durante 60 segundos, permitiendo la recuperacion del servicio.
2. Flujo de Generacion
El flujo principal de generacion se ejecuta a traves del endpoint POST /ai-generation/generate. La IA genera exclusivamente textos emotivos (v2: text-only). Estos textos se combinan con datos reales del evento para construir un InvitationSchemaV2 que los templates artesanales consumen.
2.1 Diagrama de Secuencia
2.2 Enriquecimiento de Prompt
El servicio EnrichPromptService inyecta contexto del evento antes de enviar el prompt al proveedor de IA. La informacion enriquecida incluye:
- Datos del evento: nombre, tipo, fecha, hora, descripcion, codigo de vestimenta, ubicacion.
- Conteo de invitados: total de guests registrados o
maxCapacity. - Secciones a generar: determinadas dinamicamente segun los servicios habilitados en
serviceConfig.enabledServices. - Secciones opcionales: gallery, itinerary, accommodation, registry, sponsors, prayer, thankYou, dressCode.
- Secciones por tipo de evento: story (bodas, XV), faq (eventos grandes o formales).
El prompt enriquecido incluye instrucciones estrictas:
- Generar solo textos emotivos en espanol (Mexico/Latinoamerica).
- No generar colores, fuentes ni aspectos de diseno.
- Para
hero, generar solo subtitle (el titulo es el nombre real del evento). - Para
event_detailsylocation, generar solo titulo de seccion (datos reales se inyectan automaticamente).
2.3 Validacion y Construccion del Schema
Despues de recibir la respuesta de la IA:
- Validacion:
ValidationService.validateTextsJSON()valida la estructura del JSON generado usando schemas Zod (invitation-schema.zod.ts). - Construccion:
buildSchemaV2()combina los textos generados con datos reales del evento para crear elInvitationSchemaV2final. - Persistencia: El schema se guarda en la invitacion y se crea un registro de version via
VersionManagerService.
2.4 Calculo de Costo
Los costos se calculan por millon de tokens segun la tabla de precios:
| Modelo | Input (USD/1M tokens) | Output (USD/1M tokens) |
|---|---|---|
gpt-4o | $2.50 | $10.00 |
gpt-4o-mini | $0.15 | $0.60 |
claude-sonnet-4-5-20250929 | $3.00 | $15.00 |
3. Analisis de Vision
El sistema permite generar invitaciones a partir de imagenes de referencia. El usuario sube un archivo (imagen o PDF) y el sistema extrae colores, estilos y elementos de diseno para enriquecer la generacion.
3.1 Proveedores de Vision
El modulo de Vision opera independientemente del modulo de generacion de texto, con tres proveedores:
| Proveedor | Tipo | Modelo | Uso |
|---|---|---|---|
| OpenAI Vision | IA | gpt-4o | Extraccion de colores y analisis de diseno |
| Claude Vision | IA | claude-sonnet-4-5-20250929 | Extraccion de colores y analisis de diseno |
| Local | Libreria | node-vibrant / sharp | Extraccion basica de colores sin IA |
El VisionProviderService gestiona la seleccion y el fallback entre proveedores de vision:
- Modo auto: cascada segun el orden configurado (
openai -> claude -> local). - Modo explicito: el usuario selecciona un proveedor especifico.
- Fallback automatico: si un proveedor falla y el modo no es explicito, se intenta el siguiente en la lista.
3.2 Diagrama de Secuencia - Analisis de Vision
3.3 Pipeline de Procesamiento de Imagen
El DesignExtractionService ejecuta el siguiente pipeline:
- Validacion: formato permitido (
JPEG,PNG,WebP,GIF), tamano maximo 20 MB. - Optimizacion: redimensionamiento a 1920x1920 max (sin ampliacion) y compresion JPEG al 85% usando
sharp. - Extraccion de colores: retorna
ColorPaletteconcolors[],dominantColor, ypalette(primary, secondary, accent, background, text). - Analisis de diseno: retorna
DesignAnalysisconcolorScheme(vibrant/muted/monochrome/pastel),styleHints[](modern, elegant, romantic, etc.) ytypography. - Analisis de esquema de color: determina tipo (monocromatico, analogo, complementario, triadico), armonia, contraste y temperatura (calido/frio/neutro).
- Sugerencia de fuentes: mapeo de estilos a familias tipograficas:
| Estilo detectado | Heading | Body | Accent |
|---|---|---|---|
| Elegant / Formal | Playfair Display | Lora | Great Vibes |
| Modern / Minimalist | Montserrat | Inter | Raleway |
| Playful / Fun | Quicksand | Nunito | Pacifico |
| Romantic | Dancing Script | Crimson Text | Tangerine |
| Default | Poppins | Open Sans | Satisfy |
- Prompt enriquecido: se construye con la paleta exacta, esquema de color, hints de estilo y tipografia sugerida.
4. Cuotas por Plan
El sistema de cuotas (QuotaService) controla la cantidad de generaciones permitidas por organizacion, con limites mensuales y diarios segun el plan contratado.
4.1 Limites por Plan
| Plan | Generaciones/mes | Generaciones/dia | Notas |
|---|---|---|---|
| Free | 5 | 2 | Ideal para prueba |
| Starter | 20 | 10 | Eventos pequenos |
| Pro | 100 | 30 | Eventos frecuentes |
| VIP | Ilimitado (-1) | Ilimitado (-1) | Sin restricciones |
4.2 Mecanismo de Control
El flujo de verificacion de cuotas es:
- Verificacion:
checkQuotaOrThrow(organizationId)consulta el registroAIQuotade la organizacion. - Reset automatico: si el mes o dia cambio respecto al registro, los contadores se reinician a cero (medianoche UTC).
- Validacion de limites: se compara
monthlyUsed < monthlyLimitydailyUsed < dailyLimit. - Excepcion controlada: si se excede el limite diario, se lanza
ForbiddenExceptioncon mensaje indicando que se reinicia a medianoche UTC. Si se excede el mensual, se sugiere actualizar el plan. - Ambiente de desarrollo: en
NODE_ENV=development, la verificacion de cuotas se omite para facilitar pruebas. - Super Admins: las organizaciones sin
organizationId(Super Admins) no tienen restriccion de cuota.
4.3 Incremento de Uso
Despues de cada generacion exitosa:
await quotaService.incrementUsage(organizationId, costUsd);
Esto incrementa monthlyUsed, dailyUsed, totalCostUsd y monthCostUsd de forma atomica en la base de datos.
4.4 Endpoint de Consulta
El endpoint GET /ai-generation/quota retorna la informacion completa de cuota:
interface QuotaInfo {
canGenerate: boolean;
monthlyLimit: number;
monthlyUsed: number;
monthlyRemaining: number;
dailyLimit: number;
dailyUsed: number;
dailyRemaining: number;
totalCostUsd: number;
monthCostUsd: number;
}
5. Tracking de Generaciones
Cada generacion se registra en el modelo AIGeneration de Prisma, proporcionando un historial completo de uso, costos y rendimiento.
5.1 Modelo AIGeneration
| Campo | Tipo | Descripcion |
|---|---|---|
id | string | Identificador unico |
organizationId | string? | Organizacion que genero (null para Super Admins) |
userId | string | Usuario que solicito la generacion |
invitationId | string? | Invitacion asociada |
provider | string | Proveedor usado (openai, claude, cache) |
model | string | Modelo exacto (gpt-4o, claude-sonnet-4-5-20250929, cached) |
prompt | string | Prompt original del usuario |
designInput | JSON? | Input de diseno (colores, URL de referencia, estilo) |
generatedSchema | JSON? | Schema generado (InvitationSchemaV2 o textos) |
status | string | Estado: pending, completed, failed |
tokensUsed | number? | Total de tokens consumidos |
costUsd | Decimal? | Costo en USD de la generacion |
latencyMs | number? | Tiempo de respuesta en milisegundos |
errorMessage | string? | Mensaje de error si fallo |
startedAt | DateTime | Timestamp de inicio |
completedAt | DateTime? | Timestamp de finalizacion |
5.2 Ciclo de Vida del Registro
- Creacion: al iniciar la generacion, se crea con
status: pending. - Exito: se actualiza con
status: completed, el schema generado, tokens, costo y latencia. - Fallo: se actualiza con
status: failedy elerrorMessage. - Cache: si se sirve desde cache, se registra con
provider: cache,model: cached,costUsd: 0,tokensUsed: 0.
5.3 Endpoints de Consulta
| Metodo | Endpoint | Descripcion |
|---|---|---|
GET | /ai-generation/generations/:id | Obtener detalle de una generacion |
GET | /ai-generation/generations?limit=20&offset=0 | Listar generaciones de la organizacion (paginado) |
6. Cache
El servicio AiCacheService implementa un cache en Redis para evitar llamadas repetidas a los proveedores de IA cuando se reciben prompts similares.
6.1 Funcionamiento
- Clave de cache: hash SHA-256 del JSON compuesto por
{ prompt, designInput }. - Prefijo:
ai:generation:. - TTL: 3600 segundos (1 hora) por defecto, configurable via
AI_CACHE_TTL. - Almacenamiento: Redis con
SETEXpara TTL automatico.
6.2 Flujo de Cache
- Consulta: antes de llamar al proveedor de IA, se busca en cache con
cacheService.get(prompt, designInput). - Cache hit: se valida el JSON cacheado, se construye el schema, se crea registro con
provider: cachey costo $0. - Cache miss: se procede con la generacion normal y al completarse, se almacena con
cacheService.set(prompt, content, designInput). - Invalidacion: disponible via
invalidate(prompt, designInput)para forzar regeneracion. - Limpieza total:
clearAll()elimina todas las claves con prefijoai:generation:*.
6.3 Configuracion
| Variable de entorno | Descripcion | Default |
|---|---|---|
AI_CACHE_ENABLED | Habilitar/deshabilitar cache | true |
AI_CACHE_TTL | Tiempo de vida en segundos | 3600 (1 hora) |
Si Redis no esta disponible, el cache se deshabilita automaticamente y todas las peticiones se procesan directamente contra los proveedores de IA.
7. Configuracion
Toda la configuracion del modulo de IA se centraliza en src/config/ai.config.ts y se inyecta via ConfigService de NestJS.
7.1 Variables de Entorno - Proveedores de Generacion
| Variable | Descripcion | Default |
|---|---|---|
OPENAI_API_KEY | API key de OpenAI | Requerido |
OPENAI_DEFAULT_MODEL | Modelo de generacion OpenAI | gpt-4o |
OPENAI_MAX_TOKENS | Tokens maximos de respuesta OpenAI | 4000 |
OPENAI_TEMPERATURE | Temperatura de generacion OpenAI | 0.7 |
ANTHROPIC_API_KEY | API key de Anthropic | Requerido |
CLAUDE_DEFAULT_MODEL | Modelo de generacion Claude | claude-sonnet-4-5-20250929 |
CLAUDE_MAX_TOKENS | Tokens maximos de respuesta Claude | 4000 |
CLAUDE_TEMPERATURE | Temperatura de generacion Claude | 0.7 |
7.2 Variables de Entorno - Vision
| Variable | Descripcion | Default |
|---|---|---|
VISION_PROVIDER_DEFAULT | Provider de vision por defecto | auto |
VISION_AUTO_FALLBACK | Habilitar fallback automatico | true |
VISION_FALLBACK_ORDER | Orden de fallback (separado por comas) | openai,claude,local |
VISION_MAX_IMAGE_SIZE_MB | Tamano maximo de imagen en MB | 10 |
VISION_OPENAI_ENABLED | Habilitar OpenAI Vision | true |
OPENAI_VISION_MODEL | Modelo de vision OpenAI | gpt-4o |
VISION_CLAUDE_ENABLED | Habilitar Claude Vision | true |
CLAUDE_VISION_MODEL | Modelo de vision Claude | claude-sonnet-4-5-20250929 |
VISION_LOCAL_ENABLED | Habilitar procesamiento local | true |
VISION_LOCAL_QUALITY | Calidad de extraccion local | 5 |
VISION_LOCAL_COLOR_COUNT | Cantidad de colores a extraer (local) | 64 |
VISION_LOCAL_MAX_IMAGE_SIZE | Tamano max imagen local (px) | 800 |
7.3 Variables de Entorno - Cache y Cuotas
| Variable | Descripcion | Default |
|---|---|---|
AI_CACHE_ENABLED | Habilitar cache de generacion | true |
AI_CACHE_TTL | TTL del cache en segundos | 3600 |
Las cuotas se configuran directamente en ai.config.ts bajo la clave quotas (ver seccion 4.1).
7.4 Estructura del Modulo
src/modules/ai-generation/
ai-generation.module.ts # Modulo NestJS
ai-generation.controller.ts # Endpoints REST
ai-generation.service.ts # Servicio principal de generacion
cache.service.ts # Cache Redis para generaciones
quota.service.ts # Control de cuotas por plan
dto/
generate-from-prompt.dto.ts # DTO para generacion desde prompt
generate-from-design.dto.ts # DTO para generacion desde diseno
modify-invitation.dto.ts # DTO para modificacion conversacional
generation-result.dto.ts # DTO de respuesta
interfaces/
vision-provider.interface.ts # Interfaz para proveedores de vision
providers/
ai-provider.interface.ts # Interfaz comun de proveedores IA
openai.provider.ts # Proveedor OpenAI (generacion + colores)
claude.provider.ts # Proveedor Claude (generacion + colores)
openai-vision.provider.ts # Proveedor OpenAI Vision
claude-vision.provider.ts # Proveedor Claude Vision
local-vision.provider.ts # Proveedor local (node-vibrant)
prompts/
invitation-system-prompt.ts # System prompt para generacion
schemas/
invitation-schema.zod.ts # Schema Zod de validacion
validation.service.ts # Servicio de validacion de respuestas
services/
design-extraction.service.ts # Extraccion de contexto de diseno
enrich-prompt.service.ts # Enriquecimiento de prompt con evento
vision-provider.service.ts # Orquestador de proveedores de vision
7.5 Endpoints Disponibles
| Metodo | Endpoint | Descripcion | Auth |
|---|---|---|---|
POST | /ai-generation/generate | Generar invitacion desde prompt | ClerkAuth |
POST | /ai-generation/generate-from-design | Generar desde imagen de referencia | ClerkAuth |
POST | /ai-generation/modify | Modificar invitacion existente con IA | ClerkAuth |
GET | /ai-generation/generations/:id | Obtener detalle de generacion | ClerkAuth |
GET | /ai-generation/generations | Listar generaciones (paginado) | ClerkAuth |
GET | /ai-generation/quota | Consultar cuota de la organizacion | ClerkAuth |