다음을 통해 공유


의미 체계 커널 벡터 저장소 커넥터란? (미리 보기)

Warning

의미 체계 커널 벡터 저장소 기능은 미리 보기 상태이며 릴리스 전에 제한된 상황에서도 호환성이 손상되는 변경이 필요한 개선 사항이 계속 발생할 수 있습니다.

레거시 메모리 저장소 커넥터에 대한 정보를 찾는 경우 메모리 저장소 페이지를 참조하세요.

벡터 데이터베이스에는 NLP(자연어 처리), CV(컴퓨터 비전), RS(권장 시스템) 및 데이터의 의미 체계 이해 및 일치가 필요한 기타 영역을 포함하는 여러 도메인 및 애플리케이션에서 많은 사용 사례가 있습니다.

벡터 데이터베이스에 정보를 저장하는 한 가지 사용 사례는 LLM(큰 언어 모델)이 보다 관련성 있고 일관된 응답을 생성할 수 있도록 하는 것입니다. 대용량 언어 모델은 부정확하거나 관련이 없는 정보를 생성하는 것과 같은 문제에 직면하는 경우가 많습니다. 사실 일관성 또는 상식이 결여됨; 반복하거나 자신을 모순; 편향되거나 공격적입니다. 이러한 문제를 해결하기 위해 벡터 데이터베이스를 사용하여 원하는 도메인 또는 장르와 관련된 다양한 토픽, 키워드, 팩트, 의견 및/또는 원본에 대한 정보를 저장할 수 있습니다. 벡터 데이터베이스를 사용하면 특정 질문 또는 토픽과 관련된 정보의 하위 집합을 효율적으로 찾을 수 있습니다. 그런 다음 프롬프트를 사용하여 벡터 데이터베이스의 정보를 대용량 언어 모델로 전달하여 보다 정확하고 관련 있는 콘텐츠를 생성할 수 있습니다.

예를 들어 AI의 최신 추세에 대한 블로그 게시물을 작성하려는 경우 벡터 데이터베이스를 사용하여 해당 토픽에 대한 최신 정보를 저장하고 LLM에 요청과 함께 정보를 전달하여 최신 정보를 활용하는 블로그 게시물을 생성할 수 있습니다.

의미 체계 커널 및 .net은 벡터 저장소와 상호 작용하기 위한 추상화 및 이러한 추상화 구현을 구현하는 기본 제공 커넥터 목록을 제공합니다. 기능에는 레코드 컬렉션 만들기, 나열 및 삭제, 레코드 업로드, 검색 및 삭제가 포함됩니다. 추상화하면 무료 또는 로컬로 호스트되는 Vector Store를 쉽게 실험한 다음, 강화해야 할 때 서비스로 전환할 수 있습니다.

벡터 저장소 추상화

벡터 저장소 추상화의 기본 인터페이스는 다음과 같습니다.

Microsoft.Extensions.VectorData.IVectorStore

IVectorStore 에는 벡터 저장소의 모든 컬렉션(예: ListCollectionNames)에 걸쳐 있는 작업이 포함됩니다. 또한 인스턴스를 가져오는 IVectorStoreRecordCollection<TKey, TRecord> 기능도 제공합니다.

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

IVectorStoreRecordCollection<TKey, TRecord> 는 컬렉션을 나타냅니다. 이 컬렉션은 존재할 수도 있고 존재하지 않을 수도 있으며, 인터페이스는 컬렉션이 있는지 확인하거나 만들거나 삭제하는 메서드를 제공합니다. 또한 인터페이스는 레코드를 upsert, 가져오기 및 삭제하는 메서드를 제공합니다. 마지막으로 인터페이스는 벡터 검색 기능 제공에서 IVectorizedSearch<TRecord> 상속됩니다.

Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>

IVectorizedSearch<TRecord> 에는 벡터 검색을 수행하는 메서드가 포함되어 있습니다. IVectorStoreRecordCollection<TKey, TRecord>IVectorizedSearch<TRecord> 검색만 필요하고 레코드 또는 컬렉션 관리가 필요하지 않은 경우 자체적으로 사용할 IVectorizedSearch<TRecord> 수 있도록 하는 것을 상속합니다.

IVectorizableTextSearch<TRecord>

IVectorizableTextSearch<TRecord> 에는 벡터 데이터베이스가 포함을 자동으로 생성하는 기능이 있는 벡터 검색을 수행하는 메서드가 포함되어 있습니다. 예를 들어 텍스트 문자열을 사용하여 이 메서드를 호출할 수 있으며 데이터베이스는 포함을 생성하고 벡터 필드를 검색합니다. 이는 모든 벡터 데이터베이스에서 지원되지 않으므로 선택한 커넥터에서만 구현됩니다.

벡터 저장소 추상화

벡터 저장소 추상화의 기본 인터페이스는 다음과 같습니다.

com.microsoft.semantickernel.data.vectorstorage.VectorStore

VectorStore 에는 벡터 저장소의 모든 컬렉션(예: listCollectionNames)에 걸쳐 있는 작업이 포함됩니다. 또한 인스턴스를 가져오는 VectorStoreRecordCollection<Key, Record> 기능도 제공합니다.

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

VectorStoreRecordCollection<Key, Record> 는 컬렉션을 나타냅니다. 이 컬렉션은 존재할 수도 있고 존재하지 않을 수도 있으며, 인터페이스는 컬렉션이 있는지 확인하거나 만들거나 삭제하는 메서드를 제공합니다. 또한 인터페이스는 레코드를 upsert, 가져오기 및 삭제하는 메서드를 제공합니다. 마지막으로 인터페이스는 벡터 검색 기능 제공에서 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 패키지 가져오기

모든 벡터 저장소 인터페이스 및 추상화 관련 클래스는 nuget 패키지에서 Microsoft.Extensions.VectorData.Abstractions 사용할 수 있습니다. 각 벡터 저장소 구현은 자체 nuget 패키지에서 사용할 수 있습니다. 알려진 구현 목록은 기본 제공 커넥터 페이지를 참조 하세요.

추상화 패키지는 다음과 같이 추가할 수 있습니다.

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

Warning

의미 체계 커널 버전 1.23.0에서 Microsoft.SemanticKernel.Abstractions 벡터 저장소 추상화가 제거되었으며 새 전용 Microsoft.Extensions.VectorData.Abstractions 패키지에서 사용할 수 있습니다.

버전 1.23.0 Microsoft.SemanticKernel.Abstractions 에서는 종속성이 Microsoft.Extensions.VectorData.Abstractions있으므로 추가 패키지를 참조할 필요가 없습니다. 그러나 추상화는 이제 새 Microsoft.Extensions.VectorData 네임스페이스에 있습니다.

1.22.0 이하에서 1.23.0 이상으로 업그레이드하는 경우 Vector Store 추상화 형식(예: IVectorStore, , IVectorStoreRecordCollectionVectorStoreRecordKeyPropertyVectorStoreRecordDataAttribute등)이 사용되는 파일에 추가 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 클래스이며, 속성은 a ulong 이고 Qdrant는 키만 지원하거나 ulong 키만 지원 Guid 하므로 키 유형이 됩니다ulongHotelId.

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 클래스이며, 속성은 a str 이고 Qdrant는 키만 지원하거나 int 키만 지원 str 하므로 키 유형이 됩니다strHotelId.

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 클래스이며, 속성은 a String 이고 JDBC 저장소는 키만 지원 String 하므로 키 형식이 됩니다StringhotelId.

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());

포함을 생성하는 방법에 대한 자세한 내용은 포함 생성을 참조 하세요.

다음 단계