mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-11 14:41:21 +00:00
refactor(responses): remove compact model suffix handling (#6770)
This commit is contained in:
+1
-1
@@ -88,7 +88,7 @@ func ChannelType2APIType(channelType int) (int, bool) {
|
|||||||
return apiType, true
|
return apiType, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsResponsesCompactAPIType(apiType int) bool {
|
func SupportsResponsesCompact(channelType, apiType int) bool {
|
||||||
switch apiType {
|
switch apiType {
|
||||||
case constant.APITypeOpenAI,
|
case constant.APITypeOpenAI,
|
||||||
constant.APITypeCodex,
|
constant.APITypeCodex,
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import (
|
|||||||
"github.com/QuantumNous/new-api/relaykit/types"
|
"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/setting/ratio_setting"
|
|
||||||
hosttypes "github.com/QuantumNous/new-api/types"
|
hosttypes "github.com/QuantumNous/new-api/types"
|
||||||
|
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
@@ -42,14 +41,11 @@ type testResult struct {
|
|||||||
newAPIError *types.NewAPIError
|
newAPIError *types.NewAPIError
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeChannelTestEndpoint(channel *model.Channel, modelName, endpointType string) string {
|
func normalizeChannelTestEndpoint(channel *model.Channel, endpointType string) string {
|
||||||
normalized := strings.TrimSpace(endpointType)
|
normalized := strings.TrimSpace(endpointType)
|
||||||
if normalized != "" {
|
if normalized != "" {
|
||||||
return normalized
|
return normalized
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(modelName, ratio_setting.CompactModelSuffix) {
|
|
||||||
return string(constant.EndpointTypeOpenAIResponseCompact)
|
|
||||||
}
|
|
||||||
if channel != nil && channel.Type == constant.ChannelTypeCodex {
|
if channel != nil && channel.Type == constant.ChannelTypeCodex {
|
||||||
return string(constant.EndpointTypeOpenAIResponse)
|
return string(constant.EndpointTypeOpenAIResponse)
|
||||||
}
|
}
|
||||||
@@ -111,7 +107,7 @@ func testChannel(ctx context.Context, channel *model.Channel, testUserID int, te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointType = normalizeChannelTestEndpoint(channel, testModel, endpointType)
|
endpointType = normalizeChannelTestEndpoint(channel, endpointType)
|
||||||
|
|
||||||
requestPath := "/v1/chat/completions"
|
requestPath := "/v1/chat/completions"
|
||||||
|
|
||||||
@@ -146,20 +142,12 @@ func testChannel(ctx context.Context, channel *model.Channel, testUserID int, te
|
|||||||
requestPath = "/v1/responses"
|
requestPath = "/v1/responses"
|
||||||
}
|
}
|
||||||
|
|
||||||
// responses compaction models (must use /v1/responses/compact)
|
|
||||||
if strings.HasSuffix(testModel, ratio_setting.CompactModelSuffix) {
|
|
||||||
requestPath = "/v1/responses/compact"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Gemini 原生流式通过 URL action(:streamGenerateContent)表达而非请求体字段,
|
// Gemini 原生流式通过 URL action(:streamGenerateContent)表达而非请求体字段,
|
||||||
// GeminiChatRequest.IsStream 依据请求 URL 判定,合成请求路径需与生产入口保持一致
|
// GeminiChatRequest.IsStream 依据请求 URL 判定,合成请求路径需与生产入口保持一致
|
||||||
if isStream && constant.EndpointType(endpointType) == constant.EndpointTypeGemini {
|
if isStream && constant.EndpointType(endpointType) == constant.EndpointTypeGemini {
|
||||||
requestPath = strings.Replace(requestPath, ":generateContent", ":streamGenerateContent", 1)
|
requestPath = strings.Replace(requestPath, ":generateContent", ":streamGenerateContent", 1)
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(requestPath, "/v1/responses/compact") {
|
|
||||||
testModel = ratio_setting.WithCompactModelSuffix(testModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Request = httptest.NewRequestWithContext(ctx, http.MethodPost, requestPath, nil)
|
c.Request = httptest.NewRequestWithContext(ctx, http.MethodPost, requestPath, nil)
|
||||||
|
|
||||||
cache, err := model.GetUserCache(testUserID)
|
cache, err := model.GetUserCache(testUserID)
|
||||||
@@ -277,7 +265,7 @@ func testChannel(ctx context.Context, channel *model.Channel, testUserID int, te
|
|||||||
|
|
||||||
apiType, _ := common.ChannelType2APIType(channel.Type)
|
apiType, _ := common.ChannelType2APIType(channel.Type)
|
||||||
if info.RelayMode == relayconstant.RelayModeResponsesCompact &&
|
if info.RelayMode == relayconstant.RelayModeResponsesCompact &&
|
||||||
!common.IsResponsesCompactAPIType(apiType) {
|
!common.SupportsResponsesCompact(channel.Type, apiType) {
|
||||||
return testResult{
|
return testResult{
|
||||||
context: c,
|
context: c,
|
||||||
localErr: fmt.Errorf("responses compaction test is not supported for api type %d", apiType),
|
localErr: fmt.Errorf("responses compaction test is not supported for api type %d", apiType),
|
||||||
@@ -806,14 +794,6 @@ func buildTestRequest(model string, endpointType string, channel *model.Channel,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Responses compaction models (must use /v1/responses/compact)
|
|
||||||
if strings.HasSuffix(model, ratio_setting.CompactModelSuffix) {
|
|
||||||
return &dto.OpenAIResponsesCompactionRequest{
|
|
||||||
Model: model,
|
|
||||||
Input: testResponsesInput,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Responses-only models (e.g. codex series)
|
// Responses-only models (e.g. codex series)
|
||||||
if strings.Contains(strings.ToLower(model), "codex") {
|
if strings.Contains(strings.ToLower(model), "codex") {
|
||||||
return &dto.OpenAIResponsesRequest{
|
return &dto.OpenAIResponsesRequest{
|
||||||
|
|||||||
@@ -95,23 +95,25 @@ func TestNewAPIChannelRegistration(t *testing.T) {
|
|||||||
assert.Empty(t, constant.ChannelBaseURLs[constant.ChannelTypeNewAPI])
|
assert.Empty(t, constant.ChannelBaseURLs[constant.ChannelTypeNewAPI])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponsesCompactAPITypeSupport(t *testing.T) {
|
func TestResponsesCompactChannelSupport(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
apiType int
|
channelType int
|
||||||
want bool
|
apiType int
|
||||||
|
want bool
|
||||||
}{
|
}{
|
||||||
{name: "OpenAI", apiType: constant.APITypeOpenAI, want: true},
|
{name: "OpenAI", channelType: constant.ChannelTypeOpenAI, apiType: constant.APITypeOpenAI, want: true},
|
||||||
{name: "Codex", apiType: constant.APITypeCodex, want: true},
|
{name: "Azure", channelType: constant.ChannelTypeAzure, apiType: constant.APITypeOpenAI, want: true},
|
||||||
{name: "Advanced Custom", apiType: constant.APITypeAdvancedCustom, want: true},
|
{name: "Codex", channelType: constant.ChannelTypeCodex, apiType: constant.APITypeCodex, want: true},
|
||||||
{name: "Sub2API", apiType: constant.APITypeSub2API, want: true},
|
{name: "Advanced Custom", channelType: constant.ChannelTypeAdvancedCustom, apiType: constant.APITypeAdvancedCustom, want: true},
|
||||||
{name: "New API", apiType: constant.APITypeNewAPI, want: true},
|
{name: "Sub2API", channelType: constant.ChannelTypeSub2API, apiType: constant.APITypeSub2API, want: true},
|
||||||
{name: "Anthropic", apiType: constant.APITypeAnthropic, want: false},
|
{name: "New API", channelType: constant.ChannelTypeNewAPI, apiType: constant.APITypeNewAPI, want: true},
|
||||||
|
{name: "Anthropic", channelType: constant.ChannelTypeAnthropic, apiType: constant.APITypeAnthropic, want: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
assert.Equal(t, test.want, common.IsResponsesCompactAPIType(test.apiType))
|
assert.Equal(t, test.want, common.SupportsResponsesCompact(test.channelType, test.apiType))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -410,9 +410,6 @@ func getModelRequest(c *gin.Context) (*ModelRequest, bool, error) {
|
|||||||
common.SetContextKey(c, constant.ContextKeyTokenGroup, modelRequest.Group)
|
common.SetContextKey(c, constant.ContextKeyTokenGroup, modelRequest.Group)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(c.Request.URL.Path, "/v1/responses/compact") && modelRequest.Model != "" {
|
|
||||||
modelRequest.Model = ratio_setting.WithCompactModelSuffix(modelRequest.Model)
|
|
||||||
}
|
|
||||||
return &modelRequest, shouldSelectChannel, nil
|
return &modelRequest, shouldSelectChannel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
package codex
|
package codex
|
||||||
|
|
||||||
import (
|
var ModelList = []string{
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/QuantumNous/new-api/setting/ratio_setting"
|
|
||||||
)
|
|
||||||
|
|
||||||
var baseModelList = []string{
|
|
||||||
"gpt-5.6-sol",
|
"gpt-5.6-sol",
|
||||||
"gpt-5.6-terra",
|
"gpt-5.6-terra",
|
||||||
"gpt-5.6-luna",
|
"gpt-5.6-luna",
|
||||||
@@ -17,11 +11,4 @@ var baseModelList = []string{
|
|||||||
"codex-auto-review",
|
"codex-auto-review",
|
||||||
}
|
}
|
||||||
|
|
||||||
var ModelList = slices.DeleteFunc(
|
|
||||||
ratio_setting.WithCompactModelVariants(baseModelList),
|
|
||||||
func(modelName string) bool {
|
|
||||||
return modelName == ratio_setting.WithCompactModelSuffix("codex-auto-review")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const ChannelName = "codex"
|
const ChannelName = "codex"
|
||||||
|
|||||||
@@ -4,12 +4,9 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/QuantumNous/new-api/relay/common"
|
"github.com/QuantumNous/new-api/relay/common"
|
||||||
relayconstant "github.com/QuantumNous/new-api/relay/constant"
|
|
||||||
"github.com/QuantumNous/new-api/relaykit/dto"
|
"github.com/QuantumNous/new-api/relaykit/dto"
|
||||||
"github.com/QuantumNous/new-api/setting/ratio_setting"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,13 +15,6 @@ func ModelMappedHelper(c *gin.Context, info *common.RelayInfo, request dto.Reque
|
|||||||
info.ChannelMeta = &common.ChannelMeta{}
|
info.ChannelMeta = &common.ChannelMeta{}
|
||||||
}
|
}
|
||||||
|
|
||||||
isResponsesCompact := info.RelayMode == relayconstant.RelayModeResponsesCompact
|
|
||||||
originModelName := info.OriginModelName
|
|
||||||
mappingModelName := originModelName
|
|
||||||
if isResponsesCompact && strings.HasSuffix(originModelName, ratio_setting.CompactModelSuffix) {
|
|
||||||
mappingModelName = strings.TrimSuffix(originModelName, ratio_setting.CompactModelSuffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// map model name
|
// map model name
|
||||||
modelMapping := c.GetString("model_mapping")
|
modelMapping := c.GetString("model_mapping")
|
||||||
if modelMapping != "" && modelMapping != "{}" {
|
if modelMapping != "" && modelMapping != "{}" {
|
||||||
@@ -35,7 +25,7 @@ func ModelMappedHelper(c *gin.Context, info *common.RelayInfo, request dto.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 支持链式模型重定向,最终使用链尾的模型
|
// 支持链式模型重定向,最终使用链尾的模型
|
||||||
currentModel := mappingModelName
|
currentModel := info.OriginModelName
|
||||||
visitedModels := map[string]bool{
|
visitedModels := map[string]bool{
|
||||||
currentModel: true,
|
currentModel: true,
|
||||||
}
|
}
|
||||||
@@ -66,14 +56,6 @@ func ModelMappedHelper(c *gin.Context, info *common.RelayInfo, request dto.Reque
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isResponsesCompact {
|
|
||||||
finalUpstreamModelName := mappingModelName
|
|
||||||
if info.IsModelMapped && info.UpstreamModelName != "" {
|
|
||||||
finalUpstreamModelName = info.UpstreamModelName
|
|
||||||
}
|
|
||||||
info.UpstreamModelName = finalUpstreamModelName
|
|
||||||
info.OriginModelName = ratio_setting.WithCompactModelSuffix(finalUpstreamModelName)
|
|
||||||
}
|
|
||||||
if request != nil {
|
if request != nil {
|
||||||
request.SetModelName(info.UpstreamModelName)
|
request.SetModelName(info.UpstreamModelName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
func ResponsesHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *types.NewAPIError) {
|
func ResponsesHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *types.NewAPIError) {
|
||||||
info.InitChannelMeta(c)
|
info.InitChannelMeta(c)
|
||||||
if info.RelayMode == relayconstant.RelayModeResponsesCompact &&
|
if info.RelayMode == relayconstant.RelayModeResponsesCompact &&
|
||||||
!common.IsResponsesCompactAPIType(info.ApiType) {
|
!common.SupportsResponsesCompact(info.ChannelType, info.ApiType) {
|
||||||
return types.NewErrorWithStatusCode(
|
return types.NewErrorWithStatusCode(
|
||||||
fmt.Errorf("unsupported endpoint %q for api type %d", "/v1/responses/compact", info.ApiType),
|
fmt.Errorf("unsupported endpoint %q for api type %d", "/v1/responses/compact", info.ApiType),
|
||||||
types.ErrorCodeInvalidRequest,
|
types.ErrorCodeInvalidRequest,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"github.com/QuantumNous/new-api/constant"
|
"github.com/QuantumNous/new-api/constant"
|
||||||
"github.com/QuantumNous/new-api/model"
|
"github.com/QuantumNous/new-api/model"
|
||||||
"github.com/QuantumNous/new-api/setting/ratio_setting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func FetchCodexChannelModels(channel *model.Channel) ([]string, error) {
|
func FetchCodexChannelModels(channel *model.Channel) ([]string, error) {
|
||||||
@@ -78,13 +77,5 @@ func fetchCodexChannelModels(
|
|||||||
if statusCode < http.StatusOK || statusCode >= http.StatusMultipleChoices {
|
if statusCode < http.StatusOK || statusCode >= http.StatusMultipleChoices {
|
||||||
return nil, fmt.Errorf("upstream status: %d", statusCode)
|
return nil, fmt.Errorf("upstream status: %d", statusCode)
|
||||||
}
|
}
|
||||||
modelVariants := make([]string, 0, len(models)*2)
|
return models, nil
|
||||||
modelVariants = append(modelVariants, models...)
|
|
||||||
for _, modelName := range models {
|
|
||||||
if modelName == "codex-auto-review" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
modelVariants = append(modelVariants, ratio_setting.WithCompactModelSuffix(modelName))
|
|
||||||
}
|
|
||||||
return modelVariants, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
package ratio_setting
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
const CompactModelSuffix = "-openai-compact"
|
|
||||||
const CompactWildcardModelKey = "*" + CompactModelSuffix
|
|
||||||
|
|
||||||
func WithCompactModelSuffix(modelName string) string {
|
|
||||||
if strings.HasSuffix(modelName, CompactModelSuffix) {
|
|
||||||
return modelName
|
|
||||||
}
|
|
||||||
return modelName + CompactModelSuffix
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithCompactModelVariants(models []string) []string {
|
|
||||||
variants := make([]string, 0, len(models)*2)
|
|
||||||
seen := make(map[string]struct{}, len(models)*2)
|
|
||||||
for _, model := range models {
|
|
||||||
if _, ok := seen[model]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
seen[model] = struct{}{}
|
|
||||||
variants = append(variants, model)
|
|
||||||
}
|
|
||||||
for _, model := range models {
|
|
||||||
compactModel := WithCompactModelSuffix(model)
|
|
||||||
if _, ok := seen[compactModel]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
seen[compactModel] = struct{}{}
|
|
||||||
variants = append(variants, compactModel)
|
|
||||||
}
|
|
||||||
return variants
|
|
||||||
}
|
|
||||||
@@ -364,17 +364,6 @@ func GetModelPrice(name string, printErr bool) (float64, bool) {
|
|||||||
return price, true
|
return price, true
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasSuffix(name, CompactModelSuffix) {
|
|
||||||
price, ok := modelPriceMap.Get(CompactWildcardModelKey)
|
|
||||||
if !ok {
|
|
||||||
if printErr {
|
|
||||||
common.SysError("model price not found: " + name)
|
|
||||||
}
|
|
||||||
return -1, false
|
|
||||||
}
|
|
||||||
return price, true
|
|
||||||
}
|
|
||||||
|
|
||||||
if printErr {
|
if printErr {
|
||||||
common.SysError("model price not found: " + name)
|
common.SysError("model price not found: " + name)
|
||||||
}
|
}
|
||||||
@@ -398,12 +387,6 @@ func GetModelRatio(name string) (float64, bool, string) {
|
|||||||
|
|
||||||
ratio, ok := modelRatioMap.Get(name)
|
ratio, ok := modelRatioMap.Get(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
if strings.HasSuffix(name, CompactModelSuffix) {
|
|
||||||
if wildcardRatio, ok := modelRatioMap.Get(CompactWildcardModelKey); ok {
|
|
||||||
return wildcardRatio, true, name
|
|
||||||
}
|
|
||||||
//return 0, true, name
|
|
||||||
}
|
|
||||||
return 37.5, operation_setting.SelfUseModeEnabled, name
|
return 37.5, operation_setting.SelfUseModeEnabled, name
|
||||||
}
|
}
|
||||||
return ratio, true, name
|
return ratio, true, name
|
||||||
|
|||||||
Reference in New Issue
Block a user