mirror of
https://github.com/msoedov/agentic_security.git
synced 2026-06-27 15:49:56 +02:00
f25520869f
Merged upstream/main into fix/cost-calculation-model-aware. Conflict resolved in cost_module.py: - Kept upstream's updated PRICING table (2026-06-03 verified prices) - Kept upstream's DEFAULT_MODEL = "claude-sonnet" - Kept upstream's 50/50 input/output token split - Preserved our float | None return type for unknown models - Preserved our logger.warning instead of raise ValueError
43 lines
1.8 KiB
Python
43 lines
1.8 KiB
Python
from agentic_security.logutils import logger
|
|
|
|
# API pricing, USD per token. Values are dollars per 1M tokens / 1_000_000.
|
|
# Verified against vendor pricing pages on 2026-06-03.
|
|
PRICING = {
|
|
# Anthropic Claude (current generation: Opus 4.x, Sonnet 4.x, Haiku 4.5)
|
|
"claude-opus": {"input": 5 / 1_000_000, "output": 25 / 1_000_000},
|
|
"claude-sonnet": {"input": 3 / 1_000_000, "output": 15 / 1_000_000},
|
|
"claude-haiku": {"input": 1 / 1_000_000, "output": 5 / 1_000_000},
|
|
# OpenAI
|
|
"gpt-4o": {"input": 2.5 / 1_000_000, "output": 10 / 1_000_000},
|
|
"gpt-4o-mini": {"input": 0.15 / 1_000_000, "output": 0.6 / 1_000_000},
|
|
"gpt-4-turbo": {"input": 10 / 1_000_000, "output": 30 / 1_000_000},
|
|
"gpt-4": {"input": 30 / 1_000_000, "output": 60 / 1_000_000},
|
|
"gpt-3.5-turbo": {"input": 0.5 / 1_000_000, "output": 1.5 / 1_000_000},
|
|
# DeepSeek (deepseek-chat, cache-miss input rate)
|
|
"deepseek-chat": {"input": 0.14 / 1_000_000, "output": 0.28 / 1_000_000},
|
|
# Mistral
|
|
"mistral-large": {"input": 0.5 / 1_000_000, "output": 1.5 / 1_000_000},
|
|
"mixtral-8x7b": {"input": 0.7 / 1_000_000, "output": 0.7 / 1_000_000},
|
|
}
|
|
|
|
DEFAULT_MODEL = "claude-sonnet"
|
|
|
|
|
|
def calculate_cost(tokens: int, model: str = DEFAULT_MODEL) -> float | None:
|
|
"""Calculate API cost in USD for a total token count.
|
|
|
|
Assumes a 1:1 input/output split, since callers only track a combined total.
|
|
|
|
Returns:
|
|
float | None: Cost in USD, or None if the model pricing is unknown.
|
|
"""
|
|
if model not in PRICING:
|
|
logger.warning(
|
|
f"Unknown model '{model}': pricing not available, cost will not be estimated."
|
|
)
|
|
return None
|
|
|
|
half = max(tokens, 0) / 2
|
|
rates = PRICING[model]
|
|
return round(half * rates["input"] + half * rates["output"], 6)
|