Skip to content

Embedding Space

three.js

A cloud of document chunks. Choosing a question draws lines to the closest chunks and ranks them with scores.

Install

$ npx shadcn@latest add https://spotcheckui.com/r/embedding-space.json

Also installs three, @react-three/fiber.

Usage

"use client"

import dynamic from "next/dynamic"

const EmbeddingSpace = dynamic(
  () => import("@/components/spotcheck/embedding-space").then((module) => module.EmbeddingSpace),
  { ssr: false },
)

<EmbeddingSpace
  label="Help centre chunks, reduced to three dimensions"
  points={[
    { id: "a", position: [-3.1, 0.8, 0.4], label: "Duplicate charges" },
    { id: "b", position: [-2.8, 1.1, 0.2], label: "Refund to wallet" },
    { id: "c", position: [3, 0.2, -1], label: "Tracking delays" },
  ]}
  queries={[
    {
      id: "charged-twice",
      label: "Why was I charged twice?",
      position: [-3, 0.9, 0.3],
      neighbours: [
        { id: "a", score: 0.912 },
        { id: "b", score: 0.874 },
      ],
    },
  ]}
/>

Your data, your scores

The component doesn't compute embeddings or scores. Your app passes the 3D positions, the neighbours and their scores, usually by reducing real embeddings to three dimensions and reading the scores from your search. Keep positions roughly within 4.5 of the centre, which is the edge of the frame.

The positions and scores in the demo above are made up. They come from a seeded random cloud, so they show how the component looks, not how any real model ranks these questions.

Rotating

Dragging sideways rotates the cloud, and a vertical swipe still scrolls the page on phones. Rotating has no keyboard control, because the query buttons and the ranked list carry all the data. The list is an ordered list, and each query change is announced to screen readers.

Props

  • points * RequiredEmbeddingPoint[]Default —Every chunk, with a 3D position you've worked out. The component doesn't compute embeddings.
  • queries * RequiredEmbeddingQuery[]Default —The questions to choose from, each with its own position, neighbours and scores.
  • valuestringDefault —The chosen query's id, when you control it.
  • defaultValuestringDefault —The starting query's id, when the component manages itself.
  • onValueChange(value: string) => voidDefault —Runs when a different query is chosen.
  • labelstringDefault Point cloud of document chunksDescribes the cloud for screen readers.
  • formatScore(score: number) => stringDefault (score) => score.toFixed(3)Formats each score. Pass it from a client component.

Keyboard

TabMove between the query buttons
EnterChoose the focused query

Reduced motion

The cloud holds still with no spin, the marker jumps to the query, and the lines appear in one frame.