fix(billing): 修正模型计费配置继承优先级

This commit is contained in:
2026-07-22 00:24:36 +08:00
parent 56d4a3a6b7
commit 6b675c406e
8 changed files with 263 additions and 68 deletions
+34 -23
View File
@@ -7,46 +7,57 @@ import (
)
func (s *Server) platformModelResponse(ctx context.Context, model store.PlatformModel) store.PlatformModel {
return s.platformModelResponseWithRuleSets(model, s.responsePricingRuleSetConfigs(ctx, []store.PlatformModel{model}))
}
func (s *Server) platformModelResponseWithRuleSets(model store.PlatformModel, ruleSetConfigs map[string]map[string]any) store.PlatformModel {
model.Capabilities = store.EffectivePlatformModelCapabilities(model.BaseCapabilities, model.Capabilities)
model.Capabilities = enrichResponseCapabilities(model)
model = s.withEffectiveResponseBillingConfig(ctx, model)
model = withEffectiveResponseBillingConfig(model, ruleSetConfigs)
return store.FilterPlatformModelBillingConfig(model)
}
func (s *Server) platformModelResponses(ctx context.Context, models []store.PlatformModel) []store.PlatformModel {
ruleSetConfigs := s.responsePricingRuleSetConfigs(ctx, models)
items := make([]store.PlatformModel, len(models))
for i, model := range models {
items[i] = s.platformModelResponse(ctx, model)
items[i] = s.platformModelResponseWithRuleSets(model, ruleSetConfigs)
}
return items
}
func (s *Server) withEffectiveResponseBillingConfig(ctx context.Context, model store.PlatformModel) store.PlatformModel {
config := model.BillingConfig
if model.PricingRuleSetID != "" {
if ruleSetConfig, err := s.store.PricingRuleSetBillingConfig(ctx, model.PricingRuleSetID); err == nil && len(ruleSetConfig) > 0 {
config = ruleSetConfig
func (s *Server) responsePricingRuleSetConfigs(ctx context.Context, models []store.PlatformModel) map[string]map[string]any {
configs := map[string]map[string]any{}
if s.store == nil {
return configs
}
ids := map[string]bool{}
for _, model := range models {
for _, id := range []string{firstNonEmpty(model.BasePricingRuleSetID, model.PlatformPricingRuleSetID), model.PricingRuleSetID} {
if id != "" {
ids[id] = true
}
}
}
if len(model.BillingConfigOverride) > 0 {
config = mergeResponseBillingConfig(config, model.BillingConfigOverride)
for id := range ids {
if config, err := s.store.PricingRuleSetBillingConfig(ctx, id); err == nil && len(config) > 0 {
configs[id] = config
}
}
model.BillingConfig = config
return model
return configs
}
func mergeResponseBillingConfig(base map[string]any, override map[string]any) map[string]any {
if len(base) == 0 && len(override) == 0 {
return nil
}
out := make(map[string]any, len(base)+len(override))
for key, value := range base {
out[key] = value
}
for key, value := range override {
out[key] = value
}
return out
func withEffectiveResponseBillingConfig(model store.PlatformModel, ruleSetConfigs map[string]map[string]any) store.PlatformModel {
inheritedRuleSetConfig := ruleSetConfigs[firstNonEmpty(model.BasePricingRuleSetID, model.PlatformPricingRuleSetID)]
modelRuleSetConfig := ruleSetConfigs[model.PricingRuleSetID]
model.BillingConfig = store.ResolveEffectiveBillingConfig(store.EffectiveBillingConfigInput{
BaseConfig: model.BaseBillingConfig,
LegacyPlatformModelConfig: model.BillingConfig,
InheritedRuleSetConfig: inheritedRuleSetConfig,
ModelRuleSetConfig: modelRuleSetConfig,
Override: model.BillingConfigOverride,
})
return model
}
func enrichResponseCapabilities(model store.PlatformModel) map[string]any {
@@ -173,6 +173,41 @@ func TestPlatformModelResponsePreservesTextGenerateFieldsOverFallbacks(t *testin
assertStringListValue(t, textGenerate["thinkingEffortLevels"], []string{"minimal", "low", "medium"})
}
func TestPlatformModelResponseUsesBaseBillingConfigWithoutMaterializedSnapshot(t *testing.T) {
model := store.PlatformModel{
ModelName: "base-priced-model",
ModelType: store.StringList{"video_generate"},
BaseBillingConfig: map[string]any{
"video": map[string]any{"basePrice": float64(416)},
},
}
response := (&Server{}).platformModelResponse(context.Background(), model)
video, ok := response.BillingConfig["video"].(map[string]any)
if !ok || video["basePrice"] != float64(416) {
t.Fatalf("expected base billing price 416, got %#v", response.BillingConfig)
}
}
func TestEffectiveResponseBillingConfigPrefersBaseRuleOverLegacySnapshot(t *testing.T) {
model := store.PlatformModel{
BasePricingRuleSetID: "seedance-pricing",
BillingConfig: map[string]any{
"video": map[string]any{"basePrice": float64(100)},
},
}
response := withEffectiveResponseBillingConfig(model, map[string]map[string]any{
"seedance-pricing": {
"video": map[string]any{"basePrice": float64(416)},
},
})
video, ok := response.BillingConfig["video"].(map[string]any)
if !ok || video["basePrice"] != float64(416) {
t.Fatalf("expected base rule price 416, got %#v", response.BillingConfig)
}
}
func textGenerateCapabilities(t *testing.T, model store.PlatformModel) map[string]any {
t.Helper()
capabilities, ok := model.Capabilities["text_generate"].(map[string]any)