From 3a24fd598fdb14849506cdb77414d60352d3ce39 Mon Sep 17 00:00:00 2001 From: fengsilin Date: Thu, 16 Apr 2026 23:35:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(channel-pricing):=20ModelPriceHelper=20+?= =?UTF-8?q?=20UpdatePriceDataForChannelPricing=20=E9=80=82=E9=85=8D?= =?UTF-8?q?=E6=96=B0=E7=AD=BE=E5=90=8D=EF=BC=8C=E6=94=AF=E6=8C=81=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E6=AF=94=E7=8E=87=E8=A6=86=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- relay/helper/price.go | 115 ++++++++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 32 deletions(-) diff --git a/relay/helper/price.go b/relay/helper/price.go index b63467a..532f739 100644 --- a/relay/helper/price.go +++ b/relay/helper/price.go @@ -52,17 +52,44 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens var modelRatio float64 var completionRatio float64 var channelPricingFound bool + var cacheRatio float64 + var imageRatio float64 + var cacheCreationRatio float64 + var cacheCreationRatio5m float64 + var cacheCreationRatio1h float64 + var audioRatio float64 + var audioCompletionRatio float64 // 尝试获取渠道定价(优先于全局定价) channelMetaAvailable := info != nil && info.ChannelMeta != nil && info.ChannelId > 0 if channelMetaAvailable { - cpRatio, cpCompletionRatio, cpPrice, cpUsePrice, found := model.GetEffectivePricing(info.OriginModelName, info.ChannelId) + cp, found := model.GetEffectivePricing(info.OriginModelName, info.ChannelId) if found { - modelRatio = cpRatio - completionRatio = cpCompletionRatio - modelPrice = cpPrice - usePrice = cpUsePrice + modelRatio = cp.ModelRatio + completionRatio = cp.CompletionRatio + modelPrice = cp.ModelPrice + usePrice = cp.QuotaType == model.QuotaTypeByCall channelPricingFound = true + if cp.CacheRatio != 0 { + cacheRatio = cp.CacheRatio + } + if cp.CacheCreationRatio != 0 { + cacheCreationRatio = cp.CacheCreationRatio + cacheCreationRatio5m = cp.CacheCreationRatio + cacheCreationRatio1h = cp.CacheCreationRatio * claudeCacheCreation1hMultiplier + } + if cp.ImageRatio != 0 { + imageRatio = cp.ImageRatio + } + if cp.AudioRatio != 0 { + audioRatio = cp.AudioRatio + } + if cp.AudioCompletionRatio != 0 { + audioCompletionRatio = cp.AudioCompletionRatio + } + if common.DebugEnabled { + println(fmt.Sprintf("[ChannelPricing] hit: model=%s channel=%d source=cache", info.OriginModelName, info.ChannelId)) + } } } @@ -74,13 +101,6 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens groupRatioInfo := HandleGroupRatio(c, info) var preConsumedQuota int - var cacheRatio float64 - var imageRatio float64 - var cacheCreationRatio float64 - var cacheCreationRatio5m float64 - var cacheCreationRatio1h float64 - var audioRatio float64 - var audioCompletionRatio float64 var freeModel bool if !usePrice { preConsumedTokens := common.Max(promptTokens, common.PreConsumedQuota) @@ -103,14 +123,24 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens } completionRatio = ratio_setting.GetCompletionRatio(info.OriginModelName) } - cacheRatio, _ = ratio_setting.GetCacheRatio(info.OriginModelName) - cacheCreationRatio, _ = ratio_setting.GetCreateCacheRatio(info.OriginModelName) - cacheCreationRatio5m = cacheCreationRatio - // 固定1h和5min缓存写入价格的比例 - cacheCreationRatio1h = cacheCreationRatio * claudeCacheCreation1hMultiplier - imageRatio, _ = ratio_setting.GetImageRatio(info.OriginModelName) - audioRatio = ratio_setting.GetAudioRatio(info.OriginModelName) - audioCompletionRatio = ratio_setting.GetAudioCompletionRatio(info.OriginModelName) + if cacheRatio == 0 { + cacheRatio, _ = ratio_setting.GetCacheRatio(info.OriginModelName) + } + if cacheCreationRatio == 0 { + cacheCreationRatio, _ = ratio_setting.GetCreateCacheRatio(info.OriginModelName) + cacheCreationRatio5m = cacheCreationRatio + // 固定1h和5min缓存写入价格的比例 + cacheCreationRatio1h = cacheCreationRatio * claudeCacheCreation1hMultiplier + } + if imageRatio == 0 { + imageRatio, _ = ratio_setting.GetImageRatio(info.OriginModelName) + } + if audioRatio == 0 { + audioRatio = ratio_setting.GetAudioRatio(info.OriginModelName) + } + if audioCompletionRatio == 0 { + audioCompletionRatio = ratio_setting.GetAudioCompletionRatio(info.OriginModelName) + } ratio := modelRatio * groupRatioInfo.GroupRatio preConsumedQuota = int(float64(preConsumedTokens) * ratio) } else { @@ -217,30 +247,51 @@ func UpdatePriceDataForChannelPricing(c *gin.Context, info *relaycommon.RelayInf return } - cpRatio, cpCompletionRatio, cpPrice, cpUsePrice, found := model.GetEffectivePricing(info.OriginModelName, channelId) + cp, found := model.GetEffectivePricing(info.OriginModelName, channelId) if !found { return } - // 更新 PriceData 中的定价相关字段 - info.PriceData.ModelRatio = cpRatio - info.PriceData.CompletionRatio = cpCompletionRatio - info.PriceData.UsePrice = cpUsePrice - // 按次计费模式下使用渠道价格,按量计费模式下设置 ModelPrice = -1 让前端识别计费模式 - if cpUsePrice { - info.PriceData.ModelPrice = cpPrice + info.PriceData.ModelRatio = cp.ModelRatio + info.PriceData.CompletionRatio = cp.CompletionRatio + info.PriceData.UsePrice = cp.QuotaType == model.QuotaTypeByCall + if info.PriceData.UsePrice { + info.PriceData.ModelPrice = cp.ModelPrice } else { info.PriceData.ModelPrice = -1 } - // 重新计算预扣费额度(用于后续可能的引用) - if cpUsePrice { - info.PriceData.QuotaToPreConsume = int(cpPrice * common.QuotaPerUnit * info.PriceData.GroupRatioInfo.GroupRatio) + if cp.CacheRatio != 0 { + info.PriceData.CacheRatio = cp.CacheRatio + } + if cp.CacheCreationRatio != 0 { + info.PriceData.CacheCreationRatio = cp.CacheCreationRatio + info.PriceData.CacheCreation5mRatio = cp.CacheCreationRatio + info.PriceData.CacheCreation1hRatio = cp.CacheCreationRatio * claudeCacheCreation1hMultiplier + } + if cp.ImageRatio != 0 { + info.PriceData.ImageRatio = cp.ImageRatio + } + if cp.AudioRatio != 0 { + info.PriceData.AudioRatio = cp.AudioRatio + } + if cp.AudioCompletionRatio != 0 { + info.PriceData.AudioCompletionRatio = cp.AudioCompletionRatio + } + + if info.PriceData.UsePrice { + info.PriceData.QuotaToPreConsume = int( + cp.ModelPrice * common.QuotaPerUnit * info.PriceData.GroupRatioInfo.GroupRatio) } else { estimateTokens := info.GetEstimatePromptTokens() if estimateTokens > 0 { - ratio := cpRatio * info.PriceData.GroupRatioInfo.GroupRatio + ratio := cp.ModelRatio * info.PriceData.GroupRatioInfo.GroupRatio info.PriceData.QuotaToPreConsume = int(float64(estimateTokens) * ratio) } } + + if common.DebugEnabled { + println(fmt.Sprintf("[ChannelPricing] updatePriceData: model=%s channel=%d modelRatio=%.4f completionRatio=%.4f cacheRatio=%.4f imageRatio=%.4f audioRatio=%.4f", + info.OriginModelName, channelId, cp.ModelRatio, cp.CompletionRatio, cp.CacheRatio, cp.ImageRatio, cp.AudioRatio)) + } }