nxtgauge-backend-rust/crates/db/migrations/20260608030000_ai_ab_tests.up.sql

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;