Add pricing structure for token usage in CLI and enhance token handling in ModelDialog. Implement cost breakdown per model based on input, cached, and output tokens, and ensure proper initialization of token counts in usage handling.

This commit is contained in:
sebseb7
2025-08-21 13:31:15 +00:00
parent eb3f58b2e6
commit 46c9fe9fac
2 changed files with 79 additions and 8 deletions

65
cli2.js
View File

@@ -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);
})()

View File

@@ -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);