mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-03-30 00:51:04 +00:00
fix: 添加对 ephemeral 5m 和 1h 令牌的支持,优化费用计算逻辑
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -247,3 +247,5 @@ web/apiStats/
|
|||||||
|
|
||||||
# Admin SPA build files
|
# Admin SPA build files
|
||||||
web/admin-spa/dist/
|
web/admin-spa/dist/
|
||||||
|
|
||||||
|
.serena/
|
||||||
|
|||||||
@@ -1084,6 +1084,9 @@ class RedisClient {
|
|||||||
pipeline.hincrby(modelDaily, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(modelDaily, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(modelDaily, 'allTokens', totalTokens)
|
pipeline.hincrby(modelDaily, 'allTokens', totalTokens)
|
||||||
pipeline.hincrby(modelDaily, 'requests', 1)
|
pipeline.hincrby(modelDaily, 'requests', 1)
|
||||||
|
// 详细缓存类型统计
|
||||||
|
pipeline.hincrby(modelDaily, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(modelDaily, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
|
|
||||||
// 按模型统计 - 每月
|
// 按模型统计 - 每月
|
||||||
pipeline.hincrby(modelMonthly, 'inputTokens', finalInputTokens)
|
pipeline.hincrby(modelMonthly, 'inputTokens', finalInputTokens)
|
||||||
@@ -1092,6 +1095,9 @@ class RedisClient {
|
|||||||
pipeline.hincrby(modelMonthly, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(modelMonthly, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(modelMonthly, 'allTokens', totalTokens)
|
pipeline.hincrby(modelMonthly, 'allTokens', totalTokens)
|
||||||
pipeline.hincrby(modelMonthly, 'requests', 1)
|
pipeline.hincrby(modelMonthly, 'requests', 1)
|
||||||
|
// 详细缓存类型统计
|
||||||
|
pipeline.hincrby(modelMonthly, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(modelMonthly, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
|
|
||||||
// API Key级别的模型统计 - 每日
|
// API Key级别的模型统计 - 每日
|
||||||
pipeline.hincrby(keyModelDaily, 'inputTokens', finalInputTokens)
|
pipeline.hincrby(keyModelDaily, 'inputTokens', finalInputTokens)
|
||||||
@@ -1136,6 +1142,9 @@ class RedisClient {
|
|||||||
pipeline.hincrby(keyModelAlltime, 'cacheCreateTokens', finalCacheCreateTokens)
|
pipeline.hincrby(keyModelAlltime, 'cacheCreateTokens', finalCacheCreateTokens)
|
||||||
pipeline.hincrby(keyModelAlltime, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(keyModelAlltime, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(keyModelAlltime, 'requests', 1)
|
pipeline.hincrby(keyModelAlltime, 'requests', 1)
|
||||||
|
// 详细缓存类型统计
|
||||||
|
pipeline.hincrby(keyModelAlltime, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(keyModelAlltime, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
// 费用统计
|
// 费用统计
|
||||||
if (realCost > 0) {
|
if (realCost > 0) {
|
||||||
pipeline.hincrby(keyModelAlltime, 'realCostMicro', Math.round(realCost * 1000000))
|
pipeline.hincrby(keyModelAlltime, 'realCostMicro', Math.round(realCost * 1000000))
|
||||||
@@ -1152,6 +1161,9 @@ class RedisClient {
|
|||||||
pipeline.hincrby(hourly, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(hourly, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(hourly, 'allTokens', totalTokens)
|
pipeline.hincrby(hourly, 'allTokens', totalTokens)
|
||||||
pipeline.hincrby(hourly, 'requests', 1)
|
pipeline.hincrby(hourly, 'requests', 1)
|
||||||
|
// 详细缓存类型统计
|
||||||
|
pipeline.hincrby(hourly, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(hourly, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
|
|
||||||
// 按模型统计 - 每小时
|
// 按模型统计 - 每小时
|
||||||
pipeline.hincrby(modelHourly, 'inputTokens', finalInputTokens)
|
pipeline.hincrby(modelHourly, 'inputTokens', finalInputTokens)
|
||||||
@@ -1160,6 +1172,9 @@ class RedisClient {
|
|||||||
pipeline.hincrby(modelHourly, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(modelHourly, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(modelHourly, 'allTokens', totalTokens)
|
pipeline.hincrby(modelHourly, 'allTokens', totalTokens)
|
||||||
pipeline.hincrby(modelHourly, 'requests', 1)
|
pipeline.hincrby(modelHourly, 'requests', 1)
|
||||||
|
// 详细缓存类型统计
|
||||||
|
pipeline.hincrby(modelHourly, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(modelHourly, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
|
|
||||||
// API Key级别的模型统计 - 每小时
|
// API Key级别的模型统计 - 每小时
|
||||||
pipeline.hincrby(keyModelHourly, 'inputTokens', finalInputTokens)
|
pipeline.hincrby(keyModelHourly, 'inputTokens', finalInputTokens)
|
||||||
@@ -1168,6 +1183,9 @@ class RedisClient {
|
|||||||
pipeline.hincrby(keyModelHourly, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(keyModelHourly, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(keyModelHourly, 'allTokens', totalTokens)
|
pipeline.hincrby(keyModelHourly, 'allTokens', totalTokens)
|
||||||
pipeline.hincrby(keyModelHourly, 'requests', 1)
|
pipeline.hincrby(keyModelHourly, 'requests', 1)
|
||||||
|
// 详细缓存类型统计
|
||||||
|
pipeline.hincrby(keyModelHourly, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(keyModelHourly, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
// 费用统计
|
// 费用统计
|
||||||
if (realCost > 0) {
|
if (realCost > 0) {
|
||||||
pipeline.hincrby(keyModelHourly, 'realCostMicro', Math.round(realCost * 1000000))
|
pipeline.hincrby(keyModelHourly, 'realCostMicro', Math.round(realCost * 1000000))
|
||||||
@@ -1235,18 +1253,24 @@ class RedisClient {
|
|||||||
pipeline.hincrby('usage:global:total', 'cacheCreateTokens', finalCacheCreateTokens)
|
pipeline.hincrby('usage:global:total', 'cacheCreateTokens', finalCacheCreateTokens)
|
||||||
pipeline.hincrby('usage:global:total', 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby('usage:global:total', 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby('usage:global:total', 'allTokens', totalTokens)
|
pipeline.hincrby('usage:global:total', 'allTokens', totalTokens)
|
||||||
|
pipeline.hincrby('usage:global:total', 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby('usage:global:total', 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
pipeline.hincrby(globalDaily, 'requests', 1)
|
pipeline.hincrby(globalDaily, 'requests', 1)
|
||||||
pipeline.hincrby(globalDaily, 'inputTokens', finalInputTokens)
|
pipeline.hincrby(globalDaily, 'inputTokens', finalInputTokens)
|
||||||
pipeline.hincrby(globalDaily, 'outputTokens', finalOutputTokens)
|
pipeline.hincrby(globalDaily, 'outputTokens', finalOutputTokens)
|
||||||
pipeline.hincrby(globalDaily, 'cacheCreateTokens', finalCacheCreateTokens)
|
pipeline.hincrby(globalDaily, 'cacheCreateTokens', finalCacheCreateTokens)
|
||||||
pipeline.hincrby(globalDaily, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(globalDaily, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(globalDaily, 'allTokens', totalTokens)
|
pipeline.hincrby(globalDaily, 'allTokens', totalTokens)
|
||||||
|
pipeline.hincrby(globalDaily, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(globalDaily, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
pipeline.hincrby(globalMonthly, 'requests', 1)
|
pipeline.hincrby(globalMonthly, 'requests', 1)
|
||||||
pipeline.hincrby(globalMonthly, 'inputTokens', finalInputTokens)
|
pipeline.hincrby(globalMonthly, 'inputTokens', finalInputTokens)
|
||||||
pipeline.hincrby(globalMonthly, 'outputTokens', finalOutputTokens)
|
pipeline.hincrby(globalMonthly, 'outputTokens', finalOutputTokens)
|
||||||
pipeline.hincrby(globalMonthly, 'cacheCreateTokens', finalCacheCreateTokens)
|
pipeline.hincrby(globalMonthly, 'cacheCreateTokens', finalCacheCreateTokens)
|
||||||
pipeline.hincrby(globalMonthly, 'cacheReadTokens', finalCacheReadTokens)
|
pipeline.hincrby(globalMonthly, 'cacheReadTokens', finalCacheReadTokens)
|
||||||
pipeline.hincrby(globalMonthly, 'allTokens', totalTokens)
|
pipeline.hincrby(globalMonthly, 'allTokens', totalTokens)
|
||||||
|
pipeline.hincrby(globalMonthly, 'ephemeral5mTokens', ephemeral5mTokens)
|
||||||
|
pipeline.hincrby(globalMonthly, 'ephemeral1hTokens', ephemeral1hTokens)
|
||||||
pipeline.expire(globalDaily, 86400 * 32)
|
pipeline.expire(globalDaily, 86400 * 32)
|
||||||
pipeline.expire(globalMonthly, 86400 * 365)
|
pipeline.expire(globalMonthly, 86400 * 365)
|
||||||
|
|
||||||
|
|||||||
@@ -1289,6 +1289,8 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
|||||||
outputTokens: 0,
|
outputTokens: 0,
|
||||||
cacheCreateTokens: 0,
|
cacheCreateTokens: 0,
|
||||||
cacheReadTokens: 0,
|
cacheReadTokens: 0,
|
||||||
|
ephemeral5mTokens: 0,
|
||||||
|
ephemeral1hTokens: 0,
|
||||||
requests: 0
|
requests: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1300,6 +1302,10 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
|||||||
parseInt(data.totalCacheCreateTokens) || parseInt(data.cacheCreateTokens) || 0
|
parseInt(data.totalCacheCreateTokens) || parseInt(data.cacheCreateTokens) || 0
|
||||||
stats.cacheReadTokens +=
|
stats.cacheReadTokens +=
|
||||||
parseInt(data.totalCacheReadTokens) || parseInt(data.cacheReadTokens) || 0
|
parseInt(data.totalCacheReadTokens) || parseInt(data.cacheReadTokens) || 0
|
||||||
|
stats.ephemeral5mTokens +=
|
||||||
|
parseInt(data.totalEphemeral5mTokens) || parseInt(data.ephemeral5mTokens) || 0
|
||||||
|
stats.ephemeral1hTokens +=
|
||||||
|
parseInt(data.totalEphemeral1hTokens) || parseInt(data.ephemeral1hTokens) || 0
|
||||||
stats.requests += parseInt(data.totalRequests) || parseInt(data.requests) || 0
|
stats.requests += parseInt(data.totalRequests) || parseInt(data.requests) || 0
|
||||||
|
|
||||||
totalRequests += parseInt(data.totalRequests) || parseInt(data.requests) || 0
|
totalRequests += parseInt(data.totalRequests) || parseInt(data.requests) || 0
|
||||||
@@ -1318,15 +1324,22 @@ async function calculateKeyStats(keyId, timeRange, startDate, endDate) {
|
|||||||
cacheCreateTokens += stats.cacheCreateTokens
|
cacheCreateTokens += stats.cacheCreateTokens
|
||||||
cacheReadTokens += stats.cacheReadTokens
|
cacheReadTokens += stats.cacheReadTokens
|
||||||
|
|
||||||
const costResult = CostCalculator.calculateCost(
|
const costUsage = {
|
||||||
{
|
input_tokens: stats.inputTokens,
|
||||||
input_tokens: stats.inputTokens,
|
output_tokens: stats.outputTokens,
|
||||||
output_tokens: stats.outputTokens,
|
cache_creation_input_tokens: stats.cacheCreateTokens,
|
||||||
cache_creation_input_tokens: stats.cacheCreateTokens,
|
cache_read_input_tokens: stats.cacheReadTokens
|
||||||
cache_read_input_tokens: stats.cacheReadTokens
|
}
|
||||||
},
|
|
||||||
model
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
)
|
if (stats.ephemeral5mTokens > 0 || stats.ephemeral1hTokens > 0) {
|
||||||
|
costUsage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: stats.ephemeral5mTokens,
|
||||||
|
ephemeral_1h_input_tokens: stats.ephemeral1hTokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const costResult = CostCalculator.calculateCost(costUsage, model)
|
||||||
totalCost += costResult.costs.total
|
totalCost += costResult.costs.total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -472,7 +472,9 @@ router.get('/model-stats', authenticateAdmin, async (req, res) => {
|
|||||||
outputTokens: 0,
|
outputTokens: 0,
|
||||||
cacheCreateTokens: 0,
|
cacheCreateTokens: 0,
|
||||||
cacheReadTokens: 0,
|
cacheReadTokens: 0,
|
||||||
allTokens: 0
|
allTokens: 0,
|
||||||
|
ephemeral5mTokens: 0,
|
||||||
|
ephemeral1hTokens: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.requests += parseInt(data.requests) || 0
|
stats.requests += parseInt(data.requests) || 0
|
||||||
@@ -481,6 +483,8 @@ router.get('/model-stats', authenticateAdmin, async (req, res) => {
|
|||||||
stats.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
stats.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
||||||
stats.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
stats.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
||||||
stats.allTokens += parseInt(data.allTokens) || 0
|
stats.allTokens += parseInt(data.allTokens) || 0
|
||||||
|
stats.ephemeral5mTokens += parseInt(data.ephemeral5mTokens) || 0
|
||||||
|
stats.ephemeral1hTokens += parseInt(data.ephemeral1hTokens) || 0
|
||||||
|
|
||||||
modelStatsMap.set(normalizedModel, stats)
|
modelStatsMap.set(normalizedModel, stats)
|
||||||
}
|
}
|
||||||
@@ -497,6 +501,14 @@ router.get('/model-stats', authenticateAdmin, async (req, res) => {
|
|||||||
cache_read_input_tokens: stats.cacheReadTokens
|
cache_read_input_tokens: stats.cacheReadTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
if (stats.ephemeral5mTokens > 0 || stats.ephemeral1hTokens > 0) {
|
||||||
|
usage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: stats.ephemeral5mTokens,
|
||||||
|
ephemeral_1h_input_tokens: stats.ephemeral1hTokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 计算费用
|
// 计算费用
|
||||||
const costData = CostCalculator.calculateCost(usage, model)
|
const costData = CostCalculator.calculateCost(usage, model)
|
||||||
|
|
||||||
|
|||||||
@@ -786,6 +786,8 @@ router.get('/usage-trend', authenticateAdmin, async (req, res) => {
|
|||||||
const modelOutputTokens = parseInt(data.outputTokens) || 0
|
const modelOutputTokens = parseInt(data.outputTokens) || 0
|
||||||
const modelCacheCreateTokens = parseInt(data.cacheCreateTokens) || 0
|
const modelCacheCreateTokens = parseInt(data.cacheCreateTokens) || 0
|
||||||
const modelCacheReadTokens = parseInt(data.cacheReadTokens) || 0
|
const modelCacheReadTokens = parseInt(data.cacheReadTokens) || 0
|
||||||
|
const modelEphemeral5mTokens = parseInt(data.ephemeral5mTokens) || 0
|
||||||
|
const modelEphemeral1hTokens = parseInt(data.ephemeral1hTokens) || 0
|
||||||
const modelRequests = parseInt(data.requests) || 0
|
const modelRequests = parseInt(data.requests) || 0
|
||||||
|
|
||||||
dayInputTokens += modelInputTokens
|
dayInputTokens += modelInputTokens
|
||||||
@@ -800,6 +802,15 @@ router.get('/usage-trend', authenticateAdmin, async (req, res) => {
|
|||||||
cache_creation_input_tokens: modelCacheCreateTokens,
|
cache_creation_input_tokens: modelCacheCreateTokens,
|
||||||
cache_read_input_tokens: modelCacheReadTokens
|
cache_read_input_tokens: modelCacheReadTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
if (modelEphemeral5mTokens > 0 || modelEphemeral1hTokens > 0) {
|
||||||
|
modelUsage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: modelEphemeral5mTokens,
|
||||||
|
ephemeral_1h_input_tokens: modelEphemeral1hTokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const modelCostResult = CostCalculator.calculateCost(modelUsage, model)
|
const modelCostResult = CostCalculator.calculateCost(modelUsage, model)
|
||||||
dayCost += modelCostResult.costs.total
|
dayCost += modelCostResult.costs.total
|
||||||
}
|
}
|
||||||
@@ -948,6 +959,8 @@ router.get('/api-keys/:keyId/model-stats', authenticateAdmin, async (req, res) =
|
|||||||
outputTokens: 0,
|
outputTokens: 0,
|
||||||
cacheCreateTokens: 0,
|
cacheCreateTokens: 0,
|
||||||
cacheReadTokens: 0,
|
cacheReadTokens: 0,
|
||||||
|
ephemeral5mTokens: 0,
|
||||||
|
ephemeral1hTokens: 0,
|
||||||
allTokens: 0
|
allTokens: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -957,6 +970,8 @@ router.get('/api-keys/:keyId/model-stats', authenticateAdmin, async (req, res) =
|
|||||||
stats.outputTokens += parseInt(data.outputTokens) || 0
|
stats.outputTokens += parseInt(data.outputTokens) || 0
|
||||||
stats.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
stats.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
||||||
stats.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
stats.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
||||||
|
stats.ephemeral5mTokens += parseInt(data.ephemeral5mTokens) || 0
|
||||||
|
stats.ephemeral1hTokens += parseInt(data.ephemeral1hTokens) || 0
|
||||||
stats.allTokens += parseInt(data.allTokens) || 0
|
stats.allTokens += parseInt(data.allTokens) || 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -992,6 +1007,8 @@ router.get('/api-keys/:keyId/model-stats', authenticateAdmin, async (req, res) =
|
|||||||
outputTokens: 0,
|
outputTokens: 0,
|
||||||
cacheCreateTokens: 0,
|
cacheCreateTokens: 0,
|
||||||
cacheReadTokens: 0,
|
cacheReadTokens: 0,
|
||||||
|
ephemeral5mTokens: 0,
|
||||||
|
ephemeral1hTokens: 0,
|
||||||
allTokens: 0
|
allTokens: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1001,6 +1018,8 @@ router.get('/api-keys/:keyId/model-stats', authenticateAdmin, async (req, res) =
|
|||||||
stats.outputTokens += parseInt(data.outputTokens) || 0
|
stats.outputTokens += parseInt(data.outputTokens) || 0
|
||||||
stats.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
stats.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
||||||
stats.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
stats.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
||||||
|
stats.ephemeral5mTokens += parseInt(data.ephemeral5mTokens) || 0
|
||||||
|
stats.ephemeral1hTokens += parseInt(data.ephemeral1hTokens) || 0
|
||||||
stats.allTokens += parseInt(data.allTokens) || 0
|
stats.allTokens += parseInt(data.allTokens) || 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1016,6 +1035,14 @@ router.get('/api-keys/:keyId/model-stats', authenticateAdmin, async (req, res) =
|
|||||||
cache_read_input_tokens: stats.cacheReadTokens
|
cache_read_input_tokens: stats.cacheReadTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
if (stats.ephemeral5mTokens > 0 || stats.ephemeral1hTokens > 0) {
|
||||||
|
usage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: stats.ephemeral5mTokens,
|
||||||
|
ephemeral_1h_input_tokens: stats.ephemeral1hTokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 使用CostCalculator计算费用
|
// 使用CostCalculator计算费用
|
||||||
const costData = CostCalculator.calculateCost(usage, model)
|
const costData = CostCalculator.calculateCost(usage, model)
|
||||||
|
|
||||||
@@ -1424,6 +1451,16 @@ router.get('/account-usage-trend', authenticateAdmin, async (req, res) => {
|
|||||||
cache_read_input_tokens: parseInt(modelData.cacheReadTokens) || 0
|
cache_read_input_tokens: parseInt(modelData.cacheReadTokens) || 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
const eph5m = parseInt(modelData.ephemeral5mTokens) || 0
|
||||||
|
const eph1h = parseInt(modelData.ephemeral1hTokens) || 0
|
||||||
|
if (eph5m > 0 || eph1h > 0) {
|
||||||
|
usage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: eph5m,
|
||||||
|
ephemeral_1h_input_tokens: eph1h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const costResult = CostCalculator.calculateCost(usage, modelName)
|
const costResult = CostCalculator.calculateCost(usage, modelName)
|
||||||
cost += costResult.costs.total
|
cost += costResult.costs.total
|
||||||
}
|
}
|
||||||
@@ -1582,6 +1619,16 @@ router.get('/account-usage-trend', authenticateAdmin, async (req, res) => {
|
|||||||
cache_read_input_tokens: parseInt(modelData.cacheReadTokens) || 0
|
cache_read_input_tokens: parseInt(modelData.cacheReadTokens) || 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
const eph5m = parseInt(modelData.ephemeral5mTokens) || 0
|
||||||
|
const eph1h = parseInt(modelData.ephemeral1hTokens) || 0
|
||||||
|
if (eph5m > 0 || eph1h > 0) {
|
||||||
|
usage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: eph5m,
|
||||||
|
ephemeral_1h_input_tokens: eph1h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const costResult = CostCalculator.calculateCost(usage, modelName)
|
const costResult = CostCalculator.calculateCost(usage, modelName)
|
||||||
cost += costResult.costs.total
|
cost += costResult.costs.total
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,7 +270,9 @@ router.post('/api/user-stats', async (req, res) => {
|
|||||||
inputTokens: 0,
|
inputTokens: 0,
|
||||||
outputTokens: 0,
|
outputTokens: 0,
|
||||||
cacheCreateTokens: 0,
|
cacheCreateTokens: 0,
|
||||||
cacheReadTokens: 0
|
cacheReadTokens: 0,
|
||||||
|
ephemeral5mTokens: 0,
|
||||||
|
ephemeral1hTokens: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +281,8 @@ router.post('/api/user-stats', async (req, res) => {
|
|||||||
modelUsage.outputTokens += parseInt(data.outputTokens) || 0
|
modelUsage.outputTokens += parseInt(data.outputTokens) || 0
|
||||||
modelUsage.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
modelUsage.cacheCreateTokens += parseInt(data.cacheCreateTokens) || 0
|
||||||
modelUsage.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
modelUsage.cacheReadTokens += parseInt(data.cacheReadTokens) || 0
|
||||||
|
modelUsage.ephemeral5mTokens += parseInt(data.ephemeral5mTokens) || 0
|
||||||
|
modelUsage.ephemeral1hTokens += parseInt(data.ephemeral1hTokens) || 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +295,14 @@ router.post('/api/user-stats', async (req, res) => {
|
|||||||
cache_read_input_tokens: usage.cacheReadTokens
|
cache_read_input_tokens: usage.cacheReadTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
if (usage.ephemeral5mTokens > 0 || usage.ephemeral1hTokens > 0) {
|
||||||
|
usageData.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: usage.ephemeral5mTokens,
|
||||||
|
ephemeral_1h_input_tokens: usage.ephemeral1hTokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const costResult = CostCalculator.calculateCost(usageData, model)
|
const costResult = CostCalculator.calculateCost(usageData, model)
|
||||||
totalCost += costResult.costs.total
|
totalCost += costResult.costs.total
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -607,6 +607,16 @@ class AccountBalanceService {
|
|||||||
cache_read_input_tokens: parseInt(data.cacheReadTokens || 0)
|
cache_read_input_tokens: parseInt(data.cacheReadTokens || 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有 ephemeral 5m/1h 拆分数据,添加 cache_creation 子对象以实现精确计费
|
||||||
|
const eph5m = parseInt(data.ephemeral5mTokens || 0)
|
||||||
|
const eph1h = parseInt(data.ephemeral1hTokens || 0)
|
||||||
|
if (eph5m > 0 || eph1h > 0) {
|
||||||
|
usage.cache_creation = {
|
||||||
|
ephemeral_5m_input_tokens: eph5m,
|
||||||
|
ephemeral_1h_input_tokens: eph1h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const costResult = CostCalculator.calculateCost(usage, model)
|
const costResult = CostCalculator.calculateCost(usage, model)
|
||||||
totalCost += costResult.costs.total || 0
|
totalCost += costResult.costs.total || 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user