fix(grok): 完善按模型视频价格矩阵

This commit is contained in:
IanShaw027 committed 2026-08-07 14:42:00 +08:00
1 parent eb2e73df3d
commit 2c8836e40b
10 files changed
+277 -20

No files matched your search

+1 -3
View File
@@ -299,12 +299,10 @@ func ResolveDefaultTextModel(model string, defaultText ...string) string {
func CanonicalImagineVideoModel(model string) string {
m := strings.ToLower(StripGrokProviderPrefix(model))
switch {
case m == "" || m == DefaultImagineVideoModel:
case m == "" || m == DefaultImagineVideoModel || m == "grok-imagine-video-preview":
return DefaultImagineVideoModel
case strings.HasPrefix(m, "grok-imagine-video-1.5") || m == "grok-video-1.5":
return DefaultImagineVideo15Model
case strings.HasPrefix(m, "grok-imagine-video"):
return DefaultImagineVideoModel
default:
return m
}
+1
View File
@@ -44,6 +44,7 @@ func TestCanonicalImagineVideoModel(t *testing.T) {
require.Equal(t, DefaultImagineVideo15Model, CanonicalImagineVideoModel("grok-imagine-video-1.5"))
require.Equal(t, DefaultImagineVideo15Model, CanonicalImagineVideoModel("grok-imagine-video-1.5-preview"))
require.Equal(t, DefaultImagineVideo15Model, CanonicalImagineVideoModel("xai/grok-video-1.5"))
require.Equal(t, "grok-imagine-video-2", CanonicalImagineVideoModel("grok-imagine-video-2"))
}
func TestIsGrokModelID(t *testing.T) {
+10 -16
View File
@@ -18,14 +18,18 @@ func CanonicalGrokImagineVideoPriceFamily(model string) string {
if model == "" {
return ""
}
// Prefer shared xAI helper when available.
// Prefer shared xAI helper for known aliases. Keep future native Imagine
// models distinct so operators can assign them independent prices.
if c := xai.CanonicalImagineVideoModel(model); c != "" {
switch {
case strings.HasPrefix(c, "grok-imagine-video-1.5"):
switch c {
case xai.DefaultImagineVideo15Model:
return VideoPriceFamilyGrokImagineVideo15
case strings.HasPrefix(c, "grok-imagine-video"):
case xai.DefaultImagineVideoModel:
return VideoPriceFamilyGrokImagineVideo
}
if strings.HasPrefix(c, "grok-imagine-video-") {
return c
}
}
m := strings.ToLower(strings.TrimSpace(model))
for _, prefix := range []string{"xai/", "x-ai/", "grok/"} {
@@ -38,8 +42,8 @@ func CanonicalGrokImagineVideoPriceFamily(model string) string {
case m == "grok-imagine-video-1.5" || m == "grok-imagine-video-1.5-preview" ||
m == "grok-video-1.5" || strings.Contains(m, "video-1.5"):
return VideoPriceFamilyGrokImagineVideo15
case m == "grok-imagine-video" || m == "grok-video" || m == "grok-video-latest" ||
strings.HasPrefix(m, "grok-imagine-video") || strings.HasPrefix(m, "grok-video"):
case m == "grok-imagine-video" || m == "grok-imagine-video-preview" ||
m == "grok-video" || m == "grok-video-latest":
return VideoPriceFamilyGrokImagineVideo
default:
return ""
@@ -112,15 +116,5 @@ func LookupVideoModelPrice(prices map[string]map[string]float64, model, resoluti
p := price
return &p
}
for _, candidate := range []string{
VideoBillingResolution1080P,
VideoBillingResolution720P,
VideoBillingResolution480P,
} {
if price, ok := tierPrices[candidate]; ok {
p := price
return &p
}
}
return nil
}
@@ -12,6 +12,8 @@ func TestCanonicalGrokImagineVideoPriceFamily(t *testing.T) {
require.Equal(t, VideoPriceFamilyGrokImagineVideo15, CanonicalGrokImagineVideoPriceFamily("grok-imagine-video-1.5"))
require.Equal(t, VideoPriceFamilyGrokImagineVideo15, CanonicalGrokImagineVideoPriceFamily("grok-imagine-video-1.5-preview"))
require.Equal(t, VideoPriceFamilyGrokImagineVideo15, CanonicalGrokImagineVideoPriceFamily("xai/grok-video-1.5"))
require.Equal(t, "grok-imagine-video-2", CanonicalGrokImagineVideoPriceFamily("grok-imagine-video-2"))
require.Equal(t, "grok-imagine-video-2", CanonicalGrokImagineVideoPriceFamily("xai/grok-imagine-video-2"))
}
func TestNormalizeAndLookupVideoModelPrices(t *testing.T) {
@@ -19,11 +21,13 @@ func TestNormalizeAndLookupVideoModelPrices(t *testing.T) {
raw := map[string]map[string]float64{
"grok-imagine-video-1.5-preview": {"480p": 0.08, "720p": 0.14},
"grok-imagine-video": {"480p": 0.05},
"grok-imagine-video-2": {"1080p": 0.4},
}
norm := NormalizeVideoModelPrices(raw)
require.NotNil(t, norm)
require.Contains(t, norm, VideoPriceFamilyGrokImagineVideo15)
require.Contains(t, norm, VideoPriceFamilyGrokImagineVideo)
require.Contains(t, norm, "grok-imagine-video-2")
p15 := LookupVideoModelPrice(norm, "grok-imagine-video-1.5", "480p")
require.NotNil(t, p15)
@@ -32,7 +36,29 @@ func TestNormalizeAndLookupVideoModelPrices(t *testing.T) {
pBase := LookupVideoModelPrice(norm, "grok-imagine-video", "480p")
require.NotNil(t, pBase)
require.InDelta(t, 0.05, *pBase, 1e-9)
// A missing model-specific tier must fall back to the flat tier price,
// rather than borrowing another model-specific resolution.
require.Nil(t, LookupVideoModelPrice(norm, "grok-imagine-video", "720p"))
p2 := LookupVideoModelPrice(norm, "grok-imagine-video-2", "1080p")
require.NotNil(t, p2)
require.InDelta(t, 0.4, *p2, 1e-9)
// Unmatched model → nil (caller falls back to flat columns / defaults).
require.Nil(t, LookupVideoModelPrice(norm, "unknown-model", "480p"))
}
func TestVideoModelPriceMissingTierFallsBackToFlatTierPrice(t *testing.T) {
t.Parallel()
flat720P := 0.7
service := &BillingService{}
result := service.CalculateVideoCost("grok-imagine-video", "720p", 1, 1, &VideoPriceConfig{
Price720P: &flat720P,
ModelPrices: map[string]map[string]float64{
VideoPriceFamilyGrokImagineVideo: {VideoBillingResolution480P: 0.05},
},
}, 1)
require.InDelta(t, flat720P, result.TotalCost, 1e-9)
}