feat: implement proxy billing details handling and resolveProxyLogBilling function
This commit is contained in:
@@ -5,7 +5,6 @@ import { fetch } from 'undici';
|
||||
import { refreshModelsAndRebuildRoutes } from '../../services/modelService.js';
|
||||
import { reportProxyAllFailed, reportTokenExpired } from '../../services/alertService.js';
|
||||
import { isTokenExpiredError } from '../../services/alertRules.js';
|
||||
import { buildProxyBillingDetails, estimateProxyCost } from '../../services/modelPricingService.js';
|
||||
import { shouldRetryProxyRequest } from '../../services/proxyRetryPolicy.js';
|
||||
import { resolveProxyUsageWithSelfLogFallback } from '../../services/proxyUsageFallbackService.js';
|
||||
import { mergeProxyUsage, parseProxyUsage } from '../../services/proxyUsageParser.js';
|
||||
@@ -38,6 +37,7 @@ import {
|
||||
import { composeProxyLogMessage } from './logPathMeta.js';
|
||||
import { executeEndpointFlow, withUpstreamPath } from './endpointFlow.js';
|
||||
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
|
||||
import { resolveProxyLogBilling } from './proxyBilling.js';
|
||||
|
||||
const MAX_RETRIES = 2;
|
||||
const CLAUDE_SSE_EVENT_NAMES = new Set([
|
||||
@@ -429,33 +429,13 @@ async function handleChatProxyRequest(
|
||||
},
|
||||
});
|
||||
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
@@ -609,33 +589,13 @@ async function handleChatProxyRequest(
|
||||
},
|
||||
});
|
||||
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
@@ -687,33 +647,13 @@ async function handleChatProxyRequest(
|
||||
},
|
||||
});
|
||||
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { fetch } from 'undici';
|
||||
import { db, schema } from '../../db/index.js';
|
||||
import { tokenRouter } from '../../services/tokenRouter.js';
|
||||
import { tokenRouter } from '../../services/tokenRouter.js';
|
||||
import { refreshModelsAndRebuildRoutes } from '../../services/modelService.js';
|
||||
import { reportProxyAllFailed, reportTokenExpired } from '../../services/alertService.js';
|
||||
import { isTokenExpiredError } from '../../services/alertRules.js';
|
||||
import { buildProxyBillingDetails, estimateProxyCost } from '../../services/modelPricingService.js';
|
||||
import { shouldRetryProxyRequest } from '../../services/proxyRetryPolicy.js';
|
||||
import { resolveProxyUsageWithSelfLogFallback } from '../../services/proxyUsageFallbackService.js';
|
||||
import { mergeProxyUsage, parseProxyUsage, pullSseDataEvents } from '../../services/proxyUsageParser.js';
|
||||
@@ -13,6 +12,7 @@ import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordD
|
||||
import { withExplicitProxyRequestInit } from '../../services/siteProxy.js';
|
||||
import { composeProxyLogMessage } from './logPathMeta.js';
|
||||
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
|
||||
import { resolveProxyLogBilling } from './proxyBilling.js';
|
||||
|
||||
const MAX_RETRIES = 2;
|
||||
|
||||
@@ -160,32 +160,13 @@ export async function completionsProxyRoute(app: FastifyInstance) {
|
||||
totalTokens: parsedUsage.totalTokens,
|
||||
},
|
||||
});
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
logProxy(
|
||||
@@ -213,32 +194,13 @@ export async function completionsProxyRoute(app: FastifyInstance) {
|
||||
totalTokens: parsedUsage.totalTokens,
|
||||
},
|
||||
});
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { fetch } from 'undici';
|
||||
import { db, schema } from '../../db/index.js';
|
||||
import { tokenRouter } from '../../services/tokenRouter.js';
|
||||
import { tokenRouter } from '../../services/tokenRouter.js';
|
||||
import { refreshModelsAndRebuildRoutes } from '../../services/modelService.js';
|
||||
import { reportProxyAllFailed, reportTokenExpired } from '../../services/alertService.js';
|
||||
import { isTokenExpiredError } from '../../services/alertRules.js';
|
||||
import { buildProxyBillingDetails, estimateProxyCost } from '../../services/modelPricingService.js';
|
||||
import { shouldRetryProxyRequest } from '../../services/proxyRetryPolicy.js';
|
||||
import { resolveProxyUsageWithSelfLogFallback } from '../../services/proxyUsageFallbackService.js';
|
||||
import { parseProxyUsage } from '../../services/proxyUsageParser.js';
|
||||
@@ -13,6 +12,7 @@ import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordD
|
||||
import { withExplicitProxyRequestInit } from '../../services/siteProxy.js';
|
||||
import { composeProxyLogMessage } from './logPathMeta.js';
|
||||
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
|
||||
import { resolveProxyLogBilling } from './proxyBilling.js';
|
||||
|
||||
const MAX_RETRIES = 2;
|
||||
|
||||
@@ -108,32 +108,13 @@ export async function embeddingsProxyRoute(app: FastifyInstance) {
|
||||
totalTokens: parsedUsage.totalTokens,
|
||||
},
|
||||
});
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { resolveProxyLogBilling } from './proxyBilling.js';
|
||||
|
||||
describe('resolveProxyLogBilling', () => {
|
||||
it('uses self-log billing metadata for detail breakdown while preserving quota-derived total cost', async () => {
|
||||
const result = await resolveProxyLogBilling({
|
||||
site: {
|
||||
id: 1,
|
||||
url: 'https://anyrouter.top',
|
||||
platform: 'anyrouter',
|
||||
},
|
||||
account: {
|
||||
id: 2,
|
||||
},
|
||||
modelName: 'claude-haiku-4-5-20251001',
|
||||
parsedUsage: {
|
||||
promptTokens: 146638,
|
||||
completionTokens: 172,
|
||||
totalTokens: 146810,
|
||||
cacheReadTokens: 0,
|
||||
cacheCreationTokens: 0,
|
||||
promptTokensIncludeCache: null,
|
||||
},
|
||||
resolvedUsage: {
|
||||
promptTokens: 146638,
|
||||
completionTokens: 172,
|
||||
totalTokens: 146810,
|
||||
recoveredFromSelfLog: true,
|
||||
estimatedCostFromQuota: 0.083056,
|
||||
selfLogBillingMeta: {
|
||||
modelRatio: 2.5,
|
||||
completionRatio: 5,
|
||||
cacheRatio: 0.1,
|
||||
cacheCreationRatio: 1.25,
|
||||
groupRatio: 1,
|
||||
cacheReadTokens: 145692,
|
||||
cacheCreationTokens: 945,
|
||||
promptTokensIncludeCache: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.estimatedCost).toBe(0.083056);
|
||||
expect(result.billingDetails).toMatchObject({
|
||||
usage: {
|
||||
cacheReadTokens: 145692,
|
||||
cacheCreationTokens: 945,
|
||||
billablePromptTokens: 1,
|
||||
},
|
||||
pricing: {
|
||||
modelRatio: 2.5,
|
||||
completionRatio: 5,
|
||||
cacheRatio: 0.1,
|
||||
cacheCreationRatio: 1.25,
|
||||
groupRatio: 1,
|
||||
},
|
||||
breakdown: {
|
||||
inputPerMillion: 5,
|
||||
outputPerMillion: 25,
|
||||
cacheReadPerMillion: 0.5,
|
||||
cacheCreationPerMillion: 6.25,
|
||||
totalCost: 0.083057,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
import {
|
||||
buildProxyBillingDetails,
|
||||
estimateProxyCost,
|
||||
type ProxyBillingDetails,
|
||||
type ProxyBillingPricingOverride,
|
||||
} from '../../services/modelPricingService.js';
|
||||
import type { SelfLogBillingMeta } from '../../services/proxyUsageFallbackService.js';
|
||||
|
||||
interface ProxyBillingUsageSummary {
|
||||
promptTokens: number;
|
||||
completionTokens: number;
|
||||
totalTokens: number;
|
||||
cacheReadTokens: number;
|
||||
cacheCreationTokens: number;
|
||||
promptTokensIncludeCache: boolean | null;
|
||||
}
|
||||
|
||||
interface ResolvedProxyUsageSummary {
|
||||
promptTokens: number;
|
||||
completionTokens: number;
|
||||
totalTokens: number;
|
||||
recoveredFromSelfLog: boolean;
|
||||
estimatedCostFromQuota: number;
|
||||
selfLogBillingMeta: SelfLogBillingMeta | null;
|
||||
}
|
||||
|
||||
interface ResolveProxyLogBillingInput {
|
||||
site: {
|
||||
id: number;
|
||||
url: string;
|
||||
platform: string;
|
||||
apiKey?: string | null;
|
||||
};
|
||||
account: {
|
||||
id: number;
|
||||
accessToken?: string | null;
|
||||
apiToken?: string | null;
|
||||
};
|
||||
modelName: string;
|
||||
parsedUsage: ProxyBillingUsageSummary;
|
||||
resolvedUsage: ResolvedProxyUsageSummary;
|
||||
}
|
||||
|
||||
function toPricingOverride(meta: SelfLogBillingMeta | null): ProxyBillingPricingOverride | null {
|
||||
if (!meta) return null;
|
||||
return {
|
||||
modelRatio: meta.modelRatio,
|
||||
completionRatio: meta.completionRatio,
|
||||
cacheRatio: meta.cacheRatio,
|
||||
cacheCreationRatio: meta.cacheCreationRatio,
|
||||
groupRatio: meta.groupRatio,
|
||||
};
|
||||
}
|
||||
|
||||
export async function resolveProxyLogBilling(
|
||||
input: ResolveProxyLogBillingInput,
|
||||
): Promise<{ estimatedCost: number; billingDetails: ProxyBillingDetails | null }> {
|
||||
const selfLogMeta = input.resolvedUsage.selfLogBillingMeta;
|
||||
const billingPricingOverride = toPricingOverride(selfLogMeta);
|
||||
const cacheReadTokens = selfLogMeta?.cacheReadTokens ?? input.parsedUsage.cacheReadTokens;
|
||||
const cacheCreationTokens = selfLogMeta?.cacheCreationTokens ?? input.parsedUsage.cacheCreationTokens;
|
||||
const promptTokensIncludeCache = selfLogMeta?.promptTokensIncludeCache
|
||||
?? input.parsedUsage.promptTokensIncludeCache;
|
||||
|
||||
const billingInput = {
|
||||
site: input.site,
|
||||
account: input.account,
|
||||
modelName: input.modelName,
|
||||
promptTokens: input.resolvedUsage.promptTokens,
|
||||
completionTokens: input.resolvedUsage.completionTokens,
|
||||
totalTokens: input.resolvedUsage.totalTokens,
|
||||
cacheReadTokens,
|
||||
cacheCreationTokens,
|
||||
promptTokensIncludeCache,
|
||||
billingPricingOverride,
|
||||
};
|
||||
|
||||
let estimatedCost = await estimateProxyCost(billingInput);
|
||||
const billingDetails = await buildProxyBillingDetails(billingInput);
|
||||
|
||||
if (
|
||||
input.resolvedUsage.estimatedCostFromQuota > 0
|
||||
&& (input.resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)
|
||||
) {
|
||||
estimatedCost = input.resolvedUsage.estimatedCostFromQuota;
|
||||
}
|
||||
|
||||
return {
|
||||
estimatedCost,
|
||||
billingDetails,
|
||||
};
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import { tokenRouter } from '../../services/tokenRouter.js';
|
||||
import { refreshModelsAndRebuildRoutes } from '../../services/modelService.js';
|
||||
import { reportProxyAllFailed, reportTokenExpired } from '../../services/alertService.js';
|
||||
import { isTokenExpiredError } from '../../services/alertRules.js';
|
||||
import { buildProxyBillingDetails, estimateProxyCost } from '../../services/modelPricingService.js';
|
||||
import { shouldRetryProxyRequest } from '../../services/proxyRetryPolicy.js';
|
||||
import { resolveProxyUsageWithSelfLogFallback } from '../../services/proxyUsageFallbackService.js';
|
||||
import { mergeProxyUsage, parseProxyUsage } from '../../services/proxyUsageParser.js';
|
||||
@@ -29,6 +28,7 @@ import { ensureModelAllowedForDownstreamKey, getDownstreamRoutingPolicy, recordD
|
||||
import { composeProxyLogMessage } from './logPathMeta.js';
|
||||
import { executeEndpointFlow, withUpstreamPath } from './endpointFlow.js';
|
||||
import { formatUtcSqlDateTime } from '../../services/localTimeService.js';
|
||||
import { resolveProxyLogBilling } from './proxyBilling.js';
|
||||
|
||||
const MAX_RETRIES = 2;
|
||||
|
||||
@@ -1475,32 +1475,13 @@ export async function responsesProxyRoute(app: FastifyInstance) {
|
||||
totalTokens: parsedUsage.totalTokens,
|
||||
},
|
||||
});
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
logProxy(
|
||||
@@ -1541,32 +1522,13 @@ export async function responsesProxyRoute(app: FastifyInstance) {
|
||||
totalTokens: parsedUsage.totalTokens,
|
||||
},
|
||||
});
|
||||
let estimatedCost = await estimateProxyCost({
|
||||
const { estimatedCost, billingDetails } = await resolveProxyLogBilling({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
parsedUsage,
|
||||
resolvedUsage,
|
||||
});
|
||||
let billingDetails = await buildProxyBillingDetails({
|
||||
site: selected.site,
|
||||
account: selected.account,
|
||||
modelName: selected.actualModel || requestedModel,
|
||||
promptTokens: resolvedUsage.promptTokens,
|
||||
completionTokens: resolvedUsage.completionTokens,
|
||||
totalTokens: resolvedUsage.totalTokens,
|
||||
cacheReadTokens: parsedUsage.cacheReadTokens,
|
||||
cacheCreationTokens: parsedUsage.cacheCreationTokens,
|
||||
promptTokensIncludeCache: parsedUsage.promptTokensIncludeCache,
|
||||
});
|
||||
if (resolvedUsage.estimatedCostFromQuota > 0 && (resolvedUsage.recoveredFromSelfLog || estimatedCost <= 0)) {
|
||||
estimatedCost = resolvedUsage.estimatedCostFromQuota;
|
||||
billingDetails = null;
|
||||
}
|
||||
|
||||
tokenRouter.recordSuccess(selected.channel.id, latency, estimatedCost);
|
||||
recordDownstreamCostUsage(request, estimatedCost);
|
||||
|
||||
Reference in New Issue
Block a user