Skip to content
Batchwork
Esc
navigateopen⌘Jpreview
On this page

Embeddings

Batch thousands of texts into vectors with batch.embeddings — the same job handle, one vector per request.

Submit an embedding batch

batch.embeddings() mirrors batch(): pass a text embedding model and a list of values, and it returns the same BatchJob handle immediately. Each request produces one vector, correlated by customId.

import { batch } from "batchwork";
import { openai } from "@ai-sdk/openai";

const job = await batch.embeddings({
  model: openai.embeddingModel("text-embedding-3-small"),
  requests: [
    { customId: "a", value: "The quick brown fox." },
    { customId: "b", value: "A lazy dog sleeps." },
  ],
});

const results = await job.wait().then(() => job.collect());
for (const r of results) {
  console.log(r.customId, r.embedding?.length);
}

Everything on the job handle works unchanged — wait(), poll(), results(), collect(), and cancel() — as does rehydration with getBatch / getBatchResults / cancelBatch.

You can also pass a "provider/model" string (e.g. "openai/text-embedding-3-small"), though the model object is recommended.

Supported providers

Batch embeddings are available for the providers whose batch API accepts the embeddings endpoint:

Provider Example model Notes
OpenAI text-embedding-3-small /v1/embeddings batch endpoint.
Mistral mistral-embed Model set on the batch job.
Google Gemini gemini-embedding-001 Async :asyncBatchEmbedContent batch.

Request shape

Each request is a single text to embed plus an optional customId. There are no prompt, messages, or sampling fields — embeddings only need the input.

Field Notes
value The text to embed. One value → one vector.
customId Correlates the result. Auto-generated as request-<index> if omitted; must be unique within a batch.
providerOptions Provider-specific options (e.g. output dimensions, task type). See below.

limits and metadata work exactly as in batch().

Output dimensions and task type

Pass provider-specific knobs through providerOptions, keyed by provider — the same shape the AI SDK’s embed uses:

// OpenAI — shorten the vector
await batch.embeddings({
  model: openai.embeddingModel("text-embedding-3-small"),
  requests: [{ customId: "a", value: "…" }],
  // applied per request
});

// Google — output dimensionality + retrieval task type
await batch.embeddings({
  model: google.embeddingModel("gemini-embedding-001"),
  requests: [
    {
      customId: "a",
      value: "…",
      providerOptions: {
        google: { outputDimensionality: 768, taskType: "RETRIEVAL_DOCUMENT" },
      },
    },
  ],
});

OpenAI reads providerOptions.openai.dimensions; Google reads providerOptions.google.outputDimensionality / taskType. Check the relevant @ai-sdk/* provider docs for the exact option names.

Results

Embeddings reuse the normalized BatchResult. The vector lands on result.embedding; text is undefined for embedding batches.

for await (const result of job.results()) {
  if (result.status === "succeeded" && result.embedding) {
    index(result.customId, result.embedding); // store in your vector DB
  } else if (result.status === "errored") {
    console.error(result.customId, result.error?.message);
  }
}

usage is normalized to { inputTokens, totalTokens } where the provider reports it, billed at the batch rate (~50% off).

How it’s built

Like batch(), batch.embeddings() derives each provider request body by running the AI SDK’s embed() through a capturing fetch that records the serialized body and aborts before any network call. Each request embeds a single value, so every batch line maps to exactly one vector, correlated by customId.

Was this page helpful?