refactor(price): improve handling of other ratios in PriceData

This commit is contained in:
CaIon
2026-07-07 21:22:19 +08:00
parent 394b023dbf
commit fc1259f583
8 changed files with 256 additions and 56 deletions
@@ -1,9 +1,13 @@
package relay
import (
"math"
"testing"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestIsResponsesEventStreamContentType(t *testing.T) {
@@ -24,3 +28,44 @@ func TestIsResponsesEventStreamContentType(t *testing.T) {
})
}
}
func TestRecalcQuotaFromRatiosIgnoresInvalidMultipliers(t *testing.T) {
info := &relaycommon.RelayInfo{
PriceData: types.PriceData{
Quota: 100,
},
}
info.PriceData.AddOtherRatio("duration", 2)
quota, ok := recalcQuotaFromRatios(info, map[string]float64{
"duration": 3,
"zero": 0,
"negative": -1,
"nan": math.NaN(),
"inf": math.Inf(1),
})
require.True(t, ok)
assert.Equal(t, 150, quota)
assert.True(t, info.PriceData.HasOtherRatio("duration"))
}
func TestRecalcQuotaFromRatiosRejectsAllInvalidAdjustedRatios(t *testing.T) {
info := &relaycommon.RelayInfo{
PriceData: types.PriceData{
Quota: 100,
},
}
info.PriceData.AddOtherRatio("duration", 2)
quota, ok := recalcQuotaFromRatios(info, map[string]float64{
"zero": 0,
"negative": -1,
"nan": math.NaN(),
"inf": math.Inf(1),
})
require.False(t, ok)
assert.Equal(t, 0, quota)
assert.True(t, info.PriceData.HasOtherRatio("duration"))
}
+1 -1
View File
@@ -128,7 +128,7 @@ func ImageHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *type
// Adaptors may have already set a more accurate count from the
// upstream response; only set the default when they haven't.
if info.PriceData.UsePrice { // only price model use N ratio
if _, hasN := info.PriceData.OtherRatios["n"]; !hasN {
if !info.PriceData.HasOtherRatio("n") {
info.PriceData.AddOtherRatio("n", float64(imageN))
}
}
+15 -25
View File
@@ -196,12 +196,7 @@ func RelayTaskSubmit(c *gin.Context, info *relaycommon.RelayInfo) (*TaskSubmitRe
// 6. 将 OtherRatios 应用到基础额度(饱和转换,防止溢出成负数)
if !common.StringsContains(constant.TaskPricePatches, modelName) {
quotaWithRatios := float64(info.PriceData.Quota)
for _, ra := range info.PriceData.OtherRatios {
if ra != 1.0 {
quotaWithRatios *= ra
}
}
quotaWithRatios := info.PriceData.ApplyOtherRatiosToFloat(float64(info.PriceData.Quota))
quota, clamp := common.QuotaFromFloatChecked(quotaWithRatios)
info.PriceData.Quota = quota
noteTaskQuotaClamp(info, clamp)
@@ -232,7 +227,7 @@ func RelayTaskSubmit(c *gin.Context, info *relaycommon.RelayInfo) (*TaskSubmitRe
}
// 10. 返回 OtherRatios 给下游(header 必须在 DoResponse 写 body 之前设置)
otherRatios := info.PriceData.OtherRatios
otherRatios := info.PriceData.OtherRatios()
if otherRatios == nil {
otherRatios = map[string]float64{}
}
@@ -248,10 +243,12 @@ func RelayTaskSubmit(c *gin.Context, info *relaycommon.RelayInfo) (*TaskSubmitRe
// 11. 提交后计费调整:让适配器根据上游实际返回调整 OtherRatios
finalQuota := info.PriceData.Quota
if adjustedRatios := adaptor.AdjustBillingOnSubmit(info, taskData); len(adjustedRatios) > 0 {
// 基于调整后的 ratios 重新计算 quota
finalQuota = recalcQuotaFromRatios(info, adjustedRatios)
info.PriceData.OtherRatios = adjustedRatios
info.PriceData.Quota = finalQuota
if adjustedQuota, ok := recalcQuotaFromRatios(info, adjustedRatios); ok {
// 基于调整后的 ratios 重新计算 quota
finalQuota = adjustedQuota
info.PriceData.ReplaceOtherRatios(adjustedRatios)
info.PriceData.Quota = finalQuota
}
}
return &TaskSubmitResult{
@@ -264,25 +261,18 @@ func RelayTaskSubmit(c *gin.Context, info *relaycommon.RelayInfo) (*TaskSubmitRe
// recalcQuotaFromRatios 根据 adjustedRatios 重新计算 quota。
// 公式: baseQuota × ∏(ratio) — 其中 baseQuota 是不含 OtherRatios 的基础额度。
func recalcQuotaFromRatios(info *relaycommon.RelayInfo, ratios map[string]float64) int {
func recalcQuotaFromRatios(info *relaycommon.RelayInfo, ratios map[string]float64) (int, bool) {
// 从 PriceData 获取不含 OtherRatios 的基础价格
baseQuota := float64(info.PriceData.Quota)
// 先除掉原有的 OtherRatios 恢复基础额度
for _, ra := range info.PriceData.OtherRatios {
if ra != 1.0 && ra > 0 {
baseQuota /= ra
}
baseQuota := info.PriceData.RemoveOtherRatiosFromFloat(float64(info.PriceData.Quota))
priceData := info.PriceData
if !priceData.ReplaceOtherRatios(ratios) {
return 0, false
}
// 应用新的 ratios
result := baseQuota
for _, ra := range ratios {
if ra != 1.0 {
result *= ra
}
}
result := priceData.ApplyOtherRatiosToFloat(baseQuota)
quota, clamp := common.QuotaFromFloatChecked(result)
noteTaskQuotaClamp(info, clamp)
return quota
return quota, true
}
// noteTaskQuotaClamp records the first quota saturation event onto the task's