price.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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 usePrice {
  91. if modelPrice == 0 {
  92. preConsumedQuota = 0
  93. freeModel = true
  94. }
  95. } else {
  96. if modelRatio == 0 {
  97. preConsumedQuota = 0
  98. freeModel = true
  99. }
  100. }
  101. }
  102. priceData := types.PriceData{
  103. FreeModel: freeModel,
  104. ModelPrice: modelPrice,
  105. ModelRatio: modelRatio,
  106. CompletionRatio: completionRatio,
  107. GroupRatioInfo: groupRatioInfo,
  108. UsePrice: usePrice,
  109. CacheRatio: cacheRatio,
  110. ImageRatio: imageRatio,
  111. AudioRatio: audioRatio,
  112. AudioCompletionRatio: audioCompletionRatio,
  113. CacheCreationRatio: cacheCreationRatio,
  114. CacheCreation5mRatio: cacheCreationRatio5m,
  115. CacheCreation1hRatio: cacheCreationRatio1h,
  116. QuotaToPreConsume: preConsumedQuota,
  117. }
  118. if common.DebugEnabled {
  119. println(fmt.Sprintf("model_price_helper result: %s", priceData.ToSetting()))
  120. }
  121. info.PriceData = priceData
  122. return priceData, nil
  123. }
  124. // ModelPriceHelperPerCall 按次计费的 PriceHelper (MJ、Task)
  125. func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) types.PerCallPriceData {
  126. groupRatioInfo := HandleGroupRatio(c, info)
  127. modelPrice, success := ratio_setting.GetModelPrice(info.OriginModelName, true)
  128. // 如果没有配置价格,则使用默认价格
  129. if !success {
  130. defaultPrice, ok := ratio_setting.GetDefaultModelPriceMap()[info.OriginModelName]
  131. if !ok {
  132. modelPrice = 0.1
  133. } else {
  134. modelPrice = defaultPrice
  135. }
  136. }
  137. quota := int(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)
  138. priceData := types.PerCallPriceData{
  139. ModelPrice: modelPrice,
  140. Quota: quota,
  141. GroupRatioInfo: groupRatioInfo,
  142. }
  143. return priceData
  144. }
  145. func ContainPriceOrRatio(modelName string) bool {
  146. _, ok := ratio_setting.GetModelPrice(modelName, false)
  147. if ok {
  148. return true
  149. }
  150. _, ok, _ = ratio_setting.GetModelRatio(modelName)
  151. if ok {
  152. return true
  153. }
  154. return false
  155. }