セマンティック カーネル ベクター ストア コネクタとは (プレビュー)

警告

セマンティック カーネル ベクター ストア機能はプレビュー段階であり、破壊的変更を必要とする機能強化は、リリース前の限られた状況で引き続き発生する可能性があります。

ヒント

従来のメモリ ストア コネクタに関する情報をお探しの場合は、「 Memory Stores」ページを参照してください

ベクター データベースには、自然言語処理 (NLP)、コンピューター ビジョン (CV)、レコメンデーション システム (RS)、およびデータのセマンティックな理解と照合を必要とするその他の領域を含む、さまざまなドメインとアプリケーションに対して多くのユース ケースがあります。

ベクター データベースに情報を格納するユース ケースの 1 つは、大規模な言語モデル (LLM) がより関連性の高い一貫性のある応答を生成できるようにすることです。 大規模な言語モデルは、不正確な情報や無関係な情報の生成などの課題に直面することがよくあります。事実の整合性または一般的な感覚を欠いている。自分自身を繰り返す、または矛盾する。偏見や不快感を与える可能性があります。 これらの課題を克服するために、ベクター データベースを使用して、目的のドメインやジャンルに関連するさまざまなトピック、キーワード、事実、意見、ソースに関する情報を格納できます。 ベクター データベースを使用すると、特定の質問またはトピックに関連する情報のサブセットを効率的に検索できます。 その後、プロンプトを使用してベクター データベースから大きな言語モデルに情報を渡して、より正確で関連性の高いコンテンツを生成できます。

たとえば、AI の最新の傾向に関するブログ投稿を作成する場合は、ベクター データベースを使用して、そのトピックに関する最新情報を格納し、その情報を LLM に要求と共に渡して、最新情報を活用するブログ投稿を生成できます。

セマンティック カーネルと .net は、Vector Store と対話するための抽象化と、これらの抽象化を実装するすぐに使用できるコネクタの一覧を提供します。 機能には、レコードのコレクションの作成、一覧表示、削除、レコードのアップロード、取得、削除が含まれます。 抽象化により、無料またはローカルでホストされている Vector Store を簡単に試し、スケールアップが必要なときにサービスに切り替えることができます。

ベクター ストアの抽象化

ベクター ストアの抽象化の主なインターフェイスは次のとおりです。

Microsoft.Extensions.VectorData.IVectorStore

IVectorStore には、ベクター ストア内のすべてのコレクションにまたがる操作 (ListCollectionNames など) が含まれます。 また、 IVectorStoreRecordCollection<TKey, TRecord> インスタンスを取得する機能も提供します。

Microsoft.Extensions.VectorData.IVectorStoreRecordCollection<TKey、TRecord>

IVectorStoreRecordCollection<TKey, TRecord> はコレクションを表します。 このコレクションは存在する場合と存在しない場合があり、インターフェイスにはコレクションが存在するかどうかを確認するメソッド、コレクションを作成するメソッド、またはコレクションを削除するメソッドが用意されています。 このインターフェイスには、レコードのアップサート、取得、削除を行うメソッドも用意されています。 最後に、インターフェイスはベクター検索機能を提供 IVectorizedSearch<TRecord> から継承します。

Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>

IVectorizedSearch<TRecord> には、ベクター検索を実行するためのメソッドが含まれています。 IVectorStoreRecordCollection<TKey, TRecord>IVectorizedSearch<TRecord> を継承しているため、検索のみが必要で、レコードやコレクションの管理が必要ない場合に、 IVectorizedSearch<TRecord> を単独で使用できます。

IVectorizableTextSearch<TRecord>

IVectorizableTextSearch<TRecord> には、ベクター データベースに埋め込みを自動的に生成する機能があるベクター検索を実行するためのメソッドが含まれています。 たとえば、テキスト文字列を使用してこのメソッドを呼び出すと、データベースが埋め込みを生成し、ベクター フィールドを検索します。 これはすべてのベクター データベースでサポートされているわけではないため、選択したコネクタによってのみ実装されます。

ベクター ストアの抽象化

ベクター ストアの抽象化の主なインターフェイスは次のとおりです。

com.microsoft.semantickernel.data.vectortorage.VectorStore

VectorStore には、listCollectionNames など、ベクター ストア内のすべてのコレクションにまたがる操作が含まれています。 また、 VectorStoreRecordCollection<Key, Record> インスタンスを取得する機能も提供します。

com.microsoft.semantickernel.data.vectortorage.VectorStoreRecordCollection<Key, Record>

VectorStoreRecordCollection<Key, Record> はコレクションを表します。 このコレクションは存在する場合と存在しない場合があり、インターフェイスにはコレクションが存在するかどうかを確認するメソッド、コレクションを作成するメソッド、またはコレクションを削除するメソッドが用意されています。 このインターフェイスには、レコードのアップサート、取得、削除を行うメソッドも用意されています。 最後に、インターフェイスはベクター検索機能を提供 VectorizedSearch<Record> から継承します。

com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>

VectorizedSearch<Record> には、ベクター検索を実行するためのメソッドが含まれています。 VectorStoreRecordCollection<Key, Record>VectorizedSearch<Record> を継承しているため、検索のみが必要で、レコードやコレクションの管理が必要ない場合に、 VectorizedSearch<Record> を単独で使用できます。

com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<Record>

VectorizableTextSearch<Record> には、ベクター データベースに埋め込みを自動的に生成する機能があるベクター検索を実行するためのメソッドが含まれています。 たとえば、テキスト文字列を使用してこのメソッドを呼び出すと、データベースが埋め込みを生成し、ベクター フィールドを検索します。 これはすべてのベクター データベースでサポートされているわけではないため、選択したコネクタによってのみ実装されます。

Vector Store コネクタの概要

必要な nuget パッケージをインポートする

すべてのベクター ストア インターフェイスと抽象化関連のクラスは、 Microsoft.Extensions.VectorData.Abstractions nuget パッケージで使用できます。 各ベクター ストアの実装は、独自の nuget パッケージで使用できます。 既知の実装の一覧については、 すぐに使用するコネクタのページを参照してください。

抽象化パッケージは次のように追加できます。

dotnet add package Microsoft.Extensions.VectorData.Abstractions --prerelease

警告

セマンティック カーネルのバージョン 1.23.0 から、Vector Store の抽象化は Microsoft.SemanticKernel.Abstractions から削除され、新しい専用 Microsoft.Extensions.VectorData.Abstractions パッケージで使用できます。

バージョン 1.23.0 以降、 Microsoft.SemanticKernel.AbstractionsMicrosoft.Extensions.VectorData.Abstractionsに依存しているため、追加のパッケージを参照する必要はありません。 ただし、抽象化は新しい Microsoft.Extensions.VectorData 名前空間に追加されます。

1.22.0 以前から 1.23.0 以降にアップグレードする場合は、ベクター ストアの抽象化の種類 (IVectorStoreIVectorStoreRecordCollectionVectorStoreRecordDataAttributeVectorStoreRecordKeyPropertyなど) が使用されているファイルに、追加のusing Microsoft.Extensions.VectorData;句を追加する必要があります。

この変更は、独自の実装を作成するときにベクター ストア プロバイダーをサポートするために行われました。 プロバイダーは、 Microsoft.Extensions.VectorData.Abstractions パッケージのみを参照する必要があります。 これにより、潜在的なバージョンの競合が軽減され、セマンティック カーネルはベクター ストア プロバイダーに影響を与えずに高速に進化し続けることができます。

データ モデルを定義する

セマンティック カーネル ベクター ストア コネクタは、データベースとの対話にモデルの最初のアプローチを使用します。 つまり、最初の手順は、ストレージ スキーマにマップされるデータ モデルを定義することです。 コネクタがレコードのコレクションを作成し、ストレージ スキーマにマップできるように、モデルに注釈を付けて各プロパティの関数を示すことができます。

using Microsoft.Extensions.VectorData;

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

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

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

    [VectorStoreRecordVector(Dimensions: 4, DistanceFunction.CosineDistance, IndexKind.Hnsw)]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }

    [VectorStoreRecordData(IsFilterable = true)]
    public string[] Tags { get; set; }
}
from dataclasses import dataclass, field
from typing import Annotated
from semantic_kernel.data import (
    DistanceFunction,
    IndexKind,
    VectorStoreRecordDataField,
    VectorStoreRecordDefinition,
    VectorStoreRecordKeyField,
    VectorStoreRecordVectorField,
    vectorstoremodel,
)

@vectorstoremodel
@dataclass
class Hotel:
    hotel_id: Annotated[str, VectorStoreRecordKeyField()] = field(default_factory=lambda: str(uuid4()))
    hotel_name: Annotated[str, VectorStoreRecordDataField(is_filterable=True)]
    description: Annotated[str, VectorStoreRecordDataField(is_full_text_searchable=True)]
    description_embedding: Annotated[list[float], VectorStoreRecordVectorField(dimensions=4, distance_function=DistanceFunction.COSINE, index_kind=IndexKind.HNSW)]
    tags: Annotated[list[str], VectorStoreRecordDataField(is_filterable=True)]
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector;
import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction;
import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind;

import java.util.Collections;
import java.util.List;

public class Hotel {
    @VectorStoreRecordKey
    private String hotelId;

    @VectorStoreRecordData(isFilterable = true)
    private String name;

    @VectorStoreRecordData(isFullTextSearchable = true)
    private String description;

    @VectorStoreRecordVector(dimensions = 4, indexKind = IndexKind.HNSW, distanceFunction = DistanceFunction.COSINE_DISTANCE)
    private List<Float> descriptionEmbedding;

    @VectorStoreRecordData(isFilterable = true)
    private List<String> tags;

    public Hotel() { }

    public Hotel(String hotelId, String name, String description, List<Float> descriptionEmbedding, List<String> tags) {
        this.hotelId = hotelId;
        this.name = name;
        this.description = description;
        this.descriptionEmbedding = Collections.unmodifiableList(descriptionEmbedding);
        this.tags = Collections.unmodifiableList(tags);
    }

    public String getHotelId() { return hotelId; }
    public String getName() { return name; }
    public String getDescription() { return description; }
    public List<Float> getDescriptionEmbedding() { return descriptionEmbedding; }
    public List<String> getTags() { return tags; }
}

ヒント

データ モデルに注釈を付ける方法の詳細については、「 データ モデルの定義」を参照してください

ヒント

データ モデルに注釈を付ける代わりに、 レコード定義を使用してスキーマを定義する方法を参照してください

データベースに接続してコレクションを選択する

データ モデルを定義したら、次の手順では、任意のデータベースの VectorStore インスタンスを作成し、レコードのコレクションを選択します。

この例では、Qdrant を使用します。 そのため、Qdrant nuget パッケージをインポートする必要があります。

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

データベースではさまざまな種類のキーとレコードがサポートされているため、ジェネリックを使用してコレクションのキーとレコードの種類を指定できます。 この場合、レコードの型は既に定義した Hotel クラスになり、キーの型は ulongされます。 HotelId プロパティは ulong であり、Qdrant は Guid キーまたは ulong キーのみをサポートするためです。

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

// Create a Qdrant VectorStore object
var vectorStore = new QdrantVectorStore(new QdrantClient("localhost"));

// Choose a collection from the database and specify the type of key and record stored in it via Generic parameters.
var collection = vectorStore.GetCollection<ulong, Hotel>("skhotels");

データベースではさまざまな種類のキーとレコードがサポートされているため、ジェネリックを使用してコレクションのキーとレコードの種類を指定できます。 この場合、レコードの型は既に定義した Hotel クラスになり、キーの型は strされます。 HotelId プロパティは str であり、Qdrant は str キーまたは int キーのみをサポートするためです。

from semantic_kernel.connectors.memory.qdrant import QdrantStore

# Create a Qdrant VectorStore object, this will look in the environment for Qdrant related settings, and will fall back to the default, which is to run in-memory.
vector_store = QdrantStore()

# Choose a collection from the database and specify the type of key and record stored in it via Generic parameters.
collection = vector_store.get_collection(
    collection_name="skhotels", 
    data_model_type=Hotel
)

データベースではさまざまな種類のキーとレコードがサポートされているため、ジェネリックを使用してコレクションのキーとレコードの種類を指定できます。 この場合、レコードの型は既に定義した Hotel クラスになり、キーの型は Stringされます。 hotelId プロパティは String であり、JDBC ストアでは String キーのみがサポートされるためです。

import com.microsoft.semantickernel.data.jdbc.JDBCVectorStore;
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreOptions;
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreRecordCollectionOptions;
import com.microsoft.semantickernel.data.jdbc.mysql.MySQLVectorStoreQueryProvider;
import com.mysql.cj.jdbc.MysqlDataSource;

import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Create a MySQL data source
        var dataSource = new MysqlDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/sk");
        dataSource.setPassword("root");
        dataSource.setUser("root");

        // Create a JDBC vector store
        var vectorStore = JDBCVectorStore.builder()
            .withDataSource(dataSource)
            .withOptions(
                JDBCVectorStoreOptions.builder()
                    .withQueryProvider(MySQLVectorStoreQueryProvider.builder()
                        .withDataSource(dataSource)
                        .build())
                    .build()
            )
            .build();

        // Get a collection from the vector store
        var collection = vectorStore.getCollection("skhotels",
            JDBCVectorStoreRecordCollectionOptions.<Hotel>builder()
                .withRecordClass(Hotel.class)
                .build()
        );
    }
}

ヒント

各 Vector Store コネクタでサポートされるキーとフィールドの種類の詳細については、 各コネクタのドキュメントを参照してください。

コレクションを作成してレコードを追加する

// Create the collection if it doesn't exist yet.
await collection.CreateCollectionIfNotExistsAsync();

// Upsert a record.
string descriptionText = "A place where everyone can be happy.";
ulong hotelId = 1;

// Create a record and generate a vector for the description using your chosen embedding generation implementation.
// Just showing a placeholder embedding generation method here for brevity.
await collection.UpsertAsync(new Hotel
{
    HotelId = hotelId,
    HotelName = "Hotel Happy",
    Description = descriptionText,
    DescriptionEmbedding = await GenerateEmbeddingAsync(descriptionText),
    Tags = new[] { "luxury", "pool" }
});

// Retrieve the upserted record.
Hotel? retrievedHotel = await collection.GetAsync(hotelId);

コレクションを作成してレコードを追加する

# Create the collection if it doesn't exist yet.
await collection.create_collection_if_not_exists()

# Upsert a record.
description = "A place where everyone can be happy."
hotel_id = "1"

await collection.upsert(Hotel(
    hotel_id = hotel_id,
    hotel_name = "Hotel Happy",
    description = description,
    description_embedding = await GenerateEmbeddingAsync(description),
    tags = ["luxury", "pool"]
))

# Retrieve the upserted record.
retrieved_hotel = await collection.get(hotel_id)
// Create the collection if it doesn't exist yet.
collection.createCollectionAsync().block();

// Upsert a record.
var description = "A place where everyone can be happy";
var hotelId = "1";
var hotel = new Hotel(
    hotelId, 
    "Hotel Happy", 
    description, 
    generateEmbeddingsAsync(description).block(), 
    List.of("luxury", "pool")
);

collection.upsertAsync(hotel, null).block();

// Retrieve the upserted record.
var retrievedHotel = collection.getAsync(hotelId, null).block();

ヒント

埋め込みを生成する方法の詳細については、 エンベディングの生成を参照してください。

// Generate a vector for your search text, using your chosen embedding generation implementation.
// Just showing a placeholder method here for brevity.
var searchVector = await GenerateEmbeddingAsync("I'm looking for a hotel where customer happiness is the priority.");
// Do the search.
var searchResult = await collection.VectorizedSearchAsync(searchVector, new() { Top = 1 }).Results.ToListAsync()

// Inspect the returned hotels.
Hotel hotel = searchResult.First().Record;
Console.WriteLine("Found hotel description: " + hotel.Description);
// Generate a vector for your search text, using your chosen embedding generation implementation.
// Just showing a placeholder method here for brevity.
var searchVector = generateEmbeddingsAsync("I'm looking for a hotel where customer happiness is the priority.").block();

// Do the search.
var searchResult = collection.searchAsync(searchVector, VectorSearchOptions.builder()
    .withTop(1).build()
).block();

Hotel record = searchResult.getResults().get(0).getRecord();
System.out.printf("Found hotel description: %s\n", record.getDescription());

ヒント

埋め込みを生成する方法の詳細については、 エンベディングの生成を参照してください。

次のステップ