178 lines
7.0 KiB
SQL
178 lines
7.0 KiB
SQL
CREATE TABLE IF NOT EXISTS model_pricing_rule_sets (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
rule_set_key text NOT NULL UNIQUE,
|
|
name text NOT NULL,
|
|
description text,
|
|
category text NOT NULL DEFAULT 'general',
|
|
currency text NOT NULL DEFAULT 'resource',
|
|
status text NOT NULL DEFAULT 'active',
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE IF EXISTS model_pricing_rules
|
|
ADD COLUMN IF NOT EXISTS rule_set_id uuid REFERENCES model_pricing_rule_sets(id) ON DELETE CASCADE,
|
|
ADD COLUMN IF NOT EXISTS rule_key text NOT NULL DEFAULT ('rule_' || replace(gen_random_uuid()::text, '-', '')),
|
|
ADD COLUMN IF NOT EXISTS display_name text NOT NULL DEFAULT '',
|
|
ADD COLUMN IF NOT EXISTS calculator_type text NOT NULL DEFAULT 'unit_weight',
|
|
ADD COLUMN IF NOT EXISTS dimension_schema jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
ADD COLUMN IF NOT EXISTS formula_config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
ADD COLUMN IF NOT EXISTS priority integer NOT NULL DEFAULT 100,
|
|
ADD COLUMN IF NOT EXISTS status text NOT NULL DEFAULT 'active',
|
|
ADD COLUMN IF NOT EXISTS metadata jsonb NOT NULL DEFAULT '{}'::jsonb;
|
|
|
|
ALTER TABLE IF EXISTS integration_platforms
|
|
ADD COLUMN IF NOT EXISTS pricing_rule_set_id uuid REFERENCES model_pricing_rule_sets(id) ON DELETE SET NULL;
|
|
|
|
ALTER TABLE IF EXISTS platform_models
|
|
ADD COLUMN IF NOT EXISTS pricing_rule_set_id uuid REFERENCES model_pricing_rule_sets(id) ON DELETE SET NULL;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM pg_constraint c
|
|
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY(c.conkey)
|
|
WHERE c.contype = 'f'
|
|
AND c.conrelid = 'integration_platforms'::regclass
|
|
AND a.attname = 'pricing_rule_set_id'
|
|
) THEN
|
|
ALTER TABLE integration_platforms
|
|
ADD CONSTRAINT fk_integration_platforms_pricing_rule_set
|
|
FOREIGN KEY (pricing_rule_set_id) REFERENCES model_pricing_rule_sets(id) ON DELETE SET NULL;
|
|
END IF;
|
|
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM pg_constraint c
|
|
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY(c.conkey)
|
|
WHERE c.contype = 'f'
|
|
AND c.conrelid = 'platform_models'::regclass
|
|
AND a.attname = 'pricing_rule_set_id'
|
|
) THEN
|
|
ALTER TABLE platform_models
|
|
ADD CONSTRAINT fk_platform_models_pricing_rule_set
|
|
FOREIGN KEY (pricing_rule_set_id) REFERENCES model_pricing_rule_sets(id) ON DELETE SET NULL;
|
|
END IF;
|
|
END $$;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_model_pricing_rule_set
|
|
ON model_pricing_rules(rule_set_id, resource_type, priority);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_model_pricing_rule_set_key
|
|
ON model_pricing_rules(rule_set_id, rule_key)
|
|
WHERE rule_set_id IS NOT NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_integration_platforms_pricing_rule_set
|
|
ON integration_platforms(pricing_rule_set_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_platform_models_pricing_rule_set
|
|
ON platform_models(pricing_rule_set_id);
|
|
|
|
INSERT INTO model_pricing_rule_sets (rule_set_key, name, description, category, currency, status, metadata)
|
|
VALUES (
|
|
'default-multimodal-v1',
|
|
'默认多模态计价规则',
|
|
'覆盖文本、图像和视频的默认计价规则,可作为平台或平台模型的基础价格模板。',
|
|
'default',
|
|
'resource',
|
|
'active',
|
|
'{"source":"gateway.default","version":1}'::jsonb
|
|
)
|
|
ON CONFLICT (rule_set_key) DO UPDATE SET
|
|
name = EXCLUDED.name,
|
|
description = EXCLUDED.description,
|
|
category = EXCLUDED.category,
|
|
currency = EXCLUDED.currency,
|
|
status = EXCLUDED.status,
|
|
metadata = EXCLUDED.metadata,
|
|
updated_at = now();
|
|
|
|
WITH default_set AS (
|
|
SELECT id FROM model_pricing_rule_sets WHERE rule_set_key = 'default-multimodal-v1'
|
|
)
|
|
INSERT INTO model_pricing_rules (
|
|
rule_set_id, rule_key, display_name, scope_type, scope_id, resource_type, unit,
|
|
base_price, currency, base_weight, dynamic_weight, calculator_type,
|
|
dimension_schema, formula_config, priority, status, metadata
|
|
)
|
|
SELECT default_set.id, item.rule_key, item.display_name, 'rule_set', default_set.id,
|
|
item.resource_type, item.unit, item.base_price, 'resource',
|
|
item.base_weight, item.dynamic_weight, item.calculator_type,
|
|
item.dimension_schema, item.formula_config, item.priority, 'active',
|
|
'{"source":"gateway.default"}'::jsonb
|
|
FROM default_set
|
|
CROSS JOIN (
|
|
VALUES
|
|
(
|
|
'text_input_tokens',
|
|
'文本输入 Token',
|
|
'text_input',
|
|
'1k_tokens',
|
|
0.01::numeric,
|
|
'{"meter":"input_tokens"}'::jsonb,
|
|
'{}'::jsonb,
|
|
'token_usage',
|
|
'{"metrics":["input_tokens"],"unitScale":1000}'::jsonb,
|
|
'{"formula":"ceil(input_tokens / 1000) * base_price"}'::jsonb,
|
|
10
|
|
),
|
|
(
|
|
'text_output_tokens',
|
|
'文本输出 Token',
|
|
'text_output',
|
|
'1k_tokens',
|
|
0.03::numeric,
|
|
'{"meter":"output_tokens"}'::jsonb,
|
|
'{}'::jsonb,
|
|
'token_usage',
|
|
'{"metrics":["output_tokens"],"unitScale":1000}'::jsonb,
|
|
'{"formula":"ceil(output_tokens / 1000) * base_price"}'::jsonb,
|
|
20
|
|
),
|
|
(
|
|
'image',
|
|
'图像',
|
|
'image',
|
|
'image',
|
|
10::numeric,
|
|
'{"meter":"count"}'::jsonb,
|
|
'{"resolutionFactors":{"1K":1,"2K":1.5,"3K":1.75,"4K":2,"8K":4},"qualityFactors":{"low":0.5,"medium":1,"high":1.5}}'::jsonb,
|
|
'unit_weight',
|
|
'{"dimensions":["count","resolution","quality"],"defaults":{"count":1,"quality":"medium","resolution":"1K"}}'::jsonb,
|
|
'{"formula":"count * base_price * resolution_factor * quality_factor"}'::jsonb,
|
|
30
|
|
),
|
|
(
|
|
'video_generation',
|
|
'视频生成',
|
|
'video',
|
|
'5s',
|
|
100::numeric,
|
|
'{"meter":"duration","unitSeconds":5}'::jsonb,
|
|
'{"resolutionWeights":{"480p":0.75,"720p":1,"1080p":1.5,"2160p":2},"audioWeights":{"true":2,"false":1},"referenceVideoWeights":{"true":1.5,"false":1},"voiceSpecifiedWeights":{"true":1.2,"false":1}}'::jsonb,
|
|
'duration_weight',
|
|
'{"dimensions":["duration_seconds","resolution","audio","reference_video","voice_specified","count"],"defaults":{"count":1,"duration_seconds":5,"resolution":"720p","audio":false,"reference_video":false,"voice_specified":false}}'::jsonb,
|
|
'{"formula":"count * ceil(duration_seconds / 5) * base_price * resolution_weight * audio_weight * reference_video_weight * voice_specified_weight"}'::jsonb,
|
|
50
|
|
)
|
|
) AS item(rule_key, display_name, resource_type, unit, base_price, base_weight, dynamic_weight, calculator_type, dimension_schema, formula_config, priority)
|
|
ON CONFLICT (rule_set_id, rule_key) WHERE rule_set_id IS NOT NULL DO UPDATE SET
|
|
display_name = EXCLUDED.display_name,
|
|
scope_type = EXCLUDED.scope_type,
|
|
scope_id = EXCLUDED.scope_id,
|
|
resource_type = EXCLUDED.resource_type,
|
|
unit = EXCLUDED.unit,
|
|
base_price = EXCLUDED.base_price,
|
|
currency = EXCLUDED.currency,
|
|
base_weight = EXCLUDED.base_weight,
|
|
dynamic_weight = EXCLUDED.dynamic_weight,
|
|
calculator_type = EXCLUDED.calculator_type,
|
|
dimension_schema = EXCLUDED.dimension_schema,
|
|
formula_config = EXCLUDED.formula_config,
|
|
priority = EXCLUDED.priority,
|
|
status = EXCLUDED.status,
|
|
metadata = EXCLUDED.metadata,
|
|
updated_at = now();
|