File size: 6,309 Bytes
c84fdae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Agents table: tracks personas and their configurations
CREATE TABLE IF NOT EXISTS agents (
    id SERIAL PRIMARY KEY,
    name TEXT UNIQUE NOT NULL,
    description TEXT,
    current_version_id INT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Agent versions: versioned agent configs and prompts
CREATE TABLE IF NOT EXISTS agent_versions (
    id SERIAL PRIMARY KEY,
    agent_id INT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
    version INT NOT NULL,
    config JSONB NOT NULL,  -- Model, temperature, system prompt overrides, etc.
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by TEXT,
    UNIQUE(agent_id, version)
);

-- Prompt templates: versioned prompts per agent version
CREATE TABLE IF NOT EXISTS prompt_templates (
    id SERIAL PRIMARY KEY,
    agent_version_id INT NOT NULL REFERENCES agent_versions(id) ON DELETE CASCADE,
    name TEXT NOT NULL,  -- e.g., "system", "user_initial", "feedback"
    prompt_text TEXT NOT NULL,
    description TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Trends: detected social trends
CREATE TABLE IF NOT EXISTS trends (
    id SERIAL PRIMARY KEY,
    topic TEXT NOT NULL,
    source TEXT NOT NULL,  -- "reddit", "twitter", "google_trends", etc.
    source_url TEXT,
    score FLOAT,  -- Relevance score (0-1)
    embedding VECTOR(1536),  -- Embedding for deduplication
    status TEXT DEFAULT 'pending_generation',  -- pending_generation, generated, published, skipped, failed
    raw_data JSONB,  -- Store raw API response
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX ON trends(status);
CREATE INDEX ON trends(created_at DESC);
CREATE INDEX ON trends(source);
CREATE INDEX ON trends USING hnsw (embedding vector_cosine_ops);

-- Posts: generated social media posts
CREATE TABLE IF NOT EXISTS posts (
    id SERIAL PRIMARY KEY,
    trend_id INT REFERENCES trends(id) ON DELETE SET NULL,
    agent_version_id INT NOT NULL REFERENCES agent_versions(id),
    content TEXT NOT NULL,
    image_url TEXT,
    video_url TEXT,
    status TEXT DEFAULT 'draft',  -- draft, pending_approval, approved, rejected, scheduled, published, failed
    
    -- Publishing metadata
    platform TEXT,  -- instagram, twitter, linkedin, etc.
    platform_post_id TEXT,  -- ID from platform's API
    scheduled_at TIMESTAMP,
    published_at TIMESTAMP,
    approval_status TEXT DEFAULT 'pending',  -- pending, approved, rejected
    approval_notes TEXT,
    approved_by TEXT,
    approved_at TIMESTAMP,
    
    -- Generated metadata
    embedding VECTOR(1536),  -- For similarity/dedup
    token_count INT,
    generation_cost FLOAT,  -- Cost in USD
    hallucination_score FLOAT,  -- 0-1, higher = more hallucination risk
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX ON posts(status);
CREATE INDEX ON posts(approval_status);
CREATE INDEX ON posts(platform);
CREATE INDEX ON posts(published_at DESC);
CREATE INDEX ON posts(created_at DESC);
CREATE INDEX ON posts USING hnsw (embedding vector_cosine_ops);

-- Workflow executions: track Temporal workflow runs
CREATE TABLE IF NOT EXISTS workflow_executions (
    id SERIAL PRIMARY KEY,
    workflow_id TEXT NOT NULL,
    workflow_name TEXT NOT NULL,
    trend_id INT REFERENCES trends(id),
    post_id INT REFERENCES posts(id),
    status TEXT DEFAULT 'running',  -- running, completed, failed, timed_out
    started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP,
    error_message TEXT,
    metadata JSONB,
    
    UNIQUE(workflow_id)
);

CREATE INDEX ON workflow_executions(status);
CREATE INDEX ON workflow_executions(workflow_name);
CREATE INDEX ON workflow_executions(created_at DESC);

-- Media: store image/video metadata
CREATE TABLE IF NOT EXISTS media (
    id SERIAL PRIMARY KEY,
    post_id INT REFERENCES posts(id) ON DELETE CASCADE,
    media_type TEXT NOT NULL,  -- image, video
    file_name TEXT NOT NULL,
    file_size INT,
    mime_type TEXT,
    r2_key TEXT,  -- Path in R2 bucket
    r2_url TEXT,
    
    -- Moderation
    moderation_status TEXT DEFAULT 'pending',  -- pending, approved, rejected, flagged
    nsfw_score FLOAT,  -- 0-1, higher = more likely NSFW
    moderation_details JSONB,  -- Results from AWS Rekognition, etc.
    
    -- Thumbnails
    thumbnail_url TEXT,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX ON media(post_id);
CREATE INDEX ON media(moderation_status);

-- Observability traces: store Langfuse trace references
CREATE TABLE IF NOT EXISTS observability_traces (
    id SERIAL PRIMARY KEY,
    trace_id TEXT UNIQUE,
    post_id INT REFERENCES posts(id),
    workflow_id TEXT REFERENCES workflow_executions(workflow_id),
    trace_name TEXT,
    input JSONB,
    output JSONB,
    metadata JSONB,
    token_count INT,
    cost_usd FLOAT,
    duration_ms INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX ON observability_traces(post_id);
CREATE INDEX ON observability_traces(workflow_id);
CREATE INDEX ON observability_traces(created_at DESC);

-- API usage & costs: track quota and spending
CREATE TABLE IF NOT EXISTS api_usage (
    id SERIAL PRIMARY KEY,
    service TEXT NOT NULL,  -- openai, anthropic, instagram, twitter, rekognition, etc.
    request_count INT DEFAULT 0,
    token_count INT DEFAULT 0,
    cost_usd FLOAT DEFAULT 0,
    period_start TIMESTAMP,
    period_end TIMESTAMP,
    UNIQUE(service, period_start, period_end)
);

-- System errors & alerts
CREATE TABLE IF NOT EXISTS system_alerts (
    id SERIAL PRIMARY KEY,
    alert_type TEXT NOT NULL,  -- rate_limit, api_error, quality_degradation, etc.
    service TEXT,
    message TEXT NOT NULL,
    severity TEXT DEFAULT 'warning',  -- info, warning, error, critical
    resolved BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    resolved_at TIMESTAMP
);

CREATE INDEX ON system_alerts(severity);
CREATE INDEX ON system_alerts(resolved);
CREATE INDEX ON system_alerts(created_at DESC);