Mistral
Mistral AI provides a text embedding model and a code embedding model through its Embeddings API. There are two ways to use them with Qdrant:
- Call the Mistral 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 Mistral Embed through OpenRouter for you.
Models
| Model | Dimensions | Reducible | Max Tokens per Input |
|---|---|---|---|
mistral-embed | 1024 | No | 8192 |
codestral-embed | 1536 (up to 3072) | Yes | 8192 |
mistral-embed is for general text. codestral-embed is for code retrieval. To pin a version, use mistral-embed-2312 or codestral-embed-2505.
Mistral embeddings are normalized to length 1, so the Cosine, Dot, and Euclidean distance metrics rank results identically. This page uses Cosine.
Setup
Install the Mistral SDK and the Qdrant client:
- Python:
pip install mistralai qdrant-client - TypeScript:
npm install @mistralai/mistralai @qdrant/js-client-rest
Create both clients and a collection sized for the model. The Mistral client reads your API key from the MISTRAL_API_KEY environment variable.
from mistralai.client import Mistral
from qdrant_client import QdrantClient, models
mistral_client = Mistral()
client = QdrantClient(url="http://localhost:6333")
MODEL = "mistral-embed"
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(size=1024, distance=models.Distance.COSINE),
)
import { Mistral } from "@mistralai/mistralai";
import { QdrantClient } from "@qdrant/js-client-rest";
const mistral = new Mistral();
const client = new QdrantClient({ url: "http://localhost:6333" });
const MODEL = "mistral-embed";
await client.createCollection("{collection_name}", {
vectors: { size: 1024, 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. The SDKs type index and embedding as optional, so the example asserts that they’re set:
documents = [
"Qdrant is a vector search engine.",
"Mistral embedding models turn text into dense vectors.",
]
response = mistral_client.embeddings.create(model=MODEL, inputs=documents)
points = []
for item in response.data:
assert item.index is not None and item.embedding is not None
points.append(
models.PointStruct(
id=item.index,
vector=item.embedding,
payload={"text": documents[item.index]},
)
)
client.upsert(collection_name="{collection_name}", points=points)
const documents = [
"Qdrant is a vector search engine.",
"Mistral embedding models turn text into dense vectors.",
];
const response = await mistral.embeddings.create({ model: MODEL, inputs: documents });
await client.upsert("{collection_name}", {
points: response.data.map((item) => ({
id: item.index!,
vector: item.embedding!,
payload: { text: documents[item.index!] },
})),
});
Embed Queries
Mistral models have no separate query mode. Embed the query with the same model you used for the documents:
query_vector = (
mistral_client.embeddings.create(model=MODEL, inputs=["What is Qdrant?"])
.data[0]
.embedding
)
assert query_vector is not None
hits = client.query_points(
collection_name="{collection_name}",
query=query_vector,
limit=3,
).points
const queryResponse = await mistral.embeddings.create({
model: MODEL,
inputs: ["What is Qdrant?"],
});
const queryVector = queryResponse.data[0].embedding;
if (!queryVector) throw new Error("Mistral returned no query embedding");
const { points: hits } = await client.query("{collection_name}", {
query: queryVector,
limit: 3,
});
Reduce Vector Size
codestral-embed accepts an output_dimension parameter of up to 3072. Its dimensions are ordered by relevance, so a smaller value keeps the most informative ones. Set the collection’s size to the same value, and pass the same output_dimension when you embed queries:
response = mistral_client.embeddings.create(
model="codestral-embed",
inputs=["def add(a, b):\n return a + b"],
output_dimension=512,
)
const reduced = await mistral.embeddings.create({
model: "codestral-embed",
inputs: ["def add(a, b):\n return a + b"],
outputDimension: 512,
});
mistral-embed always returns 1024 dimensions. To store its vectors in less memory, use Binary Quantization, which shrinks each vector by 32 times. In this test of mistral-embed, recall against the exact nearest neighbors reaches 94.5% at an oversampling of 3 and a limit of 100, with rescoring enabled:
| Oversampling | 1 | 1 | 2 | 2 | 3 | 3 | |
|---|---|---|---|---|---|---|---|
| Rescore | False | True | False | True | False | True | |
| Limit | |||||||
| 10 | 0.53444 | 0.857778 | 0.534444 | 0.918889 | 0.533333 | 0.941111 | |
| 20 | 0.508333 | 0.837778 | 0.508333 | 0.903889 | 0.508333 | 0.927778 | |
| 50 | 0.492222 | 0.834444 | 0.492222 | 0.903556 | 0.492889 | 0.940889 | |
| 100 | 0.499111 | 0.845444 | 0.498556 | 0.918333 | 0.497667 | 0.944556 |
Qdrant Cloud Inference
On Qdrant Cloud, Qdrant can call Mistral Embed for you through OpenRouter. Instead of a vector, send a Document with the model name openrouter/mistralai/mistral-embed-2312. Pass your OpenRouter API key in the openrouter-api-key request header or in the options object. Qdrant does not store the key, so send it with every request. The collection’s vector size must be 1024.
To ingest documents:
PUT /collections/{collection_name}/points?wait=true
{
"points": [
{
"id": 1,
"vector": {
"text": "Recipe for baking chocolate chip cookies",
"model": "openrouter/mistralai/mistral-embed-2312",
"options": {
"openrouter-api-key": "<YOUR_OPENROUTER_API_KEY>"
}
}
}
]
}
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({"openrouter-api-key": "<YOUR_OPENROUTER_API_KEY>"}):
client.upsert(
collection_name="{collection_name}",
points=[
models.PointStruct(
id=1,
vector=models.Document(
text="Recipe for baking chocolate chip cookies",
model="openrouter/mistralai/mistral-embed-2312",
)
)
]
)
import { QdrantClient, withHeaders } from "@qdrant/js-client-rest";
await withHeaders({ 'openrouter-api-key': '<YOUR_OPENROUTER_API_KEY>' }, () =>
client.upsert("{collection_name}", {
points: [
{
id: 1,
vector: {
text: 'Recipe for baking chocolate chip cookies',
model: 'openrouter/mistralai/mistral-embed-2312',
},
},
],
})
);
use qdrant_client::{
Payload, Qdrant,
qdrant::{Document, PointStruct, UpsertPointsBuilder},
};
use std::collections::HashMap;
client
.with_header("openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>")
.upsert_points(UpsertPointsBuilder::new("{collection_name}",
vec![
PointStruct::new(1,
Document {
text: "Recipe for baking chocolate chip cookies".into(),
model: "openrouter/mistralai/mistral-embed-2312".into(),
options: HashMap::new(),
},
Payload::default())
]).wait(true))
.await?;
import static io.qdrant.client.PointIdFactory.id;
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;
Context ctx = RequestHeaders.withHeader(
Context.current(), "openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>");
ctx.call(() -> client
.upsertAsync(
"{collection_name}",
List.of(
PointStruct.newBuilder()
.setId(id(1))
.setVectors(
vectors(
Document.newBuilder()
.setModel("openrouter/mistralai/mistral-embed-2312")
.setText("Recipe for baking chocolate chip cookies")
.build()))
.build()))
.get());
using Qdrant.Client;
using Qdrant.Client.Grpc;
using (RequestHeaders.Use("openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>"))
await client.UpsertAsync(
collectionName: "{collection_name}",
points: new List<PointStruct>
{
new()
{
Id = 1,
Vectors = new Document()
{
Model = "openrouter/mistralai/mistral-embed-2312",
Text = "Recipe for baking chocolate chip cookies",
},
},
}
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
ctx := qdrant.WithHeader(context.Background(), "openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>")
client.Upsert(ctx, &qdrant.UpsertPoints{
CollectionName: "{collection_name}",
Points: []*qdrant.PointStruct{
{
Id: qdrant.NewIDNum(uint64(1)),
Vectors: qdrant.NewVectorsDocument(&qdrant.Document{
Model: "openrouter/mistralai/mistral-embed-2312",
Text: "Recipe for baking chocolate chip cookies",
}),
},
},
})
To search:
POST /collections/{collection_name}/points/query
{
"query": {
"text": "How to bake cookies?",
"model": "openrouter/mistralai/mistral-embed-2312",
"options": {
"openrouter-api-key": "<YOUR_OPENROUTER_API_KEY>"
}
}
}
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({"openrouter-api-key": "<YOUR_OPENROUTER_API_KEY>"}):
client.query_points(
collection_name="{collection_name}",
query=models.Document(
text="How to bake cookies?",
model="openrouter/mistralai/mistral-embed-2312",
)
)
import { QdrantClient, withHeaders } from "@qdrant/js-client-rest";
await withHeaders({ 'openrouter-api-key': '<YOUR_OPENROUTER_API_KEY>' }, () =>
client.query("{collection_name}", {
query: {
text: 'How to bake cookies?',
model: 'openrouter/mistralai/mistral-embed-2312',
},
})
);
use qdrant_client::{
Qdrant,
qdrant::{Document, Query, QueryPointsBuilder},
};
use std::collections::HashMap;
client
.with_header("openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>")
.query(
QueryPointsBuilder::new("{collection_name}")
.query(Query::new_nearest(Document {
text: "How to bake cookies?".into(),
model: "openrouter/mistralai/mistral-embed-2312".into(),
options: HashMap::new(),
}))
.build(),
)
.await?;
import static io.qdrant.client.QueryFactory.nearest;
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;
Context ctx = RequestHeaders.withHeader(
Context.current(), "openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>");
ctx.call(() -> client
.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("{collection_name}")
.setQuery(
nearest(
Document.newBuilder()
.setModel("openrouter/mistralai/mistral-embed-2312")
.setText("How to bake cookies?")
.build()))
.build())
.get());
using Qdrant.Client;
using Qdrant.Client.Grpc;
using (RequestHeaders.Use("openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>"))
await client.QueryAsync(
collectionName: "{collection_name}",
query: new Document()
{
Model = "openrouter/mistralai/mistral-embed-2312",
Text = "How to bake cookies?",
}
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
ctx := qdrant.WithHeader(context.Background(), "openrouter-api-key", "<YOUR_OPENROUTER_API_KEY>")
client.Query(ctx, &qdrant.QueryPoints{
CollectionName: "{collection_name}",
Query: qdrant.NewQueryDocument(&qdrant.Document{
Model: "openrouter/mistralai/mistral-embed-2312",
Text: "How to bake cookies?",
}),
})
For other ways to pass the key, see External Providers.
Store and Search the Vectors
Next Steps
- Read Mistral’s code embeddings guide for the
codestral-embedoutput types. - Filter search results by payload fields.
- Combine Mistral vectors with sparse vectors for hybrid search.
- Reduce memory use with quantization.