mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
feat(spend): report guardrail spend separately in daily activity (#51010)
* feat(spend): report guardrail spend separately in daily activity Model and key spend in /user/daily/activity/aggregated include the cost of guardrails like Bedrock guardrails, and nothing in the response says how much. A customer that bills tenants per key and per model could not get model cost alone, so tenants that pay AWS for their own guardrails were charged for them twice Daily spend rows now carry a guardrail_spend column next to spend, and every breakdown in the daily activity responses exposes it, so model cost is spend - guardrail_spend. spend keeps its meaning, so budgets still count guardrail cost as before The value comes from the request's cost_breakdown.guardrail_cost, capped at the row's spend because an allowance discount or a repeat job poll can charge less than the guardrail cost the breakdown records. The delivery ledger freezes it into the accounting payload next to accounting_savings, since the stored payload does not keep cost_breakdown, and the legacy daily queue writes the same value The migration only adds the column with a 0 default, so rows written before it read 0 * fix(spend): count guardrail spend on rows billed without a cost breakdown A request blocked before the LLM call is billed for its guardrails straight from guardrail_information, so it carries no cost_breakdown and its guardrail_spend read 0. Both writers now price guardrail_spend from guardrail_information with guardrail_information_cost, the same function success and failure rows use to add guardrail cost to spend Also fills guardrail_spend in the client usage view built from request logs, qualifies the field description for rows recorded before it existed, and adds the lock timeout the migration checks require * fix(ui): avoid a nested ternary when reading guardrail entries from request logs --------- Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
This commit is contained in:
parent
8fb2b97d5b
commit
894552205b
39 changed files with 432 additions and 7 deletions
|
|
@ -0,0 +1,22 @@
|
|||
SET LOCAL lock_timeout = '10s';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyUserSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyTeamSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyOrganizationSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyEndUserSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyAgentSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyTagSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LiteLLM_DailyGlobalSpend" ADD COLUMN IF NOT EXISTS "guardrail_spend" DOUBLE PRECISION NOT NULL DEFAULT 0.0;
|
||||
|
|
@ -883,6 +883,7 @@ model LiteLLM_DailyUserSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -919,6 +920,7 @@ model LiteLLM_DailyGlobalSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -952,6 +954,7 @@ model LiteLLM_DailyOrganizationSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -990,6 +993,7 @@ model LiteLLM_DailyEndUserSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1027,6 +1031,7 @@ model LiteLLM_DailyAgentSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1064,6 +1069,7 @@ model LiteLLM_DailyTeamSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1104,6 +1110,7 @@ model LiteLLM_DailyTagSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ def _daily_counters(row: Mapping[str, object], metadata: Mapping[str, object]) -
|
|||
("prompt_caching_savings_spend", _number(savings.get("prompt_caching"))),
|
||||
("gateway_injected_caching_savings_spend", _number(savings.get("gateway_injected_caching"))),
|
||||
("autorouter_savings_spend", 0.0 if internal else _number(savings.get("autorouter"))),
|
||||
("guardrail_spend", _number(metadata.get("accounting_guardrail_spend"))),
|
||||
("total_response_time_ms", _number(duration) if timed else 0),
|
||||
("timed_requests", int(timed)),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Final
|
|||
from pydantic import TypeAdapter, ValidationError
|
||||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm.litellm_core_utils.llm_cost_calc.guardrail_cost import guardrail_share_of_spend
|
||||
from litellm.litellm_core_utils.safe_json_dumps import safe_json_structure
|
||||
from litellm.proxy._types import SpendLogsPayload
|
||||
from litellm.proxy.spend_tracking.compression_savings import extract_compression_saved_tokens
|
||||
|
|
@ -73,6 +74,7 @@ def build_accounting_payload(
|
|||
**{key: _accounting_metadata_field(key, value) for key, value in metadata.items() if key in _METADATA_FIELDS},
|
||||
"accounting_entities": entities,
|
||||
"accounting_savings": savings._asdict(),
|
||||
"accounting_guardrail_spend": guardrail_share_of_spend(metadata, payload["spend"]),
|
||||
"accounting_model_access_groups": model_access_groups,
|
||||
"accounting_windows": windows,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,6 +311,12 @@ def guardrail_information_cost(guardrail_information: object) -> float:
|
|||
return _validated_entry_cost(guardrail_information)
|
||||
|
||||
|
||||
def guardrail_share_of_spend(spend_log_metadata: Mapping[str, object], spend: float) -> float:
|
||||
"""The part of a spend row's ``spend`` billed for its guardrails, priced the way success and failure rows add
|
||||
it to spend and capped at the row's spend, since an allowance discount or a repeat job poll can charge less."""
|
||||
return min(guardrail_information_cost(spend_log_metadata.get("guardrail_information")), max(spend, 0.0))
|
||||
|
||||
|
||||
def cost_breakdown_with_guardrail(cost_breakdown: CostBreakdown | None, guardrail_cost: float) -> CostBreakdown | None:
|
||||
if guardrail_cost <= 0.0:
|
||||
return cost_breakdown
|
||||
|
|
|
|||
|
|
@ -4882,6 +4882,12 @@
|
|||
"title": "Gateway Injected Caching Savings Spend",
|
||||
"type": "number"
|
||||
},
|
||||
"guardrail_spend": {
|
||||
"default": 0.0,
|
||||
"description": "Guardrail spend in USD, already included in spend, so model spend is spend - guardrail_spend. Rows recorded before this field existed report 0 even when their spend includes guardrail cost",
|
||||
"title": "Guardrail Spend",
|
||||
"type": "number"
|
||||
},
|
||||
"prompt_caching_savings_spend": {
|
||||
"default": 0.0,
|
||||
"title": "Prompt Caching Savings Spend",
|
||||
|
|
|
|||
|
|
@ -5335,6 +5335,7 @@ class BaseDailySpendTransaction(TypedDict):
|
|||
# missing value to zero, so requiring it here would describe a shape the aggregation
|
||||
# is explicitly tested against.
|
||||
autorouter_savings_spend: NotRequired[float]
|
||||
guardrail_spend: NotRequired[float] # writable-ok: the rollup queue accumulates into this key in place
|
||||
|
||||
# request level metrics
|
||||
spend: float
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ _SPEND_COLUMNS: Final = (
|
|||
"prompt_caching_savings_spend",
|
||||
"gateway_injected_caching_savings_spend",
|
||||
"autorouter_savings_spend",
|
||||
"guardrail_spend",
|
||||
)
|
||||
|
||||
_CASTS: Final[Mapping[str, str]] = MappingProxyType(
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ from litellm.constants import (
|
|||
from litellm.litellm_core_utils.batch_utils import BATCH_COST_REQUEST_ID_SUFFIX
|
||||
from litellm.litellm_core_utils.core_helpers import finite_cost, single_log_line
|
||||
from litellm.litellm_core_utils.litellm_logging import coerce_model_access_groups
|
||||
from litellm.litellm_core_utils.llm_cost_calc.guardrail_cost import guardrail_share_of_spend
|
||||
from litellm.litellm_core_utils.safe_json_loads import safe_json_loads
|
||||
from litellm.proxy._types import (
|
||||
DB_RETRY_SAFE_ERROR_TYPES,
|
||||
|
|
@ -3164,6 +3165,10 @@ class DBSpendUpdateWriter:
|
|||
prompt_caching_savings_spend=savings_spend.prompt_caching,
|
||||
gateway_injected_caching_savings_spend=savings_spend.gateway_injected_caching,
|
||||
autorouter_savings_spend=0.0 if is_internal_call else savings_spend.autorouter,
|
||||
guardrail_spend=guardrail_share_of_spend(
|
||||
_metadata,
|
||||
payload["spend"], # pyright: ignore[reportUnknownArgumentType] # legacy dict | SpendLogsPayload union
|
||||
),
|
||||
total_response_time_ms=timed_duration_ms or 0,
|
||||
timed_requests=0 if timed_duration_ms is None else 1,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -154,6 +154,10 @@ class DailySpendUpdateQueue(BaseUpdateQueue):
|
|||
payload.get("autorouter_savings_spend", 0) or 0
|
||||
) + daily_transaction.get("autorouter_savings_spend", 0)
|
||||
|
||||
daily_transaction["guardrail_spend"] = (
|
||||
payload.get("guardrail_spend", 0) or 0
|
||||
) + daily_transaction.get("guardrail_spend", 0)
|
||||
|
||||
daily_transaction["total_response_time_ms"] = (
|
||||
payload.get("total_response_time_ms", 0) or 0
|
||||
) + daily_transaction.get("total_response_time_ms", 0)
|
||||
|
|
|
|||
|
|
@ -163,6 +163,9 @@ class DailySpendRecord(Protocol):
|
|||
@property
|
||||
def autorouter_savings_spend(self) -> float: ...
|
||||
|
||||
@property
|
||||
def guardrail_spend(self) -> float: ...
|
||||
|
||||
@property
|
||||
def api_requests(self) -> int: ...
|
||||
|
||||
|
|
@ -250,6 +253,7 @@ def update_metrics(existing_metrics: SpendMetrics, record: DailySpendRecord) ->
|
|||
existing_metrics.prompt_caching_savings_spend += record.prompt_caching_savings_spend or 0
|
||||
existing_metrics.gateway_injected_caching_savings_spend += record.gateway_injected_caching_savings_spend or 0
|
||||
existing_metrics.autorouter_savings_spend += record.autorouter_savings_spend or 0
|
||||
existing_metrics.guardrail_spend += record.guardrail_spend or 0 # rebind-ok: callers rely on in-place accumulation
|
||||
existing_metrics.api_requests += record.api_requests or 0
|
||||
existing_metrics.successful_requests += record.successful_requests or 0
|
||||
existing_metrics.failed_requests += record.failed_requests or 0
|
||||
|
|
@ -736,6 +740,7 @@ def sum_spend_metrics(metrics: Sequence[SpendMetrics]) -> SpendMetrics:
|
|||
prompt_caching_savings_spend=sum(metric.prompt_caching_savings_spend for metric in metrics),
|
||||
gateway_injected_caching_savings_spend=sum(metric.gateway_injected_caching_savings_spend for metric in metrics),
|
||||
autorouter_savings_spend=sum(metric.autorouter_savings_spend for metric in metrics),
|
||||
guardrail_spend=sum(metric.guardrail_spend for metric in metrics),
|
||||
total_tokens=sum(metric.total_tokens for metric in metrics),
|
||||
successful_requests=sum(metric.successful_requests for metric in metrics),
|
||||
failed_requests=sum(metric.failed_requests for metric in metrics),
|
||||
|
|
@ -766,6 +771,7 @@ def _record_to_spend_metrics(record: RollupMetricsRow) -> SpendMetrics:
|
|||
prompt_caching_savings_spend=record.prompt_caching_savings_spend or 0,
|
||||
gateway_injected_caching_savings_spend=record.gateway_injected_caching_savings_spend or 0,
|
||||
autorouter_savings_spend=record.autorouter_savings_spend or 0,
|
||||
guardrail_spend=record.guardrail_spend or 0,
|
||||
api_requests=record.api_requests or 0,
|
||||
successful_requests=record.successful_requests or 0,
|
||||
failed_requests=record.failed_requests or 0,
|
||||
|
|
|
|||
|
|
@ -883,6 +883,7 @@ model LiteLLM_DailyUserSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -919,6 +920,7 @@ model LiteLLM_DailyGlobalSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -952,6 +954,7 @@ model LiteLLM_DailyOrganizationSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -990,6 +993,7 @@ model LiteLLM_DailyEndUserSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1027,6 +1031,7 @@ model LiteLLM_DailyAgentSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1064,6 +1069,7 @@ model LiteLLM_DailyTeamSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1104,6 +1110,7 @@ model LiteLLM_DailyTagSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ class _CustomerDailyRow(BaseModel):
|
|||
prompt_caching_savings_spend: float
|
||||
gateway_injected_caching_savings_spend: float
|
||||
autorouter_savings_spend: float
|
||||
guardrail_spend: float
|
||||
spend: float
|
||||
api_requests: int
|
||||
successful_requests: int
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ def _rollup_metric_select(table: DailyActivityTable) -> str:
|
|||
SUM(prompt_caching_savings_spend)::float AS prompt_caching_savings_spend,
|
||||
SUM(gateway_injected_caching_savings_spend)::float AS gateway_injected_caching_savings_spend,
|
||||
SUM(autorouter_savings_spend)::float AS autorouter_savings_spend,
|
||||
SUM(guardrail_spend)::float AS guardrail_spend,
|
||||
SUM(api_requests)::bigint AS api_requests,
|
||||
SUM(successful_requests)::bigint AS successful_requests,
|
||||
SUM(failed_requests)::bigint AS failed_requests,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ class SpendMetrics(LiteLLMBaseModel):
|
|||
prompt_caching_savings_spend: float = Field(default=0.0)
|
||||
gateway_injected_caching_savings_spend: float = Field(default=0.0)
|
||||
autorouter_savings_spend: float = Field(default=0.0)
|
||||
guardrail_spend: float = Field(
|
||||
default=0.0,
|
||||
description="Guardrail spend in USD, already included in spend, so model spend is spend - guardrail_spend. "
|
||||
"Rows recorded before this field existed report 0 even when their spend includes guardrail cost",
|
||||
)
|
||||
total_tokens: int = Field(default=0)
|
||||
successful_requests: int = Field(default=0)
|
||||
failed_requests: int = Field(default=0)
|
||||
|
|
@ -259,6 +264,7 @@ class LiteLLM_DailyUserSpend(LiteLLMBaseModel):
|
|||
prompt_caching_savings_spend: float = 0.0
|
||||
gateway_injected_caching_savings_spend: float = 0.0
|
||||
autorouter_savings_spend: float = 0.0
|
||||
guardrail_spend: float = 0.0
|
||||
spend: float = 0.0
|
||||
api_requests: int = 0
|
||||
successful_requests: int = 0
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ class RollupMetricsRow:
|
|||
prompt_caching_savings_spend: float | None
|
||||
gateway_injected_caching_savings_spend: float | None
|
||||
autorouter_savings_spend: float | None
|
||||
guardrail_spend: float | None = field(default=None, kw_only=True)
|
||||
api_requests: int | None
|
||||
successful_requests: int | None
|
||||
failed_requests: int | None
|
||||
|
|
@ -219,6 +220,7 @@ class DailyActivityRow(Protocol):
|
|||
prompt_caching_savings_spend: float
|
||||
gateway_injected_caching_savings_spend: float
|
||||
autorouter_savings_spend: float
|
||||
guardrail_spend: float
|
||||
spend: float
|
||||
api_requests: int
|
||||
successful_requests: int
|
||||
|
|
|
|||
|
|
@ -883,6 +883,7 @@ model LiteLLM_DailyUserSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -919,6 +920,7 @@ model LiteLLM_DailyGlobalSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -952,6 +954,7 @@ model LiteLLM_DailyOrganizationSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -990,6 +993,7 @@ model LiteLLM_DailyEndUserSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1027,6 +1031,7 @@ model LiteLLM_DailyAgentSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1064,6 +1069,7 @@ model LiteLLM_DailyTeamSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
@ -1104,6 +1110,7 @@ model LiteLLM_DailyTagSpend {
|
|||
prompt_caching_savings_spend Float @default(0.0)
|
||||
gateway_injected_caching_savings_spend Float @default(0.0)
|
||||
autorouter_savings_spend Float @default(0.0)
|
||||
guardrail_spend Float @default(0.0)
|
||||
spend Float @default(0.0)
|
||||
api_requests BigInt @default(0)
|
||||
successful_requests BigInt @default(0)
|
||||
|
|
|
|||
|
|
@ -424,6 +424,7 @@ async def _assert_legacy_database_parity(
|
|||
"guardrail_status": "success",
|
||||
"guardrail_usage": {"text": 2},
|
||||
"guardrail_cost_by_unit": {"text": 0.02},
|
||||
"guardrail_cost": 0.02,
|
||||
"guardrail_cost_in_spend": True,
|
||||
}
|
||||
],
|
||||
|
|
@ -579,6 +580,7 @@ async def _assert_legacy_database_parity(
|
|||
assert daily["autorouter_savings_spend"] == pytest.approx(
|
||||
(0 if origin == "auto_router" else 0.125) + (0.2 if correction_order else 0)
|
||||
)
|
||||
assert daily["guardrail_spend"] == pytest.approx(min(0.02, cost))
|
||||
group_spend = {row["access_group_name"]: row["spend"] for row in results[-1]["LiteLLM_ModelAccessGroupBudgetTable"]}
|
||||
assert group_spend == {"group": cost + prior_spend, **({"unserved-group": prior_spend} if fallback_narrowing else {})}
|
||||
assert results[-1]["LiteLLM_DailyGuardrailUsageUnits"]
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -39,6 +39,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -68,6 +69,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -97,6 +99,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -126,6 +129,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -155,6 +159,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -188,6 +193,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -217,6 +223,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -246,6 +253,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -275,6 +283,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -304,6 +313,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -327,6 +337,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -360,6 +371,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -389,6 +401,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -418,6 +431,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -447,6 +461,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -476,6 +491,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -501,6 +517,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -535,6 +552,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -558,6 +576,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -589,6 +608,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -618,6 +638,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -647,6 +668,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -670,6 +692,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -694,6 +717,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -725,6 +749,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -748,6 +773,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -781,6 +807,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -804,6 +831,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -835,6 +863,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -864,6 +893,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -893,6 +923,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -916,6 +947,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -940,6 +972,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -971,6 +1004,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -994,6 +1028,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1027,6 +1062,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1056,6 +1092,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1085,6 +1122,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1114,6 +1152,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1143,6 +1182,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1166,6 +1206,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -1190,6 +1231,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -68,6 +69,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -97,6 +99,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -126,6 +129,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -155,6 +159,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -188,6 +193,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -217,6 +223,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -246,6 +253,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -275,6 +283,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -304,6 +313,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -327,6 +337,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -360,6 +371,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -389,6 +401,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -418,6 +431,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -447,6 +461,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -476,6 +491,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -501,6 +517,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -535,6 +552,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -558,6 +576,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -589,6 +608,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -618,6 +638,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -647,6 +668,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -670,6 +692,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -694,6 +717,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -725,6 +749,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -748,6 +773,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -781,6 +807,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -804,6 +831,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -835,6 +863,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -864,6 +893,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -893,6 +923,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -916,6 +947,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -940,6 +972,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -971,6 +1004,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -994,6 +1028,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1027,6 +1062,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1056,6 +1092,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1085,6 +1122,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1114,6 +1152,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1143,6 +1182,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1166,6 +1206,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -1190,6 +1231,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -68,6 +69,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -97,6 +99,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -126,6 +129,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -155,6 +159,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -188,6 +193,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -217,6 +223,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -246,6 +253,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -275,6 +283,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -304,6 +313,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -327,6 +337,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -360,6 +371,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -389,6 +401,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -418,6 +431,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -447,6 +461,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -476,6 +491,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -502,6 +518,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -536,6 +553,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -559,6 +577,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -590,6 +609,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -619,6 +639,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -648,6 +669,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -671,6 +693,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -695,6 +718,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -726,6 +750,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -749,6 +774,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -782,6 +808,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -805,6 +832,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -836,6 +864,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -865,6 +894,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -894,6 +924,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -917,6 +948,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -941,6 +973,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -972,6 +1005,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -995,6 +1029,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1028,6 +1063,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1057,6 +1093,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1086,6 +1123,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1115,6 +1153,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1144,6 +1183,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1167,6 +1207,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -1191,6 +1232,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -68,6 +69,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -97,6 +99,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -126,6 +129,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -155,6 +159,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -188,6 +193,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -217,6 +223,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -246,6 +253,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -275,6 +283,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -304,6 +313,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -327,6 +337,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -360,6 +371,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -389,6 +401,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -418,6 +431,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -447,6 +461,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -476,6 +491,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -502,6 +518,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -536,6 +553,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -559,6 +577,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -590,6 +609,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -619,6 +639,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -648,6 +669,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -671,6 +693,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -695,6 +718,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -726,6 +750,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -749,6 +774,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -782,6 +808,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -805,6 +832,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -836,6 +864,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -865,6 +894,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -894,6 +924,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -917,6 +948,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 3,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 3,
|
||||
"completion_tokens": 6,
|
||||
|
|
@ -941,6 +973,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
|
|
@ -972,6 +1005,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -995,6 +1029,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1028,6 +1063,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1057,6 +1093,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1086,6 +1123,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1115,6 +1153,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1144,6 +1183,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 1,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 2,
|
||||
"completion_tokens": 2,
|
||||
|
|
@ -1167,6 +1207,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
@ -1191,6 +1232,7 @@
|
|||
"metrics": {
|
||||
"api_requests": 5,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 6,
|
||||
"completion_tokens": 10,
|
||||
|
|
|
|||
|
|
@ -402,6 +402,7 @@ def _daily_tag_metrics(
|
|||
"prompt_caching_savings_spend": 0.0,
|
||||
"gateway_injected_caching_savings_spend": 0.0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"total_tokens": prompt_tokens + completion_tokens,
|
||||
"successful_requests": api_requests,
|
||||
"failed_requests": 0,
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ def test_failed_daily_user_rollup_commit_is_retried_so_spend_report_and_daily_ac
|
|||
"prompt_caching_savings_spend": pytest.approx(0.0),
|
||||
"gateway_injected_caching_savings_spend": pytest.approx(0.0),
|
||||
"autorouter_savings_spend": pytest.approx(0.0),
|
||||
"guardrail_spend": pytest.approx(0.0),
|
||||
"total_tokens": 40,
|
||||
"successful_requests": 1,
|
||||
"failed_requests": 0,
|
||||
|
|
|
|||
|
|
@ -23,8 +23,23 @@ _FIELDS: Final = TypeAdapter(dict[str, object])
|
|||
@pytest.mark.parametrize("status", ["success", "failure"])
|
||||
@pytest.mark.parametrize("origin", [None, "auto_router", "billed_retry"])
|
||||
@pytest.mark.parametrize("spend", [0.0, 0.25])
|
||||
@pytest.mark.parametrize(
|
||||
("guardrail_information", "billed_guardrail_cost"),
|
||||
[
|
||||
(None, 0.0),
|
||||
([{"guardrail_name": "guard", "guardrail_cost": 0.1}], 0.1),
|
||||
([{"guardrail_name": "guard", "guardrail_cost": 0.5}], 0.5),
|
||||
([{"guardrail_name": "guard", "guardrail_cost": 0.1, "guardrail_cost_in_spend": False}], 0.0),
|
||||
],
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_daily_projection_matches_legacy_writer(status: str, origin: str | None, spend: float) -> None:
|
||||
async def test_daily_projection_matches_legacy_writer(
|
||||
status: str,
|
||||
origin: str | None,
|
||||
spend: float,
|
||||
guardrail_information: list[dict[str, object]] | None,
|
||||
billed_guardrail_cost: float,
|
||||
) -> None:
|
||||
payload: Final = get_logging_payload(
|
||||
kwargs={
|
||||
"model": "projection-test",
|
||||
|
|
@ -43,6 +58,7 @@ async def test_daily_projection_matches_legacy_writer(status: str, origin: str |
|
|||
**_FIELDS.validate_json(payload["metadata"]),
|
||||
**({BILLED_RETRY_ATTEMPT_METADATA_KEY: True} if origin == "billed_retry" else {}),
|
||||
**({INTERNAL_CALL_ORIGIN_METADATA_KEY: origin} if origin not in (None, "billed_retry") else {}),
|
||||
**({"guardrail_information": guardrail_information} if guardrail_information is not None else {}),
|
||||
}
|
||||
row: Final = {**payload, "spend": spend, "metadata": json.dumps(metadata), "request_duration_ms": 25}
|
||||
legacy: Final = await DBSpendUpdateWriter()._common_add_spend_log_transaction_to_daily_transaction(
|
||||
|
|
@ -60,6 +76,7 @@ async def test_daily_projection_matches_legacy_writer(status: str, origin: str |
|
|||
restored: Final = _FIELDS.validate_json(json.dumps(accounting, default=str))
|
||||
stored_daily: Final = next(item for item in project(restored) if item.table == "LiteLLM_DailyUserSpend")
|
||||
assert dict(stored_daily.increments) == {name: legacy[name] for name, _ in stored_daily.increments}
|
||||
assert dict(stored_daily.increments)["guardrail_spend"] == min(billed_guardrail_cost, spend)
|
||||
assert dict(stored_daily.key)["date"] == legacy["date"]
|
||||
assert dict(stored_daily.key)["api_key"] == legacy["api_key"]
|
||||
assert not {"messages", "response", "proxy_server_request", "requester_ip_address"}.intersection(accounting)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from litellm.litellm_core_utils.llm_cost_calc.guardrail_cost import (
|
|||
cost_breakdown_with_guardrail,
|
||||
guardrail_cost_total,
|
||||
guardrail_information_cost,
|
||||
guardrail_share_of_spend,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -349,3 +350,15 @@ def test_native_trace_entry_redacts_the_pii_matches_before_they_reach_spend_logs
|
|||
assert entry["guardrail_status"] == "guardrail_intervened"
|
||||
assert "123-45-6789" not in json.dumps(entry["guardrail_response"])
|
||||
assert entry["guardrail_usage"]["sensitiveInformationPolicyUnits"] == 2
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("spend", "expected"), [(1.0, 0.3), (0.2, 0.2), (-1.0, 0.0)])
|
||||
def test_guardrail_share_of_spend_is_the_billed_guardrail_cost_capped_at_the_row_spend(
|
||||
spend: float, expected: float
|
||||
) -> None:
|
||||
information: Final = [
|
||||
{"guardrail_name": "billed", "guardrail_cost": 0.3},
|
||||
{"guardrail_name": "report-only", "guardrail_cost": 0.4, "guardrail_cost_in_spend": False},
|
||||
]
|
||||
assert guardrail_share_of_spend({"guardrail_information": information}, spend) == pytest.approx(expected)
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ async def test_get_aggregated_daily_spend_update_transactions_same_key():
|
|||
"prompt_caching_savings_spend": 0,
|
||||
"gateway_injected_caching_savings_spend": 0,
|
||||
"autorouter_savings_spend": 0,
|
||||
"guardrail_spend": 0,
|
||||
"total_response_time_ms": 0,
|
||||
"timed_requests": 0,
|
||||
}
|
||||
|
|
@ -263,6 +264,7 @@ async def test_flush_and_get_aggregated_daily_spend_update_transactions(
|
|||
"prompt_caching_savings_spend": 0,
|
||||
"gateway_injected_caching_savings_spend": 0,
|
||||
"autorouter_savings_spend": 0,
|
||||
"guardrail_spend": 0,
|
||||
"total_response_time_ms": 0,
|
||||
"timed_requests": 0,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ def test_one_statement_carries_every_row_in_the_batch():
|
|||
|
||||
assert sql.count("INSERT INTO") == 1
|
||||
assert len(re.findall(r"ON CONFLICT", sql)) == 1
|
||||
# 25 bound columns per row plus the inlined updated_at, so the row count is what
|
||||
# 26 bound columns per row plus the inlined updated_at, so the row count is what
|
||||
# separates one multi-row statement from a hundred single-row ones.
|
||||
assert len(params) == 100 * 25
|
||||
assert "$2500::text" in sql
|
||||
assert len(params) == 100 * 26
|
||||
assert "$2600::text" in sql
|
||||
assert sql.count("(NOW() AT TIME ZONE 'UTC')") == 100 + 1
|
||||
|
||||
|
||||
|
|
@ -111,6 +111,7 @@ def test_conflict_target_is_the_full_unique_constraint():
|
|||
"prompt_tokens",
|
||||
"completion_tokens",
|
||||
"spend",
|
||||
"guardrail_spend",
|
||||
"api_requests",
|
||||
"successful_requests",
|
||||
"failed_requests",
|
||||
|
|
|
|||
|
|
@ -710,6 +710,7 @@ async def test_get_daily_activity_aggregated_with_endpoint_breakdown():
|
|||
"prompt_caching_savings_spend": 0.0,
|
||||
"gateway_injected_caching_savings_spend": 0.0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"total_response_time_ms": 0,
|
||||
"timed_requests": 0,
|
||||
"failed_requests": 0,
|
||||
|
|
@ -1294,6 +1295,7 @@ def test_update_breakdown_metrics_includes_user_email():
|
|||
prompt_caching_savings_spend=0,
|
||||
gateway_injected_caching_savings_spend=0,
|
||||
autorouter_savings_spend=0,
|
||||
guardrail_spend=0,
|
||||
total_response_time_ms=0,
|
||||
timed_requests=0,
|
||||
total_tokens=2,
|
||||
|
|
@ -1375,6 +1377,7 @@ async def test_tag_daily_activity_metadata_totals_not_zero():
|
|||
mock_record_1.prompt_caching_savings_spend = 0.0
|
||||
mock_record_1.gateway_injected_caching_savings_spend = 0.0
|
||||
mock_record_1.autorouter_savings_spend = 0.0
|
||||
mock_record_1.guardrail_spend = 0.0
|
||||
mock_record_1.total_response_time_ms = 18_000
|
||||
mock_record_1.timed_requests = 9
|
||||
mock_record_1.api_requests = 10
|
||||
|
|
@ -1401,6 +1404,7 @@ async def test_tag_daily_activity_metadata_totals_not_zero():
|
|||
mock_record_2.prompt_caching_savings_spend = 0.0
|
||||
mock_record_2.gateway_injected_caching_savings_spend = 0.0
|
||||
mock_record_2.autorouter_savings_spend = 0.0
|
||||
mock_record_2.guardrail_spend = 0.0
|
||||
mock_record_2.total_response_time_ms = 2_500
|
||||
mock_record_2.timed_requests = 5
|
||||
mock_record_2.api_requests = 5
|
||||
|
|
@ -1473,6 +1477,7 @@ async def test_aggregated_activity_preserves_metadata_for_deleted_keys():
|
|||
"prompt_caching_savings_spend": 0.0,
|
||||
"gateway_injected_caching_savings_spend": 0.0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"total_response_time_ms": 0,
|
||||
"timed_requests": 0,
|
||||
"failed_requests": 0,
|
||||
|
|
@ -1569,6 +1574,7 @@ async def test_aggregated_activity_flags_only_keys_that_key_info_can_still_resol
|
|||
"prompt_caching_savings_spend": 0.0,
|
||||
"gateway_injected_caching_savings_spend": 0.0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"total_response_time_ms": 0,
|
||||
"timed_requests": 0,
|
||||
"api_requests": 1,
|
||||
|
|
@ -1618,7 +1624,7 @@ async def test_aggregated_activity_flags_only_keys_that_key_info_can_still_resol
|
|||
assert key_breakdown["deleted-key"].metadata.key_alias == "deleted"
|
||||
|
||||
|
||||
def _daily_user_spend_record(*, user_id, api_key, spend, model="gpt-4", model_group="gpt-4"):
|
||||
def _daily_user_spend_record(*, user_id, api_key, spend, model="gpt-4", model_group="gpt-4", guardrail_spend=0.0):
|
||||
"""A LiteLLM_DailyUserSpend row as the per-user breakdown reads it."""
|
||||
return SimpleNamespace(
|
||||
date="2024-01-01",
|
||||
|
|
@ -1639,6 +1645,7 @@ def _daily_user_spend_record(*, user_id, api_key, spend, model="gpt-4", model_gr
|
|||
prompt_caching_savings_spend=0.0,
|
||||
gateway_injected_caching_savings_spend=0.0,
|
||||
autorouter_savings_spend=0.0,
|
||||
guardrail_spend=guardrail_spend,
|
||||
total_response_time_ms=0,
|
||||
timed_requests=0,
|
||||
api_requests=1,
|
||||
|
|
@ -1647,6 +1654,38 @@ def _daily_user_spend_record(*, user_id, api_key, spend, model="gpt-4", model_gr
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_paginated_activity_separates_guardrail_spend_per_model_and_key():
|
||||
records = [
|
||||
_daily_user_spend_record(user_id="u", api_key="key", spend=0.0076916, model="guarded", guardrail_spend=0.00015),
|
||||
_daily_user_spend_record(user_id="u", api_key="key", spend=0.002, model="unguarded"),
|
||||
]
|
||||
mock_prisma = MagicMock()
|
||||
mock_prisma.db.litellm_dailyuserspend.count = AsyncMock(return_value=len(records))
|
||||
mock_prisma.db.litellm_dailyuserspend.find_many = AsyncMock(return_value=records)
|
||||
mock_prisma.db.litellm_verificationtoken.find_many = AsyncMock(return_value=[])
|
||||
|
||||
result = await get_daily_activity(
|
||||
prisma_client=mock_prisma,
|
||||
table_name="litellm_dailyuserspend",
|
||||
entity_id_field="user_id",
|
||||
entity_id=None,
|
||||
entity_metadata_field=None,
|
||||
start_date="2024-01-01",
|
||||
end_date="2024-01-01",
|
||||
model=None,
|
||||
api_key=None,
|
||||
page=1,
|
||||
page_size=1000,
|
||||
)
|
||||
|
||||
models = result.results[0].breakdown.models
|
||||
guarded = models["guarded"].api_key_breakdown["key"].metrics
|
||||
assert guarded.spend - guarded.guardrail_spend == pytest.approx(0.0075416)
|
||||
assert models["unguarded"].api_key_breakdown["key"].metrics.guardrail_spend == 0.0
|
||||
assert result.results[0].metrics.guardrail_spend == pytest.approx(0.00015)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_daily_activity_applies_resolve_entity_metadata_to_breakdown():
|
||||
"""Regression for LIT-3889: the Spend Per User chart showed raw UUIDs.
|
||||
|
|
@ -1788,6 +1827,7 @@ async def test_get_daily_activity_aggregated_empty_result_set():
|
|||
"prompt_caching_savings_spend": None,
|
||||
"gateway_injected_caching_savings_spend": None,
|
||||
"autorouter_savings_spend": None,
|
||||
"guardrail_spend": None,
|
||||
"total_response_time_ms": None,
|
||||
"timed_requests": None,
|
||||
"api_requests": None,
|
||||
|
|
@ -1836,6 +1876,7 @@ def _no_spend_record():
|
|||
prompt_caching_savings_spend=None,
|
||||
gateway_injected_caching_savings_spend=None,
|
||||
autorouter_savings_spend=None,
|
||||
guardrail_spend=None,
|
||||
total_response_time_ms=None,
|
||||
timed_requests=None,
|
||||
api_requests=None,
|
||||
|
|
@ -1975,6 +2016,7 @@ def _spend_record(api_key, *, model="gpt-4o-mini-ptu", spend=0.0, ptu_flat_cost=
|
|||
prompt_caching_savings_spend=0,
|
||||
gateway_injected_caching_savings_spend=0,
|
||||
autorouter_savings_spend=0,
|
||||
guardrail_spend=0,
|
||||
total_response_time_ms=0,
|
||||
timed_requests=0,
|
||||
total_tokens=0,
|
||||
|
|
@ -2021,6 +2063,7 @@ def _grouping_row(
|
|||
endpoint=None,
|
||||
spend=0.0,
|
||||
ptu_flat_cost=0.0,
|
||||
guardrail_spend=None,
|
||||
):
|
||||
return GroupingSetsRow(
|
||||
date="2024-01-01",
|
||||
|
|
@ -2043,6 +2086,7 @@ def _grouping_row(
|
|||
prompt_caching_savings_spend=0.0,
|
||||
gateway_injected_caching_savings_spend=0.0,
|
||||
autorouter_savings_spend=0.0,
|
||||
guardrail_spend=guardrail_spend,
|
||||
total_response_time_ms=0,
|
||||
timed_requests=0,
|
||||
api_requests=0,
|
||||
|
|
@ -2088,6 +2132,38 @@ def test_grouping_sets_dispatcher_excludes_ptu_sentinel_from_key_breakdowns(ptu_
|
|||
assert "real-key" in model_bucket.api_key_breakdown
|
||||
|
||||
|
||||
def test_model_key_breakdown_separates_guardrail_spend_from_model_spend():
|
||||
from litellm.proxy.management_endpoints.common_daily_activity import (
|
||||
_GROUP_DATE_API_KEY,
|
||||
_GROUP_DATE_MODEL,
|
||||
_GROUP_DATE_MODEL_API_KEY,
|
||||
_GROUP_GRAND_TOTAL,
|
||||
_aggregate_grouping_sets_records_sync,
|
||||
)
|
||||
|
||||
records = [
|
||||
_grouping_row(_GROUP_DATE_MODEL, model="guarded", spend=0.0076916, guardrail_spend=0.00015),
|
||||
_grouping_row(_GROUP_DATE_MODEL, model="unguarded", spend=0.002),
|
||||
_grouping_row(
|
||||
_GROUP_DATE_MODEL_API_KEY, model="guarded", api_key="key", spend=0.0076916, guardrail_spend=0.00015
|
||||
),
|
||||
_grouping_row(_GROUP_DATE_MODEL_API_KEY, model="unguarded", api_key="key", spend=0.002),
|
||||
_grouping_row(_GROUP_DATE_API_KEY, api_key="key", spend=0.0096916, guardrail_spend=0.00015),
|
||||
_grouping_row(_GROUP_GRAND_TOTAL, spend=0.0096916, guardrail_spend=0.00015),
|
||||
]
|
||||
|
||||
aggregated = _aggregate_grouping_sets_records_sync(records=records, api_key_metadata={})
|
||||
day = aggregated["results"][0]
|
||||
|
||||
guarded = day.breakdown.models["guarded"].api_key_breakdown["key"].metrics
|
||||
unguarded = day.breakdown.models["unguarded"].api_key_breakdown["key"].metrics
|
||||
assert guarded.spend - guarded.guardrail_spend == pytest.approx(0.0075416)
|
||||
assert unguarded.guardrail_spend == 0.0
|
||||
assert day.breakdown.models["guarded"].metrics.guardrail_spend == pytest.approx(0.00015)
|
||||
assert day.breakdown.api_keys["key"].metrics.guardrail_spend == pytest.approx(0.00015)
|
||||
assert aggregated["totals"].guardrail_spend == pytest.approx(0.00015)
|
||||
|
||||
|
||||
def test_grouping_sets_dispatcher_populates_every_breakdown_level(ptu_cost_attribution_enabled):
|
||||
"""Every GROUPING SETS level lands in its bucket, and the flat-cost sentinel
|
||||
is kept out of the model_group and provider api_key sub-breakdowns too."""
|
||||
|
|
@ -2205,6 +2281,7 @@ def test_update_breakdown_metrics_covers_mcp_endpoint_and_entity(ptu_cost_attrib
|
|||
prompt_caching_savings_spend=0,
|
||||
gateway_injected_caching_savings_spend=0,
|
||||
autorouter_savings_spend=0,
|
||||
guardrail_spend=0,
|
||||
total_response_time_ms=0,
|
||||
timed_requests=0,
|
||||
total_tokens=0,
|
||||
|
|
@ -2560,6 +2637,7 @@ async def test_get_daily_activity_aggregated_with_entity_breakdown():
|
|||
"prompt_caching_savings_spend": 0.0,
|
||||
"gateway_injected_caching_savings_spend": 0.0,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"total_response_time_ms": 0,
|
||||
"timed_requests": 0,
|
||||
"failed_requests": 0,
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ class _Activity:
|
|||
prompt_caching_savings_spend: float
|
||||
gateway_injected_caching_savings_spend: float
|
||||
autorouter_savings_spend: float
|
||||
guardrail_spend: float
|
||||
api_requests: int
|
||||
successful_requests: int
|
||||
failed_requests: int
|
||||
|
|
@ -109,6 +110,7 @@ def _activity_for_entity(
|
|||
prompt_caching_savings_spend=0.2,
|
||||
gateway_injected_caching_savings_spend=0.3,
|
||||
autorouter_savings_spend=0.4,
|
||||
guardrail_spend=0.5,
|
||||
api_requests=1,
|
||||
successful_requests=1,
|
||||
failed_requests=0,
|
||||
|
|
@ -165,6 +167,7 @@ def _seeded_activity() -> tuple[_Activity, ...]:
|
|||
prompt_caching_savings_spend=0.0,
|
||||
gateway_injected_caching_savings_spend=0.0,
|
||||
autorouter_savings_spend=0.0,
|
||||
guardrail_spend=0.0,
|
||||
api_requests=1,
|
||||
successful_requests=1,
|
||||
failed_requests=0,
|
||||
|
|
@ -188,6 +191,7 @@ def _metrics(rows: Sequence[_Activity]) -> Mapping[str, int | float]:
|
|||
"prompt_caching_savings_spend": sum(row.prompt_caching_savings_spend for row in rows),
|
||||
"gateway_injected_caching_savings_spend": sum(row.gateway_injected_caching_savings_spend for row in rows),
|
||||
"autorouter_savings_spend": sum(row.autorouter_savings_spend for row in rows),
|
||||
"guardrail_spend": sum(row.guardrail_spend for row in rows),
|
||||
"api_requests": sum(row.api_requests for row in rows),
|
||||
"successful_requests": sum(row.successful_requests for row in rows),
|
||||
"failed_requests": sum(row.failed_requests for row in rows),
|
||||
|
|
@ -791,6 +795,7 @@ def test_search_folds_each_entity_key_across_days(
|
|||
"prompt_caching_savings_spend": 0.4,
|
||||
"gateway_injected_caching_savings_spend": 0.6,
|
||||
"autorouter_savings_spend": 0.8,
|
||||
"guardrail_spend": 1.0,
|
||||
"total_tokens": 30,
|
||||
"successful_requests": 2,
|
||||
"failed_requests": 0,
|
||||
|
|
|
|||
|
|
@ -19308,6 +19308,7 @@ def _db_with_one_ptu_hour_of_team_spend(team_id: str) -> MagicMock:
|
|||
prompt_caching_savings_spend=0.0,
|
||||
gateway_injected_caching_savings_spend=0.0,
|
||||
autorouter_savings_spend=0.0,
|
||||
guardrail_spend=0.0,
|
||||
total_response_time_ms=0,
|
||||
timed_requests=0,
|
||||
api_requests=3,
|
||||
|
|
|
|||
|
|
@ -675,6 +675,7 @@ async def test_customer_team_page_returns_loaded_metrics_and_retains_count_on_em
|
|||
"prompt_caching_savings_spend": 0.25,
|
||||
"gateway_injected_caching_savings_spend": 0.125,
|
||||
"autorouter_savings_spend": 0.0,
|
||||
"guardrail_spend": 0.0,
|
||||
"total_response_time_ms": 10,
|
||||
"timed_requests": 1,
|
||||
"created_at": "2026-01-01T00:00:00Z",
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ def test_aggregated_query_uses_the_caller_date_bounds(offset_minutes: int | None
|
|||
def test_aggregate_query_sums_all_savings_drivers_and_response_time() -> None:
|
||||
query = build_aggregated_sql(_scope(), api_key_limit=constants.USAGE_TOP_API_KEYS_DEFAULT)
|
||||
fields: Final = tuple(field for field in SpendMetrics.model_fields if field.endswith("_savings_spend")) + (
|
||||
"guardrail_spend",
|
||||
"total_response_time_ms",
|
||||
"timed_requests",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ const baseMetrics = (overrides: Partial<SpendMetrics>): components["schemas"]["S
|
|||
prompt_caching_savings_spend: 0,
|
||||
gateway_injected_caching_savings_spend: 0,
|
||||
autorouter_savings_spend: 0,
|
||||
guardrail_spend: 0,
|
||||
total_response_time_ms: 0,
|
||||
timed_requests: 0,
|
||||
...overrides,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,26 @@ describe("client usage from request logs", () => {
|
|||
expect(day?.date).toBe(localDay);
|
||||
});
|
||||
|
||||
it("should report guardrail spend inside model spend, capped at what each request was charged", () => {
|
||||
const guarded = (request_id: string, spend: number, guardrail_information: unknown) =>
|
||||
log({ request_id, spend, metadata: { user_agent: desktopAgent, guardrail_information } });
|
||||
const result = clientUsageFromLogs(
|
||||
page([
|
||||
guarded("billed", 0.0076916, [
|
||||
{ guardrail_cost: 0.00015 },
|
||||
{ guardrail_cost: 0.0004, guardrail_cost_in_spend: false },
|
||||
]),
|
||||
guarded("capped", 0.0001, { guardrail_cost: 0.0003 }),
|
||||
guarded("malformed", 0.002, [{ guardrail_cost: "free" }]),
|
||||
log(),
|
||||
]),
|
||||
scope,
|
||||
);
|
||||
expect(result.error).toBeNull();
|
||||
const metrics = result.data.results?.[0]?.breakdown?.models?.["provider-model"].metrics;
|
||||
expect(metrics?.guardrail_spend).toBeCloseTo(0.00025, 10);
|
||||
});
|
||||
|
||||
it("should deduplicate request ids without double counting bare and full user-agent tags", () => {
|
||||
const result = clientUsageFromLogs(page([log(), log({ spend: 0.02 })]), scope);
|
||||
expect(result.data.metadata?.total_api_requests).toBe(1);
|
||||
|
|
|
|||
|
|
@ -31,11 +31,19 @@ const usageFields = {
|
|||
input_tokens_details: cacheDetailsSchema.nullish(),
|
||||
};
|
||||
const usageSchema = z.object(usageFields);
|
||||
const guardrailEntrySchema = z.object({
|
||||
guardrail_cost: z.number().finite().nullish().catch(null),
|
||||
guardrail_cost_in_spend: z.boolean().nullish().catch(null),
|
||||
});
|
||||
const metadataFields = {
|
||||
user_agent: z.string().nullish(),
|
||||
status: z.string().nullish(),
|
||||
additional_usage_values: usageSchema.nullish(),
|
||||
usage_object: usageSchema.nullish(),
|
||||
guardrail_information: z
|
||||
.union([z.array(guardrailEntrySchema), guardrailEntrySchema])
|
||||
.nullish()
|
||||
.catch(null),
|
||||
};
|
||||
const logFields = {
|
||||
request_id: z.string().min(1),
|
||||
|
|
@ -127,6 +135,19 @@ const cacheTokens = (row: ClientLog) => {
|
|||
cacheCreationTokens: additional.cacheCreationTokens ?? usage.cacheCreationTokens,
|
||||
};
|
||||
};
|
||||
const billedGuardrailCost = (entry: z.infer<typeof guardrailEntrySchema>) =>
|
||||
entry.guardrail_cost_in_spend === false ? 0 : Math.max(entry.guardrail_cost ?? 0, 0);
|
||||
type GuardrailInformation = NonNullable<NonNullable<ClientLog["metadata"]>["guardrail_information"]>;
|
||||
const guardrailEntries = (information: GuardrailInformation) =>
|
||||
Array.isArray(information) ? information : [information];
|
||||
const guardrailSpend = (row: ClientLog) => {
|
||||
const information = row.metadata?.guardrail_information;
|
||||
const entries = information == null ? [] : guardrailEntries(information);
|
||||
return Math.min(
|
||||
entries.reduce((total, entry) => total + billedGuardrailCost(entry), 0),
|
||||
Math.max(row.spend, 0),
|
||||
);
|
||||
};
|
||||
const sum = (rows: readonly ClientLog[], value: (row: ClientLog) => number) =>
|
||||
rows.reduce((total, row) => total + value(row), 0);
|
||||
const metricsFor = (rows: readonly ClientLog[]): SpendMetrics => ({
|
||||
|
|
@ -137,6 +158,7 @@ const metricsFor = (rows: readonly ClientLog[]): SpendMetrics => ({
|
|||
prompt_caching_savings_spend: 0,
|
||||
gateway_injected_caching_savings_spend: 0,
|
||||
autorouter_savings_spend: 0,
|
||||
guardrail_spend: sum(rows, guardrailSpend),
|
||||
spend: sum(rows, (row) => row.spend),
|
||||
prompt_tokens: sum(rows, (row) => row.prompt_tokens),
|
||||
completion_tokens: sum(rows, (row) => row.completion_tokens),
|
||||
|
|
|
|||
6
ui/litellm-dashboard/src/lib/http/schema.d.ts
generated
vendored
6
ui/litellm-dashboard/src/lib/http/schema.d.ts
generated
vendored
|
|
@ -47697,6 +47697,12 @@ export interface components {
|
|||
* @default 0
|
||||
*/
|
||||
gateway_injected_caching_savings_spend: number;
|
||||
/**
|
||||
* Guardrail Spend
|
||||
* @description Guardrail spend in USD, already included in spend, so model spend is spend - guardrail_spend. Rows recorded before this field existed report 0 even when their spend includes guardrail cost
|
||||
* @default 0
|
||||
*/
|
||||
guardrail_spend: number;
|
||||
/**
|
||||
* Prompt Caching Savings Spend
|
||||
* @default 0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue