Files
igny8/AI-MODELS-DATABASE-CONFIGURATION-PLAN.md
2025-12-25 01:59:23 +00:00

30 KiB
Raw Blame History

**mkae sure to use exact max tokens and corret syntax based on differnet model for max tokens, adn make it configurebale in backeend for max tokens per ai fucntion.

AI MODELS DATABASE CONFIGURATION - IMPLEMENTATION PLAN

Date: December 24, 2025
Status: Planning Phase
Priority: HIGH - Architecture Enhancement


EXECUTIVE SUMMARY

Move AI model pricing from hardcoded constants (MODEL_RATES, IMAGE_MODEL_RATES) to database-driven configuration via new AIModelConfig model. This enables dynamic pricing updates, multi-provider support, and full Django Admin control without code deployments.


CRITICAL UNDERSTANDING: TWO DIFFERENT CREDIT CALCULATION METHODS

METHOD 1: TEXT MODELS (Token-Based Calculation)

How It Works:

  1. User triggers AI function (clustering, content generation, ideas, etc.)
  2. Request sent to OpenAI with prompt
  3. OpenAI returns response with actual token usage:
    • input_tokens: 2518 (tokens in the prompt)
    • output_tokens: 242 (tokens in the response)
    • model: "gpt-4o-mini"
  4. Backend calculates credits AFTER AI call based on:
    • Total tokens = input_tokens + output_tokens
    • Configuration: CreditCostConfig.tokens_per_credit (e.g., 150)
    • Formula: credits = CEIL(total_tokens ÷ tokens_per_credit)
    • Apply minimum: MAX(calculated_credits, min_credits)
  5. Credits deducted based on actual usage, not estimate

Example:

Operation: Clustering
Tokens: 2518 input + 242 output = 2760 total
Config: 150 tokens per credit
Calculation: 2760 ÷ 150 = 18.4 → CEIL = 19 credits
Min Credits: 10
Final: MAX(19, 10) = 19 credits charged

Models Using This Method:

  • gpt-4.1
  • gpt-4o-mini
  • gpt-4o
  • gpt-5.1
  • gpt-5.2
  • All text generation models

Key Point: Credits are NOT known until after AI response because we need actual token usage.


METHOD 2: IMAGE MODELS (Per-Image Fixed Cost)

How It Works:

  1. User triggers image generation
  2. Credits calculated BEFORE AI call based on:
    • Number of images requested (n=1, 2, 3, 4)
    • Image size (1024x1024, 1024x1792, 1792x1024, etc.)
    • Model (dall-e-2, dall-e-3)
  3. Fixed cost per image from configuration
  4. Credits deducted before generation
  5. No token calculation involved

Example:

Operation: Generate 2 images
Model: dall-e-3
Size: 1024x1792
Config: 5 credits per image (from CreditCostConfig.min_credits)
Calculation: 2 images × 5 credits = 10 credits
Final: 10 credits charged (known before AI call)

Models Using This Method:

  • dall-e-2
  • dall-e-3
  • gpt-image-1
  • gpt-image-1-mini

Key Point: Credits are known before AI call because it's a fixed rate per image.


WHY THIS MATTERS FOR THE DATABASE MODEL

The AIModelConfig model must support BOTH calculation methods:

Field Text Models Image Models
input_cost_per_1m Required Not Used
output_cost_per_1m Required Not Used
cost_per_image Not Used Required
valid_sizes Not Used Required (JSON)
context_window Required Not Used
max_output_tokens Required Not Used

Credit Calculation Logic:

IF model_type == 'text':
    # AFTER AI call
    total_tokens = input_tokens + output_tokens
    cost_usd = (input_tokens × input_cost_per_1m + output_tokens × output_cost_per_1m) ÷ 1,000,000
    credits = calculate_from_tokens(total_tokens, operation_config)
    
ELIF model_type == 'image':
    # BEFORE AI call
    cost_usd = cost_per_image × num_images
    credits = min_credits_per_image × num_images  # From CreditCostConfig

PHASE 1: CREATE NEW DATABASE MODEL

File: backend/igny8_core/business/billing/models.py

New Model: AIModelConfig

Field Specifications

Basic Information

  • model_name (CharField, max_length=100, unique=True)

    • Examples: "gpt-4o-mini", "dall-e-3", "gpt-5.1"
    • Used in API calls and configuration
  • display_name (CharField, max_length=200)

    • Examples: "GPT-4o mini - Fast & Affordable", "DALL-E 3 - High Quality Images"
    • Shown in Django Admin and frontend dropdowns
  • model_type (CharField, max_length=20, choices)

    • Choices: "text", "image", "embedding"
    • Determines which pricing fields are used
  • provider (CharField, max_length=50, choices)

    • Choices: "openai", "anthropic", "runware", "google"
    • Future-proof for multi-provider support

Text Model Pricing (Only for model_type='text')

  • input_cost_per_1m (DecimalField, max_digits=10, decimal_places=4, null=True)

    • Cost per 1 million input tokens (USD)
    • Example: 0.15 for gpt-4o-mini
  • output_cost_per_1m (DecimalField, max_digits=10, decimal_places=4, null=True)

    • Cost per 1 million output tokens (USD)
    • Example: 0.60 for gpt-4o-mini
  • context_window (IntegerField, null=True)

    • Maximum input tokens (context length)
    • Example: 16000, 128000
  • max_output_tokens (IntegerField, null=True)

    • Maximum output tokens per request
    • Example: 4096, 16000

Image Model Pricing (Only for model_type='image')

  • cost_per_image (DecimalField, max_digits=10, decimal_places=4, null=True)

    • Fixed cost per image generation (USD)
    • Example: 0.040 for dall-e-3
  • valid_sizes (JSONField, null=True, blank=True)

    • Array of valid image sizes for this model
    • Example: ["1024x1024", "1024x1792", "1792x1024"] for dall-e-3
    • Example: ["256x256", "512x512", "1024x1024"] for dall-e-2

Capabilities

  • supports_json_mode (BooleanField, default=False)

    • True for: gpt-4o, gpt-4o-mini, gpt-4-turbo-preview, gpt-5.1, gpt-5.2
  • supports_vision (BooleanField, default=False)

    • True for models that can analyze images
  • supports_function_calling (BooleanField, default=False)

    • True for models with function calling capability

Status & Configuration

  • is_active (BooleanField, default=True)

    • Enable/disable model without deleting
  • is_default (BooleanField, default=False)

    • Mark as default model for its type
    • Only one can be True per model_type
  • sort_order (IntegerField, default=0)

    • Control order in dropdown lists
    • Lower numbers appear first

Metadata

  • description (TextField, blank=True)

    • Admin notes about model usage, strengths, limitations
  • release_date (DateField, null=True, blank=True)

    • When model was released/added
  • deprecation_date (DateField, null=True, blank=True)

    • When model will be removed

Audit Fields

  • created_at (DateTimeField, auto_now_add=True)
  • updated_at (DateTimeField, auto_now=True)
  • updated_by (ForeignKey to User, null=True, on_delete=SET_NULL)

Model Meta

app_label = 'billing'
db_table = 'igny8_ai_model_config'
verbose_name = 'AI Model Configuration'
verbose_name_plural = 'AI Model Configurations'
ordering = ['model_type', 'sort_order', 'model_name']

indexes:
  - ['model_type', 'is_active']
  - ['provider', 'is_active']
  - ['is_default', 'model_type']

constraints:
  - unique_together: None (model_name is unique)
  - check: Ensure correct pricing fields based on model_type

Model Methods

  • __str__() - Return display_name
  • save() - Ensure only one is_default per model_type
  • get_cost_for_tokens(input_tokens, output_tokens) - Calculate cost for text models
  • get_cost_for_images(num_images) - Calculate cost for image models
  • validate_size(size) - Check if size is valid for this model
  • get_display_with_pricing() - For dropdowns: "GPT-4o mini - $0.15/$0.60 per 1M"

PHASE 2: CREATE MIGRATION WITH SEED DATA

File: backend/igny8_core/business/billing/migrations/00XX_create_ai_model_config.py

Migration Steps

  1. Create Table - AIModelConfig with all fields

  2. Seed Text Models (from current MODEL_RATES):

    gpt-4.1:
      display_name: "GPT-4.1 - $2.00 / $8.00 per 1M tokens"
      model_type: text
      provider: openai
      input_cost_per_1m: 2.00
      output_cost_per_1m: 8.00
      context_window: 8192
      max_output_tokens: 4096
      supports_json_mode: False
      is_active: True
      is_default: False
      sort_order: 10
    
    gpt-4o-mini:
      display_name: "GPT-4o mini - $0.15 / $0.60 per 1M tokens"
      model_type: text
      provider: openai
      input_cost_per_1m: 0.15
      output_cost_per_1m: 0.60
      context_window: 128000
      max_output_tokens: 16000
      supports_json_mode: True
      is_active: True
      is_default: True  ← DEFAULT
      sort_order: 1
    
    gpt-4o:
      display_name: "GPT-4o - $2.50 / $10.00 per 1M tokens"
      model_type: text
      provider: openai
      input_cost_per_1m: 2.50
      output_cost_per_1m: 10.00
      context_window: 128000
      max_output_tokens: 4096
      supports_json_mode: True
      supports_vision: True
      is_active: True
      is_default: False
      sort_order: 5
    
    gpt-5.1:
      display_name: "GPT-5.1 - $1.25 / $10.00 per 1M tokens (16K)"
      model_type: text
      provider: openai
      input_cost_per_1m: 1.25
      output_cost_per_1m: 10.00
      context_window: 16000
      max_output_tokens: 16000
      supports_json_mode: True
      is_active: True
      is_default: False
      sort_order: 20
    
    gpt-5.2:
      display_name: "GPT-5.2 - $1.75 / $14.00 per 1M tokens (16K)"
      model_type: text
      provider: openai
      input_cost_per_1m: 1.75
      output_cost_per_1m: 14.00
      context_window: 16000
      max_output_tokens: 16000
      supports_json_mode: True
      is_active: True
      is_default: False
      sort_order: 30
    
  3. Seed Image Models (from current IMAGE_MODEL_RATES):

    dall-e-3:
      display_name: "DALL-E 3 - High Quality - $0.040 per image"
      model_type: image
      provider: openai
      cost_per_image: 0.040
      valid_sizes: ["1024x1024", "1024x1792", "1792x1024"]
      is_active: True
      is_default: True  ← DEFAULT
      sort_order: 1
    
    dall-e-2:
      display_name: "DALL-E 2 - Standard - $0.020 per image"
      model_type: image
      provider: openai
      cost_per_image: 0.020
      valid_sizes: ["256x256", "512x512", "1024x1024"]
      is_active: True
      is_default: False
      sort_order: 10
    
    gpt-image-1:
      display_name: "GPT Image 1 - $0.042 per image"
      model_type: image
      provider: openai
      cost_per_image: 0.042
      valid_sizes: ["1024x1024"]
      is_active: False  ← Not valid for OpenAI endpoint
      is_default: False
      sort_order: 20
    
    gpt-image-1-mini:
      display_name: "GPT Image 1 Mini - $0.011 per image"
      model_type: image
      provider: openai
      cost_per_image: 0.011
      valid_sizes: ["1024x1024"]
      is_active: False  ← Not valid for OpenAI endpoint
      is_default: False
      sort_order: 30
    

PHASE 3: DJANGO ADMIN CONFIGURATION

File: backend/igny8_core/business/billing/admin.py

Admin Class: AIModelConfigAdmin

List View Configuration

list_display:

  • model_name
  • display_name
  • model_type_badge (colored badge)
  • provider_badge (colored badge)
  • pricing_display (formatted based on type)
  • is_active_icon (boolean icon)
  • is_default_icon (star icon)
  • sort_order
  • updated_at

list_filter:

  • model_type
  • provider
  • is_active
  • is_default
  • supports_json_mode
  • supports_vision
  • supports_function_calling

search_fields:

  • model_name
  • display_name
  • description

ordering:

  • model_type, sort_order, model_name

Form Configuration

Fieldsets:

  1. Basic Information

    • model_name (with help text about API usage)
    • display_name (shown in UI)
    • model_type (radio buttons: text/image/embedding)
    • provider (dropdown)
    • description (textarea)
  2. Text Model Pricing (show only if model_type='text')

    • input_cost_per_1m (with $ prefix)
    • output_cost_per_1m (with $ prefix)
    • context_window (with "tokens" suffix)
    • max_output_tokens (with "tokens" suffix)
  3. Image Model Pricing (show only if model_type='image')

    • cost_per_image (with $ prefix)
    • valid_sizes (JSON editor with validation)
  4. Capabilities

    • supports_json_mode (checkbox)
    • supports_vision (checkbox)
    • supports_function_calling (checkbox)
  5. Status & Display

    • is_active (checkbox)
    • is_default (checkbox with warning)
    • sort_order (number input)
  6. Metadata

    • release_date (date picker)
    • deprecation_date (date picker)
  7. Audit (readonly)

    • created_at
    • updated_at
    • updated_by

Admin Actions

  1. bulk_activate - Enable selected models
  2. bulk_deactivate - Disable selected models
  3. set_as_default - Set one model as default for its type
  4. test_model_connection - Test if model is accessible via API
  5. export_pricing_table - Export all models and pricing to CSV

Custom Methods

pricing_display(obj):

If model_type == 'text':
    return f"${obj.input_cost_per_1m}/${obj.output_cost_per_1m} per 1M"
If model_type == 'image':
    return f"${obj.cost_per_image} per image"

Custom save() override:

  • If is_default=True, unset other defaults for same model_type
  • Validate pricing fields based on model_type
  • Log changes to admin log

PHASE 4: UPDATE AI CORE (TEXT MODELS)

File: backend/igny8_core/ai/ai_core.py

Function: run_ai_request() (line ~93-350)

Current Implementation:

Line 16: from .constants import MODEL_RATES
Line 294: rates = MODEL_RATES.get(active_model, {'input': 2.00, 'output': 8.00})
Line 295: cost = (input_tokens × rates['input'] + output_tokens × rates['output']) ÷ 1_000_000

New Implementation:

Add new helper function:

Function: get_model_pricing(model_name)
Location: After __init__, before run_ai_request
Returns: AIModelConfig instance or None
Purpose: Query database and cache result

Update line 16:

  • Remove: from .constants import MODEL_RATES
  • Add: from igny8_core.business.billing.models import AIModelConfig

Update line 161 (model validation):

  • Replace: if active_model not in MODEL_RATES:
  • With: Query AIModelConfig.objects.filter(model_name=active_model, model_type='text', is_active=True).exists()

Update line 294 (cost calculation):

  • Replace: rates = MODEL_RATES.get(...)
  • With: Query AIModelConfig.objects.get(model_name=active_model)
  • Calculate: cost = (input_tokens × model.input_cost_per_1m + output_tokens × model.output_cost_per_1m) ÷ 1_000_000

Update line 819 (cost estimation):

  • Same replacement for MODEL_RATES.get()

Add caching (optional optimization):

Cache model configs in memory for 5 minutes
Key: f"ai_model_config:{model_name}"
Reduces database queries

PHASE 5: UPDATE IMAGE GENERATION

File: backend/igny8_core/ai/ai_core.py

Function: generate_image() (line ~400-600)

Current Implementation:

Line 17: from .constants import IMAGE_MODEL_RATES
Line 581: cost = IMAGE_MODEL_RATES.get(model, 0.040) × n

New Implementation:

Update line 17:

  • Remove: from .constants import IMAGE_MODEL_RATES
  • Already have: AIModelConfig imported

Update size validation:

  • Add function: validate_image_size(model_name, size)
  • Query: AIModelConfig.objects.get(model_name=model_name)
  • Check: size in model.valid_sizes

Update line 581 (cost calculation):

  • Replace: cost = IMAGE_MODEL_RATES.get(model, 0.040) × n
  • With:
    model_config = AIModelConfig.objects.get(model_name=model, model_type='image')
    cost = model_config.cost_per_image × n
    

Add validation:

  • Ensure model is_active=True
  • Ensure model.valid_sizes includes requested size
  • Raise clear error if model not found

PHASE 6: UPDATE VALIDATORS

File: backend/igny8_core/ai/validators.py

Function: validate_model() (line ~147-155)

Current Implementation:

Line 147: from .constants import MODEL_RATES, VALID_OPENAI_IMAGE_MODELS
Line 150: if model not in MODEL_RATES:

New Implementation:

Replace line 147:

  • Remove: from .constants import MODEL_RATES
  • Add: from igny8_core.business.billing.models import AIModelConfig

Replace line 150:

exists = AIModelConfig.objects.filter(
    model_name=model,
    model_type='text',
    is_active=True
).exists()

if not exists:
    return {
        'valid': False,
        'error': f'Invalid model: {model}. Check available models in Django Admin.'
    }

Add new function: validate_image_model_and_size(model, size)

Purpose: Validate image model and size together

Implementation:

Query: AIModelConfig.objects.get(model_name=model, model_type='image', is_active=True)
Check: size in model.valid_sizes
Return: {'valid': True/False, 'error': '...', 'model': model_config}

PHASE 7: UPDATE GLOBAL SETTINGS

File: backend/igny8_core/modules/system/global_settings_models.py

Model: GlobalIntegrationSettings

Current Field (line ~86):

openai_model = CharField(
    max_length=100,
    default='gpt-4o-mini',
    choices=[
        ('gpt-4.1', 'GPT-4.1 - $2.00 / $8.00'),
        ('gpt-4o-mini', 'GPT-4o mini - $0.15 / $0.60'),
        ...
    ]
)

New Implementation:

Keep CharField but make choices dynamic:

Add method:

Function: get_text_model_choices()
Returns: List of (model_name, display_name) tuples
Query: AIModelConfig.objects.filter(model_type='text', is_active=True)
Order: By sort_order

Update admin widget:

Use custom widget that loads choices from get_text_model_choices()
Refreshes on page load
Shows current pricing in dropdown

Add new fields (optional):

dalle_model = CharField (for image generation default)
anthropic_model = CharField (for future Anthropic support)

Add validation:

Clean method: Validate selected model exists in AIModelConfig
Save method: Ensure model is active

PHASE 8: UPDATE INTEGRATION SETTINGS

File: backend/igny8_core/modules/system/models.py

Model: IntegrationSettings

Current: Model stored in config JSON: {'model': 'gpt-4o-mini'}

New Implementation:

Add validation method:

Function: clean_config()
Purpose: Validate model in config exists and is active
Check: AIModelConfig.objects.filter(model_name=config['model'], is_active=True)
Raise: ValidationError if invalid

Update admin:

Show available models in help text
Link to AIModelConfig admin for model management

PHASE 9: CREATE API ENDPOINT

File: backend/igny8_core/api/ai/ (create directory if needed)

New File: views.py

ViewSet: AIModelViewSet(ReadOnlyModelViewSet)

Endpoint: /api/v1/ai/models/

Methods:

  • list() - Get all models with filters
  • retrieve() - Get single model by name

Query Filters:

  • ?type=text - Filter by model_type
  • ?type=image
  • ?provider=openai
  • ?active=true - Only active models
  • ?default=true - Only default models

Response Format:

{
  "count": 5,
  "results": [
    {
      "model_name": "gpt-4o-mini",
      "display_name": "GPT-4o mini - $0.15 / $0.60 per 1M tokens",
      "model_type": "text",
      "provider": "openai",
      "input_cost_per_1m": "0.1500",
      "output_cost_per_1m": "0.6000",
      "context_window": 128000,
      "max_output_tokens": 16000,
      "supports_json_mode": true,
      "supports_vision": false,
      "is_default": true,
      "sort_order": 1
    }
  ]
}

Permissions:

  • List: Authenticated users
  • Retrieve: Authenticated users
  • Create/Update/Delete: Admin only (via Django Admin)

Serializer: AIModelConfigSerializer

  • Include all relevant fields
  • Exclude audit fields from API
  • Add computed field: pricing_display

Register in URLs:

File: backend/igny8_core/urls.py or appropriate router

router.register(r'ai/models', AIModelViewSet, basename='ai-models')

PHASE 10: UPDATE SETTINGS API

File: backend/igny8_core/ai/settings.py

Function: get_model_config() (line ~20-110)

Current Implementation:

  • Returns model from GlobalIntegrationSettings or account override
  • Validates against hardcoded MODEL_RATES

New Implementation:

Update model resolution:

1. Check account IntegrationSettings override
2. If no override, get from GlobalIntegrationSettings
3. Query AIModelConfig for selected model
4. Validate model exists and is_active=True
5. Return model configuration

Update validation:

  • Replace: if model not in MODEL_RATES:
  • With: Query AIModelConfig and check exists()

Return enhanced config:

{
    'model': model_config.model_name,
    'max_tokens': model_config.max_output_tokens,
    'temperature': 0.7,  # From settings
    'context_window': model_config.context_window,
    'supports_json_mode': model_config.supports_json_mode,
    'pricing': {
        'input': model_config.input_cost_per_1m,
        'output': model_config.output_cost_per_1m
    }
}

PHASE 11: DEPRECATE CONSTANTS

File: backend/igny8_core/ai/constants.py

Current: Contains MODEL_RATES and IMAGE_MODEL_RATES dicts

New Implementation:

Add deprecation warnings:

"""
DEPRECATED: MODEL_RATES and IMAGE_MODEL_RATES are deprecated.
Use AIModelConfig model instead: billing.models.AIModelConfig
This file will be removed in version X.X.X
"""

import warnings

MODEL_RATES = {
    # ... existing data ...
}

def get_model_rate(model):
    warnings.warn(
        "MODEL_RATES is deprecated. Use AIModelConfig.objects.get(model_name=model)",
        DeprecationWarning,
        stacklevel=2
    )
    return MODEL_RATES.get(model)

Keep for backward compatibility:

  • Don't remove immediately
  • Mark as deprecated in docstrings
  • Plan removal in next major version
  • All new code should use AIModelConfig

Update imports across codebase:

  • Search for: from .constants import MODEL_RATES
  • Update to: from igny8_core.business.billing.models import AIModelConfig

PHASE 12: UPDATE REPORTS

Files:

  • backend/igny8_core/modules/reports/views.py
  • backend/igny8_core/modules/reports/ai_cost_analysis.py

Current: May reference MODEL_RATES for display

New Implementation:

Use AIModelConfig for display:

# Get model display name
model_config = AIModelConfig.objects.get(model_name=model_used)
display_name = model_config.display_name

# Show model capabilities
supports_json = model_config.supports_json_mode

Cost calculations:

  • Already using CreditUsageLog.cost_usd (correct)
  • No changes needed to calculation logic
  • Only update display/filtering

Add model metadata to reports:

  • Context window in "Model Details" section
  • Pricing in "Cost Breakdown" section
  • Capabilities in "Model Comparison" table

PHASE 13: UPDATE TESTS

New Test File: test_ai_model_config.py

Test Cases:

  1. Create text model with valid pricing
  2. Create image model with valid pricing
  3. Validate only one default per type
  4. Test cost calculation methods
  5. Test size validation for images
  6. Test model activation/deactivation

Update Existing Tests:

Files:

  • backend/igny8_core/business/billing/tests/test_credit_service.py
  • backend/igny8_core/ai/tests/test_ai_core.py
  • backend/igny8_core/api/tests/test_ai_framework.py

Changes:

  • Create AIModelConfig fixtures in setUp()
  • Replace MODEL_RATES mocks with database records
  • Update assertions for database queries
  • Test dynamic model loading

API Tests: test_ai_model_api.py

Test Cases:

  1. List all models
  2. Filter by type
  3. Filter by provider
  4. Get default model
  5. Permissions (readonly for users)

PHASE 14: DATA MIGRATION STRATEGY

For Existing Production Data:

No Schema Changes Needed:

  • CreditUsageLog.model_used already stores model name
  • CreditUsageLog.cost_usd already stores actual cost
  • Historical data remains accurate

Migration Steps:

  1. Deploy migration (creates table, seeds data)
  2. Code continues using constants (no breaking changes)
  3. Gradually switch code to database (per function)
  4. Monitor for issues (rollback to constants if needed)
  5. Mark constants as deprecated
  6. Remove constants in next major version

Rollback Plan:

  • If issues occur, code falls back to constants
  • AIModelConfig table can be dropped without data loss
  • No impact on existing credit calculations

For Zero-Downtime Deployment:

Step 1: Deploy migration only

python manage.py migrate billing
# Creates AIModelConfig table, seeds data
# Code still uses constants - no breaking changes

Step 2: Deploy code that reads from both

def get_model_pricing(model_name):
    try:
        # Try database first
        return AIModelConfig.objects.get(model_name=model_name)
    except AIModelConfig.DoesNotExist:
        # Fallback to constants
        return MODEL_RATES.get(model_name)

Step 3: Monitor and verify

  • Check logs for database queries
  • Verify cost calculations match
  • Compare with constant-based calculations

Step 4: Remove constant fallbacks

  • After verification period (1-2 weeks)
  • All code now uses database only

PHASE 15: FRONTEND UPDATES

File: frontend/src/pages/Settings/AI.tsx

Current: Hardcoded model dropdown

New Implementation:

Add API call:

const { data: models } = useQuery('/api/v1/ai/models/?type=text&active=true')

Update dropdown:

<Select>
  {models.map(model => (
    <option value={model.model_name}>
      {model.display_name}
    </option>
  ))}
</Select>

Show model details:

  • Context window
  • Max output tokens
  • JSON mode support
  • Pricing (input/output costs)

File: frontend/src/pages/Settings/Integration.tsx

Current: Shows current model from GlobalIntegrationSettings

New Implementation:

Display model information:

<ModelCard>
  <h3>{model.display_name}</h3>
  <p>Provider: {model.provider}</p>
  <p>Context: {model.context_window.toLocaleString()} tokens</p>
  <p>Pricing: ${model.input_cost_per_1m}/${model.output_cost_per_1m} per 1M</p>
  {model.supports_json_mode && <Badge>JSON Mode</Badge>}
  {model.supports_vision && <Badge>Vision</Badge>}
</ModelCard>

Add model comparison:

  • Show all available models in table
  • Compare pricing side-by-side
  • Help users choose best model for their needs

BENEFITS OF THIS IMPLEMENTATION

Operational Benefits

  1. No Code Deploys for Pricing Updates - Update costs in Django Admin
  2. Multi-Provider Ready - Easy to add Anthropic, Google, etc.
  3. Model Testing - Enable/disable models without code changes
  4. Granular Control - Different models for different accounts/plans

Technical Benefits

  1. Backward Compatible - Existing code works during migration
  2. Zero Downtime - Gradual migration strategy
  3. Fully Tested - Comprehensive test coverage
  4. Audit Trail - Track all pricing changes with timestamps

Business Benefits

  1. Dynamic Pricing - React quickly to OpenAI price changes
  2. Cost Forecasting - Accurate model cost data for projections
  3. Model Analytics - Track usage and costs per model
  4. A/B Testing - Easy to test new models with subset of users

User Benefits

  1. Model Selection - Users can choose model based on their needs
  2. Transparent Pricing - See exact costs before using models
  3. Better Control - Enterprise accounts can restrict models
  4. Latest Models - Access new models as soon as they're added

IMPLEMENTATION TIMELINE

Week 1: Foundation

  • Day 1-2: Create AIModelConfig model and migration
  • Day 3: Create Django Admin interface
  • Day 4-5: Seed data and test in development

Week 2: Backend Integration

  • Day 1-2: Update ai_core.py to query database
  • Day 3: Update validators and settings
  • Day 4-5: Create API endpoint and serializers

Week 3: Testing & Migration

  • Day 1-2: Write comprehensive tests
  • Day 3: Test migration on staging
  • Day 4-5: Deploy to production with monitoring

Week 4: Frontend & Cleanup

  • Day 1-2: Update frontend to use new API
  • Day 3: Add deprecation warnings to constants
  • Day 4-5: Documentation and training

FILES AFFECTED SUMMARY

New Files (4)

  1. Migration: billing/migrations/00XX_create_ai_model_config.py
  2. Tests: billing/tests/test_ai_model_config.py
  3. API Views: api/ai/views.py
  4. API Tests: api/tests/test_ai_model_api.py

Modified Files (12)

  1. billing/models.py - Add AIModelConfig model
  2. billing/admin.py - Add AIModelConfigAdmin
  3. ai/ai_core.py - Replace MODEL_RATES with database queries
  4. ai/validators.py - Update model validation
  5. ai/settings.py - Update get_model_config()
  6. ai/constants.py - Add deprecation warnings
  7. system/global_settings_models.py - Dynamic model choices
  8. system/models.py - Validate model overrides
  9. reports/views.py - Use AIModelConfig for display
  10. Frontend: Settings/AI.tsx
  11. Frontend: Settings/Integration.tsx
  12. URLs: Register new API endpoint

Total Changes

  • 1 new database model
  • 1 new admin interface
  • 1 new API endpoint
  • 4 new test files
  • 12 files updated
  • ~500-800 lines of code
  • All existing data preserved
  • Zero downtime migration

ROLLBACK PLAN

If Issues Occur:

  1. Database: Keep AIModelConfig table (no harm)
  2. Code: Revert to using constants
  3. Data: No CreditUsageLog changes, all historical data intact
  4. Time: Can rollback in < 5 minutes

Indicators for Rollback:

  • Model queries timing out
  • Incorrect cost calculations
  • Missing models causing errors
  • Performance degradation

Prevention:

  • Thorough testing on staging first
  • Monitor logs and metrics closely
  • Keep constants for 2-4 weeks as backup
  • Gradual rollout to production

SUCCESS METRICS

Technical Metrics

  • All tests passing (100% coverage for new code)
  • Database query time < 10ms
  • API response time < 100ms
  • Zero downtime during deployment

Operational Metrics

  • Admin can add new model in < 2 minutes
  • Pricing update takes < 1 minute
  • Model enable/disable is instant
  • No code deploys needed for model changes

Business Metrics

  • Cost tracking accuracy: 100%
  • Model usage data: Available in real-time
  • Time to market for new models: < 1 day (vs 1 week)
  • Pricing error rate: 0%

END OF PLAN