082_refactor_channel_pricing.sql 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. -- Extend channel_model_pricing with billing_mode and add context-interval child table.
  2. -- Supports three billing modes: token (per-token with context intervals),
  3. -- per_request (per-request with context-size tiers), and image (per-image).
  4. SET LOCAL lock_timeout = '5s';
  5. SET LOCAL statement_timeout = '10min';
  6. -- 1. 为 channel_model_pricing 添加 billing_mode 列
  7. ALTER TABLE channel_model_pricing
  8. ADD COLUMN IF NOT EXISTS billing_mode VARCHAR(20) NOT NULL DEFAULT 'token';
  9. COMMENT ON COLUMN channel_model_pricing.billing_mode IS '计费模式:token(按 token 区间计费)、per_request(按次计费)、image(图片计费)';
  10. -- 2. 创建区间定价子表
  11. CREATE TABLE IF NOT EXISTS channel_pricing_intervals (
  12. id BIGSERIAL PRIMARY KEY,
  13. pricing_id BIGINT NOT NULL REFERENCES channel_model_pricing(id) ON DELETE CASCADE,
  14. min_tokens INT NOT NULL DEFAULT 0,
  15. max_tokens INT,
  16. tier_label VARCHAR(50),
  17. input_price NUMERIC(20,12),
  18. output_price NUMERIC(20,12),
  19. cache_write_price NUMERIC(20,12),
  20. cache_read_price NUMERIC(20,12),
  21. per_request_price NUMERIC(20,12),
  22. sort_order INT NOT NULL DEFAULT 0,
  23. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  24. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  25. );
  26. CREATE INDEX IF NOT EXISTS idx_channel_pricing_intervals_pricing_id
  27. ON channel_pricing_intervals (pricing_id);
  28. COMMENT ON TABLE channel_pricing_intervals IS '渠道定价区间:支持按 token 区间、按次分层、图片分辨率分层';
  29. COMMENT ON COLUMN channel_pricing_intervals.min_tokens IS '区间下界(含),token 模式使用';
  30. COMMENT ON COLUMN channel_pricing_intervals.max_tokens IS '区间上界(不含),NULL 表示无上限';
  31. COMMENT ON COLUMN channel_pricing_intervals.tier_label IS '层级标签,按次/图片模式使用(如 1K、2K、4K、HD)';
  32. COMMENT ON COLUMN channel_pricing_intervals.input_price IS 'token 模式:每 token 输入价';
  33. COMMENT ON COLUMN channel_pricing_intervals.output_price IS 'token 模式:每 token 输出价';
  34. COMMENT ON COLUMN channel_pricing_intervals.cache_write_price IS 'token 模式:缓存写入价';
  35. COMMENT ON COLUMN channel_pricing_intervals.cache_read_price IS 'token 模式:缓存读取价';
  36. COMMENT ON COLUMN channel_pricing_intervals.per_request_price IS '按次/图片模式:每次请求价格';
  37. -- 3. 迁移现有 flat 定价为单区间 [0, +inf)
  38. -- 仅迁移有明确定价(至少一个价格字段非 NULL)的条目
  39. INSERT INTO channel_pricing_intervals (pricing_id, min_tokens, max_tokens, input_price, output_price, cache_write_price, cache_read_price, sort_order)
  40. SELECT
  41. cmp.id,
  42. 0,
  43. NULL,
  44. cmp.input_price,
  45. cmp.output_price,
  46. cmp.cache_write_price,
  47. cmp.cache_read_price,
  48. 0
  49. FROM channel_model_pricing cmp
  50. WHERE cmp.billing_mode = 'token'
  51. AND (cmp.input_price IS NOT NULL OR cmp.output_price IS NOT NULL
  52. OR cmp.cache_write_price IS NOT NULL OR cmp.cache_read_price IS NOT NULL)
  53. AND NOT EXISTS (
  54. SELECT 1 FROM channel_pricing_intervals cpi WHERE cpi.pricing_id = cmp.id
  55. );
  56. -- 4. 迁移 image_output_price 为 image 模式的区间条目
  57. -- 将有 image_output_price 的现有条目复制为 billing_mode='image' 的独立条目
  58. -- 注意:这里不改变原条目的 billing_mode,而是将 image_output_price 作为向后兼容字段保留
  59. -- 实际的 image 计费在未来由独立的 billing_mode='image' 条目处理