mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
feat: 优化 Claude 模型缓存费用计算,支持 5 分钟和 1 小时两种缓存类型
- 在 pricingService 中硬编码 1 小时缓存价格(Opus: $30/MTok, Sonnet: $6/MTok, Haiku: $1.6/MTok) - 更新 usage 捕获逻辑以分别记录 ephemeral_5m 和 ephemeral_1h 缓存 tokens - 改进费用计算逻辑,正确计算两种缓存类型的费用 - 新增 recordUsageWithDetails 方法支持详细的缓存数据 - 保持向后兼容性,支持旧的数据格式 - 删除测试脚本 test-openai-refresh.js - 修复 OpenAI token 刷新逻辑 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -96,22 +96,42 @@ async function handleMessagesRequest(req, res) {
|
||||
) {
|
||||
const inputTokens = usageData.input_tokens || 0
|
||||
const outputTokens = usageData.output_tokens || 0
|
||||
const cacheCreateTokens = usageData.cache_creation_input_tokens || 0
|
||||
// 兼容处理:如果有详细的 cache_creation 对象,使用它;否则使用总的 cache_creation_input_tokens
|
||||
let cacheCreateTokens = usageData.cache_creation_input_tokens || 0
|
||||
let ephemeral5mTokens = 0
|
||||
let ephemeral1hTokens = 0
|
||||
|
||||
if (usageData.cache_creation && typeof usageData.cache_creation === 'object') {
|
||||
ephemeral5mTokens = usageData.cache_creation.ephemeral_5m_input_tokens || 0
|
||||
ephemeral1hTokens = usageData.cache_creation.ephemeral_1h_input_tokens || 0
|
||||
// 总的缓存创建 tokens 是两者之和
|
||||
cacheCreateTokens = ephemeral5mTokens + ephemeral1hTokens
|
||||
}
|
||||
|
||||
const cacheReadTokens = usageData.cache_read_input_tokens || 0
|
||||
const model = usageData.model || 'unknown'
|
||||
|
||||
// 记录真实的token使用量(包含模型信息和所有4种token以及账户ID)
|
||||
const { accountId: usageAccountId } = usageData
|
||||
|
||||
// 构建 usage 对象以传递给 recordUsage
|
||||
const usageObject = {
|
||||
input_tokens: inputTokens,
|
||||
output_tokens: outputTokens,
|
||||
cache_creation_input_tokens: cacheCreateTokens,
|
||||
cache_read_input_tokens: cacheReadTokens
|
||||
}
|
||||
|
||||
// 如果有详细的缓存创建数据,添加到 usage 对象中
|
||||
if (ephemeral5mTokens > 0 || ephemeral1hTokens > 0) {
|
||||
usageObject.cache_creation = {
|
||||
ephemeral_5m_input_tokens: ephemeral5mTokens,
|
||||
ephemeral_1h_input_tokens: ephemeral1hTokens
|
||||
}
|
||||
}
|
||||
|
||||
apiKeyService
|
||||
.recordUsage(
|
||||
req.apiKey.id,
|
||||
inputTokens,
|
||||
outputTokens,
|
||||
cacheCreateTokens,
|
||||
cacheReadTokens,
|
||||
model,
|
||||
usageAccountId
|
||||
)
|
||||
.recordUsageWithDetails(req.apiKey.id, usageObject, model, usageAccountId)
|
||||
.catch((error) => {
|
||||
logger.error('❌ Failed to record stream usage:', error)
|
||||
})
|
||||
@@ -161,22 +181,42 @@ async function handleMessagesRequest(req, res) {
|
||||
) {
|
||||
const inputTokens = usageData.input_tokens || 0
|
||||
const outputTokens = usageData.output_tokens || 0
|
||||
const cacheCreateTokens = usageData.cache_creation_input_tokens || 0
|
||||
// 兼容处理:如果有详细的 cache_creation 对象,使用它;否则使用总的 cache_creation_input_tokens
|
||||
let cacheCreateTokens = usageData.cache_creation_input_tokens || 0
|
||||
let ephemeral5mTokens = 0
|
||||
let ephemeral1hTokens = 0
|
||||
|
||||
if (usageData.cache_creation && typeof usageData.cache_creation === 'object') {
|
||||
ephemeral5mTokens = usageData.cache_creation.ephemeral_5m_input_tokens || 0
|
||||
ephemeral1hTokens = usageData.cache_creation.ephemeral_1h_input_tokens || 0
|
||||
// 总的缓存创建 tokens 是两者之和
|
||||
cacheCreateTokens = ephemeral5mTokens + ephemeral1hTokens
|
||||
}
|
||||
|
||||
const cacheReadTokens = usageData.cache_read_input_tokens || 0
|
||||
const model = usageData.model || 'unknown'
|
||||
|
||||
// 记录真实的token使用量(包含模型信息和所有4种token以及账户ID)
|
||||
const usageAccountId = usageData.accountId
|
||||
|
||||
// 构建 usage 对象以传递给 recordUsage
|
||||
const usageObject = {
|
||||
input_tokens: inputTokens,
|
||||
output_tokens: outputTokens,
|
||||
cache_creation_input_tokens: cacheCreateTokens,
|
||||
cache_read_input_tokens: cacheReadTokens
|
||||
}
|
||||
|
||||
// 如果有详细的缓存创建数据,添加到 usage 对象中
|
||||
if (ephemeral5mTokens > 0 || ephemeral1hTokens > 0) {
|
||||
usageObject.cache_creation = {
|
||||
ephemeral_5m_input_tokens: ephemeral5mTokens,
|
||||
ephemeral_1h_input_tokens: ephemeral1hTokens
|
||||
}
|
||||
}
|
||||
|
||||
apiKeyService
|
||||
.recordUsage(
|
||||
req.apiKey.id,
|
||||
inputTokens,
|
||||
outputTokens,
|
||||
cacheCreateTokens,
|
||||
cacheReadTokens,
|
||||
model,
|
||||
usageAccountId
|
||||
)
|
||||
.recordUsageWithDetails(req.apiKey.id, usageObject, model, usageAccountId)
|
||||
.catch((error) => {
|
||||
logger.error('❌ Failed to record stream usage:', error)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user