diff --git a/cli2.js b/cli2.js index cf86f9a..4504646 100644 --- a/cli2.js +++ b/cli2.js @@ -16,8 +16,34 @@ modelDialog.on('reasoningUpdate', (output) => { //console.log(chalk.blue('reasoning event'),output); }); - - +// $ / 1million tokens +const price = { + 'gpt-5-2025-08-07': { + input: 1.25, + cached: 0.125, + output: 10 + }, + 'gpt-5-mini-2025-08-07': { + input: 0.25, + cached: 0.025, + output: 2 + }, + 'gpt-5-nano-2025-08-07': { + input: 0.05, + cached: 0.005, + output: 0.4 + }, + 'gpt-4.1-2025-04-14': { + input: 2, + cached: 0.5, + output: 8 + }, + 'gpt-4.1-mini-2025-04-14': { + input: 0.4, + cached: 0.1, + output: 1.6 + }, +}; (async ()=>{ @@ -27,5 +53,40 @@ modelDialog.on('reasoningUpdate', (output) => { const output2 = await modelDialog.interrogate('Hi, use the list files tools and the read files tool on /readme.txt in same variations to test it. use the tools in parallel.'); console.log('final output:',output2.output); console.log('reasoning:',output2.reasoning); + //Ti: { 'gpt-5-2025-08-07': 3019 } Tc: { 'gpt-5-2025-08-07': 0 } To: { 'gpt-5-2025-08-07': 751 } console.log('Ti:',output2.inputTokens,'Tc:',output2.cachedTokens,'To:',output2.outputTokens); + // cost breakdown per model and totals (prices are per 1M tokens) + const perMillion = 1_000_000; + const models = new Set([ + ...Object.keys(output2.inputTokens || {}), + ...Object.keys(output2.cachedTokens || {}), + ...Object.keys(output2.outputTokens || {}) + ]); + + let grandTotal = 0; + for (const model of models) { + const inputT = (output2.inputTokens || {})[model]; + const cachedT = (output2.cachedTokens || {})[model]; + const outputT = (output2.outputTokens || {})[model]; + + const p = price[model]; + const inputCost = (typeof inputT === 'number' && p) ? (inputT / perMillion) * p.input : undefined; + const cachedCost = (typeof cachedT === 'number' && p) ? (cachedT / perMillion) * p.cached : undefined; + const outputCost = (typeof outputT === 'number' && p) ? (outputT / perMillion) * p.output : undefined; + + const subtotal = [inputCost, cachedCost, outputCost].every(v => typeof v === 'number') + ? (inputCost + cachedCost + outputCost) + : undefined; + + if (typeof subtotal === 'number') grandTotal += subtotal; + + console.log('cost for', model, { + inputCost: parseFloat(inputCost.toFixed(6)), + cachedCost: parseFloat(cachedCost.toFixed(6)), + outputCost: parseFloat(outputCost.toFixed(6)), + subtotal: parseFloat(subtotal.toFixed(4)) + }); + } + + //console.log('total cost:', grandTotal); })() diff --git a/modelDialog.js b/modelDialog.js index 7b66756..06e291a 100644 --- a/modelDialog.js +++ b/modelDialog.js @@ -56,9 +56,12 @@ class ModelDialog { }; handleUsage = (usage, model) => { - this.inputTokens[model] = usage.input_tokens-usage.input_tokens_details.cached_tokens; - this.outputTokens[model] = usage.output_tokens; - this.cachedTokens[model] = usage.input_tokens_details.cached_tokens; + if (typeof this.inputTokens[model] !== 'number') this.inputTokens[model] = 0; + if (typeof this.outputTokens[model] !== 'number') this.outputTokens[model] = 0; + if (typeof this.cachedTokens[model] !== 'number') this.cachedTokens[model] = 0; + this.inputTokens[model] += usage.input_tokens - usage.input_tokens_details.cached_tokens; + this.outputTokens[model] += usage.output_tokens; + this.cachedTokens[model] += usage.input_tokens_details.cached_tokens; } on = (event, callback) => { @@ -89,16 +92,22 @@ class ModelDialog { //console.log(chalk.blue('messages:'),JSON.stringify(messagesToSend,null,2)); this.messagesSent.push(...messagesToSend); + const model = 'gpt-5-mini'; + const call = { - model: 'gpt-5', + model: model, input: messagesToSend, - text: { format: { type: 'text' }, verbosity: 'low' }, - reasoning: { effort: 'low', summary: 'detailed' }, + text: { format: { type: 'text' } }, tools: Object.values(toolsByFile).map(t => t.def), store: true, previous_response_id: this.previousResponseId, parallel_tool_calls: true } + if(model.startsWith('gpt-5')){ + call.reasoning = { effort: 'low', summary: 'detailed' }; + //call.text.format.verbosity = 'low'; + } + this.currentStream = openai.responses.stream(call); this.currentStream.on('response.created', (event) => { @@ -130,6 +139,7 @@ class ModelDialog { this.currentStream.on('response.completed', async (event) => { + //console.log(chalk.blue('response completed:'),event.response.usage); this.handleUsage(event.response.usage, event.response.model); outputs.push(...event.response.output);