vecdb-wasm / docs /getting-started.md
philipp-zettl's picture
docs: add comprehensive documentation β€” getting started guide
054c959 verified
|
Raw
History Blame Contribute Delete
8.03 kB

Getting Started

Installation

npm install vecdb-wasm

The package includes:

  • ESM and CJS bundles with full TypeScript declarations
  • A background Web Worker for ONNX embedding inference
  • The compiled WASM binary (~172 KB) for HNSW vector search

Browser Requirements

VecDB-WASM runs entirely in the browser. It requires:

Feature Used For Support
WebAssembly HNSW vector search engine All modern browsers
Web Workers Background embedding inference All modern browsers
OPFS Persistent vROM cache Chrome 86+, Firefox 111+, Safari 15.2+
ES Modules in Workers Worker type: 'module' Chrome 80+, Firefox 114+, Safari 15+

Note: The embedding worker loads transformers.js from CDN at runtime. The first model load requires an internet connection; subsequent loads use the browser's Cache API.

Quick Start

import { AgentMemory } from 'vecdb-wasm';

// 1. Create and initialize
const memory = new AgentMemory();
await memory.init();

// 2. Mount a pre-built knowledge base
await memory.mount('hf-transformers-docs');

// 3. Search with natural language
const results = await memory.search('how to fine-tune a model');

// 4. Format for LLM context injection
const context = memory.formatContext(results, { maxTokens: 2000 });

// 5. Clean up when done
memory.destroy();

That's it. Five lines of meaningful code to go from zero to a searchable knowledge base with semantic search.

What Happens Under the Hood

When you run the code above, VecDB-WASM:

  1. init() β€” Loads the 172 KB WASM binary (HNSW engine) and spawns a background Web Worker for embedding inference.

  2. mount('hf-transformers-docs') β€” Does four things:

    • Checks the vROM Registry for the requested knowledge base
    • Downloads the pre-computed HNSW index (~12 MB) from Hugging Face CDN, or loads it from the OPFS cache if already downloaded
    • Deserializes the index into the WASM engine via VectorDB.load()
    • Loads the required embedding model (all-MiniLM-L6-v2, ~22 MB q8) in the background worker, or skips this if the same model is already loaded
  3. search('how to fine-tune a model') β€” Embeds the query text in the background worker (~50ms), then runs HNSW approximate nearest neighbor search in WASM (<1ms).

  4. formatContext(results) β€” Concatenates result texts with source URLs into a string ready for LLM system/user prompt injection.

5-Minute Tutorial

Step 1: Set Up a Project

mkdir my-rag-app && cd my-rag-app
npm init -y
npm install vecdb-wasm

Step 2: Create the App

Create index.html:

<!DOCTYPE html>
<html>
<head><title>My RAG App</title></head>
<body>
  <input id="query" placeholder="Ask anything about HF Transformers..." style="width: 400px">
  <button id="search">Search</button>
  <pre id="results"></pre>

  <script type="module">
    import { AgentMemory } from './node_modules/vecdb-wasm/dist/index.js';

    const memory = new AgentMemory({ logLevel: 'info' });

    // Show loading progress
    memory.onProgress(({ file, loaded, total }) => {
      const pct = total > 0 ? ((loaded / total) * 100).toFixed(0) : '?';
      document.getElementById('results').textContent = `Loading ${file}... ${pct}%`;
    });

    // Initialize
    await memory.init();
    document.getElementById('results').textContent = 'WASM ready. Mounting knowledge base...';

    // Mount with download progress
    const status = await memory.mount('hf-transformers-docs', {
      onProgress: ({ phase, loaded, total }) => {
        if (phase === 'index' && total > 0) {
          const mb = (loaded / 1e6).toFixed(1);
          document.getElementById('results').textContent = `Downloading index... ${mb} MB`;
        }
      }
    });

    document.getElementById('results').textContent =
      `Ready! ${status.vectors} vectors, ${status.dim}d, model: ${status.model}`;

    // Search handler
    document.getElementById('search').addEventListener('click', async () => {
      const query = document.getElementById('query').value;
      if (!query) return;

      const results = await memory.search(query, {
        topK: 5,
        expandContext: true,
        contextWindow: 1,
      });

      let output = '';
      for (const r of results) {
        output += `[d=${r.distance.toFixed(4)}] ${r.metadata.section_heading}\n`;
        output += `${r.text.slice(0, 200)}...\n`;
        if (r.metadata.url) output += `Source: ${r.metadata.url}\n`;
        output += '\n---\n\n';
      }
      document.getElementById('results').textContent = output;
    });
  </script>
</body>
</html>

Step 3: Serve and Test

npx serve .
# Open http://localhost:3000

Type a query like "how to use the pipeline API" and hit Search. Results appear in milliseconds.

Step 4: Use the Context in an LLM Call

const results = await memory.search(userQuestion, { topK: 5, expandContext: true });
const context = memory.formatContext(results, { maxTokens: 2000 });

// Inject into any LLM API
const response = await fetch('https://api.openai.com/v1/chat/completions', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    model: 'gpt-4o-mini',
    messages: [
      { role: 'system', content: `Answer using this context:\n\n${context}` },
      { role: 'user', content: userQuestion },
    ],
  }),
});

Framework Integration

Vite

VecDB-WASM works out of the box with Vite. Import normally:

import { AgentMemory } from 'vecdb-wasm';

The worker and WASM paths auto-resolve via import.meta.url. If you encounter issues with the worker path, override it:

import workerUrl from 'vecdb-wasm/embed-worker?url';

const memory = new AgentMemory({
  workerPath: workerUrl,
});

Next.js (App Router)

The SDK is browser-only. Use dynamic imports to avoid SSR:

'use client';

import { useEffect, useRef, useState } from 'react';
import type { AgentMemory as AgentMemoryType, MountStatus } from 'vecdb-wasm';

export function useAgentMemory(vromId: string) {
  const memoryRef = useRef<AgentMemoryType | null>(null);
  const [status, setStatus] = useState<MountStatus | null>(null);

  useEffect(() => {
    let destroyed = false;

    (async () => {
      const { AgentMemory } = await import('vecdb-wasm');
      if (destroyed) return;

      const memory = new AgentMemory({ logLevel: 'warn' });
      await memory.init();
      const mountStatus = await memory.mount(vromId);

      if (destroyed) { memory.destroy(); return; }
      memoryRef.current = memory;
      setStatus(mountStatus);
    })();

    return () => {
      destroyed = true;
      memoryRef.current?.destroy();
    };
  }, [vromId]);

  return { memory: memoryRef.current, status };
}

Vanilla (CDN / No Bundler)

<script type="module">
  import { AgentMemory } from 'https://cdn.jsdelivr.net/npm/vecdb-wasm/dist/index.js';

  const memory = new AgentMemory({
    // Explicit paths when not using a bundler
    workerPath: 'https://cdn.jsdelivr.net/npm/vecdb-wasm/dist/embed-worker.js',
    wasmPkgPath: 'https://cdn.jsdelivr.net/npm/vecdb-wasm/wasm-pkg/vecdb_wasm.js',
  });

  await memory.init();
  await memory.mount('hf-transformers-docs');
</script>

Next Steps

  • API Reference β€” Full documentation of every class, method, option, and type
  • Guides β€” Deep dives on vROMs, context expansion, custom knowledge bases, and the Python CLI
  • Architecture β€” How the HNSW engine, worker protocol, and OPFS cache work internally