billing_token_cost_request.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package service
  2. import (
  3. "context"
  4. "time"
  5. )
  6. // TokenCostRequest 通用网关 token 计费请求。
  7. type TokenCostRequest struct {
  8. Ctx context.Context
  9. Model string
  10. Group *Group
  11. Tokens UsageTokens
  12. RateMultiplier float64
  13. PricingAt time.Time
  14. ServiceTier string
  15. ReasoningEffort string
  16. Resolver *ModelPricingResolver
  17. // Resolved 为调用方预先解析的定价(Resolver.Resolve 的结果),nil 表示未解析。
  18. Resolved *ResolvedPricing
  19. }
  20. // CalculateTokenCostForRequest 按通用网关的路径选择计算 token 费用:
  21. // 1. 分组/渠道显式定价,或有解析器与分组 → 统一计费
  22. // (区间、分组卡、目录长上下文阶梯均在其中,阶梯由目录数据驱动);
  23. // 2. 否则按模型目录直接计费。
  24. //
  25. // 模型广场的阶梯表查询与网关使用同一入口,保证展示与扣费同源。
  26. func (s *BillingService) CalculateTokenCostForRequest(req TokenCostRequest) (*CostBreakdown, error) {
  27. resolved := req.Resolved
  28. if resolved != nil && (resolved.Source == PricingSourceGlobal || resolved.Source == PricingSourceGroup || resolved.Source == PricingSourceChannel) {
  29. return s.CalculateCostUnified(s.tokenCostInput(req, resolved))
  30. }
  31. if req.Resolver != nil && req.Group != nil {
  32. return s.CalculateCostUnified(s.tokenCostInput(req, resolved))
  33. }
  34. if req.ReasoningEffort != "" {
  35. return s.CalculateCostUnified(s.tokenCostInput(req, resolved))
  36. }
  37. return s.CalculateCost(req.Model, req.Tokens, req.RateMultiplier)
  38. }
  39. func (s *BillingService) tokenCostInput(req TokenCostRequest, resolved *ResolvedPricing) CostInput {
  40. input := CostInput{
  41. Ctx: req.Ctx,
  42. Model: req.Model,
  43. Group: req.Group,
  44. Tokens: req.Tokens,
  45. RequestCount: 1,
  46. RateMultiplier: req.RateMultiplier,
  47. PricingAt: req.PricingAt,
  48. ServiceTier: req.ServiceTier,
  49. ReasoningEffort: req.ReasoningEffort,
  50. Resolver: req.Resolver,
  51. Resolved: resolved,
  52. }
  53. if req.Group != nil {
  54. gid := req.Group.ID
  55. input.GroupID = &gid
  56. }
  57. return input
  58. }