| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- 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
- }
- if g.Platform != PlatformComposite {
- g.AllowMessagesDispatch = false
- }
- g.DefaultMappedModel = ""
- g.MessagesDispatchModelConfig = OpenAIMessagesDispatchModelConfig{}
- }
|