Multimodal Grid Embeddings

EmbeddingGemma 2 creates normalized vectors from ordered text, image, audio, video, and mixed inputs. Use the same model in the desktop app for private Local work or through the OpenAI-compatible Grid endpoint.

Release candidate ยท default off

The pinned runtime has passed real M4 multimodal tests. Production discovery and traffic remain disabled until the release migration, packaged lifecycle, and live billing/failover canaries pass. Treat the model as available only when GET /v1/models?type=embeddingreturns embeddinggemma-2.

Local or Grid

Local in the Node app

Choose Local โ†’ Embeddings โ†’ EmbeddingGemma 2. Add and reorder media, choose the retrieval task and dimensions, start Local AI, then generate and copy the vector. Input stays on your computer.

The candidate requires Apple Silicon and macOS 15+. Developer builds need the exact opt-ins VITE_EMBEDDINGGEMMA2_ENABLED=trueand SGL_EMBEDDINGGEMMA2_ENABLED=true.

SGL Grid

Call POST https://grid.x402compute.cc/v1/embeddingswith a Grid API key backed by credits, or complete the returned x402 challenge. Multimodal input is sealed to a node that advertises the exact ready runtime, modalities, dimensions, and processor.

Text request

curl https://grid.x402compute.cc/v1/embeddings \
  -H "X-API-Key: $SGL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"embeddinggemma-2","input":["A searchable document"],"input_type":"document","dimensions":256}'

Existing string and string-array input is preserved. EmbeddingGemma 2 supports 768, 512, 256, and 128 dimensions. Each vector is normalized after Matryoshka truncation. If input_type is omitted, the Grid uses query. Send unspecified only when you explicitly want no retrieval prefix.

Ordered multimodal request

Hash the decoded file bytes with SHA-256 and send the same bytes as canonical base64. Media URLs are not fetched. Audio and video also require their real duration in seconds.

{
  "model": "embeddinggemma-2",
  "dimensions": 256,
  "input_type": "document",
  "input": [{
    "content": [
      { "type": "text", "text": "Product demo" },
      {
        "type": "image",
        "media": {
          "encoding": "base64",
          "mime_type": "image/png",
          "data": "iVBORw0KGgo...",
          "sha256": "<64 lowercase hex characters>"
        }
      },
      {
        "type": "audio",
        "duration_seconds": 4.2,
        "media": {
          "encoding": "base64",
          "mime_type": "audio/mpeg",
          "data": "SUQzBAAAAA...",
          "sha256": "<64 lowercase hex characters>"
        }
      }
    ]
  }]
}

Limits

Request body24 MiB encoded JSON
Batch1-16 top-level items; one vector per item
Parts1-16 ordered parts per item
ImagesJPEG/PNG/WebP; up to 8; 8 MiB each and per-item total; 16 MP
AudioOne WAV/FLAC/MP3 per item; 8 MiB; 30 seconds
VideoOne MP4 per item; 16 MiB; 32 seconds; up to 32 sampled frames
Request media20 MiB decoded total
Context8,192 processed tokens per item

Response and billing

The response contains one finite, unit-normalized float vector per item, ordered by index. Usage is input only and includes a text/image/audio/video breakdown. The Grid validates vectors and usage before debiting credits or settling x402 payment. Client-invalid media and timeouts are not charged. The array below is shortened for display; real vectors contain exactly the requested number of floats.

{
  "object": "list",
  "data": [{ "object": "embedding", "index": 0, "embedding": [0.014, -0.031] }],
  "model": "embeddinggemma-2",
  "usage": {
    "prompt_tokens": 313,
    "total_tokens": 313,
    "cost_usd": 0.000001,
    "breakdown": { "text": 32, "image": 256, "audio": 25, "video": 0 }
  },
  "embedding_protocol": "embedding-multimodal-v1"
}

A successful x402 response can add billing_pending: true and ajob_id when capture succeeded and durable split accounting is still recovering. Do not resubmit that paid request.

Privacy and retention

The complete ordered input and effective retrieval type are sealed to the selected node with negotiated v2/base64 X25519 transport. The job row stores the encrypted envelope during processing. After terminal completion, input payloads become purge-eligible after 30 minutes and encrypted results after one hour. Cleanup runs hourly, so practical upper bounds are about 90 minutes and two hours. Plaintext node errors can contain prompts, media, paths, or tracebacks, so node-supplied text is never persisted. It is reduced toembedding_input_invalid, embedding_context_overflow, or embedding_runtime_failed. Internal validation paths can store bounded service reasons, which the public job API normalizes to those codes.

Stable errors

  • 400 invalid_request_error: malformed request; runtime input failures can add embedding_input_invalid or embedding_context_overflow.
  • 401 invalid_api_key or invalid_session: replace the key or reconnect the wallet session.
  • 403 insufficient_scope: use a key with grid:write.
  • 402 payment_required, insufficient_credits, pod_cap_reached, or payment_error: follow the response's payment/cap instruction.
  • 404 model_not_found: correct the model id. A disabled embeddings route returns plain Not found.
  • 413 invalid_request_error: encoded body exceeds 24 MiB.
  • 500 server_error: dispatch or billing infrastructure failed; read the charge/retry statement before retrying.
  • 502 inference_error: node output failed validation; invalid vectors are not returned or billed.
  • 503 model_not_available, node_not_available, or server_error: the release/capability boundary, sealed node transport, or payment configuration is unavailable.
  • 504 timeout: the request timed out and was not charged.