refactor: unify interval filtering and eliminate redundant Resolve calls
- applyRequestTierOverrides now uses filterValidIntervals consistently with applyTokenOverrides (per_request/image modes were not filtering) - CostInput accepts optional pre-resolved pricing via Resolved field, eliminating duplicate Resolver.Resolve() calls in gateway billing paths
This commit is contained in:
@@ -422,6 +422,7 @@ type CostInput struct {
|
|||||||
RateMultiplier float64
|
RateMultiplier float64
|
||||||
ServiceTier string // "priority","flex","" 等
|
ServiceTier string // "priority","flex","" 等
|
||||||
Resolver *ModelPricingResolver // 定价解析器
|
Resolver *ModelPricingResolver // 定价解析器
|
||||||
|
Resolved *ResolvedPricing // 可选:预解析的定价结果(避免重复 Resolve 调用)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalculateCostUnified 统一计费入口,支持三种计费模式。
|
// CalculateCostUnified 统一计费入口,支持三种计费模式。
|
||||||
@@ -432,10 +433,14 @@ func (s *BillingService) CalculateCostUnified(input CostInput) (*CostBreakdown,
|
|||||||
return s.calculateCostInternal(input.Model, input.Tokens, input.RateMultiplier, input.ServiceTier, nil)
|
return s.calculateCostInternal(input.Model, input.Tokens, input.RateMultiplier, input.ServiceTier, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolved := input.Resolver.Resolve(input.Ctx, PricingInput{
|
// 优先使用预解析结果,避免重复 Resolve 调用
|
||||||
Model: input.Model,
|
resolved := input.Resolved
|
||||||
GroupID: input.GroupID,
|
if resolved == nil {
|
||||||
})
|
resolved = input.Resolver.Resolve(input.Ctx, PricingInput{
|
||||||
|
Model: input.Model,
|
||||||
|
GroupID: input.GroupID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if input.RateMultiplier <= 0 {
|
if input.RateMultiplier <= 0 {
|
||||||
input.RateMultiplier = 1.0
|
input.RateMultiplier = 1.0
|
||||||
|
|||||||
@@ -8007,7 +8007,7 @@ func (s *GatewayService) calculateImageCost(
|
|||||||
billingModel string,
|
billingModel string,
|
||||||
multiplier float64,
|
multiplier float64,
|
||||||
) *CostBreakdown {
|
) *CostBreakdown {
|
||||||
if s.resolveChannelPricing(ctx, billingModel, apiKey) != nil {
|
if resolved := s.resolveChannelPricing(ctx, billingModel, apiKey); resolved != nil {
|
||||||
tokens := UsageTokens{
|
tokens := UsageTokens{
|
||||||
InputTokens: result.Usage.InputTokens,
|
InputTokens: result.Usage.InputTokens,
|
||||||
OutputTokens: result.Usage.OutputTokens,
|
OutputTokens: result.Usage.OutputTokens,
|
||||||
@@ -8022,6 +8022,7 @@ func (s *GatewayService) calculateImageCost(
|
|||||||
RequestCount: 1,
|
RequestCount: 1,
|
||||||
RateMultiplier: multiplier,
|
RateMultiplier: multiplier,
|
||||||
Resolver: s.resolver,
|
Resolver: s.resolver,
|
||||||
|
Resolved: resolved,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LegacyPrintf("service.gateway", "Calculate image token cost failed: %v", err)
|
logger.LegacyPrintf("service.gateway", "Calculate image token cost failed: %v", err)
|
||||||
@@ -8064,7 +8065,7 @@ func (s *GatewayService) calculateTokenCost(
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
// 优先尝试渠道定价 → CalculateCostUnified
|
// 优先尝试渠道定价 → CalculateCostUnified
|
||||||
if s.resolveChannelPricing(ctx, billingModel, apiKey) != nil {
|
if resolved := s.resolveChannelPricing(ctx, billingModel, apiKey); resolved != nil {
|
||||||
gid := apiKey.Group.ID
|
gid := apiKey.Group.ID
|
||||||
cost, err = s.billingService.CalculateCostUnified(CostInput{
|
cost, err = s.billingService.CalculateCostUnified(CostInput{
|
||||||
Ctx: ctx,
|
Ctx: ctx,
|
||||||
@@ -8074,6 +8075,7 @@ func (s *GatewayService) calculateTokenCost(
|
|||||||
RequestCount: 1,
|
RequestCount: 1,
|
||||||
RateMultiplier: multiplier,
|
RateMultiplier: multiplier,
|
||||||
Resolver: s.resolver,
|
Resolver: s.resolver,
|
||||||
|
Resolved: resolved,
|
||||||
})
|
})
|
||||||
} else if opts.LongContextThreshold > 0 {
|
} else if opts.LongContextThreshold > 0 {
|
||||||
// 长上下文双倍计费(如 Gemini 200K 阈值)
|
// 长上下文双倍计费(如 Gemini 200K 阈值)
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ func (r *ModelPricingResolver) applyTokenOverrides(chPricing *ChannelModelPricin
|
|||||||
|
|
||||||
// applyRequestTierOverrides 应用按次/图片模式的渠道覆盖
|
// applyRequestTierOverrides 应用按次/图片模式的渠道覆盖
|
||||||
func (r *ModelPricingResolver) applyRequestTierOverrides(chPricing *ChannelModelPricing, resolved *ResolvedPricing) {
|
func (r *ModelPricingResolver) applyRequestTierOverrides(chPricing *ChannelModelPricing, resolved *ResolvedPricing) {
|
||||||
resolved.RequestTiers = chPricing.Intervals
|
resolved.RequestTiers = filterValidIntervals(chPricing.Intervals)
|
||||||
if chPricing.PerRequestPrice != nil {
|
if chPricing.PerRequestPrice != nil {
|
||||||
resolved.DefaultPerRequestPrice = *chPricing.PerRequestPrice
|
resolved.DefaultPerRequestPrice = *chPricing.PerRequestPrice
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user