UNPKG

blackboxify

Version:

BlackboxAI API client with OpenAI-compatible interface, streaming support, multiple auth accounts, and token pricing

107 lines (90 loc) 3.24 kB
import { BlackboxError } from './errors.js'; // Simple word-based token estimation function estimateTokens(text) { if (!text) return 0; // Split on whitespace and punctuation const words = text.split(/[\s,.!?;:'"()\[\]{}|\\/<>]+/); // Filter out empty strings and multiply by 1.3 for a conservative estimate // Most language models use subword tokenization, so actual tokens are usually more than words return Math.ceil(words.filter(w => w.length > 0).length * 1.3); } function calculateMessageTokens(messages) { let total = 0; for (const message of messages) { // Add tokens for message metadata (role, etc.) total += 4; // Approximate overhead per message // Add tokens for content if (message.content) { total += estimateTokens(message.content); } // Add tokens for role if (message.role) { total += 1; } } return total; } function calculateResponseTokens(response) { if (!response || !response.choices || !response.choices[0]) return 0; const choice = response.choices[0]; if (choice.message?.content) { return estimateTokens(choice.message.content); } if (choice.delta?.content) { return estimateTokens(choice.delta.content); } return 0; } function validateModel(modelId, configuredModels) { // Check if model exists in configuration const modelConfig = configuredModels[modelId]; if (!modelConfig) { throw new BlackboxError( 'Invalid model', `Model "${modelId}" is not configured. Available models: ${Object.keys(configuredModels).join(', ')}` ); } // Ensure required fields exist if (!modelConfig.id) { throw new BlackboxError( 'Invalid model configuration', `Model "${modelId}" configuration is missing required 'id' field` ); } // Set default pricing if not specified return { ...modelConfig, input: modelConfig.input || 0, output: modelConfig.output || 0 }; } function calculateTokens(messages, modelConfig) { const inputTokens = calculateMessageTokens(messages); // Calculate estimated cost based on input tokens and model pricing // Prices are per 1M tokens, so divide by 1M const cost = (inputTokens * modelConfig.input) / 1_000_000; return { inputTokens, cost }; } function updateResponseWithTokens(response, messages, modelConfig) { const inputTokens = calculateMessageTokens(messages); const completionTokens = calculateResponseTokens(response); const totalTokens = inputTokens + completionTokens; // Calculate cost based on both input and output tokens // For blackboxai-default model, don't calculate cost const inputCost = modelConfig.input ? (inputTokens * modelConfig.input) / 1_000_000 : 0; const outputCost = modelConfig.output ? (completionTokens * modelConfig.output) / 1_000_000 : 0; const totalCost = inputCost + outputCost; return { ...response, usage: { prompt_tokens: inputTokens, completion_tokens: completionTokens, total_tokens: totalTokens, cost: totalCost } }; } export { validateModel, calculateTokens, updateResponseWithTokens };