refactor: update import paths to use new types package

This commit is contained in:
CaIon
2026-07-27 16:45:02 +08:00
parent 60a1acb703
commit b8bb3f40ac
21 changed files with 75 additions and 84 deletions
+3 -2
View File
@@ -28,6 +28,7 @@ import (
"github.com/QuantumNous/new-api/service" "github.com/QuantumNous/new-api/service"
"github.com/QuantumNous/new-api/setting/operation_setting" "github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/QuantumNous/new-api/setting/ratio_setting" "github.com/QuantumNous/new-api/setting/ratio_setting"
hosttypes "github.com/QuantumNous/new-api/types"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@@ -530,7 +531,7 @@ func attachTestBillingRequestInput(info *relaycommon.RelayInfo, request dto.Requ
return nil return nil
} }
func settleTestQuota(info *relaycommon.RelayInfo, priceData types.PriceData, usage *dto.Usage) (int, *billingexpr.TieredResult) { func settleTestQuota(info *relaycommon.RelayInfo, priceData hosttypes.PriceData, usage *dto.Usage) (int, *billingexpr.TieredResult) {
if usage != nil && info != nil && info.TieredBillingSnapshot != nil { if usage != nil && info != nil && info.TieredBillingSnapshot != nil {
isClaudeUsageSemantic := usage.UsageSemantic == "anthropic" || info.GetFinalRequestRelayFormat() == types.RelayFormatClaude isClaudeUsageSemantic := usage.UsageSemantic == "anthropic" || info.GetFinalRequestRelayFormat() == types.RelayFormatClaude
usedVars := billingexpr.UsedVars(info.TieredBillingSnapshot.ExprString) usedVars := billingexpr.UsedVars(info.TieredBillingSnapshot.ExprString)
@@ -552,7 +553,7 @@ func settleTestQuota(info *relaycommon.RelayInfo, priceData types.PriceData, usa
return int(priceData.ModelPrice * common.QuotaPerUnit), nil return int(priceData.ModelPrice * common.QuotaPerUnit), nil
} }
func buildTestLogOther(c *gin.Context, info *relaycommon.RelayInfo, priceData types.PriceData, usage *dto.Usage, tieredResult *billingexpr.TieredResult) map[string]interface{} { func buildTestLogOther(c *gin.Context, info *relaycommon.RelayInfo, priceData hosttypes.PriceData, usage *dto.Usage, tieredResult *billingexpr.TieredResult) map[string]interface{} {
other := service.GenerateTextOtherInfo(c, info, priceData.ModelRatio, priceData.GroupRatioInfo.GroupRatio, priceData.CompletionRatio, other := service.GenerateTextOtherInfo(c, info, priceData.ModelRatio, priceData.GroupRatioInfo.GroupRatio, priceData.CompletionRatio,
usage.PromptTokensDetails.CachedTokens, priceData.CacheRatio, priceData.ModelPrice, priceData.GroupRatioInfo.GroupSpecialRatio) usage.PromptTokensDetails.CachedTokens, priceData.CacheRatio, priceData.ModelPrice, priceData.GroupRatioInfo.GroupSpecialRatio)
if tieredResult != nil { if tieredResult != nil {
+1 -1
View File
@@ -13,9 +13,9 @@ import (
"github.com/QuantumNous/new-api/pkg/billingexpr" "github.com/QuantumNous/new-api/pkg/billingexpr"
relaycommon "github.com/QuantumNous/new-api/relay/common" relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/dto" "github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/service" "github.com/QuantumNous/new-api/service"
"github.com/QuantumNous/new-api/setting/operation_setting" "github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/QuantumNous/new-api/dto" "github.com/QuantumNous/new-api/dto"
"github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/model"
"github.com/QuantumNous/new-api/relay" "github.com/QuantumNous/new-api/relay"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/logger"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
+1 -1
View File
@@ -10,9 +10,9 @@ import (
"github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/constant" "github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/relaykit/dto" "github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/billing_setting" "github.com/QuantumNous/new-api/setting/billing_setting"
"github.com/QuantumNous/new-api/setting/ratio_setting" "github.com/QuantumNous/new-api/setting/ratio_setting"
"github.com/QuantumNous/new-api/types"
) )
type Pricing struct { type Pricing struct {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing" "testing"
relaycommon "github.com/QuantumNous/new-api/relay/common" relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/types"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
+2 -1
View File
@@ -16,6 +16,7 @@ import (
"github.com/QuantumNous/new-api/relaykit/relayconvert/convmeta" "github.com/QuantumNous/new-api/relaykit/relayconvert/convmeta"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/model_setting" "github.com/QuantumNous/new-api/setting/model_setting"
hosttypes "github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
@@ -155,7 +156,7 @@ type RelayInfo struct {
// *bytes.Reader/Buffer/strings.Reader). 0 means "let net/http decide". // *bytes.Reader/Buffer/strings.Reader). 0 means "let net/http decide".
UpstreamRequestBodySize int64 UpstreamRequestBodySize int64
PriceData types.PriceData PriceData hosttypes.PriceData
// QuotaClamp is set (non-nil) when a quota conversion saturated at the // QuotaClamp is set (non-nil) when a quota conversion saturated at the
// int32 bound (or NaN fallback) while computing this request's charge. // int32 bound (or NaN fallback) while computing this request's charge.
+19 -18
View File
@@ -13,6 +13,7 @@ import (
"github.com/QuantumNous/new-api/setting/billing_setting" "github.com/QuantumNous/new-api/setting/billing_setting"
"github.com/QuantumNous/new-api/setting/operation_setting" "github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/QuantumNous/new-api/setting/ratio_setting" "github.com/QuantumNous/new-api/setting/ratio_setting"
hosttypes "github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -41,8 +42,8 @@ const claudeCacheCreation1hMultiplier = 6 / 3.75
const defaultTieredPreConsumeMaxTokens = 8192 const defaultTieredPreConsumeMaxTokens = 8192
// HandleGroupRatio checks for "auto_group" in the context and updates the group ratio and relayInfo.UsingGroup if present // HandleGroupRatio checks for "auto_group" in the context and updates the group ratio and relayInfo.UsingGroup if present
func HandleGroupRatio(ctx *gin.Context, relayInfo *relaycommon.RelayInfo) types.GroupRatioInfo { func HandleGroupRatio(ctx *gin.Context, relayInfo *relaycommon.RelayInfo) hosttypes.GroupRatioInfo {
groupRatioInfo := types.GroupRatioInfo{ groupRatioInfo := hosttypes.GroupRatioInfo{
GroupRatio: 1.0, // default ratio GroupRatio: 1.0, // default ratio
GroupSpecialRatio: -1, GroupSpecialRatio: -1,
} }
@@ -69,7 +70,7 @@ func HandleGroupRatio(ctx *gin.Context, relayInfo *relaycommon.RelayInfo) types.
return groupRatioInfo return groupRatioInfo
} }
func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta) (types.PriceData, error) { func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta) (hosttypes.PriceData, error) {
modelPrice, usePrice := ratio_setting.GetModelPrice(info.OriginModelName, false) modelPrice, usePrice := ratio_setting.GetModelPrice(info.OriginModelName, false)
groupRatioInfo := HandleGroupRatio(c, info) groupRatioInfo := HandleGroupRatio(c, info)
@@ -104,7 +105,7 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens
acceptUnsetRatio = true acceptUnsetRatio = true
} }
if !acceptUnsetRatio { if !acceptUnsetRatio {
return types.PriceData{}, modelPriceNotConfiguredError(matchName, info.UserId) return hosttypes.PriceData{}, modelPriceNotConfiguredError(matchName, info.UserId)
} }
} }
completionRatio = ratio_setting.GetCompletionRatio(info.OriginModelName) completionRatio = ratio_setting.GetCompletionRatio(info.OriginModelName)
@@ -119,7 +120,7 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens
ratio := modelRatio * groupRatioInfo.GroupRatio ratio := modelRatio * groupRatioInfo.GroupRatio
quota, err := common.QuotaFromFloatStrict(float64(preConsumedTokens) * ratio) quota, err := common.QuotaFromFloatStrict(float64(preConsumedTokens) * ratio)
if err != nil { if err != nil {
return types.PriceData{}, err return hosttypes.PriceData{}, err
} }
preConsumedQuota = quota preConsumedQuota = quota
} else { } else {
@@ -147,7 +148,7 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens
} }
} }
priceData := types.PriceData{ priceData := hosttypes.PriceData{
FreeModel: freeModel, FreeModel: freeModel,
ModelPrice: modelPrice, ModelPrice: modelPrice,
ModelRatio: modelRatio, ModelRatio: modelRatio,
@@ -170,7 +171,7 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens
quotaToPreConsume := priceData.ApplyOtherRatiosToFloat(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio) quotaToPreConsume := priceData.ApplyOtherRatiosToFloat(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)
quota, err := common.QuotaFromFloatStrict(quotaToPreConsume) quota, err := common.QuotaFromFloatStrict(quotaToPreConsume)
if err != nil { if err != nil {
return types.PriceData{}, err return hosttypes.PriceData{}, err
} }
priceData.QuotaToPreConsume = quota priceData.QuotaToPreConsume = quota
} }
@@ -183,7 +184,7 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens
} }
// ModelPriceHelperPerCall 按次/按量计费的 PriceHelper (MJ、Task) // ModelPriceHelperPerCall 按次/按量计费的 PriceHelper (MJ、Task)
func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (types.PriceData, error) { func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (hosttypes.PriceData, error) {
groupRatioInfo := HandleGroupRatio(c, info) groupRatioInfo := HandleGroupRatio(c, info)
modelPrice, success := ratio_setting.GetModelPrice(info.OriginModelName, true) modelPrice, success := ratio_setting.GetModelPrice(info.OriginModelName, true)
@@ -204,7 +205,7 @@ func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (types
acceptUnsetRatio = true acceptUnsetRatio = true
} }
if !ratioSuccess && !acceptUnsetRatio { if !ratioSuccess && !acceptUnsetRatio {
return types.PriceData{}, modelPriceNotConfiguredError(matchName, info.UserId) return hosttypes.PriceData{}, modelPriceNotConfiguredError(matchName, info.UserId)
} }
} }
} }
@@ -216,7 +217,7 @@ func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (types
var err error var err error
quota, err = common.QuotaFromFloatStrict(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio) quota, err = common.QuotaFromFloatStrict(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)
if err != nil { if err != nil {
return types.PriceData{}, err return hosttypes.PriceData{}, err
} }
if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume { if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume {
if groupRatioInfo.GroupRatio == 0 || modelPrice == 0 { if groupRatioInfo.GroupRatio == 0 || modelPrice == 0 {
@@ -229,7 +230,7 @@ func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (types
var err error var err error
quota, err = common.QuotaFromFloatStrict(modelRatio / 2 * common.QuotaPerUnit * groupRatioInfo.GroupRatio) quota, err = common.QuotaFromFloatStrict(modelRatio / 2 * common.QuotaPerUnit * groupRatioInfo.GroupRatio)
if err != nil { if err != nil {
return types.PriceData{}, err return hosttypes.PriceData{}, err
} }
modelPrice = -1 modelPrice = -1
if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume { if !operation_setting.GetQuotaSetting().EnableFreeModelPreConsume {
@@ -240,7 +241,7 @@ func ModelPriceHelperPerCall(c *gin.Context, info *relaycommon.RelayInfo) (types
} }
} }
priceData := types.PriceData{ priceData := hosttypes.PriceData{
FreeModel: freeModel, FreeModel: freeModel,
ModelPrice: modelPrice, ModelPrice: modelPrice,
ModelRatio: modelRatio, ModelRatio: modelRatio,
@@ -265,10 +266,10 @@ func HasModelBillingConfig(modelName string) bool {
return ok && strings.TrimSpace(expr) != "" return ok && strings.TrimSpace(expr) != ""
} }
func modelPriceHelperTiered(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta, groupRatioInfo types.GroupRatioInfo) (types.PriceData, error) { func modelPriceHelperTiered(c *gin.Context, info *relaycommon.RelayInfo, promptTokens int, meta *types.TokenCountMeta, groupRatioInfo hosttypes.GroupRatioInfo) (hosttypes.PriceData, error) {
exprStr, ok := billing_setting.GetBillingExpr(info.OriginModelName) exprStr, ok := billing_setting.GetBillingExpr(info.OriginModelName)
if !ok { if !ok {
return types.PriceData{}, fmt.Errorf("model %s is configured as tiered_expr but has no billing expression", info.OriginModelName) return hosttypes.PriceData{}, fmt.Errorf("model %s is configured as tiered_expr but has no billing expression", info.OriginModelName)
} }
estimatedCompletionTokens := meta.MaxTokens estimatedCompletionTokens := meta.MaxTokens
@@ -278,7 +279,7 @@ func modelPriceHelperTiered(c *gin.Context, info *relaycommon.RelayInfo, promptT
requestInput, err := ResolveIncomingBillingExprRequestInput(c, info) requestInput, err := ResolveIncomingBillingExprRequestInput(c, info)
if err != nil { if err != nil {
return types.PriceData{}, err return hosttypes.PriceData{}, err
} }
rawCost, trace, err := billingexpr.RunExprWithRequest(exprStr, billingexpr.TokenParams{ rawCost, trace, err := billingexpr.RunExprWithRequest(exprStr, billingexpr.TokenParams{
@@ -287,14 +288,14 @@ func modelPriceHelperTiered(c *gin.Context, info *relaycommon.RelayInfo, promptT
Len: float64(promptTokens), Len: float64(promptTokens),
}, requestInput) }, requestInput)
if err != nil { if err != nil {
return types.PriceData{}, fmt.Errorf("model %s tiered expr run failed: %w", info.OriginModelName, err) return hosttypes.PriceData{}, fmt.Errorf("model %s tiered expr run failed: %w", info.OriginModelName, err)
} }
// Expression coefficients are $/1M tokens prices; convert to quota the same way per-call billing does. // Expression coefficients are $/1M tokens prices; convert to quota the same way per-call billing does.
quotaBeforeGroup := rawCost / 1_000_000 * common.QuotaPerUnit quotaBeforeGroup := rawCost / 1_000_000 * common.QuotaPerUnit
preConsumedQuota, err := billingexpr.QuotaRoundStrict(quotaBeforeGroup * groupRatioInfo.GroupRatio) preConsumedQuota, err := billingexpr.QuotaRoundStrict(quotaBeforeGroup * groupRatioInfo.GroupRatio)
if err != nil { if err != nil {
return types.PriceData{}, err return hosttypes.PriceData{}, err
} }
freeModel := false freeModel := false
@@ -323,7 +324,7 @@ func modelPriceHelperTiered(c *gin.Context, info *relaycommon.RelayInfo, promptT
info.TieredBillingSnapshot = snapshot info.TieredBillingSnapshot = snapshot
info.BillingRequestInput = &requestInput info.BillingRequestInput = &requestInput
priceData := types.PriceData{ priceData := hosttypes.PriceData{
FreeModel: freeModel, FreeModel: freeModel,
GroupRatioInfo: groupRatioInfo, GroupRatioInfo: groupRatioInfo,
QuotaToPreConsume: preConsumedQuota, QuotaToPreConsume: preConsumedQuota,
-1
View File
@@ -5,7 +5,6 @@ go 1.25.1
require ( require (
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/samber/lo v1.53.0 github.com/samber/lo v1.53.0
github.com/shopspring/decimal v1.4.0
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
github.com/tidwall/gjson v1.19.0 github.com/tidwall/gjson v1.19.0
github.com/tidwall/sjson v1.2.5 github.com/tidwall/sjson v1.2.5
-2
View File
@@ -18,8 +18,6 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM= github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+2 -1
View File
@@ -12,6 +12,7 @@ import (
relaycommon "github.com/QuantumNous/new-api/relay/common" relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/dto" "github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/relaykit/types"
hosttypes "github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -289,7 +290,7 @@ func GenerateClaudeOtherInfo(ctx *gin.Context, relayInfo *relaycommon.RelayInfo,
return info return info
} }
func GenerateMjOtherInfo(relayInfo *relaycommon.RelayInfo, priceData types.PriceData) map[string]interface{} { func GenerateMjOtherInfo(relayInfo *relaycommon.RelayInfo, priceData hosttypes.PriceData) map[string]interface{} {
other := make(map[string]interface{}) other := make(map[string]interface{})
other["model_price"] = priceData.ModelPrice other["model_price"] = priceData.ModelPrice
other["group_ratio"] = priceData.GroupRatioInfo.GroupRatio other["group_ratio"] = priceData.GroupRatioInfo.GroupRatio
+1 -1
View File
@@ -15,8 +15,8 @@ import (
perfmetrics "github.com/QuantumNous/new-api/pkg/perf_metrics" perfmetrics "github.com/QuantumNous/new-api/pkg/perf_metrics"
relaycommon "github.com/QuantumNous/new-api/relay/common" relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/dto" "github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/ratio_setting" "github.com/QuantumNous/new-api/setting/ratio_setting"
"github.com/QuantumNous/new-api/types"
"github.com/bytedance/gopkg/util/gopool" "github.com/bytedance/gopkg/util/gopool"
+1 -1
View File
@@ -10,8 +10,8 @@ import (
"github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/logger"
"github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/model"
relaycommon "github.com/QuantumNous/new-api/relay/common" relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/ratio_setting" "github.com/QuantumNous/new-api/setting/ratio_setting"
"github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/model"
relaycommon "github.com/QuantumNous/new-api/relay/common" relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/types"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
+33 -32
View File
@@ -14,6 +14,7 @@ import (
"github.com/QuantumNous/new-api/relaykit/dto" "github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/operation_setting" "github.com/QuantumNous/new-api/setting/operation_setting"
hosttypes "github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
@@ -37,14 +38,14 @@ func TestCalculateTextQuotaSummaryUnifiedForClaudeSemantic(t *testing.T) {
ClaudeCacheCreation1hTokens: 20, ClaudeCacheCreation1hTokens: 20,
} }
priceData := types.PriceData{ priceData := hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 2, CompletionRatio: 2,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
CacheCreation5mRatio: 1.25, CacheCreation5mRatio: 1.25,
CacheCreation1hRatio: 2, CacheCreation1hRatio: 2,
GroupRatioInfo: types.GroupRatioInfo{ GroupRatioInfo: hosttypes.GroupRatioInfo{
GroupRatio: 1, GroupRatio: 1,
}, },
} }
@@ -83,14 +84,14 @@ func TestCalculateTextQuotaSummaryUsesSplitClaudeCacheCreationRatios(t *testing.
RelayFormat: types.RelayFormatOpenAI, RelayFormat: types.RelayFormatOpenAI,
FinalRequestRelayFormat: types.RelayFormatClaude, FinalRequestRelayFormat: types.RelayFormatClaude,
OriginModelName: "claude-3-7-sonnet", OriginModelName: "claude-3-7-sonnet",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
CacheRatio: 0, CacheRatio: 0,
CacheCreationRatio: 1, CacheCreationRatio: 1,
CacheCreation5mRatio: 2, CacheCreation5mRatio: 2,
CacheCreation1hRatio: 3, CacheCreation1hRatio: 3,
GroupRatioInfo: types.GroupRatioInfo{ GroupRatioInfo: hosttypes.GroupRatioInfo{
GroupRatio: 1, GroupRatio: 1,
}, },
}, },
@@ -121,14 +122,14 @@ func TestCalculateTextQuotaSummaryUsesAnthropicUsageSemanticFromUpstreamUsage(t
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
RelayFormat: types.RelayFormatOpenAI, RelayFormat: types.RelayFormatOpenAI,
OriginModelName: "claude-3-7-sonnet", OriginModelName: "claude-3-7-sonnet",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 2, CompletionRatio: 2,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
CacheCreation5mRatio: 1.25, CacheCreation5mRatio: 1.25,
CacheCreation1hRatio: 2, CacheCreation1hRatio: 2,
GroupRatioInfo: types.GroupRatioInfo{ GroupRatioInfo: hosttypes.GroupRatioInfo{
GroupRatio: 1, GroupRatio: 1,
}, },
}, },
@@ -162,14 +163,14 @@ func TestCalculateTextQuotaSummaryUsesClaudeBillingUsageBeforeTopLevelUsage(t *t
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
RelayFormat: types.RelayFormatOpenAI, RelayFormat: types.RelayFormatOpenAI,
OriginModelName: "claude-3-7-sonnet", OriginModelName: "claude-3-7-sonnet",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 2, CompletionRatio: 2,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
CacheCreation5mRatio: 1.25, CacheCreation5mRatio: 1.25,
CacheCreation1hRatio: 2, CacheCreation1hRatio: 2,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -211,11 +212,11 @@ func TestCalculateTextQuotaSummaryUsesGeminiBillingUsageBeforeTopLevelUsage(t *t
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
RelayFormat: types.RelayFormatOpenAI, RelayFormat: types.RelayFormatOpenAI,
OriginModelName: "gemini-2.5-flash", OriginModelName: "gemini-2.5-flash",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 2, CompletionRatio: 2,
CacheRatio: 0.1, CacheRatio: 0.1,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -253,10 +254,10 @@ func TestCalculateTextQuotaSummaryUsesOpenAIBillingUsageBeforeTopLevelUsage(t *t
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
RelayFormat: types.RelayFormatClaude, RelayFormat: types.RelayFormatClaude,
OriginModelName: "gpt-4o", OriginModelName: "gpt-4o",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 2, CompletionRatio: 2,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -352,14 +353,14 @@ func TestCalculateTextQuotaSummaryHandlesLegacyClaudeDerivedOpenAIUsage(t *testi
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
RelayFormat: types.RelayFormatOpenAI, RelayFormat: types.RelayFormatOpenAI,
OriginModelName: "claude-3-7-sonnet", OriginModelName: "claude-3-7-sonnet",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 5, CompletionRatio: 5,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
CacheCreation5mRatio: 1.25, CacheCreation5mRatio: 1.25,
CacheCreation1hRatio: 2, CacheCreation1hRatio: 2,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -387,12 +388,12 @@ func TestCalculateTextQuotaSummaryBillsOpenAICacheWriteTokens(t *testing.T) {
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
RelayFormat: types.RelayFormatOpenAI, RelayFormat: types.RelayFormatOpenAI,
OriginModelName: "gpt-5.1", OriginModelName: "gpt-5.1",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 2, CompletionRatio: 2,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -445,12 +446,12 @@ func TestCalculateTextQuotaSummarySeparatesOpenRouterCacheReadFromPromptBilling(
ChannelMeta: &relaycommon.ChannelMeta{ ChannelMeta: &relaycommon.ChannelMeta{
ChannelType: constant.ChannelTypeOpenRouter, ChannelType: constant.ChannelTypeOpenRouter,
}, },
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -482,11 +483,11 @@ func TestCalculateTextQuotaSummarySeparatesOpenRouterCacheCreationFromPromptBill
ChannelMeta: &relaycommon.ChannelMeta{ ChannelMeta: &relaycommon.ChannelMeta{
ChannelType: constant.ChannelTypeOpenRouter, ChannelType: constant.ChannelTypeOpenRouter,
}, },
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -518,12 +519,12 @@ func TestCalculateTextQuotaSummaryKeepsPrePRClaudeOpenRouterBilling(t *testing.T
ChannelMeta: &relaycommon.ChannelMeta{ ChannelMeta: &relaycommon.ChannelMeta{
ChannelType: constant.ChannelTypeOpenRouter, ChannelType: constant.ChannelTypeOpenRouter,
}, },
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
CacheRatio: 0.1, CacheRatio: 0.1,
CacheCreationRatio: 1.25, CacheCreationRatio: 1.25,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
StartTime: time.Now(), StartTime: time.Now(),
} }
@@ -559,10 +560,10 @@ func TestComposeTieredTextQuotaKeepsToolCallSurcharges(t *testing.T) {
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
OriginModelName: "o1", OriginModelName: "o1",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
ResponsesUsageInfo: &relaycommon.ResponsesUsageInfo{ ResponsesUsageInfo: &relaycommon.ResponsesUsageInfo{
BuiltInTools: map[string]*relaycommon.BuildInToolInfo{ BuiltInTools: map[string]*relaycommon.BuildInToolInfo{
@@ -609,10 +610,10 @@ func TestComposeTieredTextQuotaFallbackKeepsToolCallSurcharges(t *testing.T) {
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
OriginModelName: "claude-3-7-sonnet", OriginModelName: "claude-3-7-sonnet",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1.25}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1.25},
}, },
TieredBillingSnapshot: &billingexpr.BillingSnapshot{ TieredBillingSnapshot: &billingexpr.BillingSnapshot{
BillingMode: "tiered_expr", BillingMode: "tiered_expr",
@@ -643,10 +644,10 @@ func TestComposeTieredTextQuotaErrorFallbackUsesPreConsumedQuota(t *testing.T) {
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
OriginModelName: "claude-3-7-sonnet", OriginModelName: "claude-3-7-sonnet",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1.25}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1.25},
}, },
TieredBillingSnapshot: &billingexpr.BillingSnapshot{ TieredBillingSnapshot: &billingexpr.BillingSnapshot{
BillingMode: "tiered_expr", BillingMode: "tiered_expr",
@@ -726,10 +727,10 @@ func TestTryTieredSettleNoClampInRange(t *testing.T) {
func TestCalculateTextQuotaSummaryFixedPriceAppliesImageCountOnceAndAllowsOverride(t *testing.T) { func TestCalculateTextQuotaSummaryFixedPriceAppliesImageCountOnceAndAllowsOverride(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
ctx, _ := gin.CreateTestContext(httptest.NewRecorder()) ctx, _ := gin.CreateTestContext(httptest.NewRecorder())
priceData := types.PriceData{ priceData := hosttypes.PriceData{
ModelPrice: 0.12, ModelPrice: 0.12,
UsePrice: true, UsePrice: true,
GroupRatioInfo: types.GroupRatioInfo{ GroupRatioInfo: hosttypes.GroupRatioInfo{
GroupRatio: 1, GroupRatio: 1,
}, },
} }
@@ -911,10 +912,10 @@ func TestCalculateTextQuotaSummaryDoesNotApplyRequestMultipliersToToolSurcharge(
relayInfo := &relaycommon.RelayInfo{ relayInfo := &relaycommon.RelayInfo{
OriginModelName: "o1", OriginModelName: "o1",
PriceData: types.PriceData{ PriceData: hosttypes.PriceData{
ModelRatio: 1, ModelRatio: 1,
CompletionRatio: 1, CompletionRatio: 1,
GroupRatioInfo: types.GroupRatioInfo{GroupRatio: 1}, GroupRatioInfo: hosttypes.GroupRatioInfo{GroupRatio: 1},
}, },
ResponsesUsageInfo: &relaycommon.ResponsesUsageInfo{ ResponsesUsageInfo: &relaycommon.ResponsesUsageInfo{
BuiltInTools: map[string]*relaycommon.BuildInToolInfo{ BuiltInTools: map[string]*relaycommon.BuildInToolInfo{
+1 -1
View File
@@ -1,7 +1,7 @@
package ratio_setting package ratio_setting
import ( import (
"github.com/QuantumNous/new-api/relaykit/types" "github.com/QuantumNous/new-api/types"
) )
var defaultCacheRatio = map[string]float64{ var defaultCacheRatio = map[string]float64{
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"errors" "errors"
"github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/config" "github.com/QuantumNous/new-api/setting/config"
"github.com/QuantumNous/new-api/types"
) )
var defaultGroupRatio = map[string]float64{ var defaultGroupRatio = map[string]float64{
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"strings" "strings"
"github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/setting/operation_setting" "github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/QuantumNous/new-api/types"
) )
// from songquanpeng/one-api // from songquanpeng/one-api
@@ -104,8 +104,6 @@ func (p *PriceData) RemoveOtherRatiosFromFloat(value float64) float64 {
} }
func isValidOtherRatio(ratio float64) bool { func isValidOtherRatio(ratio float64) bool {
// NaN/Inf would poison every downstream quota multiplication
// (int(NaN * quota) wraps to a negative charge).
return ratio > 0 && !math.IsInf(ratio, 1) return ratio > 0 && !math.IsInf(ratio, 1)
} }
+5 -8
View File
@@ -3,7 +3,7 @@ package types
import ( import (
"sync" "sync"
kitutil "github.com/QuantumNous/new-api/relaykit/relayconvert/kitutil" "github.com/QuantumNous/new-api/common"
) )
type RWMap[K comparable, V any] struct { type RWMap[K comparable, V any] struct {
@@ -15,13 +15,13 @@ func (m *RWMap[K, V]) UnmarshalJSON(b []byte) error {
m.mutex.Lock() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
m.data = make(map[K]V) m.data = make(map[K]V)
return kitutil.Unmarshal(b, &m.data) return common.Unmarshal(b, &m.data)
} }
func (m *RWMap[K, V]) MarshalJSON() ([]byte, error) { func (m *RWMap[K, V]) MarshalJSON() ([]byte, error) {
m.mutex.RLock() m.mutex.RLock()
defer m.mutex.RUnlock() defer m.mutex.RUnlock()
return kitutil.Marshal(m.data) return common.Marshal(m.data)
} }
func NewRWMap[K comparable, V any]() *RWMap[K, V] { func NewRWMap[K comparable, V any]() *RWMap[K, V] {
@@ -57,7 +57,6 @@ func (m *RWMap[K, V]) Clear() {
m.data = make(map[K]V) m.data = make(map[K]V)
} }
// ReadAll returns a copy of the entire map.
func (m *RWMap[K, V]) ReadAll() map[K]V { func (m *RWMap[K, V]) ReadAll() map[K]V {
m.mutex.RLock() m.mutex.RLock()
defer m.mutex.RUnlock() defer m.mutex.RUnlock()
@@ -78,22 +77,20 @@ func LoadFromJsonString[K comparable, V any](m *RWMap[K, V], jsonStr string) err
m.mutex.Lock() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
m.data = make(map[K]V) m.data = make(map[K]V)
return kitutil.Unmarshal([]byte(jsonStr), &m.data) return common.Unmarshal([]byte(jsonStr), &m.data)
} }
// LoadFromJsonStringWithCallback loads a JSON string into the RWMap and calls the callback on success.
func LoadFromJsonStringWithCallback[K comparable, V any](m *RWMap[K, V], jsonStr string, onSuccess func()) error { func LoadFromJsonStringWithCallback[K comparable, V any](m *RWMap[K, V], jsonStr string, onSuccess func()) error {
m.mutex.Lock() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
m.data = make(map[K]V) m.data = make(map[K]V)
err := kitutil.Unmarshal([]byte(jsonStr), &m.data) err := common.Unmarshal([]byte(jsonStr), &m.data)
if err == nil && onSuccess != nil { if err == nil && onSuccess != nil {
onSuccess() onSuccess()
} }
return err return err
} }
// MarshalJSONString returns the JSON string representation of the RWMap.
func (m *RWMap[K, V]) MarshalJSONString() string { func (m *RWMap[K, V]) MarshalJSONString() string {
bytes, err := m.MarshalJSON() bytes, err := m.MarshalJSON()
if err != nil { if err != nil {
-6
View File
@@ -4,7 +4,6 @@ type Set[T comparable] struct {
items map[T]struct{} items map[T]struct{}
} }
// NewSet 创建并返回一个新的 Set
func NewSet[T comparable]() *Set[T] { func NewSet[T comparable]() *Set[T] {
return &Set[T]{ return &Set[T]{
items: make(map[T]struct{}), items: make(map[T]struct{}),
@@ -15,24 +14,19 @@ func (s *Set[T]) Add(item T) {
s.items[item] = struct{}{} s.items[item] = struct{}{}
} }
// Remove 从 Set 中移除一个元素
func (s *Set[T]) Remove(item T) { func (s *Set[T]) Remove(item T) {
delete(s.items, item) delete(s.items, item)
} }
// Contains 检查 Set 是否包含某个元素
func (s *Set[T]) Contains(item T) bool { func (s *Set[T]) Contains(item T) bool {
_, exists := s.items[item] _, exists := s.items[item]
return exists return exists
} }
// Len 返回 Set 中元素的数量
func (s *Set[T]) Len() int { func (s *Set[T]) Len() int {
return len(s.items) return len(s.items)
} }
// Items 返回 Set 中所有元素组成的切片
// 注意:由于 map 的无序性,返回的切片元素顺序是随机的
func (s *Set[T]) Items() []T { func (s *Set[T]) Items() []T {
items := make([]T, 0, s.Len()) items := make([]T, 0, s.Len())
for item := range s.items { for item := range s.items {