// ==================================== // Voice Bot Utilities // Helper functions for text processing, metrics calculation, // and pricing calculations for the voice bot system // ==================================== const { encoding_for_model } = require('tiktoken'); const prices = require('./prices.json'); require('dotenv').config(); // ==================================== // Text Processing Functions // ==================================== /** * Checks if a string ends with a sentence terminator (., !, ?, or :) * Used to determine when to send text for speech synthesis * @param {string} text - The text to check * @returns {boolean} - True if the text ends with a sentence terminator */ function matchesSentenceEnding(text) { return /([.!?:]([\s]|$|\n))/.test(text); } /** * Removes special characters and formatting markers from text * Cleans up text before processing or displaying * @param {string} text - The text to clean * @returns {string} - Cleaned text */ function removeSpecialCharacters(text) { return text .replace(/[*#\n]/g, '') // Remove asterisks, hashtags, and newlines .replace(/【\d+:\d+†[^】]+】/g, '') // Remove timestamp-like markers .trim(); } /** * Calculates the duration of an audio buffer * @param {Buffer} buffer - The audio buffer * @param {number} sampleRate - The sample rate of the audio * @param {number} channels - Number of audio channels * @returns {number} - Duration in seconds */ function getAudioDuration(buffer, sampleRate, channels) { const bytesPerSample = 2; // Assuming 16-bit audio const totalBytes = buffer.length; const duration = totalBytes / (sampleRate * channels * bytesPerSample); return Math.ceil(duration); } /** * Converts a hex string to a UUID format string * @param {string} hex - The hex string to convert to UUID * @returns {string} - Formatted UUID string */ function toUUID(hex) { return hex.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5'); } // ==================================== // Metrics and Pricing Calculator // ==================================== /** * Calculates various metrics and costs for processing text * Handles different roles (system, user, assistant) with different pricing models * * @param {string} role - The role of the message (system, user, or assistant) * @param {string} text - The text content to analyze * @param {number} [wordsPerMinute=130] - Words per minute rate for duration calculation * @param {number} [costPerWord=0.00001] - Cost per word * @param {number} [costPerChar=0.0000075] - Cost per character * @param {number} [costPerSecond=0.00025] - Cost per second of audio * @returns {Object} - Object containing various metrics and costs */ function calculateMetricsAndPricing( role, text, wordsPerMinute = 130, costPerWord = 0.00001, costPerChar = 0.0000075, costPerSecond = 0.00025 ) { // Determine which model to use, fallback to gpt-3.5-turbo if specified model not in prices const model = prices[process.env.OPENAI_MODEL || 'gpt-3.5-turbo'] ? process.env.OPENAI_MODEL || 'gpt-3.5-turbo' : 'gpt-4'; // Initialize tokenizer for the selected model const encoder = encoding_for_model(model); // Calculate basic metrics const charCount = text.length; const wordCount = text.trim().split(/\s+/).length; const durationInSeconds = Math.ceil((wordCount / wordsPerMinute) * 60); const tokenCount = encoder.encode(text).length; // Calculate costs with precision const costByWord = parseFloat((wordCount * costPerWord).toFixed(7)); const costByCharacter = parseFloat((charCount * costPerChar).toFixed(7)); const costBySecond = parseFloat((durationInSeconds * costPerSecond).toFixed(7)); const costByToken = parseFloat( (tokenCount * prices[model][role === 'assistant' ? 'output' : 'input'] / 1000) .toFixed(7) ); // Free up encoder resources encoder.free(); // Return appropriate metrics based on role switch (role) { case 'system': return { tokenCount, costByToken, model }; case 'user': return { durationInSeconds, tokenCount, costBySecond, costByToken, model }; case 'assistant': return { charCount, tokenCount, costByCharacter, costByToken, model }; default: // Return all metrics if role is not specified return { charCount, wordCount, tokenCount, durationInSeconds, costByWord, costByCharacter, costBySecond, costByToken, model }; } } // Export utility functions module.exports = { removeSpecialCharacters, matchesSentenceEnding, calculateMetricsAndPricing, getAudioDuration, toUUID };