Embedding Space
three.jsA 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.jsonAlso 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 * Required
EmbeddingPoint[]Default —Every chunk, with a 3D position you've worked out. The component doesn't compute embeddings. - queries * Required
EmbeddingQuery[]Default —The questions to choose from, each with its own position, neighbours and scores. - value
stringDefault —The chosen query's id, when you control it. - defaultValue
stringDefault —The starting query's id, when the component manages itself. - onValueChange
(value: string) => voidDefault —Runs when a different query is chosen. - label
stringDefault 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
| Tab | Move between the query buttons |
|---|---|
| Enter | Choose 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.