Budget Model
See Cost Accounting for how budgets are used.
Budget models.
A Budget is a reusable spending limit. Attaching it to a resource creates a
ResourceConstraint. The constraint is evaluated each time a charge is created for
the resource, and hourly by Celery Beat. When the resource’s spending reaches a limit, the
constraint creates a ResourceLock, and charge_authorization() then refuses
more charges to the resource until the lock is removed: when the billing period ends, when
the budget is raised, or when the budget is detached.
A budget can be attached to anything that has a record locator: a UserProfile, a User (each of their UserProfiles), an Account, an LLMClient, a Provider, a Proxy, an LLMHostCompute, a plugin, an MCPClient, and so on. Charges are created for each resource that took part in a request, so a budget on any of them sees its share of the spending.
Assumed to be always been under the control of superusers, so no ownership nor permissions are implemented.
Example:
budget = Budget.objects.create(
name="student_monthly_allowance",
period=BudgetPeriod.MONTH,
periodic_limit=Decimal("10.00"),
message="You have used this month's AI allowance. It renews on the 1st.",
)
budget.attach(user_profile)
- class smarter.apps.account.models.budget.Budget(*args, **kwargs)[source]
Bases:
MetaDataModelA budget is a catalogue of spending limits that can be enforced on a resource, either.
in a given period of time, or over the life of the resource.
Examples
a per-User budget of $10 per month, with a total limit of $100 for the life of the student.
a per-Account budget of $100 per month, with a total limit of $1,000 for the life of the account.
a custom project budget of $1000 per month, with a total limit of $10,000 for the life of the project.
a customer project budget of $10,000 over the life of the project, with no monthly limit.
a per-User throttle of 50,000 tokens per hour.
an LLMHostCompute budget of $500 per month of node time.
A limit of 0 means no limit.
- Parameters:
id (Unknown) – Primary key: ID
created_at (Unknown) – Created at
updated_at (Unknown) – Updated at
description (Unknown) – Description. A brief description of this resource. Be verbose, but not too verbose.
version (Unknown) – Version. Semantic version in the format MAJOR.MINOR.PATCH, e.g., ‘1.0.0’.
annotations (Unknown) – Annotations. Key-value pairs for annotating this resource.
name (Unknown) – Name. The budget’s name, in snake_case. Unique: manifests refer to budgets by name.
period (Unknown) – Period. The billing period of the periodic limit, and of the duration.
unit (Unknown) – Unit. What the limits measure: cost in USD, or total tokens.
duration (Unknown) – Duration. The duration of the budget in billing periods, from when it is attached. Afterwards, the budget no longer applies. 0 means no limit.
periodic_limit (Unknown) – Periodic limit. The maximum cost or tokens that can be incurred in a billing period. 0 means no limit.
absolute_limit (Unknown) – Absolute limit. The maximum cost or tokens that can be incurred in total, from when it is attached. 0 means no limit.
action (Unknown) – Action. What happens when a limit is reached: block further charges, or only send the budget_exceeded signal.
warning_threshold (Unknown) – Warning threshold. The percentage of a limit at which the budget_warning signal is sent, once per billing period. 0 means never.
message (Unknown) – Message. What people are told when this budget blocks their request, e.g. in the chat window. Empty means a description of the limit that was reached.
Relationship fields:
- Parameters:
tags (Unknown) – Tags. Tags for categorizing and organizing this resource. (related name:
budget)tagged_items (Unknown) – Tagged items (related name:
+)
Reverse relationships:
- Parameters:
constraints (Unknown) – All constraints of this budget (related name of
budget)
- exception DoesNotExist
Bases:
ObjectDoesNotExist
- exception MultipleObjectsReturned
Bases:
MultipleObjectsReturned
- exception NotUpdated
Bases:
ObjectNotUpdated,DatabaseError
- absolute_limit
-
Absolute limit. The maximum cost or tokens that can be incurred in total, from when it is attached. 0 means no limit.
- Type:
Type
- action
-
Action. What happens when a limit is reached: block further charges, or only send the budget_exceeded signal.
Choices:
blockwarn
- Type:
Type
- attach(resource, start_date=None)[source]
Enforce this budget on a resource, from start_date or now.
Attaching it again reactivates it, and keeps its start date.
- Return type:
- Returns:
The resource constraints, one per record locator.
- constraints
Reverse
ForeignKeyfromResourceConstraintAll constraints of this budget (related name of
budget)- Type:
Type
- created_at
-
Created at
Timestamp indicating when the model instance was created.
This field is automatically set to the current date and time when the instance is first created. It is indexed in the database for efficient querying.
- Type:
Type
- description
-
Description. A brief description of this resource. Be verbose, but not too verbose.
- Type:
Type
- detach(resource)[source]
Stop enforcing this budget on a resource, and remove its locks.
- Return type:
- Returns:
The number of resource constraints removed.
- duration
-
Duration. The duration of the budget in billing periods, from when it is attached. Afterwards, the budget no longer applies. 0 means no limit.
- Type:
Type
- format_amount(amount)[source]
An amount in this budget’s unit, e.g. “$10.00” or “50,000 tokens”.
- Return type:
- get_action_display(*, field=<django.db.models.CharField: action>)
Shows the label of the
action. Seeget_FOO_display()for more information.
- get_period_display(*, field=<django.db.models.CharField: period>)
Shows the label of the
period. Seeget_FOO_display()for more information.
- get_unit_display(*, field=<django.db.models.CharField: unit>)
Shows the label of the
unit. Seeget_FOO_display()for more information.
- id
-
Primary key: ID
- Type:
Type
- message
-
Message. What people are told when this budget blocks their request, e.g. in the chat window. Empty means a description of the limit that was reached.
- Type:
Type
- name
-
Name. The budget’s name, in snake_case. Unique: manifests refer to budgets by name.
- Type:
Type
- objects = <django.db.models.Manager object>
- period
-
Period. The billing period of the periodic limit, and of the duration.
Choices:
hourdayweekmonth
- Type:
Type
- periodic_limit
-
Periodic limit. The maximum cost or tokens that can be incurred in a billing period. 0 means no limit.
- Type:
Type
- tagged_items
Reverse
GenericRelationfromBudgetAll + of this tagged item (related name of
tagged_items)- Type:
Type
- tags = <taggit.managers._TaggableManager object>
- unit
-
Unit. What the limits measure: cost in USD, or total tokens.
Choices:
costtokens
- Type:
Type
- updated_at
-
Updated at
Timestamp indicating when the model instance was last updated.
This field is automatically updated to the current date and time whenever the instance is saved. It is indexed in the database for efficient querying.
- Type:
Type
- version
-
Version. Semantic version in the format MAJOR.MINOR.PATCH, e.g., ‘1.0.0’.
- Type:
Type
- warning_threshold
-
Warning threshold. The percentage of a limit at which the budget_warning signal is sent, once per billing period. 0 means never.
- Type:
Type
- class smarter.apps.account.models.budget.BudgetAction(*values)[source]
Bases:
TextChoicesWhat happens when a budget’s limit is reached.
- BLOCK = 'block'
- WARN = 'warn'
- class smarter.apps.account.models.budget.BudgetPeriod(*values)[source]
Bases:
TextChoicesThe billing period of a budget’s periodic limit.
- DAY = 'day'
- HOUR = 'hour'
- MONTH = 'month'
- WEEK = 'week'
- class smarter.apps.account.models.budget.BudgetUnit(*values)[source]
Bases:
TextChoicesWhat a budget’s limits measure.
- COST = 'cost'
- TOKENS = 'tokens'
- class smarter.apps.account.models.budget.ResourceConstraint(*args, **kwargs)[source]
Bases:
TimestampedModelA budget attached to a resource.
Note
resource_locator intentionally overrides the parent class’s TimestampedModel.resource_locator field.
- Parameters:
id (Unknown) – Primary key: ID
created_at (Unknown) – Created at
updated_at (Unknown) – Updated at
resource_locator (Unknown) – Resource locator. The TimestampedModel.resource_locator of the resource that this constraint is associated with.
is_active (Unknown) – Is active. Whether the budget is enforced.
start_date (Unknown) – Start date. When the budget began to apply to the resource. The duration and the absolute limit count from here.
warned_at (Unknown) – Warned at. When the budget_warning signal was last sent for this resource.
exceeded_at (Unknown) – Exceeded at. When the budget_exceeded signal was last sent for this resource.
Relationship fields:
- Parameters:
budget (Unknown) – Budget. The budget that is enforced on the resource. (related name:
constraints)
Reverse relationships:
- Parameters:
locks (Unknown) – All locks of this resource constraint (related name of
resource_constraint)
- exception DoesNotExist
Bases:
ObjectDoesNotExist
- exception MultipleObjectsReturned
Bases:
MultipleObjectsReturned
- exception NotUpdated
Bases:
ObjectNotUpdated,DatabaseError
- budget
ForeignKeytoBudgetBudget. The budget that is enforced on the resource. (related name:
constraints)- Type:
Type
- created_at
-
Created at
Timestamp indicating when the model instance was created.
This field is automatically set to the current date and time when the instance is first created. It is indexed in the database for efficient querying.
- Type:
Type
- evaluate(now=None)[source]
Compare the actual spending to the budget, and lock or unlock the resource.
Sends budget_warning when spending reaches the budget’s warning threshold, budget_exceeded when it reaches a limit, and budget_released when a lock is removed. Each is sent once per billing period.
An inactive budget, or one whose duration has ended, no longer applies: it removes its lock.
- Return type:
- Returns:
The resource’s lock, if it is locked.
- exceeded_at
-
Exceeded at. When the budget_exceeded signal was last sent for this resource.
- Type:
Type
- get_next_by_start_date(*, field=<django.db.models.DateTimeField: start_date>, is_next=True, **kwargs)
Finds next instance based on
start_date. Seeget_next_by_FOO()for more information.
- get_previous_by_start_date(*, field=<django.db.models.DateTimeField: start_date>, is_next=False, **kwargs)
Finds previous instance based on
start_date. Seeget_previous_by_FOO()for more information.
- id
-
Primary key: ID
- Type:
Type
- is_active
-
Is active. Whether the budget is enforced.
- Type:
Type
- is_expired(now=None)[source]
Whether the budget’s duration has ended, after which the budget no longer applies.
- Return type:
- locks
Reverse
ForeignKeyfromResourceLockAll locks of this resource constraint (related name of
resource_constraint)- Type:
Type
- objects = <django.db.models.Manager object>
- periodic_actual(now=None)[source]
Spending in the billing period that contains now, counted from the start date.
- Return type:
- resource_locator
-
Resource locator. The TimestampedModel.resource_locator of the resource that this constraint is associated with.
- Type:
Type
- series(periods=12, now=None)[source]
The budget versus the actual spending of each of the last periods billing periods, for charts.
The first period is not earlier than the one that contains the start date.
- start_date
-
Start date. When the budget began to apply to the resource. The duration and the absolute limit count from here.
- Type:
Type
- updated_at
-
Updated at
Timestamp indicating when the model instance was last updated.
This field is automatically updated to the current date and time whenever the instance is saved. It is indexed in the database for efficient querying.
- Type:
Type
- validate()[source]
Validate the model.
Attention
Intended to be overridden in subclasses to provide custom validation logic.
- warned_at
-
Warned at. When the budget_warning signal was last sent for this resource.
- Type:
Type
- class smarter.apps.account.models.budget.ResourceLock(*args, **kwargs)[source]
Bases:
TimestampedModelA mechanism to prevent spending on a resource when its.
budget constraint has been exceeded. The existence of a resource lock indicates that the resource is locked and cannot be used until the lock is removed, or it expires.
- Parameters:
id (Unknown) – Primary key: ID
created_at (Unknown) – Created at
updated_at (Unknown) – Updated at
resource_locator (Unknown) – Resource locator. The TimestampedModel.resource_locator of the resource that this lock is associated with.
expiration_date (Unknown) – Expiration date. The date and time when this lock will expire. If null, the lock will not expire until it is manually removed.
reason (Unknown) – Reason. Which limit was reached.
Relationship fields:
- Parameters:
resource_constraint (Unknown) – Resource constraint. The resource constraint that this lock is associated with. (related name:
locks)
- exception DoesNotExist
Bases:
ObjectDoesNotExist
- exception MultipleObjectsReturned
Bases:
MultipleObjectsReturned
- exception NotUpdated
Bases:
ObjectNotUpdated,DatabaseError
- created_at
-
Created at
Timestamp indicating when the model instance was created.
This field is automatically set to the current date and time when the instance is first created. It is indexed in the database for efficient querying.
- Type:
Type
- expiration_date
-
Expiration date. The date and time when this lock will expire. If null, the lock will not expire until it is manually removed.
- Type:
Type
- id
-
Primary key: ID
- Type:
Type
- objects = <django.db.models.Manager object>
- resource_constraint
ForeignKeytoResourceConstraintResource constraint. The resource constraint that this lock is associated with. (related name:
locks)- Type:
Type
- resource_constraint_id
Internal field, use
resource_constraintinstead.
- resource_locator
-
Resource locator. The TimestampedModel.resource_locator of the resource that this lock is associated with.
- Type:
Type
- updated_at
-
Updated at
Timestamp indicating when the model instance was last updated.
This field is automatically updated to the current date and time whenever the instance is saved. It is indexed in the database for efficient querying.
- Type:
Type
- exception smarter.apps.account.models.budget.SmarterBudgetExceeded(message='', resource_locator=None)[source]
Bases:
SmarterChargeAuthorizationFailedA budget’s resource lock forbids charges to a resource.
messageis meant for the person who made the request, e.g. in the chat window.
- exception smarter.apps.account.models.budget.SmarterChargeAuthorizationFailed(message='')[source]
Bases:
SmarterExceptionException raised when a charge authorization fails.
- smarter.apps.account.models.budget.charge_authorization(resource_locator, on_behalf_of=None)[source]
Check if a charge is authorized for the given list of resource locators.
Call this before doing anything that creates charges, e.g. before calling an LLM.
- Parameters:
- Return type:
- Returns:
True if the charge is authorized.
- Raises:
SmarterBudgetExceeded – if a budget’s resource lock forbids charges to one of them.
- smarter.apps.account.models.budget.evaluate_budgets(now=None)[source]
Remove expired locks, and the locks of inactive constraints, then evaluate every active constraint.
Runs hourly from Celery Beat, so that budgets roll over at the end of their billing period and changes to a budget take effect even if no charge is created.
- Return type:
- Returns:
The number of locked resources.
- smarter.apps.account.models.budget.evaluate_resource_constraints(resource_locator, now=None)[source]
Evaluate every budget attached to a resource, e.g. after a charge to it is created.
- Return type:
- Returns:
The resource’s locks.
- smarter.apps.account.models.budget.get_resource_lock_message(resource_locator)[source]
The message of a resource’s unexpired lock, or None if it is not locked.
Cached, because it is checked on every request. A lock invalidates it when it is created or removed.
- smarter.apps.account.models.budget.is_visible(user_profile, resource_locator)[source]
Whether the user may see the budgets attached to a resource.
- Return type: