price.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package helper
  2. import (
  3. "fmt"
  4. "github.com/QuantumNous/new-api/common"
  5. "github.com/QuantumNous/new-api/logger"
  6. relaycommon "github.com/QuantumNous/new-api/relay/common"
  7. "github.com/QuantumNous/new-api/setting/operation_setting"
  8. "github.com/QuantumNous/new-api/setting/ratio_setting"
  9. "github.com/QuantumNous/new-api/types"
  10. "github.com/gin-gonic/gin"
  11. )
  12. // https://docs.claude.com/en/docs/build-with-claude/prompt-caching#1-hour-cache-duration
  13. const claudeCacheCreation1hMultiplier = 6 / 3.75
  14. // HandleGroupRatio checks for "auto_group" in the context and updates the group ratio and relayInfo.UsingGroup if present
  15. func HandleGroupRatio(ctx *gin.Context, relayInfo *relaycommon.RelayInfo) types.GroupRatioInfo {
  16. groupRatioInfo := types.GroupRatioInfo{
  17. GroupRatio: 1.0, // default ratio
  18. GroupSpecialRatio: -1,
  19. }
  20. // check auto group
  21. autoGroup, exists := ctx.Get("auto_group")
  22. if exists {
  23. logger.LogDebug(ctx, fmt.Sprintf("final group: %s", autoGroup))
  24. relayInfo.UsingGroup = autoGroup.(string)
  25. }
  26. // check user group special ratio
  27. userGroupRatio, ok := ratio_setting.GetGroupGroupRatio(relayInfo.UserGroup, relayInfo.UsingGroup)
  28. if ok {
  29. // user group special ratio
  30. groupRatioInfo.GroupSpecialRatio = userGroupRatio
  31. groupRatioInfo.GroupRatio = userGroupRatio
  32. groupRatioInfo.HasSpecialRatio = true
  33. } else {
  34. // normal group ratio
  35. groupRatioInfo.GroupRatio = ratio_setting.GetGroupRatio(relayInfo.UsingGroup)
  36. }
  37. return groupRatioInfo
  38. }
  39. func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta) (types.PriceData, error) {
  40. modelPrice, usePrice := ratio_setting.GetModelPrice(info.OriginModelName, false)
  41. groupRatioInfo := HandleGroupRatio(c, info)
  42. var preConsumedQuota int
  43. var modelRatio float64
  44. var completionRatio float64
  45. var cacheRatio float64
  46. var imageRatio float64
  47. var cacheCreationRatio float64
  48. var cacheCreationRatio5m float64
  49. var cacheCreationRatio1h float64
  50. var audioRatio float64
  51. var audioCompletionRatio float64
  52. var freeModel bool
  53. if !usePrice {
  54. preConsumedTokens := common.Max(promptTokens, common.PreConsumedQuota)
  55. if meta.MaxTokens != 0 {
  56. preConsumedTokens += meta.MaxTokens
  57. }
  58. var success bool
  59. var matchName string
  60. modelRatio, success, matchName = ratio_setting.GetModelRatio(info.OriginModelName)
  61. if !success {
  62. acceptUnsetRatio := false
  63. if info.UserSetting.AcceptUnsetRatioModel {
  64. acceptUnsetRatio = true
  65. }
  66. if !acceptUnsetRatio {
  67. return types.PriceData{}, fmt.Errorf("模型 %s 倍率或价格未配置,请联系管理员设置或开始自用模式;Model %s ratio or price not set, please set or start self-use mode", matchName, matchName)
  68. }
  69. }
  70. completionRatio = ratio_setting.GetCompletionRatio(info.OriginModelName)
  71. cacheRatio, _ = ratio_setting.GetCacheRatio(info.OriginModelName)
  72. cacheCreationRatio, _ = ratio_setting.GetCreateCacheRatio(info.OriginModelName)
  73. cacheCreationRatio5m = cacheCreationRatio
  74. // 固定1h和5min缓存写入价格的比例
  75. cacheCreationRatio1h = cacheCreationRatio * claudeCacheCreation1hMultiplier
  76. imageRatio, _ = ratio_setting.GetImageRatio(info.OriginModelName)
  77. audioRatio = ratio_setting.GetAudioRatio(info.OriginModelName)
  78. audioCompletionRatio = ratio_setting.GetAudioCompletionRatio(info.OriginModelName)
  79. ratio := modelRatio * groupRatioInfo.GroupRatio
  80. preConsumedQuota = int(float64(preConsumedTokens) * ratio)
  81. } else {
  82. if meta.ImagePriceRatio != 0 {
  83. modelPrice = modelPrice * meta.ImagePriceRatio
  84. }
  85. preConsumedQuota = int(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)
  86. }
  87. // check if free model pre-consume is disabled
  88. if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume {
  89. // if model price or ratio is 0, do not pre-consume quota
  90. if groupRatioInfo.GroupRatio == 0 {
  91. preConsumedQuota = 0
  92. freeModel = true
  93. } else if usePrice {
  94. if modelPrice == 0 {
  95. preConsumedQuota = 0
  96. freeModel = true
  97. }
  98. } else {
  99. if modelRatio == 0 {
  100. preConsumedQuota = 0
  101. freeModel = true
  102. }
  103. }
  104. }
  105. priceData := types.PriceData{
  106. FreeModel: freeModel,
  107. ModelPrice: modelPrice,
  108. ModelRatio: modelRatio,
  109. CompletionRatio: completionRatio,
  110. GroupRatioInfo: groupRatioInfo,
  111. UsePrice: usePrice,
  112. CacheRatio: cacheRatio,
  113. ImageRatio: imageRatio,
  114. AudioRatio: audioRatio,
  115. AudioCompletionRatio: audioCompletionRatio,
  116. CacheCreationRatio: cacheCreationRatio,
  117. CacheCreation5mRatio: cacheCreationRatio5m,
  118. CacheCreation1hRatio: cacheCreationRatio1h,
  119. QuotaToPreConsume: preConsumedQuota,
  120. }
  121. if common.DebugEnabled {
  122. println(fmt.Sprintf("model_price_helper result: %s", priceData.ToSetting()))
  123. }
  124. info.PriceData = priceData
  125. return priceData, nil
  126. }
  127. // ModelPriceHelperPerCall 按次计费的 PriceHelper (MJ、Task)
  128. func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) types.PriceData {
  129. groupRatioInfo := HandleGroupRatio(c, info)
  130. modelPrice, success := ratio_setting.GetModelPrice(info.OriginModelName, true)
  131. // 如果没有配置价格,则使用默认价格
  132. if !success {
  133. defaultPrice, ok := ratio_setting.GetDefaultModelPriceMap()[info.OriginModelName]
  134. if !ok {
  135. modelPrice = 0.1
  136. } else {
  137. modelPrice = defaultPrice
  138. }
  139. }
  140. quota := int(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)
  141. // 免费模型检测(与 ModelPriceHelper 对齐)
  142. freeModel := false
  143. if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume {
  144. if groupRatioInfo.GroupRatio == 0 || modelPrice == 0 {
  145. quota = 0
  146. freeModel = true
  147. }
  148. }
  149. priceData := types.PriceData{
  150. FreeModel: freeModel,
  151. ModelPrice: modelPrice,
  152. Quota: quota,
  153. GroupRatioInfo: groupRatioInfo,
  154. }
  155. return priceData
  156. }
  157. func ContainPriceOrRatio(modelName string) bool {
  158. _, ok := ratio_setting.GetModelPrice(modelName, false)
  159. if ok {
  160. return true
  161. }
  162. _, ok, _ = ratio_setting.GetModelRatio(modelName)
  163. if ok {
  164. return true
  165. }
  166. return false
  167. }