7.0 KiB
7.0 KiB
AI Configuration Refactor - Master Overview
Created: January 4, 2026
Goal: Clean, unified AI configuration with single source of truth
Documentation Files
| File | Purpose |
|---|---|
| REFACTOR-OVERVIEW.md | This file - master overview |
| implementation-plan-for-ai-models-and-cost.md | Detailed implementation plan with schema changes |
| safe-migration-and-testing-plan.md | Testing strategy and verification steps |
What We're Fixing
Current Problems
-
Duplicate configuration sources
AIModelConfig(database) has model definitionsGlobalIntegrationSettings(database) has hardcoded CHOICES duplicating the same infoconstants.pyhasMODEL_RATESandIMAGE_MODEL_RATEShardcoded- Frontend
Settings.tsxhas hardcoded model choices
-
Broken/inconsistent data
GlobalIntegrationSettings.runware_model = "bria:10@1"but this model doesn't existGlobalIntegrationSettings.openai_model = "gpt-4o-mini"but default should begpt-5.1
-
API keys mixed with model config
GlobalIntegrationSettingsstores both API keys and model preferences- No separation of concerns
- Can't easily extend to other integrations (email, payment, etc.)
-
Credit calculation scattered
CreditCostConfigfor token-based operationsModelRegistry.calculate_cost()for image costs- No clear per-model credit rate
Target State
Single Source of Truth
IntegrationProvider (NEW)
├── openai (api_key, active)
├── runware (api_key, active)
├── resend (api_key, active) ← future
├── stripe (api_key, webhook_secret, active) ← future
└── ...
AIModelConfig (ENHANCED)
├── Text Models
│ ├── gpt-5.1 (is_default=true, tokens_per_credit=1000)
│ ├── gpt-4o (tokens_per_credit=1000)
│ └── gpt-4o-mini (tokens_per_credit=10000)
└── Image Models
├── runware:97@1 (credits_per_image=1, quality_tier=basic)
├── dall-e-3 (is_default=true, credits_per_image=5, quality_tier=quality)
└── google:4@2 (credits_per_image=15, quality_tier=premium)
No More Hardcoding
- Backend: Remove
MODEL_RATES,IMAGE_MODEL_RATESfrom constants.py - Backend: Remove hardcoded CHOICES from
GlobalIntegrationSettings - Backend:
ModelRegistryalways uses database, no fallbacks - Frontend: Load model choices from API endpoint
Clear Credit Calculation
| Model Type | How Credits Calculated |
|---|---|
| Text | ceil(total_tokens / tokens_per_credit) from AIModelConfig |
| Image | credits_per_image * num_images from AIModelConfig |
Migration Phases Summary
| Phase | What Changes | Risk | Rollback |
|---|---|---|---|
| 1 | Add new models/fields | None - additive only | Drop new tables |
| 2 | Add parallel code paths | Low - old code untouched | Remove new methods |
| 3 | IntegrationProvider for keys | Medium - API key loading | Revert key loading |
| 4 | Switch to new credit calc | Medium - financial impact | Revert credit service |
| 5 | Create API endpoint | None - new endpoint | Remove endpoint |
| 6 | Update frontend | Low - UI only | Revert frontend |
| 7 | Cleanup legacy code | High if bugs found | Restore from backup |
Rule: Run full test suite after EACH phase before proceeding.
Files Being Modified
Backend Files
| File | Changes |
|---|---|
billing/models.py |
Add IntegrationProvider, add fields to AIModelConfig |
ai/model_registry.py |
Add get_default_model(), remove constants fallback |
ai/ai_core.py |
Use IntegrationProvider for API keys |
ai/constants.py |
Remove MODEL_RATES, IMAGE_MODEL_RATES |
billing/services/credit_service.py |
Model-based credit calculation |
modules/system/global_settings_models.py |
Remove API keys, hardcoded choices |
api/views/system.py |
Add /api/v1/system/ai-models/ endpoint |
Frontend Files
| File | Changes |
|---|---|
src/pages/Sites/Settings.tsx |
Load models from API, remove hardcodes |
New Files
| File | Purpose |
|---|---|
tests/test_ai_system_integration.py |
Integration tests for migration |
Credit Values (Final)
Text Models (per 1 credit)
| Model | Tokens per Credit | Example: 5000 tokens |
|---|---|---|
| gpt-5.1 | 1,000 | 5 credits |
| gpt-4o | 1,000 | 5 credits |
| gpt-4o-mini | 10,000 | 1 credit |
Image Models (per image)
| Model | Credits per Image | UI Display |
|---|---|---|
| runware:97@1 | 1 | "Basic (1 credit/image)" |
| dall-e-3 | 5 | "Quality (5 credits/image)" |
| google:4@2 | 15 | "Premium (15 credits/image)" |
Execution Paths That Must Keep Working
All these paths use the same AI functions and must work identically after migration:
-
Manual Buttons (Planner/Writer pages)
- Cluster Keywords →
auto_cluster - Generate Ideas →
generate_ideas - Generate Content →
generate_content - Extract Prompts →
generate_image_prompts - Generate Images →
generate_images
- Cluster Keywords →
-
Automation Manual Run (Automation page → Run Now)
- Same AI functions called via AutomationService
-
Scheduled Automation (Celery Beat scheduler)
- Same AI functions called via scheduled tasks
-
Direct Services (Linker, Optimizer modules)
- Use CreditService directly for credit deduction
Success Criteria
Migration is COMPLETE when:
- All integration tests pass
- All manual test checklist items pass
- No errors in production logs for 1 week
- Credit calculations match expected values
- All execution paths work (manual, automation, scheduled)
- Frontend loads models dynamically from API
- No legacy code remains:
- No
MODEL_RATES/IMAGE_MODEL_RATESin constants.py - No API keys in
GlobalIntegrationSettings - No hardcoded models in frontend
- No fallback to constants in
ModelRegistry - No unused fields in
GlobalIntegrationSettings
- No
Quick Reference Commands
# Run integration tests
docker exec igny8_backend python manage.py test igny8_core.tests.test_ai_system_integration -v 2
# Check AIModelConfig
docker exec igny8_backend python manage.py shell -c "
from igny8_core.business.billing.models import AIModelConfig
for m in AIModelConfig.objects.all().order_by('model_type'):
print(f'{m.model_name}: {m.model_type}, default={m.is_default}')
"
# Check recent credit usage
docker exec igny8_backend python manage.py shell -c "
from igny8_core.business.billing.models import CreditUsageLog
for log in CreditUsageLog.objects.order_by('-created_at')[:10]:
print(f'{log.operation_type}: {log.credits_used} credits')
"
# Check account credits
docker exec igny8_backend python manage.py shell -c "
from igny8_core.auth.models import Account
for acc in Account.objects.all():
print(f'{acc.name}: {acc.credits} credits')
"