refactor: unify interval filtering and eliminate redundant Resolve calls

- applyRequestTierOverrides now uses filterValidIntervals consistently
- CostInput.Resolved allows passing pre-resolved pricing to skip duplicate Resolve
- Gateway billing paths capture resolveChannelPricing result and pass it through
This commit is contained in:
erio
2026-04-04 15:48:12 +08:00
parent 950ac48f9f
commit d1499ee56f
3 changed files with 13 additions and 7 deletions
+8 -4
View File
@@ -422,6 +422,7 @@ type CostInput struct {
RateMultiplier float64
ServiceTier string // "priority","flex","" 等
Resolver *ModelPricingResolver // 定价解析器
Resolved *ResolvedPricing // 可选:已解析的定价,跳过重复 Resolve
}
// CalculateCostUnified 统一计费入口,支持三种计费模式。
@@ -432,10 +433,13 @@ func (s *BillingService) CalculateCostUnified(input CostInput) (*CostBreakdown,
return s.calculateCostInternal(input.Model, input.Tokens, input.RateMultiplier, input.ServiceTier, nil)
}
resolved := input.Resolver.Resolve(input.Ctx, PricingInput{
Model: input.Model,
GroupID: input.GroupID,
})
resolved := input.Resolved
if resolved == nil {
resolved = input.Resolver.Resolve(input.Ctx, PricingInput{
Model: input.Model,
GroupID: input.GroupID,
})
}
if input.RateMultiplier <= 0 {
input.RateMultiplier = 1.0
+4 -2
View File
@@ -8200,7 +8200,7 @@ func (s *GatewayService) calculateImageCost(
billingModel string,
multiplier float64,
) *CostBreakdown {
if s.resolveChannelPricing(ctx, billingModel, apiKey) != nil {
if resolved := s.resolveChannelPricing(ctx, billingModel, apiKey); resolved != nil {
tokens := UsageTokens{
InputTokens: result.Usage.InputTokens,
OutputTokens: result.Usage.OutputTokens,
@@ -8215,6 +8215,7 @@ func (s *GatewayService) calculateImageCost(
RequestCount: 1,
RateMultiplier: multiplier,
Resolver: s.resolver,
Resolved: resolved,
})
if err != nil {
logger.LegacyPrintf("service.gateway", "Calculate image token cost failed: %v", err)
@@ -8257,7 +8258,7 @@ func (s *GatewayService) calculateTokenCost(
var err error
// 优先尝试渠道定价 → CalculateCostUnified
if s.resolveChannelPricing(ctx, billingModel, apiKey) != nil {
if resolved := s.resolveChannelPricing(ctx, billingModel, apiKey); resolved != nil {
gid := apiKey.Group.ID
cost, err = s.billingService.CalculateCostUnified(CostInput{
Ctx: ctx,
@@ -8267,6 +8268,7 @@ func (s *GatewayService) calculateTokenCost(
RequestCount: 1,
RateMultiplier: multiplier,
Resolver: s.resolver,
Resolved: resolved,
})
} else if opts.LongContextThreshold > 0 {
// 长上下文双倍计费(如 Gemini 200K 阈值)
@@ -151,7 +151,7 @@ func (r *ModelPricingResolver) applyTokenOverrides(chPricing *ChannelModelPricin
// applyRequestTierOverrides 应用按次/图片模式的渠道覆盖
func (r *ModelPricingResolver) applyRequestTierOverrides(chPricing *ChannelModelPricing, resolved *ResolvedPricing) {
resolved.RequestTiers = chPricing.Intervals
resolved.RequestTiers = filterValidIntervals(chPricing.Intervals)
if chPricing.PerRequestPrice != nil {
resolved.DefaultPerRequestPrice = *chPricing.PerRequestPrice
}