Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions controller/compact_filter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package controller

import (
"testing"

"github.com/QuantumNous/new-api/model"
"github.com/stretchr/testify/require"
)

func TestFilterPricingHidesCompactModels(t *testing.T) {
pricing := []model.Pricing{
{ModelName: "gpt-5.4", EnableGroup: []string{"default"}},
{ModelName: "gpt-5.4-openai-compact", EnableGroup: []string{"default"}},
{ModelName: "gpt-5.4-mini", EnableGroup: []string{"default"}},
}

filtered := filterPricingByUsableGroups(pricing, map[string]string{"default": "default"})

require.Len(t, filtered, 2)
require.Equal(t, "gpt-5.4", filtered[0].ModelName)
require.Equal(t, "gpt-5.4-mini", filtered[1].ModelName)
}
44 changes: 40 additions & 4 deletions controller/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controller
import (
"fmt"
"net/http"
"strings"
"time"

"github.com/QuantumNous/new-api/common"
Expand All @@ -18,6 +19,7 @@ import (
"github.com/QuantumNous/new-api/relay/helper"
"github.com/QuantumNous/new-api/service"
"github.com/QuantumNous/new-api/setting/operation_setting"
"github.com/QuantumNous/new-api/setting/ratio_setting"
"github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin"
"github.com/samber/lo"
Expand Down Expand Up @@ -132,7 +134,10 @@ func ListModels(c *gin.Context, modelType int) {
} else {
tokenModelLimit = map[string]bool{}
}
for allowModel, _ := range tokenModelLimit {
for allowModel := range tokenModelLimit {
if isCompactModelName(allowModel) {
continue
}
if !acceptUnsetRatioModel {
if !helper.HasModelBillingConfig(allowModel) {
continue
Expand Down Expand Up @@ -180,6 +185,9 @@ func ListModels(c *gin.Context, modelType int) {
models = model.GetGroupEnabledModels(group)
}
for _, modelName := range models {
if isCompactModelName(modelName) {
continue
}
if !acceptUnsetRatioModel {
if !helper.HasModelBillingConfig(modelName) {
continue
Expand Down Expand Up @@ -241,24 +249,52 @@ func ListModels(c *gin.Context, modelType int) {
func ChannelListModels(c *gin.Context) {
c.JSON(200, gin.H{
"success": true,
"data": openAIModels,
"data": filterCompactOpenAIModels(openAIModels),
})
}

func DashboardListModels(c *gin.Context) {
filtered := make(map[int][]string, len(channelId2Models))
for channelId, models := range channelId2Models {
filtered[channelId] = filterCompactModelNames(models)
}
c.JSON(200, gin.H{
"success": true,
"data": channelId2Models,
"data": filtered,
})
}

func EnabledListModels(c *gin.Context) {
c.JSON(200, gin.H{
"success": true,
"data": model.GetEnabledModels(),
"data": filterCompactModelNames(model.GetEnabledModels()),
})
}

func isCompactModelName(modelName string) bool {
return strings.HasSuffix(modelName, ratio_setting.CompactModelSuffix)
}

func filterCompactModelNames(modelNames []string) []string {
filtered := make([]string, 0, len(modelNames))
for _, modelName := range modelNames {
if !isCompactModelName(modelName) {
filtered = append(filtered, modelName)
}
}
return filtered
}

func filterCompactOpenAIModels(models []dto.OpenAIModels) []dto.OpenAIModels {
filtered := make([]dto.OpenAIModels, 0, len(models))
for _, item := range models {
if !isCompactModelName(item.Id) {
filtered = append(filtered, item)
}
}
return filtered
}

func RetrieveModel(c *gin.Context, modelType int) {
modelId := c.Param("model")
if aiModel, ok := openAIModelsMap[modelId]; ok {
Expand Down
3 changes: 3 additions & 0 deletions controller/pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ func filterPricingByUsableGroups(pricing []model.Pricing, usableGroup map[string

filtered := make([]model.Pricing, 0, len(pricing))
for _, item := range pricing {
if isCompactModelName(item.ModelName) {
continue
}
if common.StringsContains(item.EnableGroup, "all") {
filtered = append(filtered, item)
continue
Expand Down
10 changes: 10 additions & 0 deletions setting/ratio_setting/cache_ratio.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ func UpdateCreateCacheRatioByJSONString(jsonStr string) error {
func GetCacheRatio(name string) (float64, bool) {
ratio, ok := cacheRatioMap.Get(name)
if !ok {
if baseModelName, isCompact := CompactBaseModelName(name); isCompact {
if ratio, ok := cacheRatioMap.Get(baseModelName); ok {
return ratio, true
}
}
return 1, false // Default to 1 if not found
}
return ratio, true
Expand All @@ -150,6 +155,11 @@ func GetCacheRatio(name string) (float64, bool) {
func GetCreateCacheRatio(name string) (float64, bool) {
ratio, ok := createCacheRatioMap.Get(name)
if !ok {
if baseModelName, isCompact := CompactBaseModelName(name); isCompact {
if ratio, ok := createCacheRatioMap.Get(baseModelName); ok {
return ratio, true
}
}
return 1.25, false // Default to 1.25 if not found
}
return ratio, true
Expand Down
7 changes: 7 additions & 0 deletions setting/ratio_setting/compact_suffix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import "strings"
const CompactModelSuffix = "-openai-compact"
const CompactWildcardModelKey = "*" + CompactModelSuffix

func CompactBaseModelName(modelName string) (string, bool) {
if !strings.HasSuffix(modelName, CompactModelSuffix) {
return modelName, false
}
return strings.TrimSuffix(modelName, CompactModelSuffix), true
}

func WithCompactModelSuffix(modelName string) string {
if strings.HasSuffix(modelName, CompactModelSuffix) {
return modelName
Expand Down
77 changes: 77 additions & 0 deletions setting/ratio_setting/compact_suffix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ratio_setting

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestCompactModelBillingInheritsBaseModel(t *testing.T) {
restoreRatioSettings(t)

require.NoError(t, UpdateModelPriceByJSONString(`{"gpt-5.4":0.42,"*-openai-compact":9.9}`))
require.NoError(t, UpdateModelRatioByJSONString(`{"gpt-5.4":3.14,"*-openai-compact":8.8}`))
require.NoError(t, UpdateCompletionRatioByJSONString(`{"gpt-5.4":6.28}`))
require.NoError(t, UpdateCacheRatioByJSONString(`{"gpt-5.4":0.5}`))
require.NoError(t, UpdateCreateCacheRatioByJSONString(`{"gpt-5.4":1.5}`))

compact := "gpt-5.4-openai-compact"
price, ok := GetModelPrice(compact, false)
require.True(t, ok)
require.Equal(t, 0.42, price)

ratio, ok, matchName := GetModelRatio(compact)
require.True(t, ok)
require.Equal(t, 3.14, ratio)
require.Equal(t, "gpt-5.4", matchName)

require.Equal(t, 6.28, GetCompletionRatio(compact))

cacheRatio, ok := GetCacheRatio(compact)
require.True(t, ok)
require.Equal(t, 0.5, cacheRatio)

createCacheRatio, ok := GetCreateCacheRatio(compact)
require.True(t, ok)
require.Equal(t, 1.5, createCacheRatio)
}

func TestCompactModelBillingFallsBackToWildcard(t *testing.T) {
restoreRatioSettings(t)

require.NoError(t, UpdateModelPriceByJSONString(`{"*-openai-compact":9.9}`))
require.NoError(t, UpdateModelRatioByJSONString(`{"*-openai-compact":8.8}`))

compact := "gpt-5.4-openai-compact"
price, ok := GetModelPrice(compact, false)
require.True(t, ok)
require.Equal(t, 9.9, price)

ratio, ok, matchName := GetModelRatio(compact)
require.True(t, ok)
require.Equal(t, 8.8, ratio)
require.Equal(t, CompactWildcardModelKey, matchName)
}

func TestWithCompactModelSuffixDoesNotDuplicateSuffix(t *testing.T) {
require.Equal(t, "gpt-5.4-openai-compact", WithCompactModelSuffix("gpt-5.4"))
require.Equal(t, "gpt-5.4-openai-compact", WithCompactModelSuffix("gpt-5.4-openai-compact"))
}

func restoreRatioSettings(t *testing.T) {
t.Helper()

modelPriceJSON := ModelPrice2JSONString()
modelRatioJSON := ModelRatio2JSONString()
completionRatioJSON := CompletionRatio2JSONString()
cacheRatioJSON := CacheRatio2JSONString()
createCacheRatioJSON := CreateCacheRatio2JSONString()

t.Cleanup(func() {
require.NoError(t, UpdateModelPriceByJSONString(modelPriceJSON))
require.NoError(t, UpdateModelRatioByJSONString(modelRatioJSON))
require.NoError(t, UpdateCompletionRatioByJSONString(completionRatioJSON))
require.NoError(t, UpdateCacheRatioByJSONString(cacheRatioJSON))
require.NoError(t, UpdateCreateCacheRatioByJSONString(createCacheRatioJSON))
})
}
26 changes: 23 additions & 3 deletions setting/ratio_setting/model_ratio.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,10 @@ func GetModelPrice(name string, printErr bool) (float64, bool) {
return price, true
}

if strings.HasSuffix(name, CompactModelSuffix) {
if baseModelName, isCompact := CompactBaseModelName(name); isCompact {
if price, ok := modelPriceMap.Get(baseModelName); ok {
return price, true
}
price, ok := modelPriceMap.Get(CompactWildcardModelKey)
if !ok {
if printErr {
Expand Down Expand Up @@ -405,9 +408,12 @@ func GetModelRatio(name string) (float64, bool, string) {

ratio, ok := modelRatioMap.Get(name)
if !ok {
if strings.HasSuffix(name, CompactModelSuffix) {
if baseModelName, isCompact := CompactBaseModelName(name); isCompact {
if baseRatio, ok := modelRatioMap.Get(baseModelName); ok {
return baseRatio, true, baseModelName
}
if wildcardRatio, ok := modelRatioMap.Get(CompactWildcardModelKey); ok {
return wildcardRatio, true, name
return wildcardRatio, true, CompactWildcardModelKey
}
//return 0, true, name
}
Expand Down Expand Up @@ -448,6 +454,11 @@ func GetCompletionRatio(name string) float64 {
return ratio
}
}
if baseModelName, isCompact := CompactBaseModelName(name); isCompact {
if ratio, ok := completionRatioMap.Get(baseModelName); ok {
return ratio
}
}
hardCodedRatio, contain := getHardcodedCompletionModelRatio(name)
if contain {
return hardCodedRatio
Expand Down Expand Up @@ -475,6 +486,15 @@ func GetCompletionRatioInfo(name string) CompletionRatioInfo {
}
}

if baseModelName, isCompact := CompactBaseModelName(name); isCompact {
if ratio, ok := completionRatioMap.Get(baseModelName); ok {
return CompletionRatioInfo{
Ratio: ratio,
Locked: false,
}
}
}

hardCodedRatio, locked := getHardcodedCompletionModelRatio(name)
if locked {
return CompletionRatioInfo{
Expand Down