remdb 0.3.0__py3-none-any.whl → 0.3.114__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of remdb might be problematic. Click here for more details.
- rem/__init__.py +129 -2
- rem/agentic/README.md +76 -0
- rem/agentic/__init__.py +15 -0
- rem/agentic/agents/__init__.py +16 -2
- rem/agentic/agents/sse_simulator.py +500 -0
- rem/agentic/context.py +28 -22
- rem/agentic/llm_provider_models.py +301 -0
- rem/agentic/otel/setup.py +92 -4
- rem/agentic/providers/phoenix.py +32 -43
- rem/agentic/providers/pydantic_ai.py +142 -22
- rem/agentic/schema.py +358 -21
- rem/agentic/tools/rem_tools.py +3 -3
- rem/api/README.md +238 -1
- rem/api/deps.py +255 -0
- rem/api/main.py +151 -37
- rem/api/mcp_router/resources.py +1 -1
- rem/api/mcp_router/server.py +17 -2
- rem/api/mcp_router/tools.py +143 -7
- rem/api/middleware/tracking.py +172 -0
- rem/api/routers/admin.py +277 -0
- rem/api/routers/auth.py +124 -0
- rem/api/routers/chat/completions.py +152 -16
- rem/api/routers/chat/models.py +7 -3
- rem/api/routers/chat/sse_events.py +526 -0
- rem/api/routers/chat/streaming.py +608 -45
- rem/api/routers/dev.py +81 -0
- rem/api/routers/feedback.py +148 -0
- rem/api/routers/messages.py +473 -0
- rem/api/routers/models.py +78 -0
- rem/api/routers/query.py +357 -0
- rem/api/routers/shared_sessions.py +406 -0
- rem/auth/middleware.py +126 -27
- rem/cli/commands/README.md +201 -70
- rem/cli/commands/ask.py +13 -10
- rem/cli/commands/cluster.py +1359 -0
- rem/cli/commands/configure.py +4 -3
- rem/cli/commands/db.py +350 -137
- rem/cli/commands/experiments.py +76 -72
- rem/cli/commands/process.py +22 -15
- rem/cli/commands/scaffold.py +47 -0
- rem/cli/commands/schema.py +95 -49
- rem/cli/main.py +29 -6
- rem/config.py +2 -2
- rem/models/core/core_model.py +7 -1
- rem/models/core/rem_query.py +5 -2
- rem/models/entities/__init__.py +21 -0
- rem/models/entities/domain_resource.py +38 -0
- rem/models/entities/feedback.py +123 -0
- rem/models/entities/message.py +30 -1
- rem/models/entities/session.py +83 -0
- rem/models/entities/shared_session.py +180 -0
- rem/models/entities/user.py +10 -3
- rem/registry.py +373 -0
- rem/schemas/agents/rem.yaml +7 -3
- rem/services/content/providers.py +94 -140
- rem/services/content/service.py +92 -20
- rem/services/dreaming/affinity_service.py +2 -16
- rem/services/dreaming/moment_service.py +2 -15
- rem/services/embeddings/api.py +24 -17
- rem/services/embeddings/worker.py +16 -16
- rem/services/phoenix/EXPERIMENT_DESIGN.md +3 -3
- rem/services/phoenix/client.py +252 -19
- rem/services/postgres/README.md +159 -15
- rem/services/postgres/__init__.py +2 -1
- rem/services/postgres/diff_service.py +426 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +427 -129
- rem/services/postgres/repository.py +132 -0
- rem/services/postgres/schema_generator.py +86 -5
- rem/services/postgres/service.py +6 -6
- rem/services/rate_limit.py +113 -0
- rem/services/rem/README.md +14 -0
- rem/services/rem/parser.py +44 -9
- rem/services/rem/service.py +36 -2
- rem/services/session/compression.py +17 -1
- rem/services/session/reload.py +1 -1
- rem/services/user_service.py +98 -0
- rem/settings.py +169 -17
- rem/sql/background_indexes.sql +21 -16
- rem/sql/migrations/001_install.sql +231 -54
- rem/sql/migrations/002_install_models.sql +457 -393
- rem/sql/migrations/003_optional_extensions.sql +326 -0
- rem/utils/constants.py +97 -0
- rem/utils/date_utils.py +228 -0
- rem/utils/embeddings.py +17 -4
- rem/utils/files.py +167 -0
- rem/utils/mime_types.py +158 -0
- rem/utils/model_helpers.py +156 -1
- rem/utils/schema_loader.py +191 -35
- rem/utils/sql_types.py +3 -1
- rem/utils/vision.py +9 -14
- rem/workers/README.md +14 -14
- rem/workers/db_maintainer.py +74 -0
- {remdb-0.3.0.dist-info → remdb-0.3.114.dist-info}/METADATA +303 -164
- {remdb-0.3.0.dist-info → remdb-0.3.114.dist-info}/RECORD +96 -70
- {remdb-0.3.0.dist-info → remdb-0.3.114.dist-info}/WHEEL +1 -1
- rem/sql/002_install_models.sql +0 -1068
- rem/sql/install_models.sql +0 -1038
- {remdb-0.3.0.dist-info → remdb-0.3.114.dist-info}/entry_points.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
-- REM Model Schema (install_models.sql)
|
|
2
2
|
-- Generated from Pydantic models
|
|
3
|
-
-- Source
|
|
4
|
-
-- Generated at: 2025-11-
|
|
3
|
+
-- Source: model registry
|
|
4
|
+
-- Generated at: 2025-11-29T11:08:16.713884
|
|
5
5
|
--
|
|
6
|
-
-- DO NOT EDIT MANUALLY - Regenerate with: rem schema generate
|
|
6
|
+
-- DO NOT EDIT MANUALLY - Regenerate with: rem db schema generate
|
|
7
7
|
--
|
|
8
8
|
-- This script creates:
|
|
9
9
|
-- 1. Primary entity tables
|
|
@@ -19,34 +19,113 @@ DO $$
|
|
|
19
19
|
BEGIN
|
|
20
20
|
-- Check that install.sql has been run
|
|
21
21
|
IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'kv_store') THEN
|
|
22
|
-
RAISE EXCEPTION 'KV_STORE table not found. Run
|
|
22
|
+
RAISE EXCEPTION 'KV_STORE table not found. Run migrations/001_install.sql first.';
|
|
23
23
|
END IF;
|
|
24
24
|
|
|
25
25
|
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'vector') THEN
|
|
26
|
-
RAISE EXCEPTION 'pgvector extension not found. Run
|
|
26
|
+
RAISE EXCEPTION 'pgvector extension not found. Run migrations/001_install.sql first.';
|
|
27
27
|
END IF;
|
|
28
28
|
|
|
29
29
|
RAISE NOTICE 'Prerequisites check passed';
|
|
30
30
|
END $$;
|
|
31
31
|
|
|
32
32
|
-- ======================================================================
|
|
33
|
-
--
|
|
33
|
+
-- FEEDBACKS (Model: Feedback)
|
|
34
34
|
-- ======================================================================
|
|
35
35
|
|
|
36
|
-
CREATE TABLE IF NOT EXISTS
|
|
36
|
+
CREATE TABLE IF NOT EXISTS feedbacks (
|
|
37
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
38
|
+
tenant_id VARCHAR(100) NOT NULL,
|
|
39
|
+
user_id VARCHAR(256),
|
|
40
|
+
session_id VARCHAR(256) NOT NULL,
|
|
41
|
+
message_id VARCHAR(256),
|
|
42
|
+
rating INTEGER,
|
|
43
|
+
categories TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
44
|
+
comment TEXT,
|
|
45
|
+
trace_id VARCHAR(256),
|
|
46
|
+
span_id VARCHAR(256),
|
|
47
|
+
phoenix_synced BOOLEAN,
|
|
48
|
+
phoenix_annotation_id VARCHAR(256),
|
|
49
|
+
annotator_kind VARCHAR(256),
|
|
50
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
51
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
52
|
+
deleted_at TIMESTAMP,
|
|
53
|
+
graph_edges JSONB DEFAULT '[]'::jsonb,
|
|
54
|
+
metadata JSONB DEFAULT '{}'::jsonb,
|
|
55
|
+
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
CREATE INDEX idx_feedbacks_tenant ON feedbacks (tenant_id);
|
|
59
|
+
CREATE INDEX idx_feedbacks_user ON feedbacks (user_id);
|
|
60
|
+
CREATE INDEX idx_feedbacks_graph_edges ON feedbacks USING GIN (graph_edges);
|
|
61
|
+
CREATE INDEX idx_feedbacks_metadata ON feedbacks USING GIN (metadata);
|
|
62
|
+
CREATE INDEX idx_feedbacks_tags ON feedbacks USING GIN (tags);
|
|
63
|
+
|
|
64
|
+
-- KV_STORE trigger for feedbacks
|
|
65
|
+
-- Trigger function to maintain KV_STORE for feedbacks
|
|
66
|
+
CREATE OR REPLACE FUNCTION fn_feedbacks_kv_store_upsert()
|
|
67
|
+
RETURNS TRIGGER AS $$
|
|
68
|
+
BEGIN
|
|
69
|
+
IF (TG_OP = 'DELETE') THEN
|
|
70
|
+
-- Remove from KV_STORE on delete
|
|
71
|
+
DELETE FROM kv_store
|
|
72
|
+
WHERE entity_id = OLD.id;
|
|
73
|
+
RETURN OLD;
|
|
74
|
+
ELSIF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
|
|
75
|
+
-- Upsert to KV_STORE (O(1) lookup by entity_key)
|
|
76
|
+
INSERT INTO kv_store (
|
|
77
|
+
entity_key,
|
|
78
|
+
entity_type,
|
|
79
|
+
entity_id,
|
|
80
|
+
tenant_id,
|
|
81
|
+
user_id,
|
|
82
|
+
metadata,
|
|
83
|
+
graph_edges,
|
|
84
|
+
updated_at
|
|
85
|
+
) VALUES (
|
|
86
|
+
NEW.id::VARCHAR,
|
|
87
|
+
'feedbacks',
|
|
88
|
+
NEW.id,
|
|
89
|
+
NEW.tenant_id,
|
|
90
|
+
NEW.user_id,
|
|
91
|
+
NEW.metadata,
|
|
92
|
+
COALESCE(NEW.graph_edges, '[]'::jsonb),
|
|
93
|
+
CURRENT_TIMESTAMP
|
|
94
|
+
)
|
|
95
|
+
ON CONFLICT (tenant_id, entity_key)
|
|
96
|
+
DO UPDATE SET
|
|
97
|
+
entity_id = EXCLUDED.entity_id,
|
|
98
|
+
user_id = EXCLUDED.user_id,
|
|
99
|
+
metadata = EXCLUDED.metadata,
|
|
100
|
+
graph_edges = EXCLUDED.graph_edges,
|
|
101
|
+
updated_at = CURRENT_TIMESTAMP;
|
|
102
|
+
|
|
103
|
+
RETURN NEW;
|
|
104
|
+
END IF;
|
|
105
|
+
END;
|
|
106
|
+
$$ LANGUAGE plpgsql;
|
|
107
|
+
|
|
108
|
+
-- Create trigger
|
|
109
|
+
DROP TRIGGER IF EXISTS trg_feedbacks_kv_store ON feedbacks;
|
|
110
|
+
CREATE TRIGGER trg_feedbacks_kv_store
|
|
111
|
+
AFTER INSERT OR UPDATE OR DELETE ON feedbacks
|
|
112
|
+
FOR EACH ROW EXECUTE FUNCTION fn_feedbacks_kv_store_upsert();
|
|
113
|
+
|
|
114
|
+
-- ======================================================================
|
|
115
|
+
-- FILES (Model: File)
|
|
116
|
+
-- ======================================================================
|
|
117
|
+
|
|
118
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
37
119
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
38
120
|
tenant_id VARCHAR(100) NOT NULL,
|
|
39
121
|
user_id VARCHAR(256),
|
|
40
122
|
name VARCHAR(256) NOT NULL,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
preferred_topics TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
48
|
-
activity_level VARCHAR(256),
|
|
49
|
-
last_active_at TIMESTAMP,
|
|
123
|
+
uri VARCHAR(256) NOT NULL,
|
|
124
|
+
content TEXT,
|
|
125
|
+
timestamp VARCHAR(256),
|
|
126
|
+
size_bytes INTEGER,
|
|
127
|
+
mime_type VARCHAR(256),
|
|
128
|
+
processing_status VARCHAR(256),
|
|
50
129
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
51
130
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
52
131
|
deleted_at TIMESTAMP,
|
|
@@ -55,16 +134,16 @@ CREATE TABLE IF NOT EXISTS users (
|
|
|
55
134
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
56
135
|
);
|
|
57
136
|
|
|
58
|
-
CREATE INDEX
|
|
59
|
-
CREATE INDEX
|
|
60
|
-
CREATE INDEX
|
|
61
|
-
CREATE INDEX
|
|
62
|
-
CREATE INDEX
|
|
137
|
+
CREATE INDEX idx_files_tenant ON files (tenant_id);
|
|
138
|
+
CREATE INDEX idx_files_user ON files (user_id);
|
|
139
|
+
CREATE INDEX idx_files_graph_edges ON files USING GIN (graph_edges);
|
|
140
|
+
CREATE INDEX idx_files_metadata ON files USING GIN (metadata);
|
|
141
|
+
CREATE INDEX idx_files_tags ON files USING GIN (tags);
|
|
63
142
|
|
|
64
|
-
-- Embeddings for
|
|
65
|
-
CREATE TABLE IF NOT EXISTS
|
|
143
|
+
-- Embeddings for files
|
|
144
|
+
CREATE TABLE IF NOT EXISTS embeddings_files (
|
|
66
145
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
67
|
-
entity_id UUID NOT NULL REFERENCES
|
|
146
|
+
entity_id UUID NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
68
147
|
field_name VARCHAR(100) NOT NULL,
|
|
69
148
|
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
70
149
|
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
@@ -77,19 +156,19 @@ CREATE TABLE IF NOT EXISTS embeddings_users (
|
|
|
77
156
|
);
|
|
78
157
|
|
|
79
158
|
-- Index for entity lookup (get all embeddings for entity)
|
|
80
|
-
CREATE INDEX
|
|
159
|
+
CREATE INDEX idx_embeddings_files_entity ON embeddings_files (entity_id);
|
|
81
160
|
|
|
82
161
|
-- Index for field + provider lookup
|
|
83
|
-
CREATE INDEX
|
|
162
|
+
CREATE INDEX idx_embeddings_files_field_provider ON embeddings_files (field_name, provider);
|
|
84
163
|
|
|
85
164
|
-- HNSW index for vector similarity search (created in background)
|
|
86
165
|
-- Note: This will be created by background thread after data load
|
|
87
|
-
-- CREATE INDEX
|
|
166
|
+
-- CREATE INDEX idx_embeddings_files_vector_hnsw ON embeddings_files
|
|
88
167
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
89
168
|
|
|
90
|
-
-- KV_STORE trigger for
|
|
91
|
-
-- Trigger function to maintain KV_STORE for
|
|
92
|
-
CREATE OR REPLACE FUNCTION
|
|
169
|
+
-- KV_STORE trigger for files
|
|
170
|
+
-- Trigger function to maintain KV_STORE for files
|
|
171
|
+
CREATE OR REPLACE FUNCTION fn_files_kv_store_upsert()
|
|
93
172
|
RETURNS TRIGGER AS $$
|
|
94
173
|
BEGIN
|
|
95
174
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -109,8 +188,8 @@ BEGIN
|
|
|
109
188
|
graph_edges,
|
|
110
189
|
updated_at
|
|
111
190
|
) VALUES (
|
|
112
|
-
NEW.
|
|
113
|
-
'
|
|
191
|
+
NEW.id::VARCHAR,
|
|
192
|
+
'files',
|
|
114
193
|
NEW.id,
|
|
115
194
|
NEW.tenant_id,
|
|
116
195
|
NEW.user_id,
|
|
@@ -132,10 +211,10 @@ END;
|
|
|
132
211
|
$$ LANGUAGE plpgsql;
|
|
133
212
|
|
|
134
213
|
-- Create trigger
|
|
135
|
-
DROP TRIGGER IF EXISTS
|
|
136
|
-
CREATE TRIGGER
|
|
137
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
138
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
214
|
+
DROP TRIGGER IF EXISTS trg_files_kv_store ON files;
|
|
215
|
+
CREATE TRIGGER trg_files_kv_store
|
|
216
|
+
AFTER INSERT OR UPDATE OR DELETE ON files
|
|
217
|
+
FOR EACH ROW EXECUTE FUNCTION fn_files_kv_store_upsert();
|
|
139
218
|
|
|
140
219
|
-- ======================================================================
|
|
141
220
|
-- IMAGE_RESOURCES (Model: ImageResource)
|
|
@@ -145,7 +224,7 @@ CREATE TABLE IF NOT EXISTS image_resources (
|
|
|
145
224
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
146
225
|
tenant_id VARCHAR(100) NOT NULL,
|
|
147
226
|
user_id VARCHAR(256),
|
|
148
|
-
name VARCHAR(256)
|
|
227
|
+
name VARCHAR(256),
|
|
149
228
|
uri VARCHAR(256),
|
|
150
229
|
ordinal INTEGER,
|
|
151
230
|
content TEXT,
|
|
@@ -168,11 +247,11 @@ CREATE TABLE IF NOT EXISTS image_resources (
|
|
|
168
247
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
169
248
|
);
|
|
170
249
|
|
|
171
|
-
CREATE INDEX
|
|
172
|
-
CREATE INDEX
|
|
173
|
-
CREATE INDEX
|
|
174
|
-
CREATE INDEX
|
|
175
|
-
CREATE INDEX
|
|
250
|
+
CREATE INDEX idx_image_resources_tenant ON image_resources (tenant_id);
|
|
251
|
+
CREATE INDEX idx_image_resources_user ON image_resources (user_id);
|
|
252
|
+
CREATE INDEX idx_image_resources_graph_edges ON image_resources USING GIN (graph_edges);
|
|
253
|
+
CREATE INDEX idx_image_resources_metadata ON image_resources USING GIN (metadata);
|
|
254
|
+
CREATE INDEX idx_image_resources_tags ON image_resources USING GIN (tags);
|
|
176
255
|
|
|
177
256
|
-- Embeddings for image_resources
|
|
178
257
|
CREATE TABLE IF NOT EXISTS embeddings_image_resources (
|
|
@@ -190,14 +269,14 @@ CREATE TABLE IF NOT EXISTS embeddings_image_resources (
|
|
|
190
269
|
);
|
|
191
270
|
|
|
192
271
|
-- Index for entity lookup (get all embeddings for entity)
|
|
193
|
-
CREATE INDEX
|
|
272
|
+
CREATE INDEX idx_embeddings_image_resources_entity ON embeddings_image_resources (entity_id);
|
|
194
273
|
|
|
195
274
|
-- Index for field + provider lookup
|
|
196
|
-
CREATE INDEX
|
|
275
|
+
CREATE INDEX idx_embeddings_image_resources_field_provider ON embeddings_image_resources (field_name, provider);
|
|
197
276
|
|
|
198
277
|
-- HNSW index for vector similarity search (created in background)
|
|
199
278
|
-- Note: This will be created by background thread after data load
|
|
200
|
-
-- CREATE INDEX
|
|
279
|
+
-- CREATE INDEX idx_embeddings_image_resources_vector_hnsw ON embeddings_image_resources
|
|
201
280
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
202
281
|
|
|
203
282
|
-- KV_STORE trigger for image_resources
|
|
@@ -222,7 +301,7 @@ BEGIN
|
|
|
222
301
|
graph_edges,
|
|
223
302
|
updated_at
|
|
224
303
|
) VALUES (
|
|
225
|
-
NEW.name,
|
|
304
|
+
NEW.name::VARCHAR,
|
|
226
305
|
'image_resources',
|
|
227
306
|
NEW.id,
|
|
228
307
|
NEW.tenant_id,
|
|
@@ -250,6 +329,112 @@ CREATE TRIGGER trg_image_resources_kv_store
|
|
|
250
329
|
AFTER INSERT OR UPDATE OR DELETE ON image_resources
|
|
251
330
|
FOR EACH ROW EXECUTE FUNCTION fn_image_resources_kv_store_upsert();
|
|
252
331
|
|
|
332
|
+
-- ======================================================================
|
|
333
|
+
-- MESSAGES (Model: Message)
|
|
334
|
+
-- ======================================================================
|
|
335
|
+
|
|
336
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
337
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
338
|
+
tenant_id VARCHAR(100) NOT NULL,
|
|
339
|
+
user_id VARCHAR(256),
|
|
340
|
+
content TEXT NOT NULL,
|
|
341
|
+
message_type VARCHAR(256),
|
|
342
|
+
session_id VARCHAR(256),
|
|
343
|
+
prompt TEXT,
|
|
344
|
+
model VARCHAR(256),
|
|
345
|
+
token_count INTEGER,
|
|
346
|
+
trace_id VARCHAR(256),
|
|
347
|
+
span_id VARCHAR(256),
|
|
348
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
349
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
350
|
+
deleted_at TIMESTAMP,
|
|
351
|
+
graph_edges JSONB DEFAULT '[]'::jsonb,
|
|
352
|
+
metadata JSONB DEFAULT '{}'::jsonb,
|
|
353
|
+
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
CREATE INDEX idx_messages_tenant ON messages (tenant_id);
|
|
357
|
+
CREATE INDEX idx_messages_user ON messages (user_id);
|
|
358
|
+
CREATE INDEX idx_messages_graph_edges ON messages USING GIN (graph_edges);
|
|
359
|
+
CREATE INDEX idx_messages_metadata ON messages USING GIN (metadata);
|
|
360
|
+
CREATE INDEX idx_messages_tags ON messages USING GIN (tags);
|
|
361
|
+
|
|
362
|
+
-- Embeddings for messages
|
|
363
|
+
CREATE TABLE IF NOT EXISTS embeddings_messages (
|
|
364
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
365
|
+
entity_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
366
|
+
field_name VARCHAR(100) NOT NULL,
|
|
367
|
+
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
368
|
+
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
369
|
+
embedding vector(1536) NOT NULL,
|
|
370
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
371
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
372
|
+
|
|
373
|
+
-- Unique: one embedding per entity per field per provider
|
|
374
|
+
UNIQUE (entity_id, field_name, provider)
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
-- Index for entity lookup (get all embeddings for entity)
|
|
378
|
+
CREATE INDEX idx_embeddings_messages_entity ON embeddings_messages (entity_id);
|
|
379
|
+
|
|
380
|
+
-- Index for field + provider lookup
|
|
381
|
+
CREATE INDEX idx_embeddings_messages_field_provider ON embeddings_messages (field_name, provider);
|
|
382
|
+
|
|
383
|
+
-- HNSW index for vector similarity search (created in background)
|
|
384
|
+
-- Note: This will be created by background thread after data load
|
|
385
|
+
-- CREATE INDEX idx_embeddings_messages_vector_hnsw ON embeddings_messages
|
|
386
|
+
-- USING hnsw (embedding vector_cosine_ops);
|
|
387
|
+
|
|
388
|
+
-- KV_STORE trigger for messages
|
|
389
|
+
-- Trigger function to maintain KV_STORE for messages
|
|
390
|
+
CREATE OR REPLACE FUNCTION fn_messages_kv_store_upsert()
|
|
391
|
+
RETURNS TRIGGER AS $$
|
|
392
|
+
BEGIN
|
|
393
|
+
IF (TG_OP = 'DELETE') THEN
|
|
394
|
+
-- Remove from KV_STORE on delete
|
|
395
|
+
DELETE FROM kv_store
|
|
396
|
+
WHERE entity_id = OLD.id;
|
|
397
|
+
RETURN OLD;
|
|
398
|
+
ELSIF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
|
|
399
|
+
-- Upsert to KV_STORE (O(1) lookup by entity_key)
|
|
400
|
+
INSERT INTO kv_store (
|
|
401
|
+
entity_key,
|
|
402
|
+
entity_type,
|
|
403
|
+
entity_id,
|
|
404
|
+
tenant_id,
|
|
405
|
+
user_id,
|
|
406
|
+
metadata,
|
|
407
|
+
graph_edges,
|
|
408
|
+
updated_at
|
|
409
|
+
) VALUES (
|
|
410
|
+
NEW.id::VARCHAR,
|
|
411
|
+
'messages',
|
|
412
|
+
NEW.id,
|
|
413
|
+
NEW.tenant_id,
|
|
414
|
+
NEW.user_id,
|
|
415
|
+
NEW.metadata,
|
|
416
|
+
COALESCE(NEW.graph_edges, '[]'::jsonb),
|
|
417
|
+
CURRENT_TIMESTAMP
|
|
418
|
+
)
|
|
419
|
+
ON CONFLICT (tenant_id, entity_key)
|
|
420
|
+
DO UPDATE SET
|
|
421
|
+
entity_id = EXCLUDED.entity_id,
|
|
422
|
+
user_id = EXCLUDED.user_id,
|
|
423
|
+
metadata = EXCLUDED.metadata,
|
|
424
|
+
graph_edges = EXCLUDED.graph_edges,
|
|
425
|
+
updated_at = CURRENT_TIMESTAMP;
|
|
426
|
+
|
|
427
|
+
RETURN NEW;
|
|
428
|
+
END IF;
|
|
429
|
+
END;
|
|
430
|
+
$$ LANGUAGE plpgsql;
|
|
431
|
+
|
|
432
|
+
-- Create trigger
|
|
433
|
+
DROP TRIGGER IF EXISTS trg_messages_kv_store ON messages;
|
|
434
|
+
CREATE TRIGGER trg_messages_kv_store
|
|
435
|
+
AFTER INSERT OR UPDATE OR DELETE ON messages
|
|
436
|
+
FOR EACH ROW EXECUTE FUNCTION fn_messages_kv_store_upsert();
|
|
437
|
+
|
|
253
438
|
-- ======================================================================
|
|
254
439
|
-- MOMENTS (Model: Moment)
|
|
255
440
|
-- ======================================================================
|
|
@@ -258,7 +443,7 @@ CREATE TABLE IF NOT EXISTS moments (
|
|
|
258
443
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
259
444
|
tenant_id VARCHAR(100) NOT NULL,
|
|
260
445
|
user_id VARCHAR(256),
|
|
261
|
-
name VARCHAR(256)
|
|
446
|
+
name VARCHAR(256),
|
|
262
447
|
moment_type VARCHAR(256),
|
|
263
448
|
category VARCHAR(256),
|
|
264
449
|
starts_timestamp TIMESTAMP NOT NULL,
|
|
@@ -276,11 +461,11 @@ CREATE TABLE IF NOT EXISTS moments (
|
|
|
276
461
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
277
462
|
);
|
|
278
463
|
|
|
279
|
-
CREATE INDEX
|
|
280
|
-
CREATE INDEX
|
|
281
|
-
CREATE INDEX
|
|
282
|
-
CREATE INDEX
|
|
283
|
-
CREATE INDEX
|
|
464
|
+
CREATE INDEX idx_moments_tenant ON moments (tenant_id);
|
|
465
|
+
CREATE INDEX idx_moments_user ON moments (user_id);
|
|
466
|
+
CREATE INDEX idx_moments_graph_edges ON moments USING GIN (graph_edges);
|
|
467
|
+
CREATE INDEX idx_moments_metadata ON moments USING GIN (metadata);
|
|
468
|
+
CREATE INDEX idx_moments_tags ON moments USING GIN (tags);
|
|
284
469
|
|
|
285
470
|
-- Embeddings for moments
|
|
286
471
|
CREATE TABLE IF NOT EXISTS embeddings_moments (
|
|
@@ -298,14 +483,14 @@ CREATE TABLE IF NOT EXISTS embeddings_moments (
|
|
|
298
483
|
);
|
|
299
484
|
|
|
300
485
|
-- Index for entity lookup (get all embeddings for entity)
|
|
301
|
-
CREATE INDEX
|
|
486
|
+
CREATE INDEX idx_embeddings_moments_entity ON embeddings_moments (entity_id);
|
|
302
487
|
|
|
303
488
|
-- Index for field + provider lookup
|
|
304
|
-
CREATE INDEX
|
|
489
|
+
CREATE INDEX idx_embeddings_moments_field_provider ON embeddings_moments (field_name, provider);
|
|
305
490
|
|
|
306
491
|
-- HNSW index for vector similarity search (created in background)
|
|
307
492
|
-- Note: This will be created by background thread after data load
|
|
308
|
-
-- CREATE INDEX
|
|
493
|
+
-- CREATE INDEX idx_embeddings_moments_vector_hnsw ON embeddings_moments
|
|
309
494
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
310
495
|
|
|
311
496
|
-- KV_STORE trigger for moments
|
|
@@ -330,7 +515,7 @@ BEGIN
|
|
|
330
515
|
graph_edges,
|
|
331
516
|
updated_at
|
|
332
517
|
) VALUES (
|
|
333
|
-
NEW.name,
|
|
518
|
+
NEW.name::VARCHAR,
|
|
334
519
|
'moments',
|
|
335
520
|
NEW.id,
|
|
336
521
|
NEW.tenant_id,
|
|
@@ -359,15 +544,22 @@ AFTER INSERT OR UPDATE OR DELETE ON moments
|
|
|
359
544
|
FOR EACH ROW EXECUTE FUNCTION fn_moments_kv_store_upsert();
|
|
360
545
|
|
|
361
546
|
-- ======================================================================
|
|
362
|
-
--
|
|
547
|
+
-- ONTOLOGIES (Model: Ontology)
|
|
363
548
|
-- ======================================================================
|
|
364
549
|
|
|
365
|
-
CREATE TABLE IF NOT EXISTS
|
|
550
|
+
CREATE TABLE IF NOT EXISTS ontologies (
|
|
366
551
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
367
552
|
tenant_id VARCHAR(100) NOT NULL,
|
|
368
553
|
user_id VARCHAR(256),
|
|
369
554
|
name VARCHAR(256) NOT NULL,
|
|
370
|
-
|
|
555
|
+
file_id UUID NOT NULL,
|
|
556
|
+
agent_schema_id VARCHAR(256) NOT NULL,
|
|
557
|
+
provider_name VARCHAR(256) NOT NULL,
|
|
558
|
+
model_name VARCHAR(256) NOT NULL,
|
|
559
|
+
extracted_data JSONB NOT NULL,
|
|
560
|
+
confidence_score DOUBLE PRECISION,
|
|
561
|
+
extraction_timestamp VARCHAR(256),
|
|
562
|
+
embedding_text TEXT,
|
|
371
563
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
372
564
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
373
565
|
deleted_at TIMESTAMP,
|
|
@@ -376,15 +568,15 @@ CREATE TABLE IF NOT EXISTS persons (
|
|
|
376
568
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
377
569
|
);
|
|
378
570
|
|
|
379
|
-
CREATE INDEX
|
|
380
|
-
CREATE INDEX
|
|
381
|
-
CREATE INDEX
|
|
382
|
-
CREATE INDEX
|
|
383
|
-
CREATE INDEX
|
|
571
|
+
CREATE INDEX idx_ontologies_tenant ON ontologies (tenant_id);
|
|
572
|
+
CREATE INDEX idx_ontologies_user ON ontologies (user_id);
|
|
573
|
+
CREATE INDEX idx_ontologies_graph_edges ON ontologies USING GIN (graph_edges);
|
|
574
|
+
CREATE INDEX idx_ontologies_metadata ON ontologies USING GIN (metadata);
|
|
575
|
+
CREATE INDEX idx_ontologies_tags ON ontologies USING GIN (tags);
|
|
384
576
|
|
|
385
|
-
-- KV_STORE trigger for
|
|
386
|
-
-- Trigger function to maintain KV_STORE for
|
|
387
|
-
CREATE OR REPLACE FUNCTION
|
|
577
|
+
-- KV_STORE trigger for ontologies
|
|
578
|
+
-- Trigger function to maintain KV_STORE for ontologies
|
|
579
|
+
CREATE OR REPLACE FUNCTION fn_ontologies_kv_store_upsert()
|
|
388
580
|
RETURNS TRIGGER AS $$
|
|
389
581
|
BEGIN
|
|
390
582
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -404,8 +596,8 @@ BEGIN
|
|
|
404
596
|
graph_edges,
|
|
405
597
|
updated_at
|
|
406
598
|
) VALUES (
|
|
407
|
-
NEW.
|
|
408
|
-
'
|
|
599
|
+
NEW.id::VARCHAR,
|
|
600
|
+
'ontologies',
|
|
409
601
|
NEW.id,
|
|
410
602
|
NEW.tenant_id,
|
|
411
603
|
NEW.user_id,
|
|
@@ -427,26 +619,29 @@ END;
|
|
|
427
619
|
$$ LANGUAGE plpgsql;
|
|
428
620
|
|
|
429
621
|
-- Create trigger
|
|
430
|
-
DROP TRIGGER IF EXISTS
|
|
431
|
-
CREATE TRIGGER
|
|
432
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
433
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
622
|
+
DROP TRIGGER IF EXISTS trg_ontologies_kv_store ON ontologies;
|
|
623
|
+
CREATE TRIGGER trg_ontologies_kv_store
|
|
624
|
+
AFTER INSERT OR UPDATE OR DELETE ON ontologies
|
|
625
|
+
FOR EACH ROW EXECUTE FUNCTION fn_ontologies_kv_store_upsert();
|
|
434
626
|
|
|
435
627
|
-- ======================================================================
|
|
436
|
-
--
|
|
628
|
+
-- ONTOLOGY_CONFIGS (Model: OntologyConfig)
|
|
437
629
|
-- ======================================================================
|
|
438
630
|
|
|
439
|
-
CREATE TABLE IF NOT EXISTS
|
|
631
|
+
CREATE TABLE IF NOT EXISTS ontology_configs (
|
|
440
632
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
441
633
|
tenant_id VARCHAR(100) NOT NULL,
|
|
442
634
|
user_id VARCHAR(256),
|
|
443
635
|
name VARCHAR(256) NOT NULL,
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
636
|
+
agent_schema_id VARCHAR(256) NOT NULL,
|
|
637
|
+
description TEXT,
|
|
638
|
+
mime_type_pattern VARCHAR(256),
|
|
639
|
+
uri_pattern VARCHAR(256),
|
|
640
|
+
tag_filter TEXT[],
|
|
641
|
+
priority INTEGER,
|
|
642
|
+
enabled BOOLEAN,
|
|
643
|
+
provider_name VARCHAR(256),
|
|
644
|
+
model_name VARCHAR(256),
|
|
450
645
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
451
646
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
452
647
|
deleted_at TIMESTAMP,
|
|
@@ -455,16 +650,16 @@ CREATE TABLE IF NOT EXISTS resources (
|
|
|
455
650
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
456
651
|
);
|
|
457
652
|
|
|
458
|
-
CREATE INDEX
|
|
459
|
-
CREATE INDEX
|
|
460
|
-
CREATE INDEX
|
|
461
|
-
CREATE INDEX
|
|
462
|
-
CREATE INDEX
|
|
653
|
+
CREATE INDEX idx_ontology_configs_tenant ON ontology_configs (tenant_id);
|
|
654
|
+
CREATE INDEX idx_ontology_configs_user ON ontology_configs (user_id);
|
|
655
|
+
CREATE INDEX idx_ontology_configs_graph_edges ON ontology_configs USING GIN (graph_edges);
|
|
656
|
+
CREATE INDEX idx_ontology_configs_metadata ON ontology_configs USING GIN (metadata);
|
|
657
|
+
CREATE INDEX idx_ontology_configs_tags ON ontology_configs USING GIN (tags);
|
|
463
658
|
|
|
464
|
-
-- Embeddings for
|
|
465
|
-
CREATE TABLE IF NOT EXISTS
|
|
659
|
+
-- Embeddings for ontology_configs
|
|
660
|
+
CREATE TABLE IF NOT EXISTS embeddings_ontology_configs (
|
|
466
661
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
467
|
-
entity_id UUID NOT NULL REFERENCES
|
|
662
|
+
entity_id UUID NOT NULL REFERENCES ontology_configs(id) ON DELETE CASCADE,
|
|
468
663
|
field_name VARCHAR(100) NOT NULL,
|
|
469
664
|
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
470
665
|
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
@@ -477,19 +672,19 @@ CREATE TABLE IF NOT EXISTS embeddings_resources (
|
|
|
477
672
|
);
|
|
478
673
|
|
|
479
674
|
-- Index for entity lookup (get all embeddings for entity)
|
|
480
|
-
CREATE INDEX
|
|
675
|
+
CREATE INDEX idx_embeddings_ontology_configs_entity ON embeddings_ontology_configs (entity_id);
|
|
481
676
|
|
|
482
677
|
-- Index for field + provider lookup
|
|
483
|
-
CREATE INDEX
|
|
678
|
+
CREATE INDEX idx_embeddings_ontology_configs_field_provider ON embeddings_ontology_configs (field_name, provider);
|
|
484
679
|
|
|
485
680
|
-- HNSW index for vector similarity search (created in background)
|
|
486
681
|
-- Note: This will be created by background thread after data load
|
|
487
|
-
-- CREATE INDEX
|
|
682
|
+
-- CREATE INDEX idx_embeddings_ontology_configs_vector_hnsw ON embeddings_ontology_configs
|
|
488
683
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
489
684
|
|
|
490
|
-
-- KV_STORE trigger for
|
|
491
|
-
-- Trigger function to maintain KV_STORE for
|
|
492
|
-
CREATE OR REPLACE FUNCTION
|
|
685
|
+
-- KV_STORE trigger for ontology_configs
|
|
686
|
+
-- Trigger function to maintain KV_STORE for ontology_configs
|
|
687
|
+
CREATE OR REPLACE FUNCTION fn_ontology_configs_kv_store_upsert()
|
|
493
688
|
RETURNS TRIGGER AS $$
|
|
494
689
|
BEGIN
|
|
495
690
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -509,8 +704,8 @@ BEGIN
|
|
|
509
704
|
graph_edges,
|
|
510
705
|
updated_at
|
|
511
706
|
) VALUES (
|
|
512
|
-
NEW.
|
|
513
|
-
'
|
|
707
|
+
NEW.id::VARCHAR,
|
|
708
|
+
'ontology_configs',
|
|
514
709
|
NEW.id,
|
|
515
710
|
NEW.tenant_id,
|
|
516
711
|
NEW.user_id,
|
|
@@ -532,22 +727,26 @@ END;
|
|
|
532
727
|
$$ LANGUAGE plpgsql;
|
|
533
728
|
|
|
534
729
|
-- Create trigger
|
|
535
|
-
DROP TRIGGER IF EXISTS
|
|
536
|
-
CREATE TRIGGER
|
|
537
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
538
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
730
|
+
DROP TRIGGER IF EXISTS trg_ontology_configs_kv_store ON ontology_configs;
|
|
731
|
+
CREATE TRIGGER trg_ontology_configs_kv_store
|
|
732
|
+
AFTER INSERT OR UPDATE OR DELETE ON ontology_configs
|
|
733
|
+
FOR EACH ROW EXECUTE FUNCTION fn_ontology_configs_kv_store_upsert();
|
|
539
734
|
|
|
540
735
|
-- ======================================================================
|
|
541
|
-
--
|
|
736
|
+
-- RESOURCES (Model: Resource)
|
|
542
737
|
-- ======================================================================
|
|
543
738
|
|
|
544
|
-
CREATE TABLE IF NOT EXISTS
|
|
739
|
+
CREATE TABLE IF NOT EXISTS resources (
|
|
545
740
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
546
741
|
tenant_id VARCHAR(100) NOT NULL,
|
|
547
742
|
user_id VARCHAR(256),
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
743
|
+
name VARCHAR(256),
|
|
744
|
+
uri VARCHAR(256),
|
|
745
|
+
ordinal INTEGER,
|
|
746
|
+
content TEXT,
|
|
747
|
+
timestamp TIMESTAMP,
|
|
748
|
+
category VARCHAR(256),
|
|
749
|
+
related_entities JSONB DEFAULT '{}'::jsonb,
|
|
551
750
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
552
751
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
553
752
|
deleted_at TIMESTAMP,
|
|
@@ -556,16 +755,16 @@ CREATE TABLE IF NOT EXISTS messages (
|
|
|
556
755
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
557
756
|
);
|
|
558
757
|
|
|
559
|
-
CREATE INDEX
|
|
560
|
-
CREATE INDEX
|
|
561
|
-
CREATE INDEX
|
|
562
|
-
CREATE INDEX
|
|
563
|
-
CREATE INDEX
|
|
758
|
+
CREATE INDEX idx_resources_tenant ON resources (tenant_id);
|
|
759
|
+
CREATE INDEX idx_resources_user ON resources (user_id);
|
|
760
|
+
CREATE INDEX idx_resources_graph_edges ON resources USING GIN (graph_edges);
|
|
761
|
+
CREATE INDEX idx_resources_metadata ON resources USING GIN (metadata);
|
|
762
|
+
CREATE INDEX idx_resources_tags ON resources USING GIN (tags);
|
|
564
763
|
|
|
565
|
-
-- Embeddings for
|
|
566
|
-
CREATE TABLE IF NOT EXISTS
|
|
764
|
+
-- Embeddings for resources
|
|
765
|
+
CREATE TABLE IF NOT EXISTS embeddings_resources (
|
|
567
766
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
568
|
-
entity_id UUID NOT NULL REFERENCES
|
|
767
|
+
entity_id UUID NOT NULL REFERENCES resources(id) ON DELETE CASCADE,
|
|
569
768
|
field_name VARCHAR(100) NOT NULL,
|
|
570
769
|
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
571
770
|
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
@@ -578,19 +777,19 @@ CREATE TABLE IF NOT EXISTS embeddings_messages (
|
|
|
578
777
|
);
|
|
579
778
|
|
|
580
779
|
-- Index for entity lookup (get all embeddings for entity)
|
|
581
|
-
CREATE INDEX
|
|
780
|
+
CREATE INDEX idx_embeddings_resources_entity ON embeddings_resources (entity_id);
|
|
582
781
|
|
|
583
782
|
-- Index for field + provider lookup
|
|
584
|
-
CREATE INDEX
|
|
783
|
+
CREATE INDEX idx_embeddings_resources_field_provider ON embeddings_resources (field_name, provider);
|
|
585
784
|
|
|
586
785
|
-- HNSW index for vector similarity search (created in background)
|
|
587
786
|
-- Note: This will be created by background thread after data load
|
|
588
|
-
-- CREATE INDEX
|
|
787
|
+
-- CREATE INDEX idx_embeddings_resources_vector_hnsw ON embeddings_resources
|
|
589
788
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
590
789
|
|
|
591
|
-
-- KV_STORE trigger for
|
|
592
|
-
-- Trigger function to maintain KV_STORE for
|
|
593
|
-
CREATE OR REPLACE FUNCTION
|
|
790
|
+
-- KV_STORE trigger for resources
|
|
791
|
+
-- Trigger function to maintain KV_STORE for resources
|
|
792
|
+
CREATE OR REPLACE FUNCTION fn_resources_kv_store_upsert()
|
|
594
793
|
RETURNS TRIGGER AS $$
|
|
595
794
|
BEGIN
|
|
596
795
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -610,8 +809,8 @@ BEGIN
|
|
|
610
809
|
graph_edges,
|
|
611
810
|
updated_at
|
|
612
811
|
) VALUES (
|
|
613
|
-
NEW.
|
|
614
|
-
'
|
|
812
|
+
NEW.name::VARCHAR,
|
|
813
|
+
'resources',
|
|
615
814
|
NEW.id,
|
|
616
815
|
NEW.tenant_id,
|
|
617
816
|
NEW.user_id,
|
|
@@ -633,26 +832,25 @@ END;
|
|
|
633
832
|
$$ LANGUAGE plpgsql;
|
|
634
833
|
|
|
635
834
|
-- Create trigger
|
|
636
|
-
DROP TRIGGER IF EXISTS
|
|
637
|
-
CREATE TRIGGER
|
|
638
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
639
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
835
|
+
DROP TRIGGER IF EXISTS trg_resources_kv_store ON resources;
|
|
836
|
+
CREATE TRIGGER trg_resources_kv_store
|
|
837
|
+
AFTER INSERT OR UPDATE OR DELETE ON resources
|
|
838
|
+
FOR EACH ROW EXECUTE FUNCTION fn_resources_kv_store_upsert();
|
|
640
839
|
|
|
641
840
|
-- ======================================================================
|
|
642
|
-
--
|
|
841
|
+
-- SCHEMAS (Model: Schema)
|
|
643
842
|
-- ======================================================================
|
|
644
843
|
|
|
645
|
-
CREATE TABLE IF NOT EXISTS
|
|
844
|
+
CREATE TABLE IF NOT EXISTS schemas (
|
|
646
845
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
647
846
|
tenant_id VARCHAR(100) NOT NULL,
|
|
648
847
|
user_id VARCHAR(256),
|
|
649
848
|
name VARCHAR(256) NOT NULL,
|
|
650
|
-
uri VARCHAR(256) NOT NULL,
|
|
651
849
|
content TEXT,
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
850
|
+
spec JSONB NOT NULL,
|
|
851
|
+
category VARCHAR(256),
|
|
852
|
+
provider_configs JSONB DEFAULT '{}'::jsonb,
|
|
853
|
+
embedding_fields TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
656
854
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
657
855
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
658
856
|
deleted_at TIMESTAMP,
|
|
@@ -661,16 +859,16 @@ CREATE TABLE IF NOT EXISTS files (
|
|
|
661
859
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
662
860
|
);
|
|
663
861
|
|
|
664
|
-
CREATE INDEX
|
|
665
|
-
CREATE INDEX
|
|
666
|
-
CREATE INDEX
|
|
667
|
-
CREATE INDEX
|
|
668
|
-
CREATE INDEX
|
|
862
|
+
CREATE INDEX idx_schemas_tenant ON schemas (tenant_id);
|
|
863
|
+
CREATE INDEX idx_schemas_user ON schemas (user_id);
|
|
864
|
+
CREATE INDEX idx_schemas_graph_edges ON schemas USING GIN (graph_edges);
|
|
865
|
+
CREATE INDEX idx_schemas_metadata ON schemas USING GIN (metadata);
|
|
866
|
+
CREATE INDEX idx_schemas_tags ON schemas USING GIN (tags);
|
|
669
867
|
|
|
670
|
-
-- Embeddings for
|
|
671
|
-
CREATE TABLE IF NOT EXISTS
|
|
868
|
+
-- Embeddings for schemas
|
|
869
|
+
CREATE TABLE IF NOT EXISTS embeddings_schemas (
|
|
672
870
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
673
|
-
entity_id UUID NOT NULL REFERENCES
|
|
871
|
+
entity_id UUID NOT NULL REFERENCES schemas(id) ON DELETE CASCADE,
|
|
674
872
|
field_name VARCHAR(100) NOT NULL,
|
|
675
873
|
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
676
874
|
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
@@ -683,19 +881,19 @@ CREATE TABLE IF NOT EXISTS embeddings_files (
|
|
|
683
881
|
);
|
|
684
882
|
|
|
685
883
|
-- Index for entity lookup (get all embeddings for entity)
|
|
686
|
-
CREATE INDEX
|
|
884
|
+
CREATE INDEX idx_embeddings_schemas_entity ON embeddings_schemas (entity_id);
|
|
687
885
|
|
|
688
886
|
-- Index for field + provider lookup
|
|
689
|
-
CREATE INDEX
|
|
887
|
+
CREATE INDEX idx_embeddings_schemas_field_provider ON embeddings_schemas (field_name, provider);
|
|
690
888
|
|
|
691
889
|
-- HNSW index for vector similarity search (created in background)
|
|
692
890
|
-- Note: This will be created by background thread after data load
|
|
693
|
-
-- CREATE INDEX
|
|
891
|
+
-- CREATE INDEX idx_embeddings_schemas_vector_hnsw ON embeddings_schemas
|
|
694
892
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
695
893
|
|
|
696
|
-
-- KV_STORE trigger for
|
|
697
|
-
-- Trigger function to maintain KV_STORE for
|
|
698
|
-
CREATE OR REPLACE FUNCTION
|
|
894
|
+
-- KV_STORE trigger for schemas
|
|
895
|
+
-- Trigger function to maintain KV_STORE for schemas
|
|
896
|
+
CREATE OR REPLACE FUNCTION fn_schemas_kv_store_upsert()
|
|
699
897
|
RETURNS TRIGGER AS $$
|
|
700
898
|
BEGIN
|
|
701
899
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -715,8 +913,8 @@ BEGIN
|
|
|
715
913
|
graph_edges,
|
|
716
914
|
updated_at
|
|
717
915
|
) VALUES (
|
|
718
|
-
NEW.
|
|
719
|
-
'
|
|
916
|
+
NEW.id::VARCHAR,
|
|
917
|
+
'schemas',
|
|
720
918
|
NEW.id,
|
|
721
919
|
NEW.tenant_id,
|
|
722
920
|
NEW.user_id,
|
|
@@ -738,28 +936,28 @@ END;
|
|
|
738
936
|
$$ LANGUAGE plpgsql;
|
|
739
937
|
|
|
740
938
|
-- Create trigger
|
|
741
|
-
DROP TRIGGER IF EXISTS
|
|
742
|
-
CREATE TRIGGER
|
|
743
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
744
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
939
|
+
DROP TRIGGER IF EXISTS trg_schemas_kv_store ON schemas;
|
|
940
|
+
CREATE TRIGGER trg_schemas_kv_store
|
|
941
|
+
AFTER INSERT OR UPDATE OR DELETE ON schemas
|
|
942
|
+
FOR EACH ROW EXECUTE FUNCTION fn_schemas_kv_store_upsert();
|
|
745
943
|
|
|
746
944
|
-- ======================================================================
|
|
747
|
-
--
|
|
945
|
+
-- SESSIONS (Model: Session)
|
|
748
946
|
-- ======================================================================
|
|
749
947
|
|
|
750
|
-
CREATE TABLE IF NOT EXISTS
|
|
948
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
751
949
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
752
950
|
tenant_id VARCHAR(100) NOT NULL,
|
|
753
951
|
user_id VARCHAR(256),
|
|
754
952
|
name VARCHAR(256) NOT NULL,
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
953
|
+
mode TEXT,
|
|
954
|
+
description TEXT,
|
|
955
|
+
original_trace_id VARCHAR(256),
|
|
956
|
+
settings_overrides JSONB,
|
|
957
|
+
prompt TEXT,
|
|
958
|
+
agent_schema_uri VARCHAR(256),
|
|
959
|
+
message_count INTEGER,
|
|
960
|
+
total_tokens INTEGER,
|
|
763
961
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
764
962
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
765
963
|
deleted_at TIMESTAMP,
|
|
@@ -768,15 +966,41 @@ CREATE TABLE IF NOT EXISTS ontologies (
|
|
|
768
966
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
769
967
|
);
|
|
770
968
|
|
|
771
|
-
CREATE INDEX
|
|
772
|
-
CREATE INDEX
|
|
773
|
-
CREATE INDEX
|
|
774
|
-
CREATE INDEX
|
|
775
|
-
CREATE INDEX
|
|
969
|
+
CREATE INDEX idx_sessions_tenant ON sessions (tenant_id);
|
|
970
|
+
CREATE INDEX idx_sessions_user ON sessions (user_id);
|
|
971
|
+
CREATE INDEX idx_sessions_graph_edges ON sessions USING GIN (graph_edges);
|
|
972
|
+
CREATE INDEX idx_sessions_metadata ON sessions USING GIN (metadata);
|
|
973
|
+
CREATE INDEX idx_sessions_tags ON sessions USING GIN (tags);
|
|
776
974
|
|
|
777
|
-
--
|
|
778
|
-
|
|
779
|
-
|
|
975
|
+
-- Embeddings for sessions
|
|
976
|
+
CREATE TABLE IF NOT EXISTS embeddings_sessions (
|
|
977
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
978
|
+
entity_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
979
|
+
field_name VARCHAR(100) NOT NULL,
|
|
980
|
+
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
981
|
+
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
982
|
+
embedding vector(1536) NOT NULL,
|
|
983
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
984
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
985
|
+
|
|
986
|
+
-- Unique: one embedding per entity per field per provider
|
|
987
|
+
UNIQUE (entity_id, field_name, provider)
|
|
988
|
+
);
|
|
989
|
+
|
|
990
|
+
-- Index for entity lookup (get all embeddings for entity)
|
|
991
|
+
CREATE INDEX idx_embeddings_sessions_entity ON embeddings_sessions (entity_id);
|
|
992
|
+
|
|
993
|
+
-- Index for field + provider lookup
|
|
994
|
+
CREATE INDEX idx_embeddings_sessions_field_provider ON embeddings_sessions (field_name, provider);
|
|
995
|
+
|
|
996
|
+
-- HNSW index for vector similarity search (created in background)
|
|
997
|
+
-- Note: This will be created by background thread after data load
|
|
998
|
+
-- CREATE INDEX idx_embeddings_sessions_vector_hnsw ON embeddings_sessions
|
|
999
|
+
-- USING hnsw (embedding vector_cosine_ops);
|
|
1000
|
+
|
|
1001
|
+
-- KV_STORE trigger for sessions
|
|
1002
|
+
-- Trigger function to maintain KV_STORE for sessions
|
|
1003
|
+
CREATE OR REPLACE FUNCTION fn_sessions_kv_store_upsert()
|
|
780
1004
|
RETURNS TRIGGER AS $$
|
|
781
1005
|
BEGIN
|
|
782
1006
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -796,8 +1020,8 @@ BEGIN
|
|
|
796
1020
|
graph_edges,
|
|
797
1021
|
updated_at
|
|
798
1022
|
) VALUES (
|
|
799
|
-
NEW.name,
|
|
800
|
-
'
|
|
1023
|
+
NEW.name::VARCHAR,
|
|
1024
|
+
'sessions',
|
|
801
1025
|
NEW.id,
|
|
802
1026
|
NEW.tenant_id,
|
|
803
1027
|
NEW.user_id,
|
|
@@ -819,29 +1043,22 @@ END;
|
|
|
819
1043
|
$$ LANGUAGE plpgsql;
|
|
820
1044
|
|
|
821
1045
|
-- Create trigger
|
|
822
|
-
DROP TRIGGER IF EXISTS
|
|
823
|
-
CREATE TRIGGER
|
|
824
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
825
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
1046
|
+
DROP TRIGGER IF EXISTS trg_sessions_kv_store ON sessions;
|
|
1047
|
+
CREATE TRIGGER trg_sessions_kv_store
|
|
1048
|
+
AFTER INSERT OR UPDATE OR DELETE ON sessions
|
|
1049
|
+
FOR EACH ROW EXECUTE FUNCTION fn_sessions_kv_store_upsert();
|
|
826
1050
|
|
|
827
1051
|
-- ======================================================================
|
|
828
|
-
--
|
|
1052
|
+
-- SHARED_SESSIONS (Model: SharedSession)
|
|
829
1053
|
-- ======================================================================
|
|
830
1054
|
|
|
831
|
-
CREATE TABLE IF NOT EXISTS
|
|
1055
|
+
CREATE TABLE IF NOT EXISTS shared_sessions (
|
|
832
1056
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
833
1057
|
tenant_id VARCHAR(100) NOT NULL,
|
|
834
1058
|
user_id VARCHAR(256),
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
mime_type_pattern VARCHAR(256),
|
|
839
|
-
uri_pattern VARCHAR(256),
|
|
840
|
-
tag_filter TEXT[],
|
|
841
|
-
priority INTEGER,
|
|
842
|
-
enabled BOOLEAN,
|
|
843
|
-
provider_name VARCHAR(256),
|
|
844
|
-
model_name VARCHAR(256),
|
|
1059
|
+
session_id VARCHAR(256) NOT NULL,
|
|
1060
|
+
owner_user_id VARCHAR(256) NOT NULL,
|
|
1061
|
+
shared_with_user_id VARCHAR(256) NOT NULL,
|
|
845
1062
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
846
1063
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
847
1064
|
deleted_at TIMESTAMP,
|
|
@@ -850,41 +1067,15 @@ CREATE TABLE IF NOT EXISTS ontology_configs (
|
|
|
850
1067
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
851
1068
|
);
|
|
852
1069
|
|
|
853
|
-
CREATE INDEX
|
|
854
|
-
CREATE INDEX
|
|
855
|
-
CREATE INDEX
|
|
856
|
-
CREATE INDEX
|
|
857
|
-
CREATE INDEX
|
|
858
|
-
|
|
859
|
-
-- Embeddings for ontology_configs
|
|
860
|
-
CREATE TABLE IF NOT EXISTS embeddings_ontology_configs (
|
|
861
|
-
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
862
|
-
entity_id UUID NOT NULL REFERENCES ontology_configs(id) ON DELETE CASCADE,
|
|
863
|
-
field_name VARCHAR(100) NOT NULL,
|
|
864
|
-
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
865
|
-
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
866
|
-
embedding vector(1536) NOT NULL,
|
|
867
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
868
|
-
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
869
|
-
|
|
870
|
-
-- Unique: one embedding per entity per field per provider
|
|
871
|
-
UNIQUE (entity_id, field_name, provider)
|
|
872
|
-
);
|
|
873
|
-
|
|
874
|
-
-- Index for entity lookup (get all embeddings for entity)
|
|
875
|
-
CREATE INDEX IF NOT EXISTS idx_embeddings_ontology_configs_entity ON embeddings_ontology_configs (entity_id);
|
|
876
|
-
|
|
877
|
-
-- Index for field + provider lookup
|
|
878
|
-
CREATE INDEX IF NOT EXISTS idx_embeddings_ontology_configs_field_provider ON embeddings_ontology_configs (field_name, provider);
|
|
1070
|
+
CREATE INDEX idx_shared_sessions_tenant ON shared_sessions (tenant_id);
|
|
1071
|
+
CREATE INDEX idx_shared_sessions_user ON shared_sessions (user_id);
|
|
1072
|
+
CREATE INDEX idx_shared_sessions_graph_edges ON shared_sessions USING GIN (graph_edges);
|
|
1073
|
+
CREATE INDEX idx_shared_sessions_metadata ON shared_sessions USING GIN (metadata);
|
|
1074
|
+
CREATE INDEX idx_shared_sessions_tags ON shared_sessions USING GIN (tags);
|
|
879
1075
|
|
|
880
|
-
--
|
|
881
|
-
--
|
|
882
|
-
|
|
883
|
-
-- USING hnsw (embedding vector_cosine_ops);
|
|
884
|
-
|
|
885
|
-
-- KV_STORE trigger for ontology_configs
|
|
886
|
-
-- Trigger function to maintain KV_STORE for ontology_configs
|
|
887
|
-
CREATE OR REPLACE FUNCTION fn_ontology_configs_kv_store_upsert()
|
|
1076
|
+
-- KV_STORE trigger for shared_sessions
|
|
1077
|
+
-- Trigger function to maintain KV_STORE for shared_sessions
|
|
1078
|
+
CREATE OR REPLACE FUNCTION fn_shared_sessions_kv_store_upsert()
|
|
888
1079
|
RETURNS TRIGGER AS $$
|
|
889
1080
|
BEGIN
|
|
890
1081
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -904,8 +1095,8 @@ BEGIN
|
|
|
904
1095
|
graph_edges,
|
|
905
1096
|
updated_at
|
|
906
1097
|
) VALUES (
|
|
907
|
-
NEW.
|
|
908
|
-
'
|
|
1098
|
+
NEW.id::VARCHAR,
|
|
1099
|
+
'shared_sessions',
|
|
909
1100
|
NEW.id,
|
|
910
1101
|
NEW.tenant_id,
|
|
911
1102
|
NEW.user_id,
|
|
@@ -927,25 +1118,30 @@ END;
|
|
|
927
1118
|
$$ LANGUAGE plpgsql;
|
|
928
1119
|
|
|
929
1120
|
-- Create trigger
|
|
930
|
-
DROP TRIGGER IF EXISTS
|
|
931
|
-
CREATE TRIGGER
|
|
932
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
933
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
1121
|
+
DROP TRIGGER IF EXISTS trg_shared_sessions_kv_store ON shared_sessions;
|
|
1122
|
+
CREATE TRIGGER trg_shared_sessions_kv_store
|
|
1123
|
+
AFTER INSERT OR UPDATE OR DELETE ON shared_sessions
|
|
1124
|
+
FOR EACH ROW EXECUTE FUNCTION fn_shared_sessions_kv_store_upsert();
|
|
934
1125
|
|
|
935
1126
|
-- ======================================================================
|
|
936
|
-
--
|
|
1127
|
+
-- USERS (Model: User)
|
|
937
1128
|
-- ======================================================================
|
|
938
1129
|
|
|
939
|
-
CREATE TABLE IF NOT EXISTS
|
|
1130
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
940
1131
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
941
1132
|
tenant_id VARCHAR(100) NOT NULL,
|
|
942
1133
|
user_id VARCHAR(256),
|
|
943
1134
|
name VARCHAR(256) NOT NULL,
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1135
|
+
email VARCHAR(256),
|
|
1136
|
+
role VARCHAR(256),
|
|
1137
|
+
tier TEXT,
|
|
1138
|
+
anonymous_ids TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
1139
|
+
sec_policy JSONB DEFAULT '{}'::jsonb,
|
|
1140
|
+
summary TEXT,
|
|
1141
|
+
interests TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
1142
|
+
preferred_topics TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
1143
|
+
activity_level VARCHAR(256),
|
|
1144
|
+
last_active_at TIMESTAMP,
|
|
949
1145
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
950
1146
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
951
1147
|
deleted_at TIMESTAMP,
|
|
@@ -954,16 +1150,16 @@ CREATE TABLE IF NOT EXISTS schemas (
|
|
|
954
1150
|
tags TEXT[] DEFAULT ARRAY[]::TEXT[]
|
|
955
1151
|
);
|
|
956
1152
|
|
|
957
|
-
CREATE INDEX
|
|
958
|
-
CREATE INDEX
|
|
959
|
-
CREATE INDEX
|
|
960
|
-
CREATE INDEX
|
|
961
|
-
CREATE INDEX
|
|
1153
|
+
CREATE INDEX idx_users_tenant ON users (tenant_id);
|
|
1154
|
+
CREATE INDEX idx_users_user ON users (user_id);
|
|
1155
|
+
CREATE INDEX idx_users_graph_edges ON users USING GIN (graph_edges);
|
|
1156
|
+
CREATE INDEX idx_users_metadata ON users USING GIN (metadata);
|
|
1157
|
+
CREATE INDEX idx_users_tags ON users USING GIN (tags);
|
|
962
1158
|
|
|
963
|
-
-- Embeddings for
|
|
964
|
-
CREATE TABLE IF NOT EXISTS
|
|
1159
|
+
-- Embeddings for users
|
|
1160
|
+
CREATE TABLE IF NOT EXISTS embeddings_users (
|
|
965
1161
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
966
|
-
entity_id UUID NOT NULL REFERENCES
|
|
1162
|
+
entity_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
967
1163
|
field_name VARCHAR(100) NOT NULL,
|
|
968
1164
|
provider VARCHAR(50) NOT NULL DEFAULT 'openai',
|
|
969
1165
|
model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
|
|
@@ -976,19 +1172,19 @@ CREATE TABLE IF NOT EXISTS embeddings_schemas (
|
|
|
976
1172
|
);
|
|
977
1173
|
|
|
978
1174
|
-- Index for entity lookup (get all embeddings for entity)
|
|
979
|
-
CREATE INDEX
|
|
1175
|
+
CREATE INDEX idx_embeddings_users_entity ON embeddings_users (entity_id);
|
|
980
1176
|
|
|
981
1177
|
-- Index for field + provider lookup
|
|
982
|
-
CREATE INDEX
|
|
1178
|
+
CREATE INDEX idx_embeddings_users_field_provider ON embeddings_users (field_name, provider);
|
|
983
1179
|
|
|
984
1180
|
-- HNSW index for vector similarity search (created in background)
|
|
985
1181
|
-- Note: This will be created by background thread after data load
|
|
986
|
-
-- CREATE INDEX
|
|
1182
|
+
-- CREATE INDEX idx_embeddings_users_vector_hnsw ON embeddings_users
|
|
987
1183
|
-- USING hnsw (embedding vector_cosine_ops);
|
|
988
1184
|
|
|
989
|
-
-- KV_STORE trigger for
|
|
990
|
-
-- Trigger function to maintain KV_STORE for
|
|
991
|
-
CREATE OR REPLACE FUNCTION
|
|
1185
|
+
-- KV_STORE trigger for users
|
|
1186
|
+
-- Trigger function to maintain KV_STORE for users
|
|
1187
|
+
CREATE OR REPLACE FUNCTION fn_users_kv_store_upsert()
|
|
992
1188
|
RETURNS TRIGGER AS $$
|
|
993
1189
|
BEGIN
|
|
994
1190
|
IF (TG_OP = 'DELETE') THEN
|
|
@@ -1008,8 +1204,8 @@ BEGIN
|
|
|
1008
1204
|
graph_edges,
|
|
1009
1205
|
updated_at
|
|
1010
1206
|
) VALUES (
|
|
1011
|
-
NEW.name,
|
|
1012
|
-
'
|
|
1207
|
+
NEW.name::VARCHAR,
|
|
1208
|
+
'users',
|
|
1013
1209
|
NEW.id,
|
|
1014
1210
|
NEW.tenant_id,
|
|
1015
1211
|
NEW.user_id,
|
|
@@ -1031,10 +1227,10 @@ END;
|
|
|
1031
1227
|
$$ LANGUAGE plpgsql;
|
|
1032
1228
|
|
|
1033
1229
|
-- Create trigger
|
|
1034
|
-
DROP TRIGGER IF EXISTS
|
|
1035
|
-
CREATE TRIGGER
|
|
1036
|
-
AFTER INSERT OR UPDATE OR DELETE ON
|
|
1037
|
-
FOR EACH ROW EXECUTE FUNCTION
|
|
1230
|
+
DROP TRIGGER IF EXISTS trg_users_kv_store ON users;
|
|
1231
|
+
CREATE TRIGGER trg_users_kv_store
|
|
1232
|
+
AFTER INSERT OR UPDATE OR DELETE ON users
|
|
1233
|
+
FOR EACH ROW EXECUTE FUNCTION fn_users_kv_store_upsert();
|
|
1038
1234
|
|
|
1039
1235
|
-- ============================================================================
|
|
1040
1236
|
-- RECORD MIGRATION
|
|
@@ -1049,154 +1245,22 @@ SET applied_at = CURRENT_TIMESTAMP,
|
|
|
1049
1245
|
DO $$
|
|
1050
1246
|
BEGIN
|
|
1051
1247
|
RAISE NOTICE '============================================================';
|
|
1052
|
-
RAISE NOTICE 'REM Model Schema Applied:
|
|
1248
|
+
RAISE NOTICE 'REM Model Schema Applied: 12 tables';
|
|
1053
1249
|
RAISE NOTICE '============================================================';
|
|
1250
|
+
RAISE NOTICE ' ✓ feedbacks';
|
|
1054
1251
|
RAISE NOTICE ' ✓ files (1 embeddable fields)';
|
|
1055
1252
|
RAISE NOTICE ' ✓ image_resources (1 embeddable fields)';
|
|
1056
1253
|
RAISE NOTICE ' ✓ messages (1 embeddable fields)';
|
|
1057
1254
|
RAISE NOTICE ' ✓ moments (1 embeddable fields)';
|
|
1058
1255
|
RAISE NOTICE ' ✓ ontologies';
|
|
1059
1256
|
RAISE NOTICE ' ✓ ontology_configs (1 embeddable fields)';
|
|
1060
|
-
RAISE NOTICE ' ✓ persons';
|
|
1061
1257
|
RAISE NOTICE ' ✓ resources (1 embeddable fields)';
|
|
1062
1258
|
RAISE NOTICE ' ✓ schemas (1 embeddable fields)';
|
|
1259
|
+
RAISE NOTICE ' ✓ sessions (1 embeddable fields)';
|
|
1260
|
+
RAISE NOTICE ' ✓ shared_sessions';
|
|
1063
1261
|
RAISE NOTICE ' ✓ users (1 embeddable fields)';
|
|
1064
1262
|
RAISE NOTICE '';
|
|
1065
1263
|
RAISE NOTICE 'Next: Run background indexes if needed';
|
|
1066
1264
|
RAISE NOTICE ' rem db migrate --background-indexes';
|
|
1067
1265
|
RAISE NOTICE '============================================================';
|
|
1068
|
-
END $$;
|
|
1069
|
-
-- ============================================================================
|
|
1070
|
-
-- REM TRAVERSE (Graph Traversal)
|
|
1071
|
-
-- ============================================================================
|
|
1072
|
-
|
|
1073
|
-
-- REM TRAVERSE: Recursive graph traversal following edges
|
|
1074
|
-
-- Explores graph_edges starting from entity_key up to max_depth
|
|
1075
|
-
-- Uses cached kv_store.graph_edges for fast traversal (no polymorphic view!)
|
|
1076
|
-
-- When keys_only=false, automatically fetches full entity records
|
|
1077
|
-
CREATE OR REPLACE FUNCTION rem_traverse(
|
|
1078
|
-
p_entity_key VARCHAR(255),
|
|
1079
|
-
p_tenant_id VARCHAR(100), -- Backward compat parameter (not used for filtering)
|
|
1080
|
-
p_user_id VARCHAR(100),
|
|
1081
|
-
p_max_depth INTEGER DEFAULT 1,
|
|
1082
|
-
p_rel_type VARCHAR(100) DEFAULT NULL,
|
|
1083
|
-
p_keys_only BOOLEAN DEFAULT FALSE
|
|
1084
|
-
)
|
|
1085
|
-
RETURNS TABLE(
|
|
1086
|
-
depth INTEGER,
|
|
1087
|
-
entity_key VARCHAR(255),
|
|
1088
|
-
entity_type VARCHAR(100),
|
|
1089
|
-
entity_id UUID,
|
|
1090
|
-
rel_type VARCHAR(100),
|
|
1091
|
-
rel_weight REAL,
|
|
1092
|
-
path TEXT[],
|
|
1093
|
-
entity_record JSONB
|
|
1094
|
-
) AS $$
|
|
1095
|
-
DECLARE
|
|
1096
|
-
graph_keys RECORD;
|
|
1097
|
-
entities_by_table JSONB := '{}'::jsonb;
|
|
1098
|
-
table_keys JSONB;
|
|
1099
|
-
BEGIN
|
|
1100
|
-
-- First, build graph structure from KV store
|
|
1101
|
-
FOR graph_keys IN
|
|
1102
|
-
WITH RECURSIVE graph_traversal AS (
|
|
1103
|
-
-- Base case: Find starting entity
|
|
1104
|
-
SELECT
|
|
1105
|
-
0 AS depth,
|
|
1106
|
-
kv.entity_key,
|
|
1107
|
-
kv.entity_type,
|
|
1108
|
-
kv.entity_id,
|
|
1109
|
-
NULL::VARCHAR(100) AS rel_type,
|
|
1110
|
-
NULL::REAL AS rel_weight,
|
|
1111
|
-
ARRAY[kv.entity_key]::TEXT[] AS path
|
|
1112
|
-
FROM kv_store kv
|
|
1113
|
-
WHERE kv.user_id = p_user_id
|
|
1114
|
-
AND kv.entity_key = p_entity_key
|
|
1115
|
-
|
|
1116
|
-
UNION ALL
|
|
1117
|
-
|
|
1118
|
-
-- Recursive case: Follow outbound edges from discovered entities
|
|
1119
|
-
SELECT
|
|
1120
|
-
gt.depth + 1,
|
|
1121
|
-
target_kv.entity_key,
|
|
1122
|
-
target_kv.entity_type,
|
|
1123
|
-
target_kv.entity_id,
|
|
1124
|
-
(edge->>'rel_type')::VARCHAR(100) AS rel_type,
|
|
1125
|
-
COALESCE((edge->>'weight')::REAL, 1.0) AS rel_weight,
|
|
1126
|
-
gt.path || target_kv.entity_key AS path
|
|
1127
|
-
FROM graph_traversal gt
|
|
1128
|
-
-- Join to KV store to get source entity (with cached graph_edges!)
|
|
1129
|
-
JOIN kv_store source_kv ON source_kv.entity_key = gt.entity_key
|
|
1130
|
-
AND source_kv.user_id = p_user_id
|
|
1131
|
-
-- Extract edges directly from cached kv_store.graph_edges (NO polymorphic view!)
|
|
1132
|
-
CROSS JOIN LATERAL jsonb_array_elements(COALESCE(source_kv.graph_edges, '[]'::jsonb)) AS edge
|
|
1133
|
-
-- Lookup target entity in KV store
|
|
1134
|
-
JOIN kv_store target_kv ON target_kv.entity_key = (edge->>'dst')::VARCHAR(255)
|
|
1135
|
-
AND target_kv.user_id = p_user_id
|
|
1136
|
-
WHERE gt.depth < p_max_depth
|
|
1137
|
-
-- Filter by relationship type if specified
|
|
1138
|
-
AND (p_rel_type IS NULL OR (edge->>'rel_type')::VARCHAR(100) = p_rel_type)
|
|
1139
|
-
-- Prevent cycles by checking path
|
|
1140
|
-
AND NOT (target_kv.entity_key = ANY(gt.path))
|
|
1141
|
-
)
|
|
1142
|
-
SELECT DISTINCT ON (entity_key)
|
|
1143
|
-
gt.depth,
|
|
1144
|
-
gt.entity_key,
|
|
1145
|
-
gt.entity_type,
|
|
1146
|
-
gt.entity_id,
|
|
1147
|
-
gt.rel_type,
|
|
1148
|
-
gt.rel_weight,
|
|
1149
|
-
gt.path
|
|
1150
|
-
FROM graph_traversal gt
|
|
1151
|
-
WHERE gt.depth > 0 -- Exclude starting entity
|
|
1152
|
-
ORDER BY gt.entity_key, gt.depth
|
|
1153
|
-
LOOP
|
|
1154
|
-
IF p_keys_only THEN
|
|
1155
|
-
-- Return just graph structure (no entity_record)
|
|
1156
|
-
depth := graph_keys.depth;
|
|
1157
|
-
entity_key := graph_keys.entity_key;
|
|
1158
|
-
entity_type := graph_keys.entity_type;
|
|
1159
|
-
entity_id := graph_keys.entity_id;
|
|
1160
|
-
rel_type := graph_keys.rel_type;
|
|
1161
|
-
rel_weight := graph_keys.rel_weight;
|
|
1162
|
-
path := graph_keys.path;
|
|
1163
|
-
entity_record := NULL;
|
|
1164
|
-
RETURN NEXT;
|
|
1165
|
-
ELSE
|
|
1166
|
-
-- Build JSONB mapping {table: [keys]} for batch fetch
|
|
1167
|
-
IF entities_by_table ? graph_keys.entity_type THEN
|
|
1168
|
-
table_keys := entities_by_table->graph_keys.entity_type;
|
|
1169
|
-
entities_by_table := jsonb_set(
|
|
1170
|
-
entities_by_table,
|
|
1171
|
-
ARRAY[graph_keys.entity_type],
|
|
1172
|
-
table_keys || jsonb_build_array(graph_keys.entity_key)
|
|
1173
|
-
);
|
|
1174
|
-
ELSE
|
|
1175
|
-
entities_by_table := jsonb_set(
|
|
1176
|
-
entities_by_table,
|
|
1177
|
-
ARRAY[graph_keys.entity_type],
|
|
1178
|
-
jsonb_build_array(graph_keys.entity_key)
|
|
1179
|
-
);
|
|
1180
|
-
END IF;
|
|
1181
|
-
END IF;
|
|
1182
|
-
END LOOP;
|
|
1183
|
-
|
|
1184
|
-
-- If keys_only=false, fetch full records using rem_fetch
|
|
1185
|
-
IF NOT p_keys_only AND entities_by_table != '{}'::jsonb THEN
|
|
1186
|
-
RETURN QUERY
|
|
1187
|
-
SELECT
|
|
1188
|
-
NULL::INTEGER AS depth,
|
|
1189
|
-
f.entity_key::VARCHAR(255),
|
|
1190
|
-
f.entity_type::VARCHAR(100),
|
|
1191
|
-
NULL::UUID AS entity_id,
|
|
1192
|
-
NULL::VARCHAR(100) AS rel_type,
|
|
1193
|
-
NULL::REAL AS rel_weight,
|
|
1194
|
-
NULL::TEXT[] AS path,
|
|
1195
|
-
f.entity_record
|
|
1196
|
-
FROM rem_fetch(entities_by_table, p_user_id) f;
|
|
1197
|
-
END IF;
|
|
1198
|
-
END;
|
|
1199
|
-
$$ LANGUAGE plpgsql STABLE;
|
|
1200
|
-
|
|
1201
|
-
COMMENT ON FUNCTION rem_traverse IS
|
|
1202
|
-
'REM TRAVERSE query: Recursive graph traversal using cached kv_store.graph_edges. When keys_only=false (default), automatically fetches full entity records via rem_fetch.';
|
|
1266
|
+
END $$;
|