| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- package service
- import (
- "strings"
- "github.com/Wei-Shaw/sub2api/internal/pkg/openai"
- )
- func lastOpenAIModelSegment(model string) string {
- model = strings.TrimSpace(model)
- if model == "" {
- return ""
- }
- if strings.Contains(model, "/") {
- parts := strings.Split(model, "/")
- model = parts[len(parts)-1]
- }
- return strings.TrimSpace(model)
- }
- func canonicalizeOpenAIModelAliasSpelling(model string) string {
- return openai.CanonicalizeOpenAIModelAliasSpelling(model)
- }
- func normalizeKnownOpenAICodexModel(model string) string {
- normalized := canonicalizeOpenAIModelAliasSpelling(model)
- if normalized == "" {
- return ""
- }
- if mapped := getNormalizedCodexModel(normalized); mapped != "" {
- return mapped
- }
- if strings.HasSuffix(normalized, "-openai-compact") {
- if mapped := getNormalizedCodexModel(strings.TrimSuffix(normalized, "-openai-compact")); mapped != "" {
- return mapped
- }
- }
- switch {
- case normalized == "gpt-6" || normalized == "gpt-6-astra":
- return "gpt-6-astra"
- case strings.Contains(normalized, "gpt-5.6-sol"):
- return "gpt-5.6-sol"
- case strings.Contains(normalized, "gpt-5.6-terra"):
- return "gpt-5.6-terra"
- case strings.Contains(normalized, "gpt-5.6-luna"):
- return "gpt-5.6-luna"
- case normalized == "gpt-5.6":
- return "gpt-5.6-sol"
- case strings.HasPrefix(normalized, "gpt-5.6-"):
- suffix := strings.TrimPrefix(normalized, "gpt-5.6-")
- if suffix == "max" || isKnownCodexModelSuffix(suffix) {
- return "gpt-5.6-sol"
- }
- return ""
- case strings.Contains(normalized, "gpt-5.5-pro"):
- return "gpt-5.5-pro"
- case strings.Contains(normalized, "gpt-5.5"):
- return "gpt-5.5"
- case strings.Contains(normalized, "gpt-5.4-mini"):
- return "gpt-5.4-mini"
- case strings.Contains(normalized, "gpt-5.4-nano"):
- return "gpt-5.4-nano"
- case strings.Contains(normalized, "gpt-5.4"):
- return "gpt-5.4"
- case strings.Contains(normalized, "gpt-5.2"):
- return "gpt-5.2"
- case strings.Contains(normalized, "gpt-5.3-codex-spark"):
- return "gpt-5.3-codex-spark"
- case strings.Contains(normalized, "gpt-5.3-codex"):
- return "gpt-5.3-codex"
- case strings.Contains(normalized, "gpt-5.3"):
- return "gpt-5.3-codex"
- case strings.Contains(normalized, "codex"):
- return "gpt-5.3-codex"
- case strings.Contains(normalized, "gpt-5"):
- return "gpt-5.4"
- default:
- return ""
- }
- }
- // isOpenAIGPT56Model 判断是否 GPT-5.6 系列模型;入参可为原始模型名
- // (含大小写/路径/后缀变体)或已归一化的基名,两者均能正确识别。
- func isOpenAIGPT56Model(model string) bool {
- normalized := canonicalizeOpenAIModelAliasSpelling(model)
- if normalized == "gpt-5.6" {
- return true
- }
- if suffix, ok := strings.CutPrefix(normalized, "gpt-5.6-"); ok && (suffix == "max" || isKnownCodexModelSuffix(suffix)) {
- return true
- }
- for _, prefix := range []string{"gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"} {
- if normalized == prefix || strings.HasPrefix(normalized, prefix+"-") {
- return true
- }
- }
- return false
- }
- // isOpenAIGPT6AstraModel reports GPT-6 Astra and dated/provider-prefixed variants.
- // The public "gpt-6" alias routes to Astra; unrelated GPT-6 families stay excluded.
- func isOpenAIGPT6AstraModel(model string) bool {
- normalized := canonicalizeOpenAIModelAliasSpelling(model)
- return normalized == "gpt-6" || normalized == "gpt-6-astra" || strings.HasPrefix(normalized, "gpt-6-astra-")
- }
- func appendUsageBillingModelCandidate(candidates []string, seen map[string]struct{}, model string) []string {
- trimmed := strings.TrimSpace(model)
- if trimmed == "" {
- return candidates
- }
- add := func(candidate string) {
- candidate = strings.TrimSpace(candidate)
- if candidate == "" {
- return
- }
- key := strings.ToLower(candidate)
- if _, ok := seen[key]; ok {
- return
- }
- seen[key] = struct{}{}
- candidates = append(candidates, candidate)
- }
- add(trimmed)
- if canonical := canonicalizeOpenAIModelAliasSpelling(trimmed); canonical != "" {
- add(canonical)
- }
- if normalized := normalizeKnownOpenAICodexModel(trimmed); normalized != "" {
- add(normalized)
- }
- return candidates
- }
- func usageBillingModelCandidates(primary string, alternates ...string) []string {
- seen := make(map[string]struct{}, 1+len(alternates))
- candidates := appendUsageBillingModelCandidate(nil, seen, primary)
- for _, alternate := range alternates {
- candidates = appendUsageBillingModelCandidate(candidates, seen, alternate)
- }
- return candidates
- }
- func firstUsageBillingModel(candidates []string) string {
- for _, candidate := range candidates {
- if trimmed := strings.TrimSpace(candidate); trimmed != "" {
- return trimmed
- }
- }
- return ""
- }
|