/** * Cost calculation functions for tokenization */ import { createLogger } from '@sim/logger' import { toError } from '@sim/utils/errors' import { createTokenizationError } from '@/lib/tokenization/errors' import { estimateInputTokens, estimateOutputTokens, estimateTokenCount, } from '@/lib/tokenization/estimators' import type { CostBreakdown, StreamingCostResult, TokenizationInput, TokenUsage, } from '@/lib/tokenization/types' import { getProviderForTokenization, logTokenizationDetails, validateTokenizationInput, } from '@/lib/tokenization/utils' import { calculateCost } from '@/providers/utils' const logger = createLogger('TokenizationCalculators') /** * Calculates cost estimate for streaming execution using token estimation */ export function calculateStreamingCost( model: string, inputText: string, outputText: string, systemPrompt?: string, context?: string, messages?: Array<{ role: string; content: string }> ): StreamingCostResult { try { // Validate inputs validateTokenizationInput(model, inputText, outputText) const providerId = getProviderForTokenization(model) // Estimate input tokens (combine all input sources) const inputEstimate = estimateInputTokens(systemPrompt, context, messages, providerId) // Add the main input text to the estimation const mainInputEstimate = estimateTokenCount(inputText, providerId) const totalPromptTokens = inputEstimate.count + mainInputEstimate.count // Estimate output tokens const outputEstimate = estimateOutputTokens(outputText, providerId) const completionTokens = outputEstimate.count // Calculate total tokens const totalTokens = totalPromptTokens + completionTokens // Create token usage object const tokens: TokenUsage = { input: totalPromptTokens, output: completionTokens, total: totalTokens, } // Calculate cost using provider pricing const costResult = calculateCost(model, totalPromptTokens, completionTokens, false) const cost: CostBreakdown = { input: costResult.input, output: costResult.output, total: costResult.total, } const result: StreamingCostResult = { tokens, cost, model, provider: providerId, method: 'tokenization', } logTokenizationDetails('Streaming cost calculation completed', { model, provider: providerId, inputLength: inputText.length, outputLength: outputText.length, tokens, cost, method: 'tokenization', }) return result } catch (error) { logger.error('Streaming cost calculation failed', { model, inputLength: inputText?.length || 0, outputLength: outputText?.length || 0, error: toError(error).message, }) if (error instanceof Error && error.name === 'TokenizationError') { throw error } throw createTokenizationError( 'CALCULATION_FAILED', `Failed to calculate streaming cost: ${toError(error).message}`, { model, inputLength: inputText?.length || 0, outputLength: outputText?.length || 0 } ) } } /** * Calculates cost for tokenization input object */ export function calculateTokenizationCost(input: TokenizationInput): StreamingCostResult { return calculateStreamingCost( input.model, input.inputText, input.outputText, input.systemPrompt, input.context, input.messages ) } /** * Creates a streaming cost result from existing provider response data */ export function createCostResultFromProviderData( model: string, providerTokens: TokenUsage, providerCost: CostBreakdown ): StreamingCostResult { const providerId = getProviderForTokenization(model) return { tokens: providerTokens, cost: providerCost, model, provider: providerId, method: 'provider_response', } }