Управление коллекциями#
Коллекция — именованный набор точек (векторов с полезной нагрузкой), среди которых можно выполнять поиск. Вектор каждой точки внутри одной коллекции должен иметь одинаковую размерность и сравниваться по единой метрике. Именованные векторы могут использоваться для хранения нескольких векторов в одной точке, каждый из которых может иметь свою собственную размерность и требования к метрике.
Метрики расстояния используются для измерения сходства между векторами. Выбор метрики зависит от способа получения векторов и, в частности, от метода обучения нейросети.
Platform V Vector DB (далее - Vector DB) поддерживает следующие наиболее популярные типы метрик:
Скалярное произведение (
Dot) - сумма произведений соответствующих координат векторов. Используется для нормализованных векторов (длина = 1), где чем больше скалярное произведение, тем больше схожесть.Косинусное сходство (
Cosine) - измеряет угол между двумя векторами, игнорируя их длину. Чем меньше угол, тем выше схожесть. Используется для задач семантического поиска (например, тексты, эмбеддинги BERT), когда важна направленность векторов, а не их масштаб.Евклидово расстояние (
Euclid) - расстояние между двумя точками в многомерном пространстве. Используется для задач, где важна абсолютная разница между векторами (например, изображения, аудио).Манхеттенское расстояние (
Manhattan) - сумма абсолютных разностей координат векторов. Используется для высокоразмерных данных или задач, где важна направленность, но не масштаб (например, геолокационные данные).
Информация
Для повышения эффективности поиска косинусное сходство реализовано как скалярное произведение нормализованных векторов. Векторы автоматически нормализуются при загрузке.
Помимо метрик и размера вектора каждая коллекция использует собственный набор параметров, который контролирует оптимизацию коллекции, построение индекса и очистку памяти. Эти настройки могут быть изменены в любое время соответствующим запросом.
Настройка мультитенантности#
Рекомендуемое число коллекций: Во многих случаях рекомендуется использовать одну коллекцию с разделением на основе полезной нагрузки. Данный подход называется мультитенантностью, который эффективен для большинства пользователей, но требует дополнительной настройки.
Причина создания нескольких коллекций: Если используется ограниченное число пользователей и требуется изоляция данных. Данный подход гибкий, но может оказаться более затратным, поскольку создание множества коллекций может привести к избыточной нагрузке на ресурсы. Также необходимо убедиться, что они никаким образом не влияют друг на друга с точки зрения производительности.
Создание коллекции#
Создание коллекции:
PUT /collections/{collection_name}
{
"vectors": {
"size": 300,
"distance": "Cosine"
}
}
curl -X PUT http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"size": 300,
"distance": "Cosine"
}
}'
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(size=100, distance=models.Distance.COSINE),
)
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.createCollection("{collection_name}", {
vectors: { size: 100, distance: "Cosine" },
});
use qdrant_client::Qdrant;
use qdrant_client::qdrant::{CreateCollectionBuilder, VectorParamsBuilder};
let client = Qdrant::from_url("http://localhost:6334").build()?;
client
.create_collection(
CreateCollectionBuilder::new("{collection_name}")
.vectors_config(VectorParamsBuilder::new(100, Distance::Cosine)),
)
.await?;
import io.qdrant.client.grpc.Collections.Distance;
import io.qdrant.client.grpc.Collections.VectorParams;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
QdrantClient client = new QdrantClient(
QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client.createCollectionAsync("{collection_name}",
VectorParams.newBuilder().setDistance(Distance.Cosine).setSize(100).build()).get();
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.CreateCollectionAsync(
collectionName: "{collection_name}",
vectorsConfig: new VectorParams { Size = 100, Distance = Distance.Cosine }
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "{collection_name}",
VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{
Size: 100,
Distance: qdrant.Distance_Cosine,
}),
})
В дополнение к обязательным опциям можно указать пользовательские значения для параметров коллекции:
hnsw_config- подробнее в разделе Индексирование.wal_config- конфигурация журнала упреждающей записи. Подробное описание WAL приведено в разделе Хранилище.optimizers_config- подробнее в разделе Оптимизаторы.shard_number- определяет какое количество шардов должна содержать коллекция.on_disk_payload- задает место хранения данных полезной нагрузки. Еслиtrue- полезная нагрузка будет храниться только на диске. Это может пригодиться для ограничения использования оперативной памяти в случае большого объема полезной нагрузки.quantization_config- подробнее в разделе Квантование.strict_mode_config- подробное описание приведено в Руководстве администратора раздел Строгий режим.
Значения по умолчанию для необязательных параметров коллекции определены в файле конфигурации (config.yaml).
Информация
Для получения дополнительной информации о параметрах коллекции и вектора рекомендуется ознакомиться с соответствующим методом и описанием конфигурационного файла.
Все векторы хранятся в оперативной памяти для быстрого доступа. Параметр on_disk можно установить в векторной конфигурации. Если установлено значение true, все векторы будут постоянно находиться на диске. Это позволит использовать memmaps, что подходит для обработки больших объемов данных.
Создание коллекции из существующей#
Существует возможность инициализировать коллекцию из уже существующей коллекции.
Это может быть полезно для быстрого экспериментирования с различными конфигурациями для одного набора данных.
Важно
Использование команды init_from может вызвать непредсказуемую нагрузку на кластер. Не рекомендуется использовать команду init_from в средах, чувствительных к производительности.
Убедитесь, что векторы имеют одинаковые функции size и distance, когда настраиваете параметры векторов в новой коллекции. Если был использован пример кода из раздела Создание коллекции, то "size": 300 и "distance": "Cosine".
PUT /collections/{collection_name}
{
"vectors": {
"size": 100,
"distance": "Cosine"
},
"init_from": {
"collection": "{from_collection_name}"
}
}
curl -X PUT http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"size": 300,
"distance": "Cosine"
},
"init_from": {
"collection": {from_collection_name}
}
}'
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(size=100, distance=models.Distance.COSINE),
init_from=models.InitFrom(collection="{from_collection_name}"),
)
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.createCollection("{collection_name}", {
vectors: { size: 100, distance: "Cosine" },
init_from: { collection: "{from_collection_name}" },
});
use qdrant_client::Qdrant;
use qdrant_client::qdrant::{CreateCollectionBuilder, Distance, VectorParamsBuilder};
let client = Qdrant::from_url("http://localhost:6334").build()?;
client
.create_collection(
CreateCollectionBuilder::new("{collection_name}")
.vectors_config(VectorParamsBuilder::new(100, Distance::Cosine))
.init_from_collection("{from_collection_name}"),
)
.await?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Collections.CreateCollection;
import io.qdrant.client.grpc.Collections.Distance;
import io.qdrant.client.grpc.Collections.VectorParams;
import io.qdrant.client.grpc.Collections.VectorsConfig;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client
.createCollectionAsync(
CreateCollection.newBuilder()
.setCollectionName("{collection_name}")
.setVectorsConfig(
VectorsConfig.newBuilder()
.setParams(
VectorParams.newBuilder()
.setSize(100)
.setDistance(Distance.Cosine)
.build()))
.setInitFromCollection("{from_collection_name}")
.build())
.get();
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.CreateCollectionAsync(
collectionName: "{collection_name}",
vectorsConfig: new VectorParams { Size = 100, Distance = Distance.Cosine },
initFromCollection: "{from_collection_name}"
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "{collection_name}",
VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{
Size: 100,
Distance: qdrant.Distance_Cosine,
}),
InitFromCollection: qdrant.PtrOf("{from_collection_name}"),
})
Коллекция с несколькими векторами#
Возможно наличие нескольких векторов на запись. Данная особенность позволяет хранить несколько хранилищ векторов в рамках одной коллекции. Для различия векторов в одной записи им нужно задать уникальное имя при создании коллекции. Каждый именованный вектор в этом режиме имеет свое собственное расстояние и размер:
PUT /collections/{collection_name}
{
"vectors": {
"image": {
"size": 4,
"distance": "Dot"
},
"text": {
"size": 8,
"distance": "Cosine"
}
}
}
curl -X PUT http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"image": {
"size": 4,
"distance": "Dot"
},
"text": {
"size": 8,
"distance": "Cosine"
}
}
}'
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="{collection_name}",
vectors_config={
"image": models.VectorParams(size=4, distance=models.Distance.DOT),
"text": models.VectorParams(size=8, distance=models.Distance.COSINE),
},
)
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.createCollection("{collection_name}", {
vectors: {
image: { size: 4, distance: "Dot" },
text: { size: 8, distance: "Cosine" },
},
});
use qdrant_client::Qdrant;
use qdrant_client::qdrant::{
CreateCollectionBuilder, Distance, VectorParamsBuilder, VectorsConfigBuilder,
};
let client = Qdrant::from_url("http://localhost:6334").build()?;
let mut vectors_config = VectorsConfigBuilder::default();
vectors_config
.add_named_vector_params("image", VectorParamsBuilder::new(4, Distance::Dot).build());
vectors_config.add_named_vector_params(
"text",
VectorParamsBuilder::new(8, Distance::Cosine).build(),
);
client
.create_collection(
CreateCollectionBuilder::new("{collection_name}").vectors_config(vectors_config),
)
.await?;
import java.util.Map;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Collections.Distance;
import io.qdrant.client.grpc.Collections.VectorParams;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client
.createCollectionAsync(
"{collection_name}",
Map.of(
"image", VectorParams.newBuilder().setSize(4).setDistance(Distance.Dot).build(),
"text",
VectorParams.newBuilder().setSize(8).setDistance(Distance.Cosine).build()))
.get();
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.CreateCollectionAsync(
collectionName: "{collection_name}",
vectorsConfig: new VectorParamsMap
{
Map =
{
["image"] = new VectorParams { Size = 4, Distance = Distance.Dot },
["text"] = new VectorParams { Size = 8, Distance = Distance.Cosine },
}
}
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "{collection_name}",
VectorsConfig: qdrant.NewVectorsConfigMap(
map[string]*qdrant.VectorParams{
"image": {
Size: 4,
Distance: qdrant.Distance_Dot,
},
"text": {
Size: 8,
Distance: qdrant.Distance_Cosine,
},
}),
})
В редких случаях возможно создание коллекции вообще без какого-либо хранилища векторов.
Для каждого именованного вектора можно дополнительно указать hnsw_config или quantization_config, чтобы отклониться от конфигурации коллекции. Это может быть полезно для тонкой настройки производительности поиска на уровне отдельных векторов.
Все векторы находятся в оперативной памяти для очень быстрого доступа. На уровне отдельного вектора можно установить параметр on_disk равным true, чтобы постоянно сохранять все векторы на диске. Это активирует использование memmaps, что удобно для загрузки больших объемов данных.
Типы данных векторов#
Некоторые поставщики встраиваемых решений могут предоставлять вложения в предварительно квантованном формате. Одним из самых заметных примеров являются целочисленные вложения Cohere int8 и бинарные вложения. Vector DB напрямую поддерживает вложения типа uint8, которые также можно комбинировать с двоичным квантованием.
Чтобы создать коллекцию с вложениями типа uint8, используйте следующую конфигурацию:
PUT /collections/{collection_name}
{
"vectors": {
"size": 1024,
"distance": "Cosine",
"datatype": "uint8"
}
}
curl -X PUT http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"size": 1024,
"distance": "Cosine",
"datatype": "uint8"
}
}'
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(
size=1024,
distance=models.Distance.COSINE,
datatype=models.Datatype.UINT8,
),
)
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.createCollection("{collection_name}", {
vectors: {
image: { size: 1024, distance: "Cosine", datatype: "uint8" },
},
});
use qdrant_client::Qdrant;
use qdrant_client::qdrant::{
CreateCollectionBuilder, Datatype, Distance, VectorParamsBuilder,
};
let client = Qdrant::from_url("http://localhost:6334").build()?;
client
.create_collection(
CreateCollectionBuilder::new("{collection_name}").vectors_config(
VectorParamsBuilder::new(1024, Distance::Cosine).datatype(Datatype::Uint8),
),
)
.await?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.grpc.Collections.Datatype;
import io.qdrant.client.grpc.Collections.Distance;
import io.qdrant.client.grpc.Collections.VectorParams;
QdrantClient client = new QdrantClient(
QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client
.createCollectionAsync("{collection_name}",
VectorParams.newBuilder()
.setSize(1024)
.setDistance(Distance.Cosine)
.setDatatype(Datatype.Uint8)
.build())
.get();
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.CreateCollectionAsync(
collectionName: "{collection_name}",
vectorsConfig: new VectorParams {
Size = 1024, Distance = Distance.Cosine, Datatype = Datatype.Uint8
}
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "{collection_name}",
VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{
Size: 1024,
Distance: qdrant.Distance_Cosine,
Datatype: qdrant.Datatype_Uint8.Enum(),
}),
})
Векторы с типом данных uint8 хранятся в более компактном формате, что экономит память и повышает скорость поиска ценой некоторой потери точности. Если выбран тип данных uint8, элементы вектора будут сохраняться как беззнаковые целые числа размером 8 бит, которые могут принимать значения от 0 до 255.
Коллекция с разреженными векторами#
Vector DB поддерживает разреженные векторы как полноценную функцию.
Разреженные векторы полезны для текстового поиска, где каждое слово представлено отдельной размерностью.
Коллекции могут содержать разреженные векторы наряду с обычными плотными векторами в одной точке.
В отличие от плотных векторов, разреженным векторам обязательно нужно присваивать имена. Кроме того, разреженные и плотные векторы должны иметь разные названия в пределах одной коллекции.
PUT /collections/{collection_name}
{
"sparse_vectors": {
"text": { }
}
}
curl -X PUT http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"sparse_vectors": {
"text": { }
}
}'
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="{collection_name}",
vectors_config={},
sparse_vectors_config={
"text": models.SparseVectorParams(),
},
)
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.createCollection("{collection_name}", {
sparse_vectors: {
text: { },
},
});
use qdrant_client::Qdrant;
use qdrant_client::qdrant::{
CreateCollectionBuilder, SparseVectorParamsBuilder, SparseVectorsConfigBuilder,
};
let client = Qdrant::from_url("http://localhost:6334").build()?;
let mut sparse_vector_config = SparseVectorsConfigBuilder::default();
sparse_vector_config.add_named_vector_params("text", SparseVectorParamsBuilder::default());
client
.create_collection(
CreateCollectionBuilder::new("{collection_name}")
.sparse_vectors_config(sparse_vector_config),
)
.await?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import io.qdrant.client.grpc.Collections.CreateCollection;
import io.qdrant.client.grpc.Collections.SparseVectorConfig;
import io.qdrant.client.grpc.Collections.SparseVectorParams;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client
.createCollectionAsync(
CreateCollection.newBuilder()
.setCollectionName("{collection_name}")
.setSparseVectorsConfig(
SparseVectorConfig.newBuilder()
.putMap("text", SparseVectorParams.getDefaultInstance()))
.build())
.get();
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.CreateCollectionAsync(
collectionName: "{collection_name}",
sparseVectorsConfig: ("text", new SparseVectorParams())
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "{collection_name}",
SparseVectorsConfig: qdrant.NewSparseVectorsConfig(
map[string]*qdrant.SparseVectorParams{
"text": {},
}),
})
Функция вычисления расстояний для разреженных векторов всегда равна Dot и не нуждается в указании.
Кроме уникального имени для разреженных векторов нет никаких обязательных параметров конфигурации. Однако существуют дополнительные параметры для настройки лежащего в основе разреженного индексного вектора.
Проверка существования коллекции#
Проверка существования коллекции:
GET http://localhost:6333/collections/{collection_name}/exists
curl -X GET http://localhost:6333/collections/{collection_name}/exists
client.collection_exists(collection_name="{collection_name}")
client.collectionExists("{collection_name}");
client.collection_exists("{collection_name}").await?;
client.collectionExistsAsync("{collection_name}").get();
await client.CollectionExistsAsync("{collection_name}");
import "context"
client.CollectionExists(context.Background(), "my_collection")
Удаление коллекции#
Удаление коллекции:
DELETE http://localhost:6333/collections/{collection_name}
curl -X DELETE http://localhost:6333/collections/{collection_name}
client.delete_collection(collection_name="{collection_name}")
client.deleteCollection("{collection_name}");
client.delete_collection("{collection_name}").await?;
client.deleteCollectionAsync("{collection_name}").get();
await client.DeleteCollectionAsync("{collection_name}");
import "context"
client.DeleteCollection(context.Background(), "{collection_name}")
Обновление параметров коллекции#
Динамическое обновление параметров может быть полезным, например, для более эффективной начальной загрузки векторов: можно отключить индексирование во время процесса загрузки и включить его сразу после завершения загрузки. Таким образом, лишние вычислительные ресурсы не будут истрачены на повторную перестройку индекса.
Чтобы включить индексирование для сегментов, содержащих более 10000 КБ хранимых векторов необходимо выполнить команду:
PATCH /collections/{collection_name}
{
"optimizers_config": {
"indexing_threshold": 10000
}
}
curl -X PATCH http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"optimizers_config": {
"indexing_threshold": 10000
}
}'
client.update_collection(
collection_name="{collection_name}",
optimizers_config=models.OptimizersConfigDiff(indexing_threshold=10000),
)
client.updateCollection("{collection_name}", {
optimizers_config: {
indexing_threshold: 10000,
},
});
use qdrant_client::qdrant::{OptimizersConfigDiffBuilder, UpdateCollectionBuilder};
client
.update_collection(
UpdateCollectionBuilder::new("{collection_name}").optimizers_config(
OptimizersConfigDiffBuilder::default().indexing_threshold(10000),
),
)
.await?;
import io.qdrant.client.grpc.Collections.OptimizersConfigDiff;
import io.qdrant.client.grpc.Collections.UpdateCollection;
client.updateCollectionAsync(
UpdateCollection.newBuilder()
.setCollectionName("{collection_name}")
.setOptimizersConfig(
OptimizersConfigDiff.newBuilder().setIndexingThreshold(10000).build())
.build());
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.UpdateCollectionAsync(
collectionName: "{collection_name}",
optimizersConfig: new OptimizersConfigDiff { IndexingThreshold = 10000 }
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.UpdateCollection(context.Background(), &qdrant.UpdateCollection{
CollectionName: "{collection_name}",
OptimizersConfig: &qdrant.OptimizersConfigDiff{
IndexingThreshold: qdrant.PtrOf(uint64(10000)),
},
})
Следующие параметры могут быть обновлены:
optimizers_config- подробнее в разделе Оптимизаторы.hnsw_config- подробнее в разделе Индексирование.quantization_config- подробнее в разделе Квантование.vectors_config- специфичная для вектора конфигурация, включая индивидуальные настройкиhnsw_config,quantization_configиon_disk.params- другие параметры коллекции, включаяwrite_consistency_factorиon_disk_payload.strict_mode_config- подробное описание приведено в Руководстве администратора раздел Строгий режим.
Полная спецификация API доступна в разделе Справочник API.
Внимание
Обращения к конечной точке могут блокироваться, так как ожидают окончания работы существующих оптимизаторов. Настоятельно не рекомендуется использовать эту функцию в производственной базе данных, так как она может ввести значительную дополнительную нагрузку из-за необходимости перестроения индекса.
Обновление параметров векторов#
Информация
Чтобы обновить параметры векторов с помощью API обновления коллекции необходимо указать имя вектора. Если коллекция не содержит именованных векторов, укажите пустое ("") имя.
Доступна возможность обновления большого количества параметров коллекции во время выполнения. Индексы HNSW, квантование и дисковые конфигурации могут быть изменены без повторного создания коллекции. Сегменты (с индексированными и квантованными данными) будут автоматически перестроены в фоновом режиме, чтобы соответствовать обновленным параметрам.
Чтобы сохранить данные вектора на диске, для коллекции без именованных векторов укажите в качестве имени пустую строку "".
PATCH /collections/{collection_name}
{
"vectors": {
"": {
"on_disk": true
}
}
}
curl -X PATCH http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"": {
"on_disk": true
}
}
}'
Чтобы сохранить данные вектора на диске, для коллекции с именованными векторами создайте имя вектора.
PATCH /collections/{collection_name}
{
"vectors": {
"my_vector": {
"on_disk": true
}
}
}
curl -X PATCH http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"my_vector": {
"on_disk": true
}
}
}'
Для обновления параметров индекса HNSW и квантования для всей коллекции и конкретно для my_vector выполните:
PATCH /collections/{collection_name}
{
"vectors": {
"my_vector": {
"hnsw_config": {
"m": 32,
"ef_construct": 123
},
"quantization_config": {
"product": {
"compression": "x32",
"always_ram": true
}
},
"on_disk": true
}
},
"hnsw_config": {
"ef_construct": 123
},
"quantization_config": {
"scalar": {
"type": "int8",
"quantile": 0.8,
"always_ram": false
}
}
}
curl -X PATCH http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"vectors": {
"my_vector": {
"hnsw_config": {
"m": 32,
"ef_construct": 123
},
"quantization_config": {
"product": {
"compression": "x32",
"always_ram": true
}
},
"on_disk": true
}
},
"hnsw_config": {
"ef_construct": 123
},
"quantization_config": {
"scalar": {
"type": "int8",
"quantile": 0.8,
"always_ram": false
}
}
}'
client.update_collection(
collection_name="{collection_name}",
vectors_config={
"my_vector": models.VectorParamsDiff(
hnsw_config=models.HnswConfigDiff(
m=32,
ef_construct=123,
),
quantization_config=models.ProductQuantization(
product=models.ProductQuantizationConfig(
compression=models.CompressionRatio.X32,
always_ram=True,
),
),
on_disk=True,
),
},
hnsw_config=models.HnswConfigDiff(
ef_construct=123,
),
quantization_config=models.ScalarQuantization(
scalar=models.ScalarQuantizationConfig(
type=models.ScalarType.INT8,
quantile=0.8,
always_ram=False,
),
),
)
client.updateCollection("{collection_name}", {
vectors: {
my_vector: {
hnsw_config: {
m: 32,
ef_construct: 123,
},
quantization_config: {
product: {
compression: "x32",
always_ram: true,
},
},
on_disk: true,
},
},
hnsw_config: {
ef_construct: 123,
},
quantization_config: {
scalar: {
type: "int8",
quantile: 0.8,
always_ram: true,
},
},
});
use std::collections::HashMap;
use qdrant_client::qdrant::{
quantization_config_diff::Quantization, vectors_config_diff::Config, HnswConfigDiffBuilder,
QuantizationType, ScalarQuantizationBuilder, UpdateCollectionBuilder, VectorParamsDiffBuilder,
VectorParamsDiffMap,
};
client
.update_collection(
UpdateCollectionBuilder::new("{collection_name}")
.hnsw_config(HnswConfigDiffBuilder::default().ef_construct(123))
.vectors_config(Config::ParamsMap(VectorParamsDiffMap {
map: HashMap::from([(
("my_vector".into()),
VectorParamsDiffBuilder::default()
.hnsw_config(HnswConfigDiffBuilder::default().m(32).ef_construct(123))
.build(),
)]),
}))
.quantization_config(Quantization::Scalar(
ScalarQuantizationBuilder::default()
.r#type(QuantizationType::Int8.into())
.quantile(0.8)
.always_ram(true)
.build(),
)),
)
.await?;
import io.qdrant.client.grpc.Collections.HnswConfigDiff;
import io.qdrant.client.grpc.Collections.QuantizationConfigDiff;
import io.qdrant.client.grpc.Collections.QuantizationType;
import io.qdrant.client.grpc.Collections.ScalarQuantization;
import io.qdrant.client.grpc.Collections.UpdateCollection;
import io.qdrant.client.grpc.Collections.VectorParamsDiff;
import io.qdrant.client.grpc.Collections.VectorParamsDiffMap;
import io.qdrant.client.grpc.Collections.VectorsConfigDiff;
client
.updateCollectionAsync(
UpdateCollection.newBuilder()
.setCollectionName("{collection_name}")
.setHnswConfig(HnswConfigDiff.newBuilder().setEfConstruct(123).build())
.setVectorsConfig(
VectorsConfigDiff.newBuilder()
.setParamsMap(
VectorParamsDiffMap.newBuilder()
.putMap(
"my_vector",
VectorParamsDiff.newBuilder()
.setHnswConfig(
HnswConfigDiff.newBuilder()
.setM(3)
.setEfConstruct(123)
.build())
.build())))
.setQuantizationConfig(
QuantizationConfigDiff.newBuilder()
.setScalar(
ScalarQuantization.newBuilder()
.setType(QuantizationType.Int8)
.setQuantile(0.8f)
.setAlwaysRam(true)
.build()))
.build())
.get();
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.UpdateCollectionAsync(
collectionName: "{collection_name}",
hnswConfig: new HnswConfigDiff { EfConstruct = 123 },
vectorsConfig: new VectorParamsDiffMap
{
Map =
{
{
"my_vector",
new VectorParamsDiff
{
HnswConfig = new HnswConfigDiff { M = 3, EfConstruct = 123 }
}
}
}
},
quantizationConfig: new QuantizationConfigDiff
{
Scalar = new ScalarQuantization
{
Type = QuantizationType.Int8,
Quantile = 0.8f,
AlwaysRam = true
}
}
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.UpdateCollection(context.Background(), &qdrant.UpdateCollection{
CollectionName: "{collection_name}",
VectorsConfig: qdrant.NewVectorsConfigDiffMap(
map[string]*qdrant.VectorParamsDiff{
"my_vector": {
HnswConfig: &qdrant.HnswConfigDiff{
M: qdrant.PtrOf(uint64(3)),
EfConstruct: qdrant.PtrOf(uint64(123)),
},
},
}),
QuantizationConfig: qdrant.NewQuantizationDiffScalar(
&qdrant.ScalarQuantization{
Type: qdrant.QuantizationType_Int8,
Quantile: qdrant.PtrOf(float32(0.8)),
AlwaysRam: qdrant.PtrOf(true),
}),
})
Информация о коллекции#
Vector DB позволяет определить параметры конфигурации существующей коллекции, чтобы лучше понять, как распределены и проиндексированы точки.
GET /collections/{collection_name}
curl -X GET http://localhost:6333/collections/{collection_name}
client.get_collection(collection_name="{collection_name}")
client.getCollection("{collection_name}");
client.collection_info("{collection_name}").await?;
client.getCollectionInfoAsync("{collection_name}").get();
await client.GetCollectionInfoAsync("{collection_name}");
import "context"
client.GetCollectionInfo(context.Background(), "{collection_name}")
Ожидаемый результат
{
"result": {
"status": "green",
"optimizer_status": "ok",
"vectors_count": 1068786,
"indexed_vectors_count": 1024232,
"points_count": 1068786,
"segments_count": 31,
"config": {
"params": {
"vectors": {
"size": 384,
"distance": "Cosine"
},
"shard_number": 1,
"replication_factor": 1,
"write_consistency_factor": 1,
"on_disk_payload": false
},
"hnsw_config": {
"m": 16,
"ef_construct": 100,
"full_scan_threshold": 10000,
"max_indexing_threads": 0
},
"optimizer_config": {
"deleted_threshold": 0.2,
"vacuum_min_vector_number": 1000,
"default_segment_number": 0,
"max_segment_size": null,
"memmap_threshold": null,
"indexing_threshold": 20000,
"flush_interval_sec": 5,
"max_optimization_threads": 1
},
"wal_config": {
"wal_capacity_mb": 32,
"wal_segments_ahead": 0
}
},
"payload_schema": {}
},
"status": "ok",
"time": 0.00010143
}
В процессе вставки векторов в коллекцию, поле status может стать yellow пока идет процесс оптимизации. Оно станет green, как только все точки успешно обработаны.
Возможны следующие цветовые состояния:
🟢
green: коллекция готова;🟡
yellow: коллекция оптимизируется;⚫
grey: коллекция ожидает оптимизации (подробнее в разделе Серый статус коллекции);🔴
red: произошла ошибка.
Серый статус коллекции#
Коллекция может иметь серый статус (⚫) или отображать "ожидаются операции оптимизации" в статусе оптимизации. Обычно это вызвано перезапуском экземпляра Vector DB во время проведения операций оптимизации.
Данный статус означает, что коллекция ожидает оптимизации. Следует отправить любую операцию обновления, чтобы инициировать и запустить оптимизацию повторно.
Например:
PATCH /collections/{collection_name}
{
"optimizers_config": {}
}
curl -X PATCH http://localhost:6333/collections/{collection_name} \
-H 'Content-Type: application/json' \
--data-raw '{
"optimizers_config": {}
}'
client.update_collection(
collection_name="{collection_name}",
optimizer_config=models.OptimizersConfigDiff(),
)
client.updateCollection("{collection_name}", {
optimizers_config: {},
});
use qdrant_client::qdrant::{OptimizersConfigDiffBuilder, UpdateCollectionBuilder};
client
.update_collection(
UpdateCollectionBuilder::new("{collection_name}")
.optimizers_config(OptimizersConfigDiffBuilder::default()),
)
.await?;
import io.qdrant.client.grpc.Collections.OptimizersConfigDiff;
import io.qdrant.client.grpc.Collections.UpdateCollection;
client.updateCollectionAsync(
UpdateCollection.newBuilder()
.setCollectionName("{collection_name}")
.setOptimizersConfig(
OptimizersConfigDiff.getDefaultInstance())
.build());
using Qdrant.Client;
using Qdrant.Client.Grpc;
var client = new QdrantClient("localhost", 6334);
await client.UpdateCollectionAsync(
collectionName: "{collection_name}",
optimizersConfig: new OptimizersConfigDiff { }
);
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.UpdateCollection(context.Background(), &qdrant.UpdateCollection{
CollectionName: "{collection_name}",
OptimizersConfig: &qdrant.OptimizersConfigDiff{},
})
Приблизительное количество точек и векторов#
Vector DB обладает показателями подсчета:
points_count- общее количество объектов (векторов и их полезных нагрузок), хранящихся в коллекции;vectors_count- общее количество векторов в коллекции (полезно, когда используется несколько векторов на точку);indexed_vectors_count- общее количество векторов, хранящихся в индексе HNSW или разреженном индексе. Vector DB не сохраняет все векторы в индексе, а только те, для которых может быть создан сегмент индекса при заданной конфигурации.
Приведенные выше показатели являются приблизительными и не должны рассматриваться как точные. В зависимости от того, как используется Vector DB, они могут отличаться от ожидаемых.
Данные показатели представляют собой счетчики точек и векторов во внутреннем хранилище. Внутренне Vector DB временно дублирует точки в процессе автоматических оптимизаций. Он может некоторое время удерживать измененные или удаленные точки, а также задерживать индексацию новых точек ради оптимизации.
Таким образом, внесенные изменения непосредственно не отражаются в показателях. Если отображается сильно отличающееся количество точек, оно скорее всего стабилизируется после завершения нового цикла автоматических оптимизаций.
Внимание
Показатели не отражают точное количество точек или векторов, которые были вставлены, и не показывают точное количество различных точек или векторов, доступных для запроса. Если нужны точные подсчеты, обратитесь к API подсчета.
Индексирование векторов в HNSW#
В некоторых ситуациях значение indexed_vectors_count может быть ниже, чем vectors_count. Такое поведение предусмотрено намеренно и зависит от настроек оптимизатора. Новый сегмент индекса создается, если объем невзвешенных векторов превышает значение indexing_threshold(в килобайтах). Если коллекция очень мала или размерность векторов низкая, сегмент HNSW может не создаться и indexed_vectors_count будет равно 0.
Можно уменьшить indexing_threshold для существующей коллекции путем обновления параметров коллекции.
Алиасы коллекций#
В производственной среде иногда возникает необходимость бесшовного переключения между разными версиями векторов. Например, при переходе на новую версию нейронной сети.
В таких ситуациях нет возможности остановить сервис и заново построить коллекцию с новыми векторами. Алиасы — это альтернативные имена (псевдонимы) для существующих коллекций. Все запросы к коллекции могут быть выполнены идентично, используя вместо имени коллекции ее псевдоним.
Таким образом, можно построить вторую коллекцию в фоне и затем переключить псевдоним со старой коллекцию на новую. Поскольку изменение псевдонимов происходит атомарно, никакие параллельные запросы не пострадают во время переключения.
Создание псевдонима#
POST /collections/aliases
{
"actions": [
{
"create_alias": {
"collection_name": "example_collection",
"alias_name": "production_collection"
}
}
]
}
curl -X POST http://localhost:6333/collections/aliases \
-H 'Content-Type: application/json' \
--data-raw '{
"actions": [
{
"create_alias": {
"collection_name": "example_collection",
"alias_name": "production_collection"
}
}
]
}'
client.update_collection_aliases(
change_aliases_operations=[
models.CreateAliasOperation(
create_alias=models.CreateAlias(
collection_name="example_collection", alias_name="production_collection"
)
)
]
)
client.updateCollectionAliases({
actions: [
{
create_alias: {
collection_name: "example_collection",
alias_name: "production_collection",
},
},
],
});
use qdrant_client::qdrant::CreateAliasBuilder;
client
.create_alias(CreateAliasBuilder::new(
"example_collection",
"production_collection",
))
.await?;
client.createAliasAsync("production_collection", "example_collection").get();
await client.CreateAliasAsync(aliasName: "production_collection", collectionName: "example_collection");
import "context"
client.CreateAlias(context.Background(), "production_collection", "example_collection")
Удаление псевдонима#
POST /collections/aliases
{
"actions": [
{
"delete_alias": {
"alias_name": "production_collection"
}
}
]
}
curl -X POST http://localhost:6333/collections/aliases \
-H 'Content-Type: application/json' \
--data-raw '{
"actions": [
{
"delete_alias": {
"alias_name": "production_collection"
}
}
]
}'
client.update_collection_aliases(
change_aliases_operations=[
models.DeleteAliasOperation(
delete_alias=models.DeleteAlias(alias_name="production_collection")
),
]
)
client.updateCollectionAliases({
actions: [
{
delete_alias: {
alias_name: "production_collection",
},
},
],
});
client.delete_alias("production_collection").await?;
client.deleteAliasAsync("production_collection").get();
await client.DeleteAliasAsync("production_collection");
import "context"
client.DeleteAlias(context.Background(), "production_collection")
Смена коллекции#
Несколько действий с псевдонимами выполняются атомарно. Например, можно сменить базовую коллекцию следующей командой:
POST /collections/aliases
{
"actions": [
{
"delete_alias": {
"alias_name": "production_collection"
}
},
{
"create_alias": {
"collection_name": "example_collection",
"alias_name": "production_collection"
}
}
]
}
curl -X POST http://localhost:6333/collections/aliases \
-H 'Content-Type: application/json' \
--data-raw '{
"actions": [
{
"delete_alias": {
"alias_name": "production_collection"
}
},
{
"create_alias": {
"collection_name": "example_collection",
"alias_name": "production_collection"
}
}
]
}'
client.update_collection_aliases(
change_aliases_operations=[
models.DeleteAliasOperation(
delete_alias=models.DeleteAlias(alias_name="production_collection")
),
models.CreateAliasOperation(
create_alias=models.CreateAlias(
collection_name="example_collection", alias_name="production_collection"
)
),
]
)
client.updateCollectionAliases({
actions: [
{
delete_alias: {
alias_name: "production_collection",
},
},
{
create_alias: {
collection_name: "example_collection",
alias_name: "production_collection",
},
},
],
});
use qdrant_client::qdrant::CreateAliasBuilder;
client.delete_alias("production_collection").await?;
client
.create_alias(CreateAliasBuilder::new(
"example_collection",
"production_collection",
))
.await?;
client.deleteAliasAsync("production_collection").get();
client.createAliasAsync("production_collection", "example_collection").get();
await client.DeleteAliasAsync("production_collection");
await client.CreateAliasAsync(aliasName: "production_collection", collectionName: "example_collection");
import "context"
client.DeleteAlias(context.Background(), "production_collection")
client.CreateAlias(context.Background(), "production_collection", "example_collection")
Получение списка псевдонимов коллекции#
GET /collections/{collection_name}/aliases
curl -X GET http://localhost:6333/collections/{collection_name}/aliases
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
client.get_collection_aliases(collection_name="{collection_name}")
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.getCollectionAliases("{collection_name}");
use qdrant_client::Qdrant;
let client = Qdrant::from_url("http://localhost:6334").build()?;
client.list_collection_aliases("{collection_name}").await?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client.listCollectionAliasesAsync("{collection_name}").get();
using Qdrant.Client;
var client = new QdrantClient("localhost", 6334);
await client.ListCollectionAliasesAsync("{collection_name}");
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.ListCollectionAliases(context.Background(), "{collection_name}")
Получение всех псевдонимов#
GET /aliases
curl -X GET http://localhost:6333/aliases
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
client.get_aliases()
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.getAliases();
use qdrant_client::Qdrant;
let client = Qdrant::from_url("http://localhost:6334").build()?;
client.list_aliases().await?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client.listAliasesAsync().get();
using Qdrant.Client;
var client = new QdrantClient("localhost", 6334);
await client.ListAliasesAsync();
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.ListAliases(context.Background())
Получение всех коллекций#
GET /collections
curl -X GET http://localhost:6333/collections
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
client.get_collections()
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
client.getCollections();
use qdrant_client::Qdrant;
let client = Qdrant::from_url("http://localhost:6334").build()?;
client.list_collections().await?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
QdrantClient client =
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
client.listCollectionsAsync().get();
using Qdrant.Client;
var client = new QdrantClient("localhost", 6334);
await client.ListCollectionsAsync();
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
client.ListCollections(context.Background())