OpenAI

OpenAI provides text embedding models through its Embeddings API. There are two ways to use them with Qdrant:

  • Call the OpenAI API from your application and send the vectors to Qdrant. This works with any Qdrant deployment, and it’s what most of this page covers.
  • On Qdrant Cloud, pass text to Qdrant and let Qdrant Cloud Inference call OpenAI for you.

Models

ModelDimensionsReducibleMax Tokens per Input
text-embedding-3-small1536Yes8192
text-embedding-3-large3072Yes8192
text-embedding-ada-0021536No8192

text-embedding-ada-002 is the previous generation. Use a text-embedding-3 model for new projects.

OpenAI embeddings are normalized to length 1, so the Cosine and Dot distance metrics rank results identically. OpenAI recommends cosine similarity.

Setup

Install the OpenAI SDK and the Qdrant client:

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

Create both clients and a collection sized for the model. The OpenAI client reads your API key from the OPENAI_API_KEY environment variable.

from openai import OpenAI
from qdrant_client import QdrantClient, models

openai_client = OpenAI()
client = QdrantClient(url="http://localhost:6333")

MODEL = "text-embedding-3-small"

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

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

const MODEL = "text-embedding-3-small";

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

Embed Documents

One request embeds a list of inputs. 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.",
    "OpenAI embedding models turn text into dense vectors.",
]

response = openai_client.embeddings.create(model=MODEL, input=documents)

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.",
  "OpenAI embedding models turn text into dense vectors.",
];

const response = await openai.embeddings.create({ model: MODEL, input: documents });

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

A request accepts up to 2,048 inputs and 300,000 tokens in total, and each input must be 8,192 tokens or fewer. Split larger datasets into several requests, and see Upload Points for batching on the Qdrant side.

Embed Queries

OpenAI models have no separate query mode. Embed the query with the same model you used for the documents:

query_vector = (
    openai_client.embeddings.create(model=MODEL, input="What is Qdrant?")
    .data[0]
    .embedding
)

hits = client.query_points(
    collection_name="{collection_name}",
    query=query_vector,
    limit=3,
).points
const queryResponse = await openai.embeddings.create({
  model: MODEL,
  input: "What is Qdrant?",
});

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

Reduce Vector Size

text-embedding-3 models accept a dimensions parameter that shortens the vector with little loss in quality. Set the collection’s size to the same value, and pass the same dimensions when you embed queries:

response = openai_client.embeddings.create(
    model="text-embedding-3-large",
    input=documents,
    dimensions=1024,
)
const reduced = await openai.embeddings.create({
  model: "text-embedding-3-large",
  input: documents,
  dimensions: 1024,
});

To keep the full vectors but store them in less memory, use Binary Quantization, which shrinks each vector by 32 times. With oversampling, OpenAI models keep high recall:

ModelDimensionsTest DatasetRecallOversampling
text-embedding-3-large3072DBpedia 1M0.99663x
text-embedding-3-small1536DBpedia 100K0.98473x
text-embedding-3-large1536DBpedia 1M0.98263x
text-embedding-ada-0021536DBpedia 1M0.984x

Qdrant Cloud Inference

On Qdrant Cloud, Qdrant can call OpenAI for you. Instead of a vector, send a Document with the model name prefixed with openai/. Pass your OpenAI API key in the openai-api-key request header or in the options object. Qdrant does not store the key, so send it with every request. OpenAI parameters such as dimensions also go in options, and the collection’s vector size must match them, which is 512 in these examples.

To ingest documents:

PUT /collections/{collection_name}/points?wait=true
{
  "points": [
    {
      "id": 1,
      "vector": {
        "text": "Recipe for baking chocolate chip cookies",
        "model": "openai/text-embedding-3-large",
        "options": {
          "openai-api-key": "<YOUR_OPENAI_API_KEY>",
          "dimensions": 512
        }
      }
    }
  ]
}
from qdrant_client import QdrantClient, models
from qdrant_client.context_headers import headers

client = QdrantClient(
    url="https://xyz-example.qdrant.io:6333", 
    api_key="<your-qdrant-api-key>",
    cloud_inference=True
)

with headers({"openai-api-key": "<YOUR_OPENAI_API_KEY>"}):
    client.upsert(
        collection_name="{collection_name}",
        points=[
            models.PointStruct(
                id=1,
                vector=models.Document(
                    text="Recipe for baking chocolate chip cookies",
                    model="openai/text-embedding-3-large",
                    options={
                        "dimensions": 512
                    }
                )
            )
        ]
    )
import { QdrantClient, withHeaders } from "@qdrant/js-client-rest";

await withHeaders({ 'openai-api-key': '<YOUR_OPENAI_API_KEY>' }, () =>
    client.upsert("{collection_name}", {
        points: [
            {
                id: 1,
                vector: {
                    text: 'Recipe for baking chocolate chip cookies',
                    model: 'openai/text-embedding-3-large',
                    options: {
                        dimensions: 512,
                    },
                },
            },
        ],
    })
);
use qdrant_client::{
    Payload, Qdrant,
    qdrant::{Document, PointStruct, UpsertPointsBuilder},
};
use std::collections::HashMap;

let mut options = HashMap::new();
options.insert("dimensions".to_string(), 512.into());

client
    .with_header("openai-api-key", "<YOUR_OPENAI_API_KEY>")
    .upsert_points(UpsertPointsBuilder::new("{collection_name}",
        vec![
            PointStruct::new(1,
                Document {
                  text: "Recipe for baking chocolate chip cookies".into(),
                  model: "openai/text-embedding-3-large".into(),
                  options,
                  },
                Payload::default())
            ]).wait(true))
        .await?;
import static io.qdrant.client.PointIdFactory.id;
import static io.qdrant.client.ValueFactory.value;
import static io.qdrant.client.VectorsFactory.vectors;

import io.grpc.Context;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.RequestHeaders;
import io.qdrant.client.grpc.Points.Document;
import io.qdrant.client.grpc.Points.PointStruct;
import java.util.List;
import java.util.Map;

    Context ctx = RequestHeaders.withHeader(
        Context.current(), "openai-api-key", "<YOUR_OPENAI_API_KEY>");

    ctx.call(() -> client
        .upsertAsync(
            "{collection_name}",
            List.of(
                PointStruct.newBuilder()
                    .setId(id(1))
                    .setVectors(
                        vectors(
                            Document.newBuilder()
                                .setModel("openai/text-embedding-3-large")
                                .setText("Recipe for baking chocolate chip cookies")
                                .putAllOptions(
                                    Map.of(
                                        "dimensions",
                                        value(512)))
                                .build()))
                    .build()))
        .get());
using Qdrant.Client;
using Qdrant.Client.Grpc;

using (RequestHeaders.Use("openai-api-key", "<YOUR_OPENAI_API_KEY>"))
    await client.UpsertAsync(
        collectionName: "{collection_name}",
        points: new List<PointStruct>
        {
            new()
            {
                Id = 1,
                Vectors = new Document()
                {
                    Model = "openai/text-embedding-3-large",
                    Text = "Recipe for baking chocolate chip cookies",
                    Options = { ["dimensions"] = 512 },
                },
            },
        }
    );
import (
	"context"

	"github.com/qdrant/go-client/qdrant"
)

ctx := qdrant.WithHeader(context.Background(), "openai-api-key", "<YOUR_OPENAI_API_KEY>")

client.Upsert(ctx, &qdrant.UpsertPoints{
	CollectionName: "{collection_name}",
	Points: []*qdrant.PointStruct{
		{
			Id: qdrant.NewIDNum(uint64(1)),
			Vectors: qdrant.NewVectorsDocument(&qdrant.Document{
				Model: "openai/text-embedding-3-large",
				Text:  "Recipe for baking chocolate chip cookies",
				Options: qdrant.NewValueMap(map[string]any{
					"dimensions": 512,
				}),
			}),
		},
	},
})

To search:

POST /collections/{collection_name}/points/query
{
  "query": {
    "text": "How to bake cookies?",
    "model": "openai/text-embedding-3-large",
    "options": {
      "openai-api-key": "<YOUR_OPENAI_API_KEY>",
      "dimensions": 512
    }
  }
}
from qdrant_client import QdrantClient, models
from qdrant_client.context_headers import headers

client = QdrantClient(
    url="https://xyz-example.qdrant.io:6333",
    api_key="<your-qdrant-api-key>",
    cloud_inference=True
)

with headers({"openai-api-key": "<YOUR_OPENAI_API_KEY>"}):
    client.query_points(
        collection_name="{collection_name}",
        query=models.Document(
            text="How to bake cookies?",
            model="openai/text-embedding-3-large",
            options={
                "dimensions": 512
            }
        )
    )
import { QdrantClient, withHeaders } from "@qdrant/js-client-rest";

await withHeaders({ 'openai-api-key': '<YOUR_OPENAI_API_KEY>' }, () =>
    client.query("{collection_name}", {
        query: {
            text: 'How to bake cookies?',
            model: 'openai/text-embedding-3-large',
            options: {
                dimensions: 512,
            },
        },
    })
);
use qdrant_client::{
    Qdrant,
    qdrant::{Document, Query, QueryPointsBuilder, Value},
};
use std::collections::HashMap;

let mut options = HashMap::<String, Value>::new();
options.insert("dimensions".to_string(), 512.into());

client
    .with_header("openai-api-key", "<YOUR_OPENAI_API_KEY>")
    .query(
        QueryPointsBuilder::new("{collection_name}")
            .query(Query::new_nearest(Document {
                text: "How to bake cookies?".into(),
                model: "openai/text-embedding-3-large".into(),
                options,
            }))
            .build(),
    )
    .await?;
import static io.qdrant.client.QueryFactory.nearest;
import static io.qdrant.client.ValueFactory.value;

import io.grpc.Context;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.RequestHeaders;
import io.qdrant.client.grpc.Points.Document;
import io.qdrant.client.grpc.Points.QueryPoints;
import java.util.Map;

    Context ctx = RequestHeaders.withHeader(
        Context.current(), "openai-api-key", "<YOUR_OPENAI_API_KEY>");

    ctx.call(() -> client
        .queryAsync(
            QueryPoints.newBuilder()
                .setCollectionName("{collection_name}")
                .setQuery(
                    nearest(
                        Document.newBuilder()
                            .setModel("openai/text-embedding-3-large")
                            .setText("How to bake cookies?")
                            .putAllOptions(
                                Map.of(
                                    "dimensions",
                                    value(512)))
                            .build()))
                .build())
        .get());
using Qdrant.Client;
using Qdrant.Client.Grpc;

using (RequestHeaders.Use("openai-api-key", "<YOUR_OPENAI_API_KEY>"))
    await client.QueryAsync(
        collectionName: "{collection_name}",
        query: new Document()
        {
            Model = "openai/text-embedding-3-large",
            Text = "How to bake cookies?",
            Options = { ["dimensions"] = 512 },
        }
    );
import (
	"context"

	"github.com/qdrant/go-client/qdrant"
)

ctx := qdrant.WithHeader(context.Background(), "openai-api-key", "<YOUR_OPENAI_API_KEY>")

client.Query(ctx, &qdrant.QueryPoints{
	CollectionName: "{collection_name}",
	Query: qdrant.NewQueryDocument(&qdrant.Document{
		Model: "openai/text-embedding-3-large",
		Text:  "How to bake cookies?",
		Options: qdrant.NewValueMap(map[string]any{
			"dimensions": 512,
		}),
	}),
})

For other ways to pass the key, see External Providers.

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.