Skip to content

Latest commit

 

History

History
134 lines (102 loc) · 4.03 KB

File metadata and controls

134 lines (102 loc) · 4.03 KB

Wazoo Worlds

PostgreSQL quad store and search index for Worlds.

GitHub Ask DeepWiki

Standalone PostgreSQL quad store and search index package extracted for the @worlds ecosystem.

Install

Package managers

# Deno (first-class JSR support)
deno add jsr:@worlds/postgres

# Bun / npm / pnpm / Yarn (via JSR npm compatibility layer)
npx jsr add @worlds/postgres

CDN (browser / no build step)

esm.sh serves JSR packages as ES modules — no install, no bundler needed.

import { createPostgresWorldsSdk } from "https://esm.sh/jsr/@worlds/postgres@0.2.0";

With an import map:

<script type="importmap">
{
  "imports": {
    "@worlds/postgres": "https://esm.sh/jsr/@worlds/postgres@0.2.0"
  }
}
</script>
<script type="module">
import { createPostgresWorldsSdk } from "@worlds/postgres";
</script>

Pin to an exact build for deterministic caching:

import { createPostgresWorldsSdk } from "https://esm.sh/jsr/@worlds/postgres@0.2.0?pin=v1724100000";

Usage

The SDK factory assembles the full facade (quad store + keyword search + SPARQL engine) over a shared postgres.Sql surface:

import postgres from "postgres";
import { createPostgresWorldsSdk } from "@worlds/postgres/sdk";

const sql = postgres("postgres://localhost/worlds");
const sdk = await createPostgresWorldsSdk({ sql });

Reference subpaths mirror the other Worlds backends:

import { PostgresQuadStore } from "@worlds/postgres/quad-store";
import { PostgresSearchIndex } from "@worlds/postgres/search-index";
import { PostgresRdfjsStore } from "@worlds/postgres/rdfjs-store";

Hybrid search

PostgresSearchIndex.search has two modes:

  • Keyword-only (no embedding service): the reference's exact keyword semantics — case-insensitive substring over textual literals in the live quads table. This is the parity path.
  • Hybrid (embedding service configured): Reciprocal Rank Fusion over the reindexed chunks table — a tsvector keyword branch (to_tsvector/plainto_tsquery in the configured ftsLanguage, default "english") and a pgvector cosine branch, each ranked 1..topK and fused as 1/(60 + rank) summed, consistent with @worlds/libsql. A query-time embedding failure degrades to the keyword branch; an empty query runs the vector branch alone.
import { createPostgresWorldsSdk } from "@worlds/postgres/sdk";

const sdk = await createPostgresWorldsSdk({
  sql,
  embeddingService: myEmbeddingService,
  vectorDimensions: 1536,
  ftsLanguage: "english",
  textSplitter: new RecursiveCharacterTextSplitter({ chunkSize: 1000 }),
});
await sdk.reindex(); // populate chunk embeddings + tsvectors (keyset-paginated)
const { results } = await sdk.search({ query: "hybrid query" });

reindex() slices long literal values into chunk rows via the optional textSplitter (any TextSplitterInterface, e.g. LangChain's RecursiveCharacterTextSplitter) — each piece is embedded and FTS-indexed separately, consistent with @worlds/libsql. Without a splitter, one chunk row per textual literal is written (the identity default).

Parity

deno task ci runs a full-corpus parity suite (runParitySuite from @worlds/sdk/testing) comparing createPostgresWorldsSdk against the portable in-memory reference (@worlds/sdk/memory) over PGlite — search ordering is compared set-wise, since SQL keyword-scan order is not a parity contract.

Development

deno task ci

Dry-run a JSR publish locally:

deno task publish:dry

Publishing to JSR

Releases publish automatically when changes merge to main.