使用 Qdrant 连接器 (预览版)

警告

语义内核向量存储功能目前处于预览状态,在正式发布前可能会在有限的情况下进行需要重大更改的改进。

概述

Qdrant Vector Store 连接器可用于访问和管理 Qdrant 中的数据。 连接器具有以下特征。

功能区域 支持
集合映射到 包含负载索引和可过滤的数据字段的 Qdrant 集合
支持的键属性类型
  • ulong
  • Guid
支持的数据属性类型
  • string
  • int
  • 双倍
  • float
  • 布尔
  • 每种类型的枚举
支持的向量属性类型 只读内存<float>
支持的索引类型 Hnsw
支持的距离函数
  • 余弦相似性
  • 点积相似性 (DotProductSimilarity)
  • EuclideanDistance
  • 曼哈顿距离
支持的过滤子句
  • AnyTagEqualTo
  • EqualTo
支持记录中的多个向量 是(可配置)
是否支持Filterable?
是否支持FullTextSearchable?
存储属性名称支持吗?
支持 HybridSearch?
功能区域 支持
集合映射到 带有可筛选数据字段索引的 Qdrant 集合
支持的键属性类型
  • ulong
  • Guid
支持的数据属性类型
  • string
  • 整数
  • 双倍
  • 浮动
  • 布尔
  • 和这些类型的每一种的可迭代对象
支持的向量属性类型
  • list[float]
支持的索引类型 Hnsw
支持的距离函数
  • 余弦相似度
  • DotProductSimilarity
  • EuclideanDistance
  • 曼哈顿距离
支持的过滤子句
  • AnyTagEqualTo
  • EqualTo
支持记录中的多个向量 是(可配置)
是否支持Filterable?
是否支持FullTextSearchable?
是否支持 StoragePropertyName?

不支持

目前尚不支持。

入门

将 Qdrant Vector Store 连接器 NuGet 包添加到项目。

dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease

可以使用语义内核提供的扩展方法,将向量存储添加到位于KernelBuilder的可用依赖项注入容器,或添加到IServiceCollection依赖项注入容器。

using Microsoft.SemanticKernel;

// Using Kernel Builder.
var kernelBuilder = Kernel
    .CreateBuilder()
    .AddQdrantVectorStore("localhost");
using Microsoft.SemanticKernel;

// Using IServiceCollection with ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddQdrantVectorStore("localhost");

还提供不带参数的扩展方法。 这些要求将类的 Qdrant.Client.QdrantClient 实例单独注册到依赖项注入容器。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Qdrant.Client;

// Using Kernel Builder.
var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.Services.AddSingleton<QdrantClient>(sp => new QdrantClient("localhost"));
kernelBuilder.AddQdrantVectorStore();
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Qdrant.Client;

// Using IServiceCollection with ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<QdrantClient>(sp => new QdrantClient("localhost"));
builder.Services.AddQdrantVectorStore();

可以直接构造 Qdrant Vector Store 实例。

using Microsoft.SemanticKernel.Connectors.Qdrant;
using Qdrant.Client;

var vectorStore = new QdrantVectorStore(new QdrantClient("localhost"));

可以构造对命名集合的直接引用。

using Microsoft.SemanticKernel.Connectors.Qdrant;
using Qdrant.Client;

var collection = new QdrantVectorStoreRecordCollection<Hotel>(
    new QdrantClient("localhost"),
    "skhotels");

数据映射

当将数据从数据模型映射到存储时,Qdrant 连接器提供默认映射器。 Qdrant 要求将属性映射为标识符、有效负载和矢量分组。 默认映射器使用模型注释或记录定义来确定每个属性的类型并执行此映射。

  • 标注为键的数据模型属性将映射到 Qdrant 点 ID。
  • 作为数据注释的数据模型属性将映射到 Qdrant 点有效负载对象。
  • 批注为向量的数据模型属性将映射到 Qdrant 点向量对象。

属性名称重写

对于数据属性和向量属性(如果使用命名向量模式),可以提供替代字段名称,以便在存储中使用的字段名称与数据模型的属性名称不同。 密钥不支持此功能,因为密钥在 Qdrant 中具有固定名称。 单个未命名向量模式下的向量也不支持它,因为矢量存储在固定名称下。

属性名称重写是通过数据模型属性或记录定义设置 StoragePropertyName 选项来完成的。

下面是一个在其属性上设置的StoragePropertyName数据模型示例,以及它将如何呈现在 Qdrant 中。

using Microsoft.Extensions.VectorData;

public class Hotel
{
    [VectorStoreRecordKey]
    public ulong HotelId { get; set; }

    [VectorStoreRecordData(IsFilterable = true, StoragePropertyName = "hotel_name")]
    public string HotelName { get; set; }

    [VectorStoreRecordData(IsFullTextSearchable = true, StoragePropertyName = "hotel_description")]
    public string Description { get; set; }

    [VectorStoreRecordVector(4, DistanceFunction.CosineSimilarity, IndexKind.Hnsw, StoragePropertyName = "hotel_description_embedding")]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
}
{
    "id": 1,
    "payload": { "hotel_name": "Hotel Happy", "hotel_description": "A place where everyone can be happy." },
    "vector": {
        "hotel_description_embedding": [0.9, 0.1, 0.1, 0.1],
    }
}

入门

使用 qdrant extras 安装语义内核,其中包括 qdrant 客户端

pip install semantic-kernel[qdrant]

然后,可以使用类创建向量存储实例QdrantStore,这将使用环境变量QDRANT_URLQDRANT_API_KEY、、QDRANT_HOSTQDRANT_PORTQDRANT_GRPC_PORT、、和 QDRANT_PATHQDRANT_LOCATIONQDRANT_PREFER_GRPS连接到 Qdrant 实例创建 AsyncQdrantClient,也可以直接提供这些值。 如果没有提供任何内容,它会回退到 location=:memory:


from semantic_kernel.connectors.memory.qdrant import QdrantStore

vector_store = QdrantStore()

还可以使用自己的 qdrant 客户端实例创建矢量存储。

from qdrant_client.async_qdrant_client import AsyncQdrantClient
from semantic_kernel.connectors.memory.qdrant import QdrantStore

client = AsyncQdrantClient(host='localhost', port=6333)
vector_store = QdrantStore(client=client)

也可以直接创建集合。

from semantic_kernel.connectors.memory.qdrant import QdrantCollection

collection = QdrantCollection(collection_name="skhotels", data_model_type=hotel)

序列化

Qdrant 连接器使用名为 PointStruct 的模型来读取和写入存储。 这可以从 from qdrant_client.models import PointStruct 导入。 序列化方法需要 PointStruct 对象列表的输出,反序列化方法将接收 PointStruct 对象列表。

有一些特殊的注意事项与命名或未命名的向量有关,请参阅下文。

有关此概念的更多详细信息,请参阅 序列化文档

Qdrant 矢量模式

Qdrant 支持两种矢量存储模式,具有默认映射器的 Qdrant 连接器支持这两种模式。 默认模式是 单个未命名矢量

单个未命名矢量

使用此选项时,集合只能包含单个向量,并且它将在 Qdrant 中的存储模型中未命名。 下面是使用 单个未命名向量 模式时如何在 Qdrant 中表示对象的示例:

new Hotel
{
    HotelId = 1,
    HotelName = "Hotel Happy",
    Description = "A place where everyone can be happy.",
    DescriptionEmbedding = new float[4] { 0.9f, 0.1f, 0.1f, 0.1f }
};
{
    "id": 1,
    "payload": { "HotelName": "Hotel Happy", "Description": "A place where everyone can be happy." },
    "vector": [0.9, 0.1, 0.1, 0.1]
}

Qdrant 矢量模式

Qdrant 支持两种矢量存储模式,具有默认映射器的 Qdrant 连接器支持这两种模式。 默认模式是 单个未命名矢量

单个未命名矢量

使用此选项时,集合只能包含单个向量,并且它将在 Qdrant 中的存储模型中未命名。 下面是使用 单个未命名向量 模式时如何在 Qdrant 中表示对象的示例:

Hotel(
    hotel_id = 1,
    hotel_name = "Hotel Happy",
    description = "A place where everyone can be happy.",
    description_embedding = [0.9f, 0.1f, 0.1f, 0.1f],
)
from qdrant_client.models import PointStruct

PointStruct(
    id=1,
    payload={ "hotel_name": "Hotel Happy", "description": "A place where everyone can be happy." },
    vector=[0.9, 0.1, 0.1, 0.1],
)

命名向量

如果使用命名向量模式,则意味着集合中的每个点可能包含多个向量,并且每个点都将命名。 下面是使用 命名向量 模式时如何在 Qdrant 中表示对象的示例:

new Hotel
{
    HotelId = 1,
    HotelName = "Hotel Happy",
    Description = "A place where everyone can be happy.",
    HotelNameEmbedding = new float[4] { 0.9f, 0.5f, 0.5f, 0.5f }
    DescriptionEmbedding = new float[4] { 0.9f, 0.1f, 0.1f, 0.1f }
};
{
    "id": 1,
    "payload": { "HotelName": "Hotel Happy", "Description": "A place where everyone can be happy." },
    "vector": {
        "HotelNameEmbedding": [0.9, 0.5, 0.5, 0.5],
        "DescriptionEmbedding": [0.9, 0.1, 0.1, 0.1],
    }
}

命名向量

如果使用命名向量模式,则意味着集合中的每个点可能包含多个向量,并且每个点都将命名。 下面是使用 命名向量 模式时如何在 Qdrant 中表示对象的示例:

Hotel(
    hotel_id = 1,
    hotel_name = "Hotel Happy",
    description = "A place where everyone can be happy.",
    hotel_name_embedding = [0.9f, 0.5f, 0.5f, 0.5f],
    description_embedding = [0.9f, 0.1f, 0.1f, 0.1f],
)
from qdrant_client.models import PointStruct

PointStruct(
    id=1,
    payload={ "hotel_name": "Hotel Happy", "description": "A place where everyone can be happy." },
    vector={
        "hotel_name_embedding": [0.9, 0.5, 0.5, 0.5],
        "description_embedding": [0.9, 0.1, 0.1, 0.1],
    },
)

若要启用命名向量模式,请将其作为构造向量存储或集合时的选项传递。 也可以将相同的选项传递给任何提供的依赖项注入容器扩展方法。

using Microsoft.SemanticKernel.Connectors.Qdrant;
using Qdrant.Client;

var vectorStore = new QdrantVectorStore(
    new QdrantClient("localhost"),
    new() { HasNamedVectors = true });

var collection = new QdrantVectorStoreRecordCollection<Hotel>(
    new QdrantClient("localhost"),
    "skhotels",
    new() { HasNamedVectors = true });

若要启用命名向量模式,请将其作为构造向量存储或集合时的选项传递。 也可以将相同的选项传递给任何提供的依赖项注入容器扩展方法。

在 python 中,默认值 named_vectors 为 True,但也可以禁用此值,如下所示。

from semantic_kernel.connectors.memory.qdrant import QdrantCollection

collection = QdrantCollection(
    collection_name="skhotels", 
    data_model_type=Hotel, 
    named_vectors=False,
)