tetspv / db /schema.sql
dumamai's picture
Create db/schema.sql
096dfff verified
Raw
History Blame Contribute Delete
5.52 kB
-- ============================================================================
-- IT Knowledge Base Pipeline β€” Postgres schema
-- Implements Storage Layer (C) from the design doc: 1 database instead of
-- Postgres + Qdrant + Elasticsearch + Neo4j + Redis/Celery.
-- ============================================================================
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- gen_random_uuid()
-- ----------------------------------------------------------------------------
-- A3.5 β€” section content hashes (change detection between ingest runs)
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS section_hashes (
source_id TEXT NOT NULL,
section_id TEXT NOT NULL,
content_hash TEXT NOT NULL,
updated_at TIMESTAMP DEFAULT now(),
PRIMARY KEY (source_id, section_id)
);
-- ----------------------------------------------------------------------------
-- A4 β€” job queue, replaces Celery + Redis
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS section_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
batch_id UUID NOT NULL,
source_id TEXT NOT NULL,
section_id TEXT NOT NULL,
section_text TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending', -- pending|processing|done|manual_review|failed
attempt INT NOT NULL DEFAULT 0,
max_attempts INT NOT NULL DEFAULT 3,
llm_tier TEXT NOT NULL DEFAULT 'light', -- light|strong
next_run_at TIMESTAMP NOT NULL DEFAULT now(),
last_error TEXT,
created_at TIMESTAMP DEFAULT now(),
updated_at TIMESTAMP DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_section_jobs_poll
ON section_jobs (status, next_run_at);
-- ----------------------------------------------------------------------------
-- Knowledge atoms == verified elements after A4 (+ dedup B1 + embeddings B2)
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS knowledge_atoms (
id TEXT PRIMARY KEY, -- stable element id
source_id TEXT NOT NULL,
section_id TEXT NOT NULL,
chapter TEXT,
page_start INT,
label TEXT, -- FACT|DEFINITION|CONSTRAINT|EXAMPLE|WARNING|OTHER
raw TEXT NOT NULL, -- verbatim substring from source (A4 verification)
normalized TEXT, -- LLM-normalized/paraphrased form
confidence REAL,
contradicts_flag BOOLEAN DEFAULT FALSE,
embedding vector(768),
search_vector tsvector,
created_at TIMESTAMP DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_atoms_embedding
ON knowledge_atoms USING hnsw (embedding vector_cosine_ops);
CREATE INDEX IF NOT EXISTS idx_atoms_search
ON knowledge_atoms USING gin (search_vector);
CREATE INDEX IF NOT EXISTS idx_atoms_source_section
ON knowledge_atoms (source_id, section_id);
CREATE OR REPLACE FUNCTION knowledge_atoms_search_vector_trigger() RETURNS trigger AS $$
BEGIN
NEW.search_vector := to_tsvector('english', coalesce(NEW.normalized, NEW.raw, ''));
RETURN NEW;
END
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trg_atoms_search_vector ON knowledge_atoms;
CREATE TRIGGER trg_atoms_search_vector
BEFORE INSERT OR UPDATE ON knowledge_atoms
FOR EACH ROW EXECUTE FUNCTION knowledge_atoms_search_vector_trigger();
-- ----------------------------------------------------------------------------
-- B2 β€” Knowledge Graph (replaces Neo4j)
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS kg_nodes (
id TEXT PRIMARY KEY,
label TEXT,
type TEXT -- entity|atom
);
CREATE TABLE IF NOT EXISTS kg_edges (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
source_id TEXT REFERENCES kg_nodes(id),
target_id TEXT REFERENCES kg_nodes(id),
relation TEXT NOT NULL, -- DEFINES|EXTENDS|CONTRADICTS|...
evidence_raw TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_edges_source ON kg_edges(source_id);
CREATE INDEX IF NOT EXISTS idx_edges_target ON kg_edges(target_id);
-- ----------------------------------------------------------------------------
-- B2 β€” chunk records (parent/child, late chunking)
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS chunk_records (
id TEXT PRIMARY KEY,
type TEXT NOT NULL, -- parent|child
content TEXT NOT NULL,
parent_id TEXT REFERENCES chunk_records(id),
embedding vector(768),
metadata JSONB
);
CREATE INDEX IF NOT EXISTS idx_chunk_embedding
ON chunk_records USING hnsw (embedding vector_cosine_ops);
-- ----------------------------------------------------------------------------
-- C β€” batch monitoring (replaces Sentry + Flower)
-- ----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS batch_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
started_at TIMESTAMP DEFAULT now(),
finished_at TIMESTAMP,
total_documents INT DEFAULT 0,
total_sections INT DEFAULT 0,
failed_sections INT DEFAULT 0,
manual_review_sections INT DEFAULT 0
);