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: MetaDataModel

A 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

DecimalField

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

CharField

Action. What happens when a limit is reached: block further charges, or only send the budget_exceeded signal.

Choices:

  • block

  • warn

Type:

Type

annotations

JSONField

Annotations. Key-value pairs for annotating this resource.

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:

list[ResourceConstraint]

Returns:

The resource constraints, one per record locator.

constraints

Reverse ForeignKey from ResourceConstraint

All constraints of this budget (related name of budget)

Type:

Type

created_at

DateTimeField

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

TextField

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:

int

Returns:

The number of resource constraints removed.

duration

PositiveIntegerField

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:

str

get_action_display(*, field=<django.db.models.CharField: action>)

Shows the label of the action. See get_FOO_display() for more information.

get_period_display(*, field=<django.db.models.CharField: period>)

Shows the label of the period. See get_FOO_display() for more information.

get_unit_display(*, field=<django.db.models.CharField: unit>)

Shows the label of the unit. See get_FOO_display() for more information.

id

BigAutoField

Primary key: ID

Type:

Type

message

TextField

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

CharField

Name. The budget’s name, in snake_case. Unique: manifests refer to budgets by name.

Type:

Type

objects = <django.db.models.Manager object>
period

CharField

Period. The billing period of the periodic limit, and of the duration.

Choices:

  • hour

  • day

  • week

  • month

Type:

Type

periodic_limit

DecimalField

Periodic limit. The maximum cost or tokens that can be incurred in a billing period. 0 means no limit.

Type:

Type

tagged_items

Reverse GenericRelation from Budget

All + of this tagged item (related name of tagged_items)

Type:

Type

tags = <taggit.managers._TaggableManager object>
unit

CharField

Unit. What the limits measure: cost in USD, or total tokens.

Choices:

  • cost

  • tokens

Type:

Type

updated_at

DateTimeField

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.

version

CharField

Version. Semantic version in the format MAJOR.MINOR.PATCH, e.g., ‘1.0.0’.

Type:

Type

warning_threshold

PositiveSmallIntegerField

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: TextChoices

What happens when a budget’s limit is reached.

BLOCK = 'block'
WARN = 'warn'
class smarter.apps.account.models.budget.BudgetPeriod(*values)[source]

Bases: TextChoices

The 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: TextChoices

What a budget’s limits measure.

COST = 'cost'
TOKENS = 'tokens'
class smarter.apps.account.models.budget.ResourceConstraint(*args, **kwargs)[source]

Bases: TimestampedModel

A 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

absolute_actual(now=None)[source]

Spending since the start date.

Return type:

Decimal

budget

ForeignKey to Budget

Budget. The budget that is enforced on the resource. (related name: constraints)

Type:

Type

budget_id

Internal field, use budget instead.

created_at

DateTimeField

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

current_period(now=None)[source]

The beginning and end of the billing period that contains now.

Return type:

tuple[datetime, datetime]

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:

Optional[ResourceLock]

Returns:

The resource’s lock, if it is locked.

exceeded_at

DateTimeField

Exceeded at. When the budget_exceeded signal was last sent for this resource.

Type:

Type

property expires_at: datetime | None

When the budget’s duration ends, or None if it has none.

get_next_by_start_date(*, field=<django.db.models.DateTimeField: start_date>, is_next=True, **kwargs)

Finds next instance based on start_date. See get_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. See get_previous_by_FOO() for more information.

id

BigAutoField

Primary key: ID

Type:

Type

is_active

BooleanField

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:

bool

locks

Reverse ForeignKey from ResourceLock

All locks of this resource constraint (related name of resource_constraint)

Type:

Type

measure(actuals)[source]

Actual spending in the budget’s unit.

Return type:

Decimal

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:

Decimal

resource_locator

CharField

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.

Return type:

list[dict[str, Any]]

start_date

DateTimeField

Start date. When the budget began to apply to the resource. The duration and the absolute limit count from here.

Type:

Type

status(now=None)[source]

The budget versus the actual spending, now.

Return type:

dict[str, Any]

updated_at

DateTimeField

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

DateTimeField

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: TimestampedModel

A 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

DateTimeField

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

DateTimeField

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

BigAutoField

Primary key: ID

Type:

Type

property is_expired: bool

Whether the lock’s billing period has ended.

property message: str

What people are told when the lock refuses their request.

objects = <django.db.models.Manager object>
reason

TextField

Reason. Which limit was reached.

Type:

Type

resource_constraint

ForeignKey to ResourceConstraint

Resource constraint. The resource constraint that this lock is associated with. (related name: locks)

Type:

Type

resource_constraint_id

Internal field, use resource_constraint instead.

resource_locator

CharField

Resource locator. The TimestampedModel.resource_locator of the resource that this lock is associated with.

Type:

Type

updated_at

DateTimeField

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: SmarterChargeAuthorizationFailed

A budget’s resource lock forbids charges to a resource.

message is meant for the person who made the request, e.g. in the chat window.

__init__(message='', resource_locator=None)[source]
exception smarter.apps.account.models.budget.SmarterChargeAuthorizationFailed(message='')[source]

Bases: SmarterException

Exception 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:
  • resource_locator (Union[list[str], str]) – A list of resource locators or a single resource locator that may be used by the custom implementation.

  • on_behalf_of (Optional[str]) – An optional object representing the entity on whose behalf the charge is being authorized.

Return type:

bool

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:

int

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:

list[ResourceLock]

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.

Return type:

Optional[str]

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:

bool

smarter.apps.account.models.budget.resolve_resource(resource_locator)[source]

The model instance of a record locator, e.g. “llmclient-rc2x”, or None.

Return type:

Optional[TimestampedModel]