Skip to content
Open
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
2 changes: 1 addition & 1 deletion common/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var (
ImageGenerationModels = []string{
"dall-e-3",
"dall-e-2",
"gpt-image-1",
"gpt-image-",
"prefix:imagen-",
"flux-",
"flux.1-",
Expand Down
39 changes: 39 additions & 0 deletions common/model_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package common

import (
"testing"

"github.com/QuantumNous/new-api/constant"
"github.com/stretchr/testify/assert"
)

func TestIsImageGenerationModelRecognizesGPTImageFamily(t *testing.T) {
tests := []struct {
name string
modelName string
want bool
}{
{name: "gpt image 1", modelName: "gpt-image-1", want: true},
{name: "gpt image 1 mini", modelName: "gpt-image-1-mini", want: true},
{name: "gpt image 1.5", modelName: "gpt-image-1.5", want: true},
{name: "gpt image 2", modelName: "gpt-image-2", want: true},
{name: "provider-prefixed gpt image 2", modelName: "openai/gpt-image-2", want: true},
{name: "uppercase gpt image 2", modelName: "GPT-IMAGE-2", want: true},
{name: "chat model", modelName: "gpt-5", want: false},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.want, IsImageGenerationModel(test.modelName))
})
}
}

func TestGetEndpointTypesByChannelTypePrioritizesGPTImageGeneration(t *testing.T) {
endpointTypes := GetEndpointTypesByChannelType(constant.ChannelTypeOpenAI, "gpt-image-2")

assert.Equal(t, []constant.EndpointType{
constant.EndpointTypeImageGeneration,
constant.EndpointTypeOpenAI,
}, endpointTypes)
}
3 changes: 3 additions & 0 deletions controller/channel-test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ func normalizeChannelTestEndpoint(channel *model.Channel, modelName, endpointTyp
if normalized != "" {
return normalized
}
if common.IsImageGenerationModel(modelName) {
return string(constant.EndpointTypeImageGeneration)
}
if strings.HasSuffix(modelName, ratio_setting.CompactModelSuffix) {
return string(constant.EndpointTypeOpenAIResponseCompact)
}
Expand Down
24 changes: 24 additions & 0 deletions controller/channel_test_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,30 @@ func TestResolveChannelTestUserIDUsesRequestUser(t *testing.T) {
require.Equal(t, 2, userID)
}

func TestNormalizeChannelTestEndpointDetectsGPTImageGeneration(t *testing.T) {
endpointType := normalizeChannelTestEndpoint(
&model.Channel{Type: constant.ChannelTypeOpenAI},
"gpt-image-2",
"",
)

assert.Equal(t, string(constant.EndpointTypeImageGeneration), endpointType)
request := buildTestRequest("gpt-image-2", endpointType, nil, false)
imageRequest, ok := request.(*dto.ImageRequest)
require.True(t, ok)
assert.Equal(t, "gpt-image-2", imageRequest.Model)
}

func TestNormalizeChannelTestEndpointPreservesExplicitEndpoint(t *testing.T) {
endpointType := normalizeChannelTestEndpoint(
&model.Channel{Type: constant.ChannelTypeOpenAI},
"gpt-image-2",
string(constant.EndpointTypeOpenAI),
)

assert.Equal(t, string(constant.EndpointTypeOpenAI), endpointType)
}

func TestSelectChannelsForAutomaticTestPassiveRecoveryOnlyUsesAutoDisabled(t *testing.T) {
channels := []*model.Channel{
{Id: 1, Status: common.ChannelStatusEnabled},
Expand Down
3 changes: 2 additions & 1 deletion controller/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ func shouldRetry(c *gin.Context, openaiErr *types.NewAPIError, retryTimes int) b
}

func processChannelError(c *gin.Context, channelError types.ChannelError, err *types.NewAPIError) {
logger.LogError(c, fmt.Sprintf("channel error (channel #%d, status code: %d): %s", channelError.ChannelId, err.StatusCode, common.LocalLogPreview(err.Error())))
logger.LogError(c, fmt.Sprintf("channel error (channel #%d,channelName:%s,modelName:%s, status code: %d): %s",
channelError.ChannelId, channelError.ChannelName, c.GetString("original_model"), err.StatusCode, common.LocalLogPreview(err.Error())))
// 不要使用context获取渠道信息,异步处理时可能会出现渠道信息不一致的情况
// do not use context to get channel info, there may be inconsistent channel info when processing asynchronously
if service.ShouldDisableChannel(err) && channelError.AutoBan {
Expand Down
2 changes: 1 addition & 1 deletion model/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ func RecordTopupLog(userId int, content string, callerIp string, paymentMethod s

func RecordErrorLog(c *gin.Context, userId int, channelId int, modelName string, tokenName string, content string, tokenId int, useTimeSeconds int,
isStream bool, group string, other map[string]interface{}) {
logger.LogInfo(c, fmt.Sprintf("record error log: userId=%d, channelId=%d, modelName=%s, tokenName=%s, content=%s", userId, channelId, modelName, tokenName, common.LocalLogPreview(content)))
logger.LogError(c, fmt.Sprintf("record error log: userId=%d,userName=%s, channelId=%d, modelName=%s, tokenName=%s, content=%s", userId, c.GetString("username"), channelId, modelName, tokenName, common.LocalLogPreview(content)))
username := c.GetString("username")
requestId := c.GetString(common.RequestIdKey)
upstreamRequestId := c.GetString(common.UpstreamRequestIdKey)
Expand Down