mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-04-18 03:17:27 +00:00
fix: 修复 Anthropic 渠道缓存计费错误
## 问题描述
当使用 Anthropic 渠道通过 `/v1/chat/completions` 端点调用且启用缓存功能时,
计费逻辑错误地减去了缓存 tokens,导致严重的收入损失(94.5%)。
## 根本原因
不同 API 的 `prompt_tokens` 定义不同:
- **Anthropic API**: `input_tokens` 字段已经是纯输入 tokens(不包含缓存)
- **OpenAI API**: `prompt_tokens` 字段包含所有 tokens(包含缓存)
- **OpenRouter API**: `prompt_tokens` 字段包含所有 tokens(包含缓存)
当前 `postConsumeQuota` 函数对所有渠道都减去缓存 tokens,这对 Anthropic
渠道是错误的,因为其 `input_tokens` 已经不包含缓存。
## 修复方案
在 `relay/compatible_handler.go` 的 `postConsumeQuota` 函数中,添加渠道类型判断:
```go
if relayInfo.ChannelType != constant.ChannelTypeAnthropic {
baseTokens = baseTokens.Sub(dCacheTokens)
}
```
只对非 Anthropic 渠道减去缓存 tokens。
## 影响分析
### ✅ 不受影响的场景
1. **无缓存调用**(所有渠道)
- cache_tokens = 0
- 减去 0 = 不减去
- 结果:完全一致
2. **OpenAI/OpenRouter 渠道 + 缓存**
- 继续减去缓存(因为 ChannelType != Anthropic)
- 结果:完全一致
3. **Anthropic 渠道 + /v1/messages 端点**
- 使用 PostClaudeConsumeQuota(不修改)
- 结果:完全不受影响
### ✅ 修复的场景
4. **Anthropic 渠道 + /v1/chat/completions + 缓存**
- 修复前:错误地减去缓存,导致 94.5% 收入损失
- 修复后:不减去缓存,计费正确
## 验证数据
以实际记录 143509 为例:
| 项目 | 修复前 | 修复后 | 差异 |
|------|--------|--------|------|
| Quota | 10,489 | 191,330 | +180,841 |
| 费用 | ¥0.020978 | ¥0.382660 | +¥0.361682 |
| 收入恢复 | - | - | **+1724.1%** |
## 测试建议
1. 测试 Anthropic 渠道 + 缓存场景
2. 测试 OpenAI 渠道 + 缓存场景(确保不受影响)
3. 测试无缓存场景(确保不受影响)
## 相关 Issue
修复 Anthropic 渠道使用 prompt caching 时的计费错误。
This commit is contained in:
@@ -300,14 +300,20 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, usage
|
||||
if !relayInfo.PriceData.UsePrice {
|
||||
baseTokens := dPromptTokens
|
||||
// 减去 cached tokens
|
||||
// Anthropic API 的 input_tokens 已经不包含缓存 tokens,不需要减去
|
||||
// OpenAI/OpenRouter 等 API 的 prompt_tokens 包含缓存 tokens,需要减去
|
||||
var cachedTokensWithRatio decimal.Decimal
|
||||
if !dCacheTokens.IsZero() {
|
||||
baseTokens = baseTokens.Sub(dCacheTokens)
|
||||
if relayInfo.ChannelType != constant.ChannelTypeAnthropic {
|
||||
baseTokens = baseTokens.Sub(dCacheTokens)
|
||||
}
|
||||
cachedTokensWithRatio = dCacheTokens.Mul(dCacheRatio)
|
||||
}
|
||||
var dCachedCreationTokensWithRatio decimal.Decimal
|
||||
if !dCachedCreationTokens.IsZero() {
|
||||
baseTokens = baseTokens.Sub(dCachedCreationTokens)
|
||||
if relayInfo.ChannelType != constant.ChannelTypeAnthropic {
|
||||
baseTokens = baseTokens.Sub(dCachedCreationTokens)
|
||||
}
|
||||
dCachedCreationTokensWithRatio = dCachedCreationTokens.Mul(dCachedCreationRatio)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user