mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
Merge pull request #3587 from alfadb/fix/openai-gpt-55-pro-codex-model
fix(openai): 保留 GPT-5.5 Pro Codex 模型名
This commit is contained in:
@@ -276,8 +276,9 @@ func (s *BillingService) initFallbackPricing() {
|
||||
LongContextInputMultiplier: openAIGPT54LongContextInputMultiplier,
|
||||
LongContextOutputMultiplier: openAIGPT54LongContextOutputMultiplier,
|
||||
}
|
||||
// GPT-5.5 暂无独立定价,回退到 GPT-5.4
|
||||
// GPT-5.5 / GPT-5.5 Pro 暂无独立定价,回退到 GPT-5.4。
|
||||
s.fallbackPrices["gpt-5.5"] = s.fallbackPrices["gpt-5.4"]
|
||||
s.fallbackPrices["gpt-5.5-pro"] = s.fallbackPrices["gpt-5.4"]
|
||||
|
||||
s.fallbackPrices["gpt-5.4-mini"] = &ModelPricing{
|
||||
InputPricePerToken: 7.5e-7,
|
||||
@@ -666,6 +667,8 @@ func (s *BillingService) getFallbackPricing(model string) *ModelPricing {
|
||||
// OpenAI(GPT-5 / Codex 族):仅匹配已知型号,避免未知 OpenAI 型号误计价。
|
||||
if normalized := normalizeKnownOpenAICodexModel(modelLower); normalized != "" {
|
||||
switch normalized {
|
||||
case "gpt-5.5-pro":
|
||||
return s.fallbackPrices["gpt-5.5-pro"]
|
||||
case "gpt-5.5":
|
||||
return s.fallbackPrices["gpt-5.5"]
|
||||
case "gpt-5.4-mini":
|
||||
@@ -1057,7 +1060,7 @@ func isOpenAIGPT54Model(model string) bool {
|
||||
// normalizeCodexModel 的默认兜底把非 OpenAI 模型(claude-*、gemini-*、gpt-4o)
|
||||
// 误识别为 gpt-5.4。
|
||||
normalized := normalizeKnownOpenAICodexModel(model)
|
||||
return normalized == "gpt-5.4" || normalized == "gpt-5.5"
|
||||
return normalized == "gpt-5.4" || normalized == "gpt-5.5" || normalized == "gpt-5.5-pro"
|
||||
}
|
||||
|
||||
// CalculateCostWithConfig 使用配置中的默认倍率计算费用
|
||||
|
||||
@@ -263,6 +263,25 @@ func TestCalculateCost_OpenAIGPT54LongContextAppliesWholeSessionMultipliers(t *t
|
||||
require.InDelta(t, expectedInput+expectedOutput, cost.ActualCost, 1e-10)
|
||||
}
|
||||
|
||||
func TestCalculateCost_OpenAIGPT55ProUsesGPT55PricingPolicy(t *testing.T) {
|
||||
svc := newTestBillingService()
|
||||
|
||||
tokens := UsageTokens{
|
||||
InputTokens: 300000,
|
||||
OutputTokens: 4000,
|
||||
}
|
||||
|
||||
cost, err := svc.CalculateCost("gpt-5.5-pro", tokens, 1.0)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedInput := float64(tokens.InputTokens) * 2.5e-6 * 2.0
|
||||
expectedOutput := float64(tokens.OutputTokens) * 15e-6 * 1.5
|
||||
require.InDelta(t, expectedInput, cost.InputCost, 1e-10)
|
||||
require.InDelta(t, expectedOutput, cost.OutputCost, 1e-10)
|
||||
require.InDelta(t, expectedInput+expectedOutput, cost.TotalCost, 1e-10)
|
||||
require.InDelta(t, expectedInput+expectedOutput, cost.ActualCost, 1e-10)
|
||||
}
|
||||
|
||||
// 回归测试 #2293:长上下文计费触发时,cache_read_tokens 也应应用 LongContextInputMultiplier。
|
||||
// 修复前:CacheReadCost = tokens * 0.25e-6 (漏乘倍率,少计费用)。
|
||||
// 修复后:CacheReadCost = tokens * 0.25e-6 * LongContextInputMultiplier(=2.0)。
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
var codexModelMap = map[string]string{
|
||||
"gpt-5.5": "gpt-5.5",
|
||||
"gpt-5.5-pro": "gpt-5.5-pro",
|
||||
"codex-auto-review": "codex-auto-review",
|
||||
"gpt-5.4": "gpt-5.4",
|
||||
"gpt-5.4-mini": "gpt-5.4-mini",
|
||||
@@ -61,6 +62,7 @@ var codexVersionModelPrefixes = []struct {
|
||||
{prefix: "gpt-5.3-codex", target: "gpt-5.3-codex"},
|
||||
{prefix: "gpt-5.4-mini", target: "gpt-5.4-mini"},
|
||||
{prefix: "gpt-5.4-nano", target: "gpt-5.4-nano"},
|
||||
{prefix: "gpt-5.5-pro", target: "gpt-5.5-pro"},
|
||||
{prefix: "gpt-5.5", target: "gpt-5.5"},
|
||||
{prefix: "gpt-5.4", target: "gpt-5.4"},
|
||||
{prefix: "gpt-5.2", target: "gpt-5.2"},
|
||||
|
||||
@@ -898,6 +898,10 @@ func TestNormalizeCodexModel_Gpt53(t *testing.T) {
|
||||
"gpt-5.4": "gpt-5.4",
|
||||
"gpt5.5": "gpt-5.5",
|
||||
"openai/gpt5.5": "gpt-5.5",
|
||||
"gpt-5.5-pro": "gpt-5.5-pro",
|
||||
"gpt5.5-pro": "gpt-5.5-pro",
|
||||
"openai/gpt5.5-pro": "gpt-5.5-pro",
|
||||
"gpt-5.5-pro-high": "gpt-5.5-pro",
|
||||
"codex-auto-review": "codex-auto-review",
|
||||
"gpt5.4": "gpt-5.4",
|
||||
"gpt-5.4-high": "gpt-5.4",
|
||||
|
||||
@@ -16,6 +16,7 @@ func mustRawJSON(t *testing.T, s string) json.RawMessage {
|
||||
|
||||
func TestShouldAutoInjectPromptCacheKeyForCompat(t *testing.T) {
|
||||
require.True(t, shouldAutoInjectPromptCacheKeyForCompat("gpt-5.5"))
|
||||
require.True(t, shouldAutoInjectPromptCacheKeyForCompat("gpt-5.5-pro"))
|
||||
require.True(t, shouldAutoInjectPromptCacheKeyForCompat("gpt-5.4"))
|
||||
require.True(t, shouldAutoInjectPromptCacheKeyForCompat("gpt-5.4-mini"))
|
||||
require.True(t, shouldAutoInjectPromptCacheKeyForCompat("gpt-5.2"))
|
||||
|
||||
@@ -65,6 +65,8 @@ func normalizeKnownOpenAICodexModel(model string) string {
|
||||
}
|
||||
|
||||
switch {
|
||||
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"):
|
||||
|
||||
@@ -94,6 +94,15 @@ func TestResolveOpenAIForwardModel(t *testing.T) {
|
||||
defaultMappedModel: "gpt-5.4",
|
||||
expectedModel: "gpt-5.5",
|
||||
},
|
||||
{
|
||||
name: "preserves gpt-5.5-pro instead of group default",
|
||||
account: &Account{
|
||||
Credentials: map[string]any{},
|
||||
},
|
||||
requestedModel: "gpt-5.5-pro",
|
||||
defaultMappedModel: "gpt-5.5",
|
||||
expectedModel: "gpt-5.5-pro",
|
||||
},
|
||||
{
|
||||
name: "preserves compact-spelled gpt5.5 instead of group default",
|
||||
account: &Account{
|
||||
@@ -261,6 +270,12 @@ func TestNormalizeOpenAIModelForUpstream(t *testing.T) {
|
||||
model: "gpt-5.4-high",
|
||||
want: "gpt-5.4",
|
||||
},
|
||||
{
|
||||
name: "oauth preserves GPT-5.5 Pro model",
|
||||
account: &Account{Type: AccountTypeOAuth},
|
||||
model: "openai/gpt-5.5-pro",
|
||||
want: "gpt-5.5-pro",
|
||||
},
|
||||
{
|
||||
name: "oauth preserves codex auto review model",
|
||||
account: &Account{Type: AccountTypeOAuth},
|
||||
@@ -303,3 +318,17 @@ func TestUsageBillingModelCandidatesPreserveCodexAutoReviewModel(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsageBillingModelCandidatesPreserveGPT55ProModel(t *testing.T) {
|
||||
candidates := usageBillingModelCandidates("openai/gpt-5.5-pro")
|
||||
|
||||
expected := []string{"openai/gpt-5.5-pro", "gpt-5.5-pro"}
|
||||
if len(candidates) != len(expected) {
|
||||
t.Fatalf("usageBillingModelCandidates(openai/gpt-5.5-pro) = %#v, want %#v", candidates, expected)
|
||||
}
|
||||
for i := range expected {
|
||||
if candidates[i] != expected[i] {
|
||||
t.Fatalf("usageBillingModelCandidates(openai/gpt-5.5-pro) = %#v, want %#v", candidates, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user