-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathschema.sql
More file actions
169 lines (148 loc) · 6.4 KB
/
schema.sql
File metadata and controls
169 lines (148 loc) · 6.4 KB
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
-- Assistant AI - Single-App Database Schema
-- This schema is designed for single-application use (no multi-tenancy)
-- Run this in your Supabase SQL Editor or PostgreSQL database
-- Enable required extensions
CREATE EXTENSION IF NOT EXISTS vector;
-- ============================================================================
-- CONVERSATIONS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS ai_conversations (
id BIGSERIAL PRIMARY KEY,
uuid UUID DEFAULT gen_random_uuid() UNIQUE NOT NULL,
creator_id TEXT NOT NULL,
title TEXT NOT NULL,
message_count INTEGER DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
-- Indexes for conversations
CREATE INDEX IF NOT EXISTS idx_ai_conversations_uuid ON ai_conversations(uuid);
CREATE INDEX IF NOT EXISTS idx_ai_conversations_creator_id ON ai_conversations(creator_id);
CREATE INDEX IF NOT EXISTS idx_ai_conversations_deleted ON ai_conversations(deleted_at) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_ai_conversations_updated_at ON ai_conversations(updated_at DESC);
-- ============================================================================
-- MESSAGES TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS ai_messages (
id BIGSERIAL PRIMARY KEY,
uuid UUID DEFAULT gen_random_uuid() UNIQUE NOT NULL,
conversation_id BIGINT NOT NULL REFERENCES ai_conversations(id) ON DELETE CASCADE,
parent_message_id BIGINT REFERENCES ai_messages(id),
type TEXT NOT NULL CHECK (type IN ('user', 'assistant', 'system')),
content TEXT NOT NULL,
status TEXT DEFAULT 'completed' CHECK (status IN ('generating', 'completed', 'stopped', 'failed')),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indexes for messages
CREATE INDEX IF NOT EXISTS idx_ai_messages_uuid ON ai_messages(uuid);
CREATE INDEX IF NOT EXISTS idx_ai_messages_conversation_id ON ai_messages(conversation_id);
CREATE INDEX IF NOT EXISTS idx_ai_messages_parent_id ON ai_messages(parent_message_id);
CREATE INDEX IF NOT EXISTS idx_ai_messages_type ON ai_messages(type);
CREATE INDEX IF NOT EXISTS idx_ai_messages_created_at ON ai_messages(created_at DESC);
-- ============================================================================
-- MESSAGE FEEDBACK TABLE (Optional)
-- ============================================================================
CREATE TABLE IF NOT EXISTS ai_message_feedback (
id BIGSERIAL PRIMARY KEY,
uuid UUID DEFAULT gen_random_uuid() UNIQUE NOT NULL,
message_id BIGINT NOT NULL REFERENCES ai_messages(id) ON DELETE CASCADE,
user_id TEXT NOT NULL,
rating TEXT NOT NULL CHECK (rating IN ('positive', 'negative')),
category TEXT,
comment TEXT,
suggested_improvement TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indexes for feedback
CREATE INDEX IF NOT EXISTS idx_ai_feedback_uuid ON ai_message_feedback(uuid);
CREATE INDEX IF NOT EXISTS idx_ai_feedback_message_id ON ai_message_feedback(message_id);
CREATE INDEX IF NOT EXISTS idx_ai_feedback_user_id ON ai_message_feedback(user_id);
-- ============================================================================
-- KNOWLEDGE ITEMS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS ai_knowledge_items (
id BIGSERIAL PRIMARY KEY,
uuid UUID DEFAULT gen_random_uuid() UNIQUE NOT NULL,
parent_id BIGINT REFERENCES ai_knowledge_items(id),
title TEXT NOT NULL,
description TEXT,
type TEXT NOT NULL CHECK (type IN ('folder', 'document', 'file', 'url', 'url_directory')),
content TEXT,
file_url TEXT,
file_size BIGINT,
file_type TEXT,
metadata JSONB DEFAULT '{}',
embedding vector(1536),
processed_at TIMESTAMPTZ,
created_by TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indexes for knowledge items
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_uuid ON ai_knowledge_items(uuid);
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_parent_id ON ai_knowledge_items(parent_id);
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_type ON ai_knowledge_items(type);
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_created_at ON ai_knowledge_items(created_at DESC);
-- Full-text search index
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_search
ON ai_knowledge_items USING gin(to_tsvector('english', title || ' ' || COALESCE(description, '') || ' ' || COALESCE(content, '')));
-- Vector similarity index for semantic search
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_embedding
ON ai_knowledge_items USING ivfflat (embedding vector_cosine_ops)
WHERE embedding IS NOT NULL;
-- Sparse indexes
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_content ON ai_knowledge_items(content) WHERE content IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_ai_knowledge_file_url ON ai_knowledge_items(file_url) WHERE file_url IS NOT NULL;
-- ============================================================================
-- PERSONALITY TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS ai_personality (
id BIGSERIAL PRIMARY KEY,
uuid UUID DEFAULT gen_random_uuid() UNIQUE NOT NULL,
name TEXT NOT NULL,
description TEXT,
system_prompt TEXT NOT NULL,
metadata JSONB DEFAULT '{}',
last_built_at TIMESTAMPTZ DEFAULT NOW()
);
-- Index for personality
CREATE INDEX IF NOT EXISTS idx_ai_personality_uuid ON ai_personality(uuid);
CREATE INDEX IF NOT EXISTS idx_ai_personality_last_built ON ai_personality(last_built_at DESC);
-- ============================================================================
-- SEMANTIC SEARCH FUNCTION
-- ============================================================================
-- Based on Supabase blog: https://supabase.com/blog/openai-embeddings-postgres-vector
CREATE OR REPLACE FUNCTION match_knowledge_items(
query_embedding vector(1536),
match_threshold float,
match_count int
)
RETURNS TABLE (
uuid uuid,
title text,
description text,
content text,
type text,
metadata jsonb
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT
k.uuid,
k.title,
k.description,
k.content,
k.type,
k.metadata
FROM ai_knowledge_items k
WHERE k.embedding IS NOT NULL
AND k.embedding <#> query_embedding < match_threshold
ORDER BY k.embedding <#> query_embedding ASC
LIMIT LEAST(match_count, 10);
END;
$$;