image gen mess

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-03 22:31:30 +00:00
parent f518e1751b
commit c4de8994dd
9 changed files with 453 additions and 221 deletions

View File

@@ -403,7 +403,7 @@ class GlobalIntegrationSettingsAdmin(Igny8ModelAdmin):
"description": "Global Runware image generation configuration"
}),
("Universal Image Settings", {
"fields": ("image_quality", "image_style", "max_in_article_images", "desktop_image_size", "mobile_image_size"),
"fields": ("image_quality", "image_style", "max_in_article_images", "desktop_image_size"),
"description": "Image quality, style, and sizing settings that apply to ALL providers (DALL-E, Runware, etc.)"
}),
("Status", {

View File

@@ -198,14 +198,28 @@ class GlobalIntegrationSettings(models.Model):
('hd', 'HD'),
]
IMAGE_STYLE_CHOICES = [
('vivid', 'Vivid'),
('natural', 'Natural'),
('realistic', 'Realistic'),
('artistic', 'Artistic'),
('cartoon', 'Cartoon'),
# Image style choices with descriptions - used by both Runware and OpenAI
# Format: (value, label, description)
IMAGE_STYLE_OPTIONS = [
('photorealistic', 'Photorealistic', 'Ultra realistic photography style, natural lighting, real world look'),
('illustration', 'Illustration', 'Digital illustration, clean lines, artistic but not realistic'),
('3d_render', '3D Render', 'Computer generated 3D style, modern, polished, depth and lighting'),
('minimal_flat', 'Minimal / Flat Design', 'Simple shapes, flat colors, modern UI and graphic design look'),
('artistic', 'Artistic / Painterly', 'Expressive, painted or hand drawn aesthetic'),
('cartoon', 'Cartoon / Stylized', 'Playful, exaggerated forms, animated or mascot style'),
]
# Choices for Django model field (value, label only)
IMAGE_STYLE_CHOICES = [(opt[0], opt[1]) for opt in IMAGE_STYLE_OPTIONS]
# OpenAI DALL-E specific styles with descriptions (subset)
DALLE_STYLE_OPTIONS = [
('natural', 'Natural', 'More realistic, photographic style'),
('vivid', 'Vivid', 'Hyper-real, dramatic, artistic'),
]
DALLE_STYLE_CHOICES = [(opt[0], opt[1]) for opt in DALLE_STYLE_OPTIONS]
IMAGE_SERVICE_CHOICES = [
('openai', 'OpenAI DALL-E'),
('runware', 'Runware'),
@@ -335,8 +349,8 @@ class GlobalIntegrationSettings(models.Model):
help_text="Default image quality for all providers (accounts can override if plan allows)"
)
image_style = models.CharField(
max_length=20,
default='realistic',
max_length=30,
default='photorealistic',
choices=IMAGE_STYLE_CHOICES,
help_text="Default image style for all providers (accounts can override if plan allows)"
)

View File

@@ -723,7 +723,7 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
# Universal image settings (applies to all providers)
for key in ['image_type', 'image_quality', 'image_style', 'max_in_article_images', 'image_format',
'desktop_enabled', 'mobile_enabled', 'featured_image_size', 'desktop_image_size']:
'desktop_enabled', 'featured_image_size', 'desktop_image_size']:
if key in config:
clean_config[key] = config[key]
@@ -844,9 +844,17 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
}
elif integration_type == 'image_generation':
# Model-specific landscape sizes
MODEL_LANDSCAPE_SIZES = {
'runware:97@1': '1280x768',
'bria:10@1': '1344x768',
'google:4@2': '1376x768',
}
# Get default service and model based on global settings
default_service = global_settings.default_image_service
default_model = global_settings.dalle_model if default_service == 'openai' else global_settings.runware_model
model_landscape_size = MODEL_LANDSCAPE_SIZES.get(default_model, '1280x768')
response_data = {
'id': 'image_generation',
@@ -862,10 +870,8 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
'max_in_article_images': global_settings.max_in_article_images,
'image_format': 'webp',
'desktop_enabled': True,
'mobile_enabled': True,
'featured_image_size': global_settings.dalle_size,
'featured_image_size': model_landscape_size, # Model-specific landscape
'desktop_image_size': global_settings.desktop_image_size,
'mobile_image_size': global_settings.mobile_image_size,
'using_global': True,
}
@@ -897,7 +903,7 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
response_data['runwareModel'] = config['runwareModel']
# Universal image settings
for key in ['image_type', 'image_quality', 'image_style', 'max_in_article_images', 'image_format',
'desktop_enabled', 'mobile_enabled', 'featured_image_size', 'desktop_image_size']:
'desktop_enabled', 'featured_image_size', 'desktop_image_size']:
if key in config:
response_data[key] = config[key]
except IntegrationSettings.DoesNotExist:
@@ -923,9 +929,18 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
@action(detail=False, methods=['get'], url_path='image_generation', url_name='image_generation_settings')
def get_image_generation_settings(self, request):
"""Get image generation settings for current account
Normal users fallback to system account (aws-admin) settings
"""Get image generation settings for current account.
Architecture:
1. If account has IntegrationSettings override -> use it (with GlobalIntegrationSettings as fallback for missing fields)
2. Otherwise -> use GlobalIntegrationSettings (platform-wide defaults)
Note: API keys are ALWAYS from GlobalIntegrationSettings (accounts cannot override API keys).
Account IntegrationSettings only store model/parameter overrides.
"""
from .models import IntegrationSettings
from .global_settings_models import GlobalIntegrationSettings
account = getattr(request, 'account', None)
if not account:
@@ -933,89 +948,90 @@ class IntegrationSettingsViewSet(viewsets.ViewSet):
user = getattr(request, 'user', None)
if user and hasattr(user, 'is_authenticated') and user.is_authenticated:
account = getattr(user, 'account', None)
# Fallback to default account
if not account:
from igny8_core.auth.models import Account
try:
account = Account.objects.first()
except Exception:
pass
if not account:
return error_response(
error='Account not found',
status_code=status.HTTP_401_UNAUTHORIZED,
request=request
)
# Get GlobalIntegrationSettings (platform defaults - always available)
global_settings = GlobalIntegrationSettings.get_instance()
# Model-specific landscape sizes (from GlobalIntegrationSettings)
MODEL_LANDSCAPE_SIZES = {
'runware:97@1': '1280x768', # Hi Dream Full landscape
'bria:10@1': '1344x768', # Bria 3.2 landscape (16:9)
'google:4@2': '1376x768', # Nano Banana landscape (16:9)
'dall-e-3': '1792x1024', # DALL-E 3 landscape
'dall-e-2': '1024x1024', # DALL-E 2 square only
}
try:
from .models import IntegrationSettings
from igny8_core.auth.models import Account
# Try to get settings for user's account first
try:
integration = IntegrationSettings.objects.get(
account=account,
integration_type='image_generation',
is_active=True
)
logger.info(f"[get_image_generation_settings] Found settings for account {account.id}")
except IntegrationSettings.DoesNotExist:
# Fallback to system account (aws-admin) settings - normal users use centralized settings
logger.info(f"[get_image_generation_settings] No settings for account {account.id}, falling back to system account")
# Check if account has specific overrides
account_config = {}
if account:
try:
system_account = Account.objects.get(slug='aws-admin')
integration = IntegrationSettings.objects.get(
account=system_account,
account=account,
integration_type='image_generation',
is_active=True
)
logger.info(f"[get_image_generation_settings] Using system account (aws-admin) settings")
except (Account.DoesNotExist, IntegrationSettings.DoesNotExist):
logger.error("[get_image_generation_settings] No image generation settings found in aws-admin account")
return error_response(
error='Image generation settings not configured in aws-admin account',
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
request=request
)
account_config = integration.config or {}
logger.info(f"[get_image_generation_settings] Found account {account.id} override: {list(account_config.keys())}")
except IntegrationSettings.DoesNotExist:
logger.info(f"[get_image_generation_settings] No override for account {account.id if account else 'None'}, using GlobalIntegrationSettings")
config = integration.config or {}
# Build response using account overrides with global fallbacks
provider = account_config.get('provider') or global_settings.default_image_service
# Debug: Log what's actually in the config
logger.info(f"[get_image_generation_settings] Full config: {config}")
logger.info(f"[get_image_generation_settings] Config keys: {list(config.keys())}")
logger.info(f"[get_image_generation_settings] model field: {config.get('model')}")
logger.info(f"[get_image_generation_settings] imageModel field: {config.get('imageModel')}")
# Get model based on provider
if provider == 'runware':
model = account_config.get('model') or account_config.get('imageModel') or global_settings.runware_model
else:
model = account_config.get('model') or account_config.get('imageModel') or global_settings.dalle_model
# Get model - try 'model' first, then 'imageModel' as fallback
model = config.get('model') or config.get('imageModel') or 'dall-e-3'
# Get model-specific landscape size
model_landscape_size = MODEL_LANDSCAPE_SIZES.get(model, '1280x768')
default_featured_size = model_landscape_size if provider == 'runware' else '1792x1024'
# Set defaults for image sizes if not present
provider = config.get('provider', 'openai')
default_featured_size = '1280x832' if provider == 'runware' else '1024x1024'
# Get image style with provider-specific defaults
image_style = account_config.get('image_type') or global_settings.image_style
# Style options from GlobalIntegrationSettings model - loaded dynamically
# Runware: Uses all styles with prompt enhancement
# OpenAI DALL-E: Only supports 'natural' or 'vivid'
if provider == 'openai':
# Get DALL-E styles from model definition
available_styles = [
{'value': opt[0], 'label': opt[1], 'description': opt[2]}
for opt in GlobalIntegrationSettings.DALLE_STYLE_OPTIONS
]
# Map stored style to DALL-E compatible
if image_style not in ['vivid', 'natural']:
image_style = 'natural' # Default to natural for photorealistic
else:
# Get Runware styles from model definition
available_styles = [
{'value': opt[0], 'label': opt[1], 'description': opt[2]}
for opt in GlobalIntegrationSettings.IMAGE_STYLE_OPTIONS
]
# Default to photorealistic for Runware if not set
if not image_style or image_style in ['natural', 'vivid']:
image_style = 'photorealistic'
logger.info(f"[get_image_generation_settings] Returning: provider={provider}, model={model}, image_style={image_style}")
return success_response(
data={
'config': {
'provider': config.get('provider', 'openai'),
'provider': provider,
'model': model,
'image_type': config.get('image_type', 'realistic'),
'max_in_article_images': config.get('max_in_article_images'),
'image_format': config.get('image_format', 'webp'),
'desktop_enabled': config.get('desktop_enabled', True),
'mobile_enabled': config.get('mobile_enabled', True),
'featured_image_size': config.get('featured_image_size', default_featured_size),
'desktop_image_size': config.get('desktop_image_size', '1024x1024'),
'image_type': image_style,
'available_styles': available_styles, # Loaded from GlobalIntegrationSettings model
'max_in_article_images': account_config.get('max_in_article_images') or global_settings.max_in_article_images,
'image_format': account_config.get('image_format', 'webp'),
'desktop_enabled': account_config.get('desktop_enabled', True),
'featured_image_size': account_config.get('featured_image_size') or default_featured_size,
'desktop_image_size': account_config.get('desktop_image_size') or global_settings.desktop_image_size,
}
},
request=request
)
except IntegrationSettings.DoesNotExist:
return error_response(
error='Image generation settings not configured',
status_code=status.HTTP_404_NOT_FOUND,
request=request
)
except Exception as e:
logger.error(f"[get_image_generation_settings] Error: {str(e)}", exc_info=True)
return error_response(