Nebul Docs

Embeddings

Generate vector embeddings for semantic search, clustering, classification, and recommendations with the /v1/embeddings endpoint

The Embeddings endpoint (POST /v1/embeddings) turns text into fixed-length vectors that capture semantic meaning. Compare those vectors to power search, retrieval-augmented generation, clustering, classification, deduplication, and recommendation systems. It works with any embedding model in the Model Catalog.

Every example here reads your key from NEBUL_API_KEY; export it first. The Quick Start covers key setup and first requests in eight languages.

Request

POST https://api.inference.nebul.io/v1/embeddings

Parameters

ParameterTypeRequiredDescription
modelStringYesThe model ID, e.g. Qwen/Qwen3-Embedding-8B.
inputString or ArrayYesText to embed: a single string or an array of strings.
encoding_formatStringNo"float" (default) or "base64". Base64 packs the vector into a compact string for storage or transport.
normalizeBooleanNoScale the vectors to unit length. Defaults to false.
userStringNoIdentifier for the end user.

Set normalize when you compare vectors

With normalize: true, every vector has length 1, so a dot product is the cosine similarity: no separate normalization pass when you score results. Pair it with a vector database that expects normalized vectors.

Example

Embed one sentence:

import os

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["NEBUL_API_KEY"],
    base_url="https://api.inference.nebul.io/v1",
)

response = client.embeddings.create(
    model="Qwen/Qwen3-Embedding-8B",
    input="The quick brown fox jumps over the lazy dog.",
)

print(len(response.data[0].embedding))

The Python tab prints 4096, the vector length for this model. The same request with encoding_format: "base64" returns the vector as a base64 string instead of a float array.

Response

The vectors are in data, one per input, in input order. Token counts are in usage:

{
  "object": "list",
  "model": "Qwen/Qwen3-Embedding-8B",
  "data": [
    {
      "index": 0,
      "object": "embedding",
      "embedding": [0.007406942, -0.004879176, 0.00374756, "..."]
    }
  ],
  "usage": {
    "prompt_tokens": 11,
    "total_tokens": 11
  }
}
FieldTypeDescription
objectStringAlways "list".
modelStringThe model ID that produced the vectors.
dataArrayOne entry per input string.
data[].indexIntegerPosition of this vector in the input array.
data[].objectStringAlways "embedding".
data[].embeddingArrayThe vector: floats by default, a base64 string with encoding_format: "base64".
usage.prompt_tokensIntegerTokens counted across all inputs.
usage.total_tokensIntegerSame as prompt_tokens for embeddings.

Batches

Pass an array to embed many texts in one request. Batching amortizes the HTTP round trip and keeps inputs together, which matters when you index a corpus:

response = client.embeddings.create(
    model="Qwen/Qwen3-Embedding-8B",
    input=[
        "The weather is nice today.",
        "It's a beautiful sunny day.",
        "I love programming in Python.",
    ],
)

for item in response.data:
    print(item.index, len(item.embedding))

The call returns three vectors of 4096 floats each. Keep an eye on usage.total_tokens: each model has its own max_input_tokens limit (12,288 for this one), and the whole batch shares it.

Similarity

With normalized vectors, the dot product is the cosine similarity. Two sentences about the same scene score high; unrelated sentences score near zero:

import numpy as np

response = client.embeddings.create(
    model="Qwen/Qwen3-Embedding-8B",
    input=["The cat sat on the mat", "A feline rested on the rug"],
    normalize=True,
)

a, b = (np.array(item.embedding) for item in response.data)
print(f"Similarity: {np.dot(a, b):.3f}")

This pair scores about 0.65. For search, embed the query with the same model and rank documents by this score; for clustering, feed the vectors to your algorithm of choice.

More use cases

The same dot product drives more than search. A few patterns:

  • Clustering: embed your corpus, then run k-means or any clustering algorithm on the vectors to group similar documents.
  • Recommendation: rank items by similarity to a source item's embedding.
  • Anomaly detection: items far from every cluster centroid are your outliers.
  • Zero-shot classification: embed the class labels and the input together, then pick the label with the highest similarity. No training data needed:
response = client.embeddings.create(
    model="Qwen/Qwen3-Embedding-8B",
    input=["negative", "positive", "The coffee arrived quickly and tastes great."],
    normalize=True,
)

negative, positive, review = (item.embedding for item in response.data)
score = lambda a, b: sum(x * y for x, y in zip(a, b))

print("positive" if score(positive, review) > score(negative, review) else "negative")

With normalized vectors, this prints positive: the review scores 0.60 against the positive label and 0.48 against negative.

Base64 storage

encoding_format: "base64" returns each vector as a base64 string: 4 bytes per float, little-endian float32. Decode it when you need the numbers back:

import base64

import numpy as np

response = client.embeddings.create(
    model="Qwen/Qwen3-Embedding-8B",
    input="Text to embed",
    encoding_format="base64",
)

raw = base64.b64decode(response.data[0].embedding)
vector = np.frombuffer(raw, dtype=np.float32)
print(vector.shape)

This prints (4096,). The base64 form is about a third smaller on the wire than a float array and stores cleanly in text columns.

Models

Examples on this page use Qwen/Qwen3-Embedding-8B, the default embedding model. Dimensions and input limits differ per model, so pick one and stay with it: vectors from different models (or different dimensions) aren't comparable. The Model Catalog lists every available model with its dimensions, input limit, and price.

To reorder search results by relevance rather than vector distance alone, see Reranking. Embedding examples across languages are on the Examples page.

On this page