feat: implement AI gateway phase one runtime
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
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();
|
||||
Reference in New Issue
Block a user