# Image Generation System - Comprehensive Gap Analysis

**Date:** January 2026  
**Status:** Audit Complete  
**Reviewer:** System Audit

## Executive Summary

This document provides a comprehensive audit of the image generation system, analyzing the flow from model configuration to image delivery, both for manual and automation workflows.

---

## 1. System Architecture Overview

### Current Flow
```
User Selects Quality Tier (basic/quality/quality_option2/premium)
        ↓
AIModelConfig (database) → provider, model_name, landscape_size, square_size
        ↓
process_image_generation_queue (Celery task)
        ↓
ai_core.generate_image() → provider-specific handler
        ↓
_generate_image_openai() / _generate_image_runware()
        ↓
Downloaded to /frontend/public/images/ai-images/
        ↓
Image record updated (Images model)
```

### Image Count Determination
```
User sets max_images (1-8) in Site Settings
        ↓
AISettings.get_effective_max_images(account)
        ↓
generate_image_prompts.py: 1 featured + max_images in_article
        ↓
Images created with positions: featured(0) + in_article(0,1,2,3...)
```

---

## 2. RESOLVED Issues (Previously Fixed)

### ✅ 2.1 Quality Tier Fallback
- **Issue:** `get_effective_quality_tier()` was returning hardcoded 'basic' instead of default model's tier
- **Fixed in:** `ai_settings.py` lines 196-232
- **Solution:** Now falls back to `AIModelConfig.is_default=True` model's `quality_tier`

### ✅ 2.2 Image Sizes from Database
- **Issue:** `tasks.py` had hardcoded `MODEL_LANDSCAPE_SIZES` dict
- **Fixed in:** `tasks.py` lines 242-260
- **Solution:** Now loads `landscape_size` and `square_size` from `AIModelConfig`

### ✅ 2.3 Settings Endpoint Default Tier
- **Issue:** `settings_views.py` returned hardcoded 'basic' as default tier
- **Fixed in:** `settings_views.py` lines 616-640
- **Solution:** Gets `default_tier` from `default_image_model.quality_tier`

### ✅ 2.4 Integration Views Dynamic Sizes
- **Issue:** Two endpoints in `integration_views.py` had hardcoded size lookup
- **Fixed:** Both endpoints now load from `AIModelConfig`

---

## 3. REMAINING Gaps (Action Required)

### 🔴 GAP-1: Hardcoded Size Constants in global_settings_models.py

**Location:** `backend/igny8_core/modules/system/global_settings_models.py` lines 180-188

**Code:**
```python
# Model-specific landscape sizes (square is always 1024x1024 for all models)
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)
}

# Default square size (universal across all models)
DEFAULT_SQUARE_SIZE = '1024x1024'
```

**Impact:** These constants are UNUSED but could cause confusion. They're legacy from before the AIModelConfig migration.

**Recommendation:** 
- [ ] Remove unused `MODEL_LANDSCAPE_SIZES` dict
- [ ] Remove unused `DEFAULT_SQUARE_SIZE` constant
- [ ] Add deprecation comment if keeping for reference

---

### 🔴 GAP-2: Hardcoded Size Fallbacks in Tasks

**Location:** `backend/igny8_core/ai/tasks.py` lines 254-260

**Code:**
```python
else:
    # Fallback sizes if no model config (should never happen)
    model_landscape_size = '1792x1024'
    model_square_size = '1024x1024'
    logger.warning(f"[process_image_generation_queue] No model config, using fallback sizes")
```

**Impact:** LOW - Fallback only triggers if database is misconfigured. But the hardcoded sizes may not match actual model requirements.

**Recommendation:**
- [ ] Consider failing gracefully with clear error instead of using fallback
- [ ] Or: Load fallback from a system default in database

---

### 🔴 GAP-3: Frontend VALID_SIZES_BY_MODEL Hardcoded

**Location:** `frontend/src/components/common/ImageGenerationCard.tsx` lines 52-55

**Code:**
```tsx
const VALID_SIZES_BY_MODEL: Record<string, string[]> = {
  'dall-e-3': ['1024x1024', '1024x1792', '1792x1024'],
  'dall-e-2': ['256x256', '512x512', '1024x1024'],
};
```

**Impact:** MEDIUM - Test image generation card only shows OpenAI sizes, not Runware/Bytedance sizes.

**Recommendation:**
- [ ] Fetch valid_sizes from AIModelConfig via API
- [ ] Or: Pass sizes from backend settings endpoint

---

### 🔴 GAP-4: Backend VALID_SIZES_BY_MODEL Hardcoded

**Location:** `backend/igny8_core/ai/constants.py` lines 40-43

**Code:**
```python
VALID_SIZES_BY_MODEL = {
    'dall-e-3': ['1024x1024', '1024x1792', '1792x1024'],
    'dall-e-2': ['256x256', '512x512', '1024x1024'],
}
```

**Impact:** MEDIUM - Used for OpenAI validation only. Runware models bypass this validation.

**Status:** PARTIAL - Only affects OpenAI validation. Runware has its own validation via provider-specific code.

**Recommendation:**
- [ ] Move validation to AIModelConfig.valid_sizes field
- [ ] Validate against model's valid_sizes from database

---

### 🔴 GAP-5: Missing Runware Model Size Validation

**Location:** `backend/igny8_core/ai/ai_core.py` lines 943-1050

**Code:** The `_generate_image_runware()` method does NOT validate sizes against `valid_sizes` from database.

**Impact:** LOW - Runware API will reject invalid sizes anyway, but error message won't be clear.

**Recommendation:**
- [ ] Add validation: check `size` against `AIModelConfig.valid_sizes` before API call
- [ ] Return clear error: "Size X is not valid for model Y"

---

### 🔴 GAP-6: Seedream Minimum Pixel Validation Hardcoded

**Location:** `backend/igny8_core/ai/ai_core.py` lines 1018-1027

**Code:**
```python
elif runware_model.startswith('bytedance:'):
    # Enforce minimum size for Seedream (min 3,686,400 pixels ~ 1920x1920)
    current_pixels = width * height
    if current_pixels < 3686400:
        # Use default Seedream square size
        inference_task['width'] = 2048
        inference_task['height'] = 2048
```

**Impact:** LOW - This hardcoded check works, but should come from database.

**Recommendation:**
- [ ] Add `min_pixels` field to AIModelConfig
- [ ] Check model.min_pixels instead of hardcoded 3686400

---

### 🔴 GAP-7: Provider-Specific Steps/CFGScale Hardcoded

**Location:** `backend/igny8_core/ai/ai_core.py` lines 995-1040

**Code:**
```python
if runware_model.startswith('bria:'):
    inference_task['steps'] = 20
    # ...
elif runware_model.startswith('runware:'):
    inference_task['steps'] = 20
    inference_task['CFGScale'] = 7
```

**Impact:** LOW - Works correctly but adding new models requires code changes.

**Recommendation:**
- [ ] Add `generation_params` JSON field to AIModelConfig
- [ ] Store steps, CFGScale, etc. in database per model

---

### 🔴 GAP-8: Image Count Not Per-Content Configurable

**Location:** System-wide setting only

**Current Behavior:**
- `max_images` is a global setting (site-wide)
- All articles get the same number of in_article images

**Impact:** MEDIUM - Users cannot set different image counts per article/keyword.

**Recommendation:**
- [ ] Add `images_count` field to Content model (nullable, inherits from site default)
- [ ] Or: Add to Keywords model for keyword-level override

---

### 🟡 GAP-9: Legacy generate_images.py Function (Partially Dead Code)

**Location:** `backend/igny8_core/ai/functions/generate_images.py`

**Issue:** `generate_images_core()` function exists but appears to be legacy. Main flow uses `process_image_generation_queue()` in tasks.py.

**Impact:** LOW - Code duplication, potential maintenance burden.

**Recommendation:**
- [ ] Audit if `generate_images.py` is actually used anywhere
- [ ] If not: Add deprecation warning or remove
- [ ] If used: Ensure it uses same dynamic config loading

---

### 🟡 GAP-10: No Validation of quality_tier Values

**Location:** Multiple locations

**Issue:** When user selects a quality_tier, there's no validation that:
1. The tier exists in AIModelConfig
2. The tier has an active model
3. The user's plan allows that tier

**Impact:** MEDIUM - Could lead to runtime errors if tier doesn't exist.

**Recommendation:**
- [ ] Add validation in settings save endpoint
- [ ] Return error if selected tier has no active model

---

## 4. Image Count Flow (Working Correctly)

### How image count works:

1. **User configures:**
   - `max_images` (1-8) in Site Settings → saved to AccountSettings

2. **Prompt generation:**
   ```python
   # generate_image_prompts.py
   max_images = AISettings.get_effective_max_images(account)  # e.g., 4
   # Creates: 1 featured + 4 in_article = 5 image prompts
   ```

3. **Image types:**
   - `featured` - Always 1, position=0, landscape size
   - `in_article` - Up to max_images, positions 0,1,2,3..., alternating square/landscape

4. **Size determination:**
   ```python
   # tasks.py
   if image.image_type == 'featured':
       image_size = featured_image_size  # landscape
   elif image.image_type == 'in_article':
       position = image.position or 0
       if position % 2 == 0:  # 0, 2
           image_size = square_size
       else:  # 1, 3
           image_size = landscape_size
   ```

**STATUS:** ✅ Working correctly. No gaps identified in image count logic.

---

## 5. Automation Flow (Working Correctly)

### Stage 6: Image Generation

**Location:** `automation_service.py` lines 1236-1400

**Flow:**
1. Query `Images.objects.filter(site=site, status='pending')`
2. For each image: `process_image_generation_queue.delay(image_ids=[image.id], ...)`
3. Monitor task completion
4. Update run progress

**STATUS:** ✅ Uses same task as manual generation. Consistent behavior.

---

## 6. Model Provider Support Matrix

| Provider | Models | Status | Gaps |
|----------|--------|--------|------|
| OpenAI | dall-e-3, dall-e-2 | ✅ Working | Valid sizes hardcoded |
| Runware | runware:97@1 | ✅ Working | No size validation |
| Runware | bria:10@1 | ✅ Working | Steps hardcoded |
| Runware | google:4@2 | ✅ Working | Resolution param hardcoded |
| Runware | bytedance:seedream@4.5 | ✅ Working | Min pixels hardcoded |

---

## 7. Priority Action Items

### High Priority
1. **GAP-4/5:** Implement database-driven size validation for all providers
2. **GAP-10:** Add quality_tier validation on save

### Medium Priority
3. **GAP-6/7:** Move provider-specific params to AIModelConfig.generation_params
4. **GAP-8:** Consider per-content image count override

### Low Priority
5. **GAP-1:** Clean up unused constants
6. **GAP-9:** Audit and deprecate legacy code
7. **GAP-3:** Fetch valid sizes from API in frontend

---

## 8. Recommendations Summary

### Short-term (Before Launch)
- Ensure all hardcoded fallbacks are clearly logged
- Test each model tier end-to-end

### Medium-term (Post-Launch)
- Migrate all hardcoded params to AIModelConfig fields
- Add model validation on quality_tier save

### Long-term (Future Enhancement)
- Per-content image count override
- Per-keyword image style override
- Image regeneration without deleting existing

---

## Appendix: Key Files Reference

| File | Purpose |
|------|---------|
| `ai/tasks.py` | Main image generation Celery task |
| `ai/ai_core.py` | Provider-specific generation methods |
| `ai/functions/generate_image_prompts.py` | Extract prompts from content |
| `modules/system/ai_settings.py` | System defaults + account overrides |
| `modules/system/settings_views.py` | Frontend settings API |
| `business/billing/models.py` | AIModelConfig model |
| `business/automation/services/automation_service.py` | Automation Stage 6 |
