SliceSeeker

Search

Phase 2 search-api and the search-client SDK

Phase 2 is a read-only Express service (search-api). It embeds the query with the same gateway/model family used at index time, then runs similarity search against the chosen path's vectors (or weighted RRF for hybrid).

The admin UI can also search through indexer-api. Prefer search-api + search-client for product integrations so search scales independently of indexing.

Endpoints

MethodRouteIndex
POST/searchMultimodal chunks
POST/transcribe/searchTranscript segments
POST/frames/searchStill frames
POST/hybrid/searchHybrid weighted RRF
GET/healthLiveness
GET/readyGateway key + schema present (503 if not)

Common body fields

{
  "query": "sunset over water",
  "collectionId": "col_abc",
  "collectionIds": ["col_a", "col_b"],
  "uploadId": "upload_xyz",
  "limit": 10
}

All filters are optional. limit defaults to 10 (max 50). Empty database → empty results array, not an error.

Hybrid extras

{
  "query": "product demo with voiceover",
  "weights": { "video": 1, "speech": 1.5, "vision": 0.8 },
  "rrfK": 60,
  "perModalityLimit": 50
}

See Hybrid for process → RRF → costs and retry semantics.

Install the SDK

In this monorepo:

pnpm build:packages
{
  "dependencies": {
    "search-client": "workspace:*"
  }
}

Usage

import { SearchClient, SearchApiError } from "search-client";

const client = new SearchClient({
  baseUrl: "http://search-api:3001", // internal hostname in deploy
  timeoutMs: 30_000,
});

const { ready } = await client.ready();
if (!ready) throw new Error("search-api not ready");

const multimodal = await client.search({
  query: "sunset over water",
  collectionId: "col_abc",
  limit: 10,
});

const speech = await client.searchTranscripts({
  query: "quarterly revenue guidance",
});

const frames = await client.searchFrames({
  query: "red product box on a table",
});

const hybrid = await client.searchHybrid({
  query: "product demo with voiceover",
  weights: { video: 1, speech: 1.5, vision: 0.8 },
});

try {
  await client.search({ query: "" });
} catch (err) {
  if (err instanceof SearchApiError) {
    console.error(err.status, err.message);
  }
}

Hit shapes (summary)

MethodNotable fields
searchsegmentId, chunkIndex, startSec, endSec, score, sourceObject
searchTranscriptssame timing fields + text
searchFramesframeId, timestampSec, thumbnailObject, sourceObject
searchHybridtiming + rrfScore, ranks, sources, optional text / thumbnailObject

Resolve media with sourceObject.bucket + sourceObject.key against your S3-compatible store. The SDK returns object refs, not playback URLs. Presigned URL generation stays in the admin UI (and in your product layer) on purpose: the search stack does not opinionate how objects are served, so you can plug in your own authz, DRM, CDN, or private bucket policies.

On this page