🐞 fix: Balance and Token Usage Improvements (#2350)

* fix(processModelData): handle `openrouter/auto` edge case

* fix(Tx.create): prevent negative multiplier edge case and prevent balance from becoming negative

* fix(NavLinks): render 0 balance properly

* refactor(NavLinks): show only up to 2 decimal places for balance

* fix(OpenAIClient/titleConvo): fix cohere condition and record token usage for `this.options.titleMethod === 'completion'`
This commit is contained in:
Danny Avila 2024-04-07 23:28:40 -04:00 committed by GitHub
parent 3411d7a543
commit 6f0eb35365
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 11 deletions

View file

@ -792,14 +792,18 @@ ${convo}
}, },
]; ];
const promptTokens = this.getTokenCountForMessage(instructionsPayload[0]);
try { try {
let useChatCompletion = true; let useChatCompletion = true;
if (CohereConstants.API_URL) { if (this.options.reverseProxyUrl === CohereConstants.API_URL) {
useChatCompletion = false; useChatCompletion = false;
} }
title = ( title = (
await this.sendPayload(instructionsPayload, { modelOptions, useChatCompletion }) await this.sendPayload(instructionsPayload, { modelOptions, useChatCompletion })
).replaceAll('"', ''); ).replaceAll('"', '');
const completionTokens = this.getTokenCount(title);
this.recordTokenUsage({ promptTokens, completionTokens, context: 'title' });
} catch (e) { } catch (e) {
logger.error( logger.error(
'[OpenAIClient] There was an issue generating the title with the completion method', '[OpenAIClient] There was an issue generating the title with the completion method',
@ -951,12 +955,12 @@ ${convo}
} }
} }
async recordTokenUsage({ promptTokens, completionTokens }) { async recordTokenUsage({ promptTokens, completionTokens, context = 'message' }) {
await spendTokens( await spendTokens(
{ {
context,
user: this.user, user: this.user,
model: this.modelOptions.model, model: this.modelOptions.model,
context: 'message',
conversationId: this.conversationId, conversationId: this.conversationId,
endpointTokenConfig: this.options.endpointTokenConfig, endpointTokenConfig: this.options.endpointTokenConfig,
}, },

View file

@ -12,7 +12,7 @@ transactionSchema.methods.calculateTokenValue = function () {
this.tokenValue = this.rawAmount; this.tokenValue = this.rawAmount;
} }
const { valueKey, tokenType, model, endpointTokenConfig } = this; const { valueKey, tokenType, model, endpointTokenConfig } = this;
const multiplier = getMultiplier({ valueKey, tokenType, model, endpointTokenConfig }); const multiplier = Math.abs(getMultiplier({ valueKey, tokenType, model, endpointTokenConfig }));
this.rate = multiplier; this.rate = multiplier;
this.tokenValue = this.rawAmount * multiplier; this.tokenValue = this.rawAmount * multiplier;
if (this.context && this.tokenType === 'completion' && this.context === 'incomplete') { if (this.context && this.tokenType === 'completion' && this.context === 'incomplete') {
@ -36,18 +36,24 @@ transactionSchema.statics.create = async function (transactionData) {
return; return;
} }
// Adjust the user's balance let balance = await Balance.findOne({ user: transaction.user }).lean();
const updatedBalance = await Balance.findOneAndUpdate( let incrementValue = transaction.tokenValue;
if (balance && balance?.tokenCredits + incrementValue < 0) {
incrementValue = -balance.tokenCredits;
}
balance = await Balance.findOneAndUpdate(
{ user: transaction.user }, { user: transaction.user },
{ $inc: { tokenCredits: transaction.tokenValue } }, { $inc: { tokenCredits: incrementValue } },
{ upsert: true, new: true }, { upsert: true, new: true },
).lean(); ).lean();
return { return {
rate: transaction.rate, rate: transaction.rate,
user: transaction.user.toString(), user: transaction.user.toString(),
balance: updatedBalance.tokenCredits, balance: balance.tokenCredits,
[transaction.tokenType]: transaction.tokenValue, [transaction.tokenType]: incrementValue,
}; };
}; };

View file

@ -215,6 +215,12 @@ function processModelData(input) {
for (const model of data) { for (const model of data) {
const modelKey = model.id; const modelKey = model.id;
if (modelKey === 'openrouter/auto') {
model.pricing = {
prompt: '0.00001',
completion: '0.00003',
};
}
const prompt = parseFloat(model.pricing.prompt) * 1000000; const prompt = parseFloat(model.pricing.prompt) * 1000000;
const completion = parseFloat(model.pricing.completion) * 1000000; const completion = parseFloat(model.pricing.completion) * 1000000;

View file

@ -59,9 +59,11 @@ function NavLinks() {
<Menu as="div" className="group relative"> <Menu as="div" className="group relative">
{({ open }) => ( {({ open }) => (
<> <>
{startupConfig?.checkBalance && balanceQuery.data && ( {startupConfig?.checkBalance &&
balanceQuery.data &&
!isNaN(parseFloat(balanceQuery.data)) && (
<div className="m-1 ml-3 whitespace-nowrap text-left text-sm text-black dark:text-gray-200"> <div className="m-1 ml-3 whitespace-nowrap text-left text-sm text-black dark:text-gray-200">
{`Balance: ${balanceQuery.data}`} {`Balance: ${parseFloat(balanceQuery.data).toFixed(2)}`}
</div> </div>
)} )}
<Menu.Button <Menu.Button