Skip to content

Commit

Permalink
🧮 feat: Improve structured token spending and testing; fix: Anthropic…
Browse files Browse the repository at this point in the history
… Cache Spend (danny-avila#3766)

* chore: update jest and mongodb-memory-server dependencies

* fix: Anthropic edge case of increasing balance

* refactor: Update token calculations in Transaction model/spec

* refactor: `spendTokens` always record transactions, add Tx related tests

* feat: Add error handling for CHECK_BALANCE environment variable

* feat: Update import path for Balance model in Balance controller

* chore: remove logging

* refactor: Improve structured token spend logging in spendTokens.js

* ci: add unit tests for spend token

* ci: Improve structured token spend unit testing

* chore: improve logging phrase for no tx spent from balance
  • Loading branch information
danny-avila authored Aug 24, 2024
1 parent d7973e4 commit 4f6cc40
Show file tree
Hide file tree
Showing 8 changed files with 850 additions and 82 deletions.
41 changes: 23 additions & 18 deletions api/models/Transaction.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const mongoose = require('mongoose');
const { isEnabled } = require('../server/utils/handleText');
const { isEnabled } = require('~/server/utils/handleText');
const transactionSchema = require('./schema/transaction');
const { getMultiplier, getCacheMultiplier } = require('./tx');
const { logger } = require('~/config');
Expand Down Expand Up @@ -76,7 +76,7 @@ transactionSchema.statics.createStructured = async function (txData) {
await transaction.save();

if (!isEnabled(process.env.CHECK_BALANCE)) {
return transaction;
return;
}

let balance = await Balance.findOne({ user: transaction.user }).lean();
Expand Down Expand Up @@ -122,28 +122,33 @@ transactionSchema.methods.calculateStructuredTokenValue = function () {
read: readMultiplier,
};

const totalTokens = (this.inputTokens || 0) + (this.writeTokens || 0) + (this.readTokens || 0);
const totalPromptTokens =
Math.abs(this.inputTokens || 0) +
Math.abs(this.writeTokens || 0) +
Math.abs(this.readTokens || 0);

if (totalTokens > 0) {
if (totalPromptTokens > 0) {
this.rate =
(inputMultiplier * (this.inputTokens || 0) +
writeMultiplier * (this.writeTokens || 0) +
readMultiplier * (this.readTokens || 0)) /
totalTokens;
(Math.abs(inputMultiplier * (this.inputTokens || 0)) +
Math.abs(writeMultiplier * (this.writeTokens || 0)) +
Math.abs(readMultiplier * (this.readTokens || 0))) /
totalPromptTokens;
} else {
this.rate = inputMultiplier; // Default to input rate if no tokens
this.rate = Math.abs(inputMultiplier); // Default to input rate if no tokens
}

this.tokenValue =
this.inputTokens * inputMultiplier +
(this.writeTokens || 0) * writeMultiplier +
(this.readTokens || 0) * readMultiplier;
} else {
const multiplier = Math.abs(
getMultiplier({ tokenType: this.tokenType, model, endpointTokenConfig }),
this.tokenValue = -(
Math.abs(this.inputTokens || 0) * inputMultiplier +
Math.abs(this.writeTokens || 0) * writeMultiplier +
Math.abs(this.readTokens || 0) * readMultiplier
);
this.rate = multiplier;
this.tokenValue = this.rawAmount * multiplier;

this.rawAmount = -totalPromptTokens;
} else if (this.tokenType === 'completion') {
const multiplier = getMultiplier({ tokenType: this.tokenType, model, endpointTokenConfig });
this.rate = Math.abs(multiplier);
this.tokenValue = -Math.abs(this.rawAmount) * multiplier;
this.rawAmount = -Math.abs(this.rawAmount);
}

if (this.context && this.tokenType === 'completion' && this.context === 'incomplete') {
Expand Down
Loading

0 comments on commit 4f6cc40

Please sign in to comment.