NVIDIA

NVIDIA provides Nemotron embedding models with separate passage and query modes. There are two ways to use them with Qdrant:

  • Call the hosted NVIDIA API from your application and send the vectors to Qdrant. Most of this page covers this path.
  • Run the model in a NIM container on your own GPUs and point the same code at it. See Self-Host with NIM.

Models

ModelDimensionsMax Tokens per InputInput
nvidia/nemotron-3-embed-1b20484096Text
nvidia/llama-nemotron-embed-vl-1b-v220482048Text queries, image or text documents

The API also serves older models, such as nvidia/embed-qa-4 and nvidia/llama-3.2-nv-embedqa-1b-v1. Use nvidia/nemotron-3-embed-1b for new text projects.

NVIDIA doesn’t name a distance metric for these models. Use Cosine, which doesn’t depend on vector length.

Setup

Install the OpenAI SDK and the Qdrant client. The NVIDIA API is OpenAI-compatible, and NVIDIA’s own Python examples use the OpenAI SDK with NVIDIA’s base URL. NVIDIA has no TypeScript SDK, so the TypeScript examples call the REST API with fetch.

  • Python: pip install openai qdrant-client
  • TypeScript: npm install @qdrant/js-client-rest

Create an API key on build.nvidia.com and export it as the NVIDIA_API_KEY environment variable. Then create both clients and a collection sized for the model:

import os

from openai import OpenAI
from qdrant_client import QdrantClient, models

nvidia = OpenAI(
    api_key=os.environ["NVIDIA_API_KEY"],
    base_url="https://integrate.api.nvidia.com/v1",
)
client = QdrantClient(url="http://localhost:6333")

MODEL = "nvidia/nemotron-3-embed-1b"

client.create_collection(
    collection_name="{collection_name}",
    vectors_config=models.VectorParams(size=2048, distance=models.Distance.COSINE),
)
import { QdrantClient } from "@qdrant/js-client-rest";

const NVIDIA_URL = "https://integrate.api.nvidia.com/v1/embeddings";
const MODEL = "nvidia/nemotron-3-embed-1b";

type EmbeddingResponse = { data: { index: number; embedding: number[] }[] };

async function nvidiaEmbed(body: object): Promise<EmbeddingResponse> {
  const response = await fetch(NVIDIA_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.NVIDIA_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
  if (!response.ok) {
    throw new Error(`NVIDIA API error ${response.status}: ${await response.text()}`);
  }
  return response.json();
}

const client = new QdrantClient({ url: "http://localhost:6333" });

await client.createCollection("{collection_name}", {
  vectors: { size: 2048, distance: "Cosine" },
});

Embed Documents

Embed documents with input_type set to passage. Each item in the response carries the index of its input, which this example uses as the point ID:

documents = [
    "Qdrant is a vector search engine.",
    "NVIDIA Nemotron embedding models turn text into dense vectors.",
]

response = nvidia.embeddings.create(
    model=MODEL,
    input=documents,
    encoding_format="float",
    extra_body={"input_type": "passage", "truncate": "END"},
)

client.upsert(
    collection_name="{collection_name}",
    points=[
        models.PointStruct(
            id=item.index,
            vector=item.embedding,
            payload={"text": documents[item.index]},
        )
        for item in response.data
    ],
)
const documents = [
  "Qdrant is a vector search engine.",
  "NVIDIA Nemotron embedding models turn text into dense vectors.",
];

const response = await nvidiaEmbed({
  model: MODEL,
  input: documents,
  input_type: "passage",
  truncate: "END",
});

await client.upsert("{collection_name}", {
  points: response.data.map((item) => ({
    id: item.index,
    vector: item.embedding,
    payload: { text: documents[item.index] },
  })),
});

Each input can be up to 4096 tokens. The default truncate value, NONE, rejects longer inputs with an error, and END cuts them to fit.

Embed Queries

Embed the query with the same model and input_type set to query. The model encodes passages and queries differently, and NVIDIA warns that using the wrong input_type causes large drops in retrieval accuracy.

query_response = nvidia.embeddings.create(
    model=MODEL,
    input=["What is Qdrant?"],
    encoding_format="float",
    extra_body={"input_type": "query", "truncate": "END"},
)

hits = client.query_points(
    collection_name="{collection_name}",
    query=query_response.data[0].embedding,
    limit=3,
).points
const queryResponse = await nvidiaEmbed({
  model: MODEL,
  input: ["What is Qdrant?"],
  input_type: "query",
  truncate: "END",
});

const { points: hits } = await client.query("{collection_name}", {
  query: queryResponse.data[0].embedding,
  limit: 3,
});

Reduce Vector Size

nvidia/nemotron-3-embed-1b has no dimensions parameter and always returns 2048 values. To store smaller vectors, keep the first 1024 or 512 values of each embedding, for example item.embedding[:1024], and set the collection’s size to match. Shortened vectors must be normalized again before scoring, which Qdrant does on upload when the collection uses the Cosine distance. Shorten query vectors the same way.

Embed Images

nvidia/llama-nemotron-embed-vl-1b-v2 embeds documents as images, text, or both, and retrieves them with text queries. Pass each image as a PNG or JPEG data URL with modality set to image. Images are always documents, so they need input_type set to passage. This model’s vectors don’t share a space with nvidia/nemotron-3-embed-1b, so store them in a separate collection:

import base64

VL_MODEL = "nvidia/llama-nemotron-embed-vl-1b-v2"

client.create_collection(
    collection_name="{image_collection_name}",
    vectors_config=models.VectorParams(size=2048, distance=models.Distance.COSINE),
)

with open("chart.png", "rb") as f:
    image_url = "data:image/png;base64," + base64.b64encode(f.read()).decode()

image_response = nvidia.embeddings.create(
    model=VL_MODEL,
    input=[image_url],
    encoding_format="float",
    extra_body={"modality": ["image"], "input_type": "passage"},
)

client.upsert(
    collection_name="{image_collection_name}",
    points=[
        models.PointStruct(
            id=1,
            vector=image_response.data[0].embedding,
            payload={"file": "chart.png"},
        )
    ],
)

text_response = nvidia.embeddings.create(
    model=VL_MODEL,
    input=["Which region had the highest revenue?"],
    encoding_format="float",
    extra_body={"modality": ["text"], "input_type": "query"},
)

image_hits = client.query_points(
    collection_name="{image_collection_name}",
    query=text_response.data[0].embedding,
    limit=3,
).points
import { readFile } from "node:fs/promises";

const VL_MODEL = "nvidia/llama-nemotron-embed-vl-1b-v2";

await client.createCollection("{image_collection_name}", {
  vectors: { size: 2048, distance: "Cosine" },
});

const imageUrl = "data:image/png;base64," + (await readFile("chart.png")).toString("base64");

const imageResponse = await nvidiaEmbed({
  model: VL_MODEL,
  input: [imageUrl],
  modality: ["image"],
  input_type: "passage",
});

await client.upsert("{image_collection_name}", {
  points: [{ id: 1, vector: imageResponse.data[0].embedding, payload: { file: "chart.png" } }],
});

const textResponse = await nvidiaEmbed({
  model: VL_MODEL,
  input: ["Which region had the highest revenue?"],
  modality: ["text"],
  input_type: "query",
});

const { points: imageHits } = await client.query("{image_collection_name}", {
  query: textResponse.data[0].embedding,
  limit: 3,
});

Self-Host with NIM

NVIDIA publishes nvidia/nemotron-3-embed-1b as a NIM container, nvcr.io/nim/nvidia/nemotron-3-embed-1b. It needs an NVIDIA GPU and an NGC API key to pull, and the deploy guide has the docker run command. The container serves the same /v1/embeddings API on port 8000, so the code on this page works after you change the base URL to http://localhost:8000/v1. The deploy guide calls the local endpoint without an API key, but the OpenAI SDK needs a non-empty api_key value.

The NeMo Retriever Embedding NIM support matrix lists the models each NIM release serves, including Nemotron 3.5 Embed models that the hosted API doesn’t offer.

Store and Search the Vectors

Next Steps

Was this page useful?

Thank you for your feedback! 🙏

We are sorry to hear that. 😔 You can edit this page on GitHub, or create a GitHub issue.