mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-11 14:41:21 +00:00
fix(playground): resolve auto group model listing (#6163)
* fix(playground): resolve auto group model listing - merge and deduplicate available models in configured auto group order. - reuse special usable group rules and add model filtering regression coverage. * refactor: extract GetGroupsEnabledModels to dedupe group model expansion
This commit is contained in:
+1
-13
@@ -245,19 +245,7 @@ func ListModels(c *gin.Context, modelType int) {
|
|||||||
userModelNames = append(userModelNames, allowModel)
|
userModelNames = append(userModelNames, allowModel)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var models []string
|
models := service.GetGroupsEnabledModels(ownerGroups)
|
||||||
if groups.tokenGroup == "auto" {
|
|
||||||
for _, autoGroup := range ownerGroups {
|
|
||||||
groupModels := model.GetGroupEnabledModels(autoGroup)
|
|
||||||
for _, g := range groupModels {
|
|
||||||
if !common.StringsContains(models, g) {
|
|
||||||
models = append(models, g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
models = model.GetGroupEnabledModels(ownerGroups[0])
|
|
||||||
}
|
|
||||||
for _, modelName := range models {
|
for _, modelName := range models {
|
||||||
if !acceptUnsetRatioModel {
|
if !acceptUnsetRatioModel {
|
||||||
if !helper.HasModelBillingConfig(modelName) {
|
if !helper.HasModelBillingConfig(modelName) {
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ import (
|
|||||||
"github.com/QuantumNous/new-api/constant"
|
"github.com/QuantumNous/new-api/constant"
|
||||||
"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/setting"
|
||||||
"github.com/QuantumNous/new-api/setting/config"
|
"github.com/QuantumNous/new-api/setting/config"
|
||||||
"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/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/glebarez/sqlite"
|
"github.com/glebarez/sqlite"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -213,6 +215,56 @@ func TestGetUserModelsFiltersByRequestedGroup(t *testing.T) {
|
|||||||
require.Empty(t, decodeUserModelsResponse(t, vipRecorder))
|
require.Empty(t, decodeUserModelsResponse(t, vipRecorder))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetUserModelsExpandsAutoGroupsInConfiguredOrder(t *testing.T) {
|
||||||
|
originalAutoGroups := setting.AutoGroups2JsonString()
|
||||||
|
originalUsableGroups := setting.UserUsableGroups2JSONString()
|
||||||
|
originalSpecialGroups := ratio_setting.GetGroupRatioSetting().GroupSpecialUsableGroup.ReadAll()
|
||||||
|
t.Cleanup(func() {
|
||||||
|
require.NoError(t, setting.UpdateAutoGroupsByJsonString(originalAutoGroups))
|
||||||
|
require.NoError(t, setting.UpdateUserUsableGroupsByJSONString(originalUsableGroups))
|
||||||
|
specialGroups := ratio_setting.GetGroupRatioSetting().GroupSpecialUsableGroup
|
||||||
|
specialGroups.Clear()
|
||||||
|
specialGroups.AddAll(originalSpecialGroups)
|
||||||
|
})
|
||||||
|
|
||||||
|
require.NoError(t, setting.UpdateAutoGroupsByJsonString(`["vip","default","unavailable"]`))
|
||||||
|
require.NoError(t, setting.UpdateUserUsableGroupsByJSONString(`{"auto":"自动分组","default":"默认分组","unavailable":"不可用分组"}`))
|
||||||
|
specialGroups := ratio_setting.GetGroupRatioSetting().GroupSpecialUsableGroup
|
||||||
|
specialGroups.Clear()
|
||||||
|
specialGroups.Set("default", map[string]string{
|
||||||
|
"+:vip": "VIP 分组",
|
||||||
|
"-:unavailable": "",
|
||||||
|
})
|
||||||
|
|
||||||
|
db := setupModelListControllerTestDB(t)
|
||||||
|
require.NoError(t, db.Create(&model.User{
|
||||||
|
Id: 1003,
|
||||||
|
Username: "playground-auto-model-user",
|
||||||
|
Password: "password",
|
||||||
|
Group: "default",
|
||||||
|
Status: common.UserStatusEnabled,
|
||||||
|
}).Error)
|
||||||
|
require.NoError(t, db.Create(&[]model.Ability{
|
||||||
|
{Group: "vip", Model: "zz-vip-model", ChannelId: 1, Enabled: true},
|
||||||
|
{Group: "vip", Model: "zz-shared-model", ChannelId: 1, Enabled: true},
|
||||||
|
{Group: "default", Model: "zz-default-model", ChannelId: 1, Enabled: true},
|
||||||
|
{Group: "default", Model: "zz-shared-model", ChannelId: 2, Enabled: true},
|
||||||
|
{Group: "unavailable", Model: "zz-unavailable-model", ChannelId: 1, Enabled: true},
|
||||||
|
}).Error)
|
||||||
|
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
context, _ := gin.CreateTestContext(recorder)
|
||||||
|
context.Request = httptest.NewRequest(http.MethodGet, "/api/user/models?group=auto", nil)
|
||||||
|
context.Set("id", 1003)
|
||||||
|
|
||||||
|
GetUserModels(context)
|
||||||
|
|
||||||
|
models := decodeUserModelsResponse(t, recorder)
|
||||||
|
require.Len(t, models, 3)
|
||||||
|
assert.ElementsMatch(t, []string{"zz-vip-model", "zz-shared-model"}, models[:2])
|
||||||
|
assert.Equal(t, "zz-default-model", models[2])
|
||||||
|
}
|
||||||
|
|
||||||
func TestListModelsIncludesTieredBillingModel(t *testing.T) {
|
func TestListModelsIncludesTieredBillingModel(t *testing.T) {
|
||||||
withSelfUseModeDisabled(t)
|
withSelfUseModeDisabled(t)
|
||||||
withTieredBillingConfig(t, map[string]string{
|
withTieredBillingConfig(t, map[string]string{
|
||||||
|
|||||||
+13
-25
@@ -647,38 +647,26 @@ func GetUserModels(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
groups := service.GetUserUsableGroups(user.Group)
|
groups := service.GetUserUsableGroups(user.Group)
|
||||||
group := c.Query("group")
|
group := c.Query("group")
|
||||||
if group != "" {
|
var groupsToQuery []string
|
||||||
if _, ok := groups[group]; !ok {
|
switch {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
case group == "":
|
||||||
"success": true,
|
for g := range groups {
|
||||||
"message": "",
|
groupsToQuery = append(groupsToQuery, g)
|
||||||
"data": []string{},
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
case group == "auto":
|
||||||
c.JSON(http.StatusOK, gin.H{
|
if _, ok := groups[group]; ok {
|
||||||
"success": true,
|
groupsToQuery = service.GetUserAutoGroup(user.Group)
|
||||||
"message": "",
|
}
|
||||||
"data": model.GetGroupEnabledModels(group),
|
default:
|
||||||
})
|
if _, ok := groups[group]; ok {
|
||||||
return
|
groupsToQuery = []string{group}
|
||||||
}
|
|
||||||
|
|
||||||
var models []string
|
|
||||||
for group := range groups {
|
|
||||||
for _, g := range model.GetGroupEnabledModels(group) {
|
|
||||||
if !common.StringsContains(models, g) {
|
|
||||||
models = append(models, g)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
"data": models,
|
"data": service.GetGroupsEnabledModels(groupsToQuery),
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateUser(c *gin.Context) {
|
func UpdateUser(c *gin.Context) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/QuantumNous/new-api/model"
|
||||||
"github.com/QuantumNous/new-api/setting"
|
"github.com/QuantumNous/new-api/setting"
|
||||||
"github.com/QuantumNous/new-api/setting/ratio_setting"
|
"github.com/QuantumNous/new-api/setting/ratio_setting"
|
||||||
)
|
)
|
||||||
@@ -53,6 +54,21 @@ func GetUserAutoGroup(userGroup string) []string {
|
|||||||
return autoGroups
|
return autoGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetGroupsEnabledModels 按 groups 顺序获取各分组启用的模型并去重
|
||||||
|
func GetGroupsEnabledModels(groups []string) []string {
|
||||||
|
seen := make(map[string]struct{})
|
||||||
|
models := make([]string, 0)
|
||||||
|
for _, group := range groups {
|
||||||
|
for _, modelName := range model.GetGroupEnabledModels(group) {
|
||||||
|
if _, ok := seen[modelName]; !ok {
|
||||||
|
seen[modelName] = struct{}{}
|
||||||
|
models = append(models, modelName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return models
|
||||||
|
}
|
||||||
|
|
||||||
// GetUserGroupRatio 获取用户使用某个分组的倍率
|
// GetUserGroupRatio 获取用户使用某个分组的倍率
|
||||||
// userGroup 用户分组
|
// userGroup 用户分组
|
||||||
// group 需要获取倍率的分组
|
// group 需要获取倍率的分组
|
||||||
|
|||||||
Reference in New Issue
Block a user