tiered_billing.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package billing_setting
  2. import (
  3. "fmt"
  4. "github.com/QuantumNous/new-api/pkg/billingexpr"
  5. "github.com/QuantumNous/new-api/setting/config"
  6. )
  7. const (
  8. BillingModeRatio = "ratio"
  9. BillingModeTieredExpr = "tiered_expr"
  10. )
  11. // BillingSetting is managed by config.GlobalConfig.Register.
  12. // DB keys: billing_setting.billing_mode, billing_setting.billing_expr
  13. type BillingSetting struct {
  14. BillingMode map[string]string `json:"billing_mode"`
  15. BillingExpr map[string]string `json:"billing_expr"`
  16. }
  17. var billingSetting = BillingSetting{
  18. BillingMode: make(map[string]string),
  19. BillingExpr: make(map[string]string),
  20. }
  21. func init() {
  22. config.GlobalConfig.Register("billing_setting", &billingSetting)
  23. }
  24. // ---------------------------------------------------------------------------
  25. // Read accessors (hot path, must be fast)
  26. // ---------------------------------------------------------------------------
  27. func GetBillingMode(model string) string {
  28. if mode, ok := billingSetting.BillingMode[model]; ok {
  29. return mode
  30. }
  31. return BillingModeRatio
  32. }
  33. func GetBillingExpr(model string) (string, bool) {
  34. expr, ok := billingSetting.BillingExpr[model]
  35. return expr, ok
  36. }
  37. // ---------------------------------------------------------------------------
  38. // Smoke test (called externally for validation before save)
  39. // ---------------------------------------------------------------------------
  40. func SmokeTestExpr(exprStr string) error {
  41. return smokeTestExpr(exprStr)
  42. }
  43. func smokeTestExpr(exprStr string) error {
  44. vectors := []billingexpr.TokenParams{
  45. {P: 0, C: 0},
  46. {P: 1000, C: 1000},
  47. {P: 100000, C: 100000},
  48. {P: 1000000, C: 1000000},
  49. }
  50. requests := []billingexpr.RequestInput{
  51. {},
  52. {
  53. Headers: map[string]string{
  54. "anthropic-beta": "fast-mode-2026-02-01",
  55. },
  56. Body: []byte(`{"service_tier":"fast","stream_options":{"include_usage":true},"messages":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]}`),
  57. },
  58. }
  59. for _, v := range vectors {
  60. for _, request := range requests {
  61. result, _, err := billingexpr.RunExprWithRequest(exprStr, v, request)
  62. if err != nil {
  63. return fmt.Errorf("vector {p=%g, c=%g}: run failed: %w", v.P, v.C, err)
  64. }
  65. if result < 0 {
  66. return fmt.Errorf("vector {p=%g, c=%g}: result %f < 0", v.P, v.C, result)
  67. }
  68. }
  69. }
  70. return nil
  71. }