Skip to main content
Whilst provides powerful search capabilities combining PostgreSQL full-text search with OpenAI vector embeddings for semantic similarity.

Search Modes

Semantic

Uses OpenAI embeddings (text-embedding-3-small, 1536 dimensions) to find conceptually similar results even with different wording.

Full-Text

PostgreSQL tsvector search with GIN indexes. Fast exact keyword matching with ranking.

Hybrid (RRF)

Combines both approaches using Reciprocal Rank Fusion for best-in-class accuracy.

How It Works

User Query

Generate Embedding (if semantic/hybrid)

Execute Search
    ├─ Semantic: pgvector cosine similarity
    ├─ Full-text: ts_rank matching
    └─ Hybrid: Both + RRF re-ranking

Apply Filters (folder, tags, workspace)

Rank & Return Results

Usage

import { searchDocs } from '@/lib/ai/actions/search-docs';

// Semantic search
const results = await searchDocs({
  query: 'machine learning best practices',
  mode: 'semantic',
  limit: 10,
  workspaceId: 'workspace-uuid',
});

// Full-text search
const results = await searchDocs({
  query: 'react hooks',
  mode: 'fulltext',
  limit: 10,
  workspaceId: 'workspace-uuid',
});

// Hybrid search (recommended)
const results = await searchDocs({
  query: 'deployment strategies',
  mode: 'hybrid',
  limit: 10,
  workspaceId: 'workspace-uuid',
});
// Search within a folder
const results = await searchDocs({
  query: 'API documentation',
  mode: 'semantic',
  folderId: 'folder-uuid',
  workspaceId: 'workspace-uuid',
});

// Search by tags
const results = await searchDocs({
  query: 'infrastructure',
  mode: 'semantic',
  tags: ['aws', 'devops'],
  workspaceId: 'workspace-uuid',
});

Database Schema

The search system relies on these database features:
-- Documents with FTS and vector support
CREATE TABLE docs (
  id UUID PRIMARY KEY,
  workspace_id UUID NOT NULL,
  title TEXT NOT NULL,
  content TEXT,
  content_tsv tsvector GENERATED ALWAYS AS (
    to_tsvector('english', coalesce(title, '') || ' ' || coalesce(content, ''))
  ) STORED,
  embedding vector(1536)
);

-- Full-text search index
CREATE INDEX docs_fts_idx ON docs USING GIN(content_tsv);

-- Vector similarity index
CREATE INDEX docs_embedding_idx ON docs
  USING ivfflat(embedding vector_cosine_ops)
  WITH (lists = 100);

Embedding Generation

Embeddings are generated automatically when documents are created or updated. For bulk operations:
import { batchGenerateEmbeddings } from '@/lib/ai/embeddings';

const docs = await getDocs();
const texts = docs.map(d => d.title + ' ' + d.content);
const embeddings = await batchGenerateEmbeddings(texts);

API Endpoint

Search is also available via the REST API at /api/docs/hybrid-search. See the API Reference for details.