40 lines
1.7 KiB
PL/PgSQL
40 lines
1.7 KiB
PL/PgSQL
-- Phase 4: A/B testing tables for Ask Ash prompt variations.
|
|
|
|
BEGIN;
|
|
|
|
CREATE TABLE IF NOT EXISTS ai_ab_tests (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
name TEXT NOT NULL UNIQUE,
|
|
description TEXT,
|
|
-- Each variant is an arbitrary JSON blob the request handler decides how
|
|
-- to interpret (e.g. {"persona":"job_seekers","system_prompt_override":"..."})
|
|
variant_a JSONB NOT NULL,
|
|
variant_b JSONB NOT NULL,
|
|
-- 0.0 → all traffic to A, 1.0 → all traffic to B, 0.5 → 50/50.
|
|
-- DOUBLE PRECISION because sqlx's default feature set doesn't include
|
|
-- bigdecimal/rust_decimal; double has plenty of precision for 0-1.
|
|
traffic_split DOUBLE PRECISION NOT NULL DEFAULT 0.50
|
|
CHECK (traffic_split >= 0.0 AND traffic_split <= 1.0),
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS ai_ab_assignments (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
test_id BIGINT NOT NULL REFERENCES ai_ab_tests(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
-- References ai_conversations.id which is UUID.
|
|
conversation_id UUID REFERENCES ai_conversations(id) ON DELETE SET NULL,
|
|
variant TEXT NOT NULL CHECK (variant IN ('A', 'B')),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Hot path: "what variant was user X assigned to test Y?"
|
|
CREATE INDEX IF NOT EXISTS idx_ai_ab_assignments_user
|
|
ON ai_ab_assignments (user_id, test_id);
|
|
|
|
-- Hot path: aggregate results per test
|
|
CREATE INDEX IF NOT EXISTS idx_ai_ab_assignments_variant
|
|
ON ai_ab_assignments (test_id, variant, created_at DESC);
|
|
|
|
COMMIT;
|