101 lines
3.5 KiB
SQL
101 lines
3.5 KiB
SQL
-- content-atom: schema для MVP stage 1
|
|
-- Postgres (atom-db) + pgvector (расширение "vector")
|
|
|
|
CREATE EXTENSION IF NOT EXISTS vector;
|
|
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
|
CREATE EXTENSION IF NOT EXISTS btree_gin;
|
|
|
|
-- Проекты (домены)
|
|
CREATE TABLE projects (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
slug TEXT UNIQUE NOT NULL,
|
|
name TEXT NOT NULL,
|
|
kind TEXT NOT NULL, -- site | service | social | podcast
|
|
niche TEXT,
|
|
role TEXT NOT NULL DEFAULT 'satellite', -- flagship | satellite | experiment | service
|
|
locale TEXT DEFAULT 'ru',
|
|
settings JSONB DEFAULT '{}',
|
|
status TEXT DEFAULT 'active', -- active | paused | archived
|
|
created_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
CREATE INDEX ON projects (role, niche);
|
|
|
|
-- Атомы
|
|
CREATE TABLE atoms (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
|
|
type TEXT NOT NULL, -- claim | fact | stat | quote | definition | instruction | case | comparison | qa | opinion | hook | transition | cta | media_ref
|
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
title TEXT,
|
|
summary TEXT,
|
|
body JSONB NOT NULL,
|
|
plain_text TEXT,
|
|
language TEXT DEFAULT 'ru',
|
|
entities JSONB DEFAULT '[]',
|
|
topics TEXT[] DEFAULT '{}',
|
|
intent TEXT,
|
|
audience TEXT,
|
|
confidence NUMERIC(3,2),
|
|
quality_score NUMERIC(4,2),
|
|
word_count INT,
|
|
source_refs JSONB DEFAULT '[]',
|
|
embedding VECTOR(1024),
|
|
generator JSONB,
|
|
cost JSONB,
|
|
pipeline_stage TEXT,
|
|
parent_atom_id UUID,
|
|
lineage_root_id UUID,
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
updated_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
CREATE INDEX ON atoms (project_id, type, status);
|
|
CREATE INDEX ON atoms USING gin (plain_text gin_trgm_ops);
|
|
CREATE INDEX ON atoms USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
|
|
|
-- Версии под каналы
|
|
CREATE TABLE atom_versions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
atom_id UUID REFERENCES atoms(id) ON DELETE CASCADE,
|
|
channel TEXT NOT NULL, -- web_article | telegram | youtube_script | podcast | newsletter | service_card
|
|
format TEXT NOT NULL, -- markdown | html | plain | srt | ssml | json
|
|
content TEXT NOT NULL,
|
|
meta JSONB DEFAULT '{}',
|
|
quality_score NUMERIC(4,2),
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
UNIQUE (atom_id, channel, format)
|
|
);
|
|
CREATE INDEX ON atom_versions (channel, created_at DESC);
|
|
|
|
-- Задачи пайплайна + стоимость
|
|
CREATE TABLE jobs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
kind TEXT NOT NULL, -- generate | edit | adapt | publish | index
|
|
atom_id UUID REFERENCES atoms(id),
|
|
status TEXT DEFAULT 'queued',
|
|
attempts INT DEFAULT 0,
|
|
max_attempts INT DEFAULT 3,
|
|
payload JSONB DEFAULT '{}',
|
|
error TEXT,
|
|
scheduled_at TIMESTAMPTZ DEFAULT now(),
|
|
started_at TIMESTAMPTZ,
|
|
finished_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE runs (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
job_id UUID REFERENCES jobs(id) ON DELETE CASCADE,
|
|
stage TEXT NOT NULL,
|
|
model TEXT,
|
|
tokens_in INT,
|
|
tokens_out INT,
|
|
seconds NUMERIC,
|
|
cost_usd NUMERIC DEFAULT 0,
|
|
quality NUMERIC(4,2),
|
|
created_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
-- Индексы
|
|
CREATE INDEX ON jobs (status, scheduled_at);
|
|
CREATE INDEX ON runs (stage, created_at DESC);
|