-- Enable pgvector create extension if not exists vector; -- Thoughts table create table thoughts ( id uuid default gen_random_uuid() primary key, content text not null, embedding vector(1536), metadata jsonb default '{}'::jsonb, created_at timestamptz default now(), updated_at timestamptz default now() ); -- Indexes create index on thoughts using hnsw (embedding vector_cosine_ops); create index on thoughts using gin (metadata); create index on thoughts (created_at desc); -- Auto-update updated_at create or replace function update_updated_at() returns trigger as $$ begin new.updated_at = now(); return new; end; $$ language plpgsql; create trigger thoughts_updated_at before update on thoughts for each row execute function update_updated_at(); -- Semantic search function create or replace function match_thoughts( query_embedding vector(1536), match_threshold float default 0.7, match_count int default 10, filter jsonb default '{}'::jsonb ) returns table ( id uuid, content text, metadata jsonb, similarity float, created_at timestamptz ) language plpgsql as $$ begin return query select t.id, t.content, t.metadata, 1 - (t.embedding <=> query_embedding) as similarity, t.created_at from thoughts t where 1 - (t.embedding <=> query_embedding) > match_threshold and (filter = '{}'::jsonb or t.metadata @> filter) order by t.embedding <=> query_embedding limit match_count; end; $$;