警告
セマンティック カーネル ベクター ストア機能はプレビュー段階であり、破壊的変更を必要とする機能強化は、リリース前の限られた状況で引き続き発生する可能性があります。
警告
セマンティック カーネル ベクター ストア機能はプレビュー段階であり、破壊的変更を必要とする機能強化は、リリース前の限られた状況で引き続き発生する可能性があります。
ヒント
従来のメモリ ストア コネクタに関する情報をお探しの場合は、「 Memory Stores」ページを参照してください。
ベクター データベースには、自然言語処理 (NLP)、コンピューター ビジョン (CV)、レコメンデーション システム (RS)、およびデータのセマンティックな理解と照合を必要とするその他の領域を含む、さまざまなドメインとアプリケーションに対して多くのユース ケースがあります。
ベクター データベースに情報を格納するユース ケースの 1 つは、大規模な言語モデル (LLM) がより関連性の高い一貫性のある応答を生成できるようにすることです。 大規模な言語モデルは、不正確な情報や無関係な情報の生成などの課題に直面することがよくあります。事実の整合性または一般的な感覚を欠いている。自分自身を繰り返す、または矛盾する。偏見や不快感を与える可能性があります。 これらの課題を克服するために、ベクター データベースを使用して、目的のドメインやジャンルに関連するさまざまなトピック、キーワード、事実、意見、ソースに関する情報を格納できます。 ベクター データベースを使用すると、特定の質問またはトピックに関連する情報のサブセットを効率的に検索できます。 その後、プロンプトを使用してベクター データベースから大きな言語モデルに情報を渡して、より正確で関連性の高いコンテンツを生成できます。
たとえば、AI の最新の傾向に関するブログ投稿を作成する場合は、ベクター データベースを使用して、そのトピックに関する最新情報を格納し、その情報を LLM に要求と共に渡して、最新情報を活用するブログ投稿を生成できます。
セマンティック カーネルと .net は、Vector Store と対話するための抽象化と、これらの抽象化を実装するすぐに使用できるコネクタの一覧を提供します。 機能には、レコードのコレクションの作成、一覧表示、削除、レコードのアップロード、取得、削除が含まれます。 抽象化により、無料またはローカルでホストされている Vector Store を簡単に試し、スケールアップが必要なときにサービスに切り替えることができます。
ベクター ストアを使用した検索拡張生成 (RAG)
ベクター ストアの抽象化は、ベクター ストアからデータを追加および取得するための低レベルの API です。
セマンティック カーネルには、RAG 用のベクター ストア実装のいずれかを使用するためのサポートが組み込まれています。
これを実現するには、IVectorSearchable<TRecord>
をラップし、テキスト検索の実装として公開します。
ヒント
RAG にベクター ストアを使用する方法の詳細については、「セマンティック カーネル テキスト検索でベクター ストアを使用する方法」を参照してください。
ヒント
テキスト検索の詳細については、「セマンティック カーネル テキスト検索とは」を参照してください。
ベクター ストアの抽象化
Vector Store 抽象化の主な抽象基本クラスとインターフェイスは次のとおりです。
Microsoft.Extensions.VectorData.VectorStore
VectorStore
には、ベクター ストア内のすべてのコレクションにまたがる操作 (ListCollectionNames など) が含まれます。
また、 VectorStoreCollection<TKey, TRecord>
インスタンスを取得する機能も提供します。
Microsoft.Extensions.VectorData.VectorStoreCollection<TKey、TRecord>
VectorStoreCollection<TKey, TRecord>
はコレクションを表します。
このコレクションは存在する場合と存在しない場合があり、抽象基底クラスには、コレクションが存在するかどうかを確認するメソッド、コレクションを作成するメソッド、またはコレクションを削除するメソッドが用意されています。
抽象基底クラスには、レコードのアップサート、取得、削除を行うメソッドも用意されています。
最後に、抽象基底クラスはベクター検索機能を提供 IVectorSearchable<TRecord>
から継承します。
Microsoft.Extensions.VectorData.IVectorSearchable<TRecord>
-
SearchAsync<TRecord>
を使用して、次のいずれかを実行できます。- ベクター検索は、登録された埋め込み生成器またはそれをサポートするベクターデータベースによってベクトル化できる入力を取得します。
- vector は、ベクトルを入力として取り込む検索を行います。
ベクター ストアを使用した検索拡張生成 (RAG)
ベクター ストアの抽象化は、ベクター ストアからデータを追加および取得するための低レベルの API です。
セマンティック カーネルには、RAG 用のベクター ストア実装のいずれかを使用するためのサポートが組み込まれています。
これを実現するには、VectorSearchBase[TKey, TModel]
、VectorizedSearchMixin[Tmodel]
、または VectorizableTextSearchMixin[TModel]
で VectorTextSearch[TModel]
をラップし、テキスト検索の実装として公開します。
ヒント
RAG にベクター ストアを使用する方法の詳細については、「セマンティック カーネル テキスト検索でベクター ストアを使用する方法」を参照してください。
ヒント
テキスト検索の詳細については、「セマンティック カーネル テキスト検索とは」を参照してください。
ベクター ストアの抽象化
ベクター ストアの抽象化の主なインターフェイスは次のとおりです。
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore
には、listCollectionNames など、ベクター ストア内のすべてのコレクションにまたがる操作が含まれています。
また、 VectorStoreRecordCollection<Key, Record>
インスタンスを取得する機能も提供します。
com.microsoft.semantickernel.data.vectorstorage.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
データ モデルを定義する
セマンティック カーネル ベクター ストア コネクタは、データベースとの対話にモデルの最初のアプローチを使用します。 つまり、最初の手順は、ストレージ スキーマにマップされるデータ モデルを定義することです。 コネクタがレコードのコレクションを作成し、ストレージ スキーマにマップできるように、モデルに注釈を付けて各プロパティの関数を示すことができます。
using Microsoft.Extensions.VectorData;
public class Hotel
{
[VectorStoreKey]
public ulong HotelId { get; set; }
[VectorStoreData(IsIndexed = true)]
public string HotelName { get; set; }
[VectorStoreData(IsFullTextIndexed = true)]
public string Description { get; set; }
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
[VectorStoreData(IsIndexed = 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
Docker を使用して Qdrant をローカルで実行する場合は、次のコマンドを使用して、この例で使用されている設定で Qdrant コンテナーを起動します。
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant:latest
Qdrant インスタンスが正常に稼働していることを確認するには、Qdrant Docker コンテナーに組み込まれている Qdrant ダッシュボードにアクセスします。http://localhost:6333/dashboard
データベースではさまざまな種類のキーとレコードがサポートされているため、ジェネリックを使用してコレクションのキーとレコードの種類を指定できます。
この場合、レコードの型は既に定義した 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"), ownsClient: true);
// 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 コネクタでサポートされるキーとフィールドの種類の詳細については、 各コネクタのドキュメントを参照してください。
コレクションを作成してレコードを追加する
// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
// your logic here
}
// Create the collection if it doesn't exist yet.
await collection.EnsureCollectionExistsAsync();
// 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.
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();
ヒント
埋め込みを生成する方法の詳細については、 エンベディングの生成を参照してください。
ベクター検索を実行する
// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
// your logic here
}
// Generate a vector for your search text, using your chosen embedding generation implementation.
ReadOnlyMemory<float> searchVector = await GenerateEmbeddingAsync("I'm looking for a hotel where customer happiness is the priority.");
// Do the search.
var searchResult = collection.SearchAsync(searchVector, top: 1);
// Inspect the returned hotel.
await foreach (var record in searchResult)
{
Console.WriteLine("Found hotel description: " + record.Record.Description);
Console.WriteLine("Found record score: " + record.Score);
}
ベクター検索を実行する
# Generate a vector for your search text, using your chosen embedding generation implementation.
# Just showing a placeholder method here for brevity.
search_vector = await GenerateEmbedding("I'm looking for a hotel where customer happiness is the priority.");
# Do the search.
search_result = await collection.vectorized_search(vector=searchVector, VectorSearchOptions(top = 1 ))
# Inspect the returned hotels.
async for result in search_result.results:
print(f"Found hotel description: {result.record.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());
ヒント
埋め込みを生成する方法の詳細については、 エンベディングの生成を参照してください。