Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultOpenAIMessagesDispatchOpusMappedModel = "gpt-5.4"
|
||||
defaultOpenAIMessagesDispatchSonnetMappedModel = "gpt-5.3-codex"
|
||||
defaultOpenAIMessagesDispatchHaikuMappedModel = "gpt-5.4-mini"
|
||||
)
|
||||
|
||||
func normalizeOpenAIMessagesDispatchMappedModel(model string) string {
|
||||
model = NormalizeOpenAICompatRequestedModel(strings.TrimSpace(model))
|
||||
return strings.TrimSpace(model)
|
||||
}
|
||||
|
||||
func normalizeOpenAIMessagesDispatchModelConfig(cfg OpenAIMessagesDispatchModelConfig) OpenAIMessagesDispatchModelConfig {
|
||||
out := OpenAIMessagesDispatchModelConfig{
|
||||
OpusMappedModel: normalizeOpenAIMessagesDispatchMappedModel(cfg.OpusMappedModel),
|
||||
SonnetMappedModel: normalizeOpenAIMessagesDispatchMappedModel(cfg.SonnetMappedModel),
|
||||
HaikuMappedModel: normalizeOpenAIMessagesDispatchMappedModel(cfg.HaikuMappedModel),
|
||||
}
|
||||
|
||||
if len(cfg.ExactModelMappings) > 0 {
|
||||
out.ExactModelMappings = make(map[string]string, len(cfg.ExactModelMappings))
|
||||
for requestedModel, mappedModel := range cfg.ExactModelMappings {
|
||||
requestedModel = strings.TrimSpace(requestedModel)
|
||||
mappedModel = normalizeOpenAIMessagesDispatchMappedModel(mappedModel)
|
||||
if requestedModel == "" || mappedModel == "" {
|
||||
continue
|
||||
}
|
||||
out.ExactModelMappings[requestedModel] = mappedModel
|
||||
}
|
||||
if len(out.ExactModelMappings) == 0 {
|
||||
out.ExactModelMappings = nil
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func claudeMessagesDispatchFamily(model string) string {
|
||||
normalized := strings.ToLower(strings.TrimSpace(model))
|
||||
if !strings.HasPrefix(normalized, "claude") {
|
||||
return ""
|
||||
}
|
||||
switch {
|
||||
case strings.Contains(normalized, "opus"):
|
||||
return "opus"
|
||||
case strings.Contains(normalized, "sonnet"):
|
||||
return "sonnet"
|
||||
case strings.Contains(normalized, "haiku"):
|
||||
return "haiku"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Group) ResolveMessagesDispatchModel(requestedModel string) string {
|
||||
if g == nil {
|
||||
return ""
|
||||
}
|
||||
requestedModel = strings.TrimSpace(requestedModel)
|
||||
if requestedModel == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
if g.Platform == PlatformGrok {
|
||||
if claudeMessagesDispatchFamily(requestedModel) == "" {
|
||||
return ""
|
||||
}
|
||||
opts := xai.RuntimeModelMappingOptions()
|
||||
if !opts.EnableCrossClientMap {
|
||||
return ""
|
||||
}
|
||||
return xai.ModelMappingWithOptions(opts)["claude-*"]
|
||||
}
|
||||
|
||||
// 国产供应商分组:调度级模型映射不适用(其配置被 sanitize 置空,且下方的
|
||||
// gpt-5.x 默认值是 openai 专属,发给 CN 上游必错)。模型改写完全交给账号级
|
||||
// model_mapping;anthropic 协议上游本身接受 claude-* 模型名。
|
||||
if IsCNProvider(g.Platform) {
|
||||
return ""
|
||||
}
|
||||
|
||||
cfg := normalizeOpenAIMessagesDispatchModelConfig(g.MessagesDispatchModelConfig)
|
||||
if mappedModel := strings.TrimSpace(cfg.ExactModelMappings[requestedModel]); mappedModel != "" {
|
||||
return mappedModel
|
||||
}
|
||||
|
||||
switch claudeMessagesDispatchFamily(requestedModel) {
|
||||
case "opus":
|
||||
if mappedModel := strings.TrimSpace(cfg.OpusMappedModel); mappedModel != "" {
|
||||
return mappedModel
|
||||
}
|
||||
return defaultOpenAIMessagesDispatchOpusMappedModel
|
||||
case "sonnet":
|
||||
if mappedModel := strings.TrimSpace(cfg.SonnetMappedModel); mappedModel != "" {
|
||||
return mappedModel
|
||||
}
|
||||
return defaultOpenAIMessagesDispatchSonnetMappedModel
|
||||
case "haiku":
|
||||
if mappedModel := strings.TrimSpace(cfg.HaikuMappedModel); mappedModel != "" {
|
||||
return mappedModel
|
||||
}
|
||||
return defaultOpenAIMessagesDispatchHaikuMappedModel
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeGroupMessagesDispatchFields(g *Group) {
|
||||
if g == nil || g.Platform == PlatformOpenAI {
|
||||
return
|
||||
}
|
||||
g.AllowMessagesDispatch = false
|
||||
g.DefaultMappedModel = ""
|
||||
g.MessagesDispatchModelConfig = OpenAIMessagesDispatchModelConfig{}
|
||||
}
|
||||
Reference in New Issue
Block a user