New Model & tokens/credits updates

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-23 06:26:15 +00:00
parent 1d4825ad77
commit d768ed71d4
9 changed files with 945 additions and 35 deletions

View File

@@ -19,6 +19,102 @@ PAYMENT_METHOD_CHOICES = [
]
class AIModelConfig(models.Model):
"""
AI Model Configuration - Centralized pricing and token ratios
Single source of truth for all AI model costs
"""
# Model identification
model_name = models.CharField(
max_length=100,
unique=True,
help_text="Technical model name (e.g., gpt-4-turbo, gpt-3.5-turbo)"
)
provider = models.CharField(
max_length=50,
choices=[
('openai', 'OpenAI'),
('anthropic', 'Anthropic'),
('runware', 'Runware'),
('other', 'Other'),
],
help_text="AI provider"
)
model_type = models.CharField(
max_length=20,
choices=[
('text', 'Text Generation'),
('image', 'Image Generation'),
('embedding', 'Embeddings'),
],
default='text',
help_text="Type of AI model"
)
# Pricing (per 1K tokens for text models)
cost_per_1k_input_tokens = models.DecimalField(
max_digits=10,
decimal_places=6,
default=Decimal('0.001'),
validators=[MinValueValidator(Decimal('0'))],
help_text="Cost in USD per 1,000 input tokens"
)
cost_per_1k_output_tokens = models.DecimalField(
max_digits=10,
decimal_places=6,
default=Decimal('0.002'),
validators=[MinValueValidator(Decimal('0'))],
help_text="Cost in USD per 1,000 output tokens"
)
# Token-to-credit ratio
tokens_per_credit = models.IntegerField(
default=100,
validators=[MinValueValidator(1)],
help_text="How many tokens equal 1 credit (e.g., 100 tokens = 1 credit)"
)
# Display
display_name = models.CharField(
max_length=150,
help_text="Human-readable name (e.g., 'GPT-4 Turbo (Premium)')"
)
description = models.TextField(
blank=True,
help_text="Model description and use cases"
)
# Status
is_active = models.BooleanField(
default=True,
help_text="Enable/disable this model"
)
is_default = models.BooleanField(
default=False,
help_text="Use as system-wide default model"
)
# Metadata
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
app_label = 'billing'
db_table = 'igny8_ai_model_config'
verbose_name = 'AI Model Configuration'
verbose_name_plural = 'AI Model Configurations'
ordering = ['provider', 'model_name']
def __str__(self):
return f"{self.display_name} ({self.model_name})"
def calculate_cost(self, tokens_input, tokens_output):
"""Calculate USD cost for given token usage"""
cost_input = (tokens_input / 1000) * self.cost_per_1k_input_tokens
cost_output = (tokens_output / 1000) * self.cost_per_1k_output_tokens
return float(cost_input + cost_output)
class CreditTransaction(AccountBaseModel):
"""Track all credit transactions (additions, deductions)"""
TRANSACTION_TYPE_CHOICES = [
@@ -89,10 +185,59 @@ class CreditUsageLog(AccountBaseModel):
operation_type = models.CharField(max_length=50, choices=OPERATION_TYPE_CHOICES, db_index=True)
credits_used = models.IntegerField(validators=[MinValueValidator(0)])
cost_usd = models.DecimalField(max_digits=10, decimal_places=4, null=True, blank=True)
model_used = models.CharField(max_length=100, blank=True)
# Model tracking
model_config = models.ForeignKey(
'billing.AIModelConfig',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='usage_logs',
help_text="AI model configuration used",
db_column='model_config_id'
)
model_name = models.CharField(
max_length=100,
blank=True,
help_text="Model name (deprecated, use model_config FK)"
)
# Token tracking
tokens_input = models.IntegerField(null=True, blank=True, validators=[MinValueValidator(0)])
tokens_output = models.IntegerField(null=True, blank=True, validators=[MinValueValidator(0)])
# Cost tracking (USD)
cost_usd_input = models.DecimalField(
max_digits=10,
decimal_places=6,
null=True,
blank=True,
help_text="USD cost for input tokens"
)
cost_usd_output = models.DecimalField(
max_digits=10,
decimal_places=6,
null=True,
blank=True,
help_text="USD cost for output tokens"
)
cost_usd_total = models.DecimalField(
max_digits=10,
decimal_places=6,
null=True,
blank=True,
help_text="Total USD cost (input + output)"
)
# Legacy cost field (deprecated)
cost_usd = models.DecimalField(
max_digits=10,
decimal_places=4,
null=True,
blank=True,
help_text="Deprecated, use cost_usd_total"
)
related_object_type = models.CharField(max_length=50, blank=True) # 'keyword', 'cluster', 'task'
related_object_id = models.IntegerField(null=True, blank=True)
metadata = models.JSONField(default=dict)
@@ -154,6 +299,8 @@ class CreditCostConfig(models.Model):
('per_200_words', 'Per 200 Words'),
('per_item', 'Per Item'),
('per_image', 'Per Image'),
('per_100_tokens', 'Per 100 Tokens'), # NEW: Token-based
('per_1000_tokens', 'Per 1000 Tokens'), # NEW: Token-based
]
unit = models.CharField(
@@ -163,6 +310,16 @@ class CreditCostConfig(models.Model):
help_text="What the cost applies to"
)
# Model configuration
default_model = models.ForeignKey(
'billing.AIModelConfig',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='operation_configs',
help_text="Default AI model for this operation (optional)"
)
# Metadata
display_name = models.CharField(max_length=100, help_text="Human-readable name")
description = models.TextField(blank=True, help_text="What this operation does")