Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Aviso
A funcionalidade Semantic Kernel Vector Store está em fase RC, e melhorias que exigem alterações disruptivas ainda podem ocorrer em circunstâncias limitadas antes do lançamento oficial.
Aviso
A funcionalidade Semantic Kernel Vetor Store está em pré-visualização, e melhorias que exigem alterações de quebra ainda podem ocorrer em circunstâncias limitadas antes do lançamento.
Gorjeta
Se você estiver procurando informações sobre os conectores de armazenamento de memória herdados, consulte a página Armazenamentos de memória.
Os bancos de dados vetoriais têm muitos casos de uso em diferentes domínios e aplicativos que envolvem processamento de linguagem natural (NLP), visão computacional (CV), sistemas de recomendação (RS) e outras áreas que exigem compreensão semântica e correspondência de dados.
Um caso de uso para armazenar informações em um banco de dados vetorial é permitir que grandes modelos de linguagem (LLMs) gerem respostas mais relevantes e coerentes. Os modelos linguísticos de grande dimensão enfrentam frequentemente desafios como a geração de informações imprecisas ou irrelevantes; falta de coerência factual ou de bom senso; repetir-se ou contradizer-se; ser tendencioso ou ofensivo. Para ajudar a superar esses desafios, você pode usar um banco de dados vetorial para armazenar informações sobre diferentes tópicos, palavras-chave, fatos, opiniões e/ou fontes relacionadas ao domínio ou gênero desejado. O banco de dados vetorial permite que você encontre eficientemente o subconjunto de informações relacionadas a uma pergunta ou tópico específico. Em seguida, você pode passar informações do banco de dados vetorial com seu prompt para seu modelo de linguagem grande para gerar conteúdo mais preciso e relevante.
Por exemplo, se você quiser escrever uma postagem de blog sobre as últimas tendências em IA, você pode usar um banco de dados vetorial para armazenar as informações mais recentes sobre esse tópico e passar as informações junto com a solicitação para um LLM, a fim de gerar uma postagem de blog que aproveite as informações mais recentes.
O Semantic Kernel e o .net fornecem uma abstração para interagir com Vetor Stores e uma lista de implementações prontas para uso que implementam essas abstrações para vários bancos de dados. Os recursos incluem criar, listar e excluir coleções de registros e carregar, recuperar e excluir registros. A abstração facilita a experimentação com uma loja de vetores gratuita ou hospedada localmente e, em seguida, alternar para um serviço quando precisar aumentar a escalabilidade.
As implementações pré-configuradas podem ser usadas com o Kernel Semântico, mas não dependem da pilha principal do Kernel Semântico e, assim, podem ser usadas completamente de forma independente, caso seja preciso. As implementações fornecidas pelo Kernel Semântico são referidas como 'conectores'.
Geração Aumentada de Recuperação (RAG) com Armazenamento Vetorial
A abstração de armazenamento vetorial é uma api de baixo nível para adicionar e recuperar dados de repositórios vetoriais.
O Semantic Kernel tem suporte integrado para usar qualquer uma das implementações do Vetor Store para RAG.
Isso é conseguido encapsulando IVectorSearchable<TRecord>
e expondo-o como uma implementação de Pesquisa de Texto.
Gorjeta
Para saber mais sobre como usar repositórios vetoriais para RAG, consulte Como usar repositórios vetoriais com pesquisa de texto do kernel semântico.
Gorjeta
Para saber mais sobre a pesquisa de texto, consulte O que é a Pesquisa de Texto do Kernel Semântico?
Gorjeta
Para saber mais sobre como adicionar rapidamente o RAG ao seu agente, consulte Adicionando geração aumentada de recuperação (RAG) aos agentes do kernel semântico.
Abstração de Armazenamento Vetorial
As abstrações do Vetor Store são fornecidas no Microsoft.Extensions.VectorData.Abstractions
pacote nuget.
A seguir estão as principais classes de base abstratas e interfaces.
Microsoft.Extensions.VectorData.VectorStore
VectorStore
contém operações que abrangem todas as coleções no repositório de vetores, por exemplo, ListCollectionNames.
Ele fornece também a possibilidade de obter instâncias de VectorStoreCollection<TKey, TRecord>
.
Microsoft.Extensions.VectorData.VectorStoreCollection<TKey, TRecord>
VectorStoreCollection<TKey, TRecord>
representa uma coleção.
Essa coleção pode ou não existir, e a classe base abstrata fornece métodos para verificar se a coleção existe, criá-la ou excluí-la.
A classe base abstrata também fornece métodos para inserir ou atualizar, obter e eliminar registos.
Finalmente, a classe base abstrata herda de IVectorSearchable<TRecord>
, que fornece capacidades de pesquisa vetorial.
Microsoft.Extensions.VectorData.IVectorSearchable<TRecord>
-
SearchAsync<TRecord>
pode ser usado para:- pesquisas vetoriais tendo alguma entrada que pode ser vetorizada por um gerador de incorporação registrado ou pelo banco de dados vetorial onde o banco de dados suporta isso.
- pesquisas vetoriais tomando um vetor como entrada.
Geração Aumentada de Recuperação (RAG) com Armazenamento Vetorial
As abstrações de armazenamento vetorial são uma api de baixo nível para adicionar e recuperar dados de repositórios vetoriais.
O Semantic Kernel tem suporte integrado para usar qualquer uma das implementações do Vetor Store para RAG.
Isso é conseguido quebrando VectorSearchBase[TKey, TModel]
com VectorizedSearchMixin[Tmodel]
, VectorizableTextSearchMixin[TModel]
ou VectorTextSearch[TModel]
e expondo-o como uma implementação de Pesquisa de Texto.
Gorjeta
Para saber mais sobre como usar repositórios vetoriais para RAG, consulte Como usar repositórios vetoriais com pesquisa de texto do kernel semântico.
Gorjeta
Para saber mais sobre a pesquisa de texto, consulte O que é a Pesquisa de Texto do Kernel Semântico?
Abstração de Armazenamento Vetorial
As principais interfaces na abstração do Vetor Store são as seguintes.
com.microsoft.semantickernel.data.vectorstorage.VectorStore
VectorStore
contém operações que abrangem todas as coleções no repositório de vetores, por exemplo, listCollectionNames.
Ele fornece também a possibilidade de obter instâncias de VectorStoreRecordCollection<Key, Record>
.
com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Registro>
VectorStoreRecordCollection<Key, Record>
representa uma coleção.
Essa coleção pode ou não existir, e a interface fornece métodos para verificar se a coleção existe, criá-la ou excluí-la.
A interface também fornece métodos para inserir ou atualizar, obter e excluir registos.
Finalmente, a interface herda de VectorizedSearch<Record>
, fornecendo capacidades de pesquisa vetorial.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Record>
VectorizedSearch<Record>
Contém um método para fazer pesquisas vetoriais.
VectorStoreRecordCollection<Key, Record>
herda de VectorizedSearch<Record>
, tornando possível utilizar VectorizedSearch<Record>
por si só nos casos em que apenas a pesquisa é necessária e não é necessário qualquer registo ou gestão de coleções.
com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<Record>
VectorizableTextSearch<Record>
Contém um método para fazer pesquisas vetoriais onde o banco de dados vetorial tem a capacidade de gerar incorporações automaticamente. Por exemplo, você pode chamar esse método com uma cadeia de texto e o banco de dados gerará a incorporação para você e pesquisará em um campo vetorial. Isso não é suportado por todos os bancos de dados vetoriais e, portanto, só é implementado por conectores selecionados.
Introdução às Vetor Stores
Importe os pacotes nuget necessários
Todas as interfaces de armazenamento vetorial e quaisquer classes relacionadas à Microsoft.Extensions.VectorData.Abstractions
abstração estão disponíveis no pacote nuget.
Cada implementação de armazenamento vetorial está disponível em seu próprio pacote nuget. Para obter uma lista de implementações conhecidas, consulte a página Conectores prontos para uso.
O pacote de abstrações pode ser adicionado assim.
dotnet add package Microsoft.Extensions.VectorData.Abstractions
Defina seu modelo de dados
As abstrações do Vetor Store usam uma abordagem de modelo inicial para interagir com bancos de dados. Isso significa que a primeira etapa é definir um modelo de dados que corresponda ao esquema de armazenamento. Para ajudar as implementações a criar coleções de registros e mapear para o esquema de armazenamento, o modelo pode ser anotado para indicar a função de cada propriedade.
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.vector import (
DistanceFunction,
IndexKind,
VectorStoreField,
vectorstoremodel,
)
@vectorstoremodel
@dataclass
class Hotel:
hotel_id: Annotated[str, VectorStoreField('key')] = field(default_factory=lambda: str(uuid4()))
hotel_name: Annotated[str, VectorStoreField('data', is_filterable=True)]
description: Annotated[str, VectorStoreField('data', is_full_text_searchable=True)]
description_embedding: Annotated[list[float], VectorStoreField('vector', dimensions=4, distance_function=DistanceFunction.COSINE, index_kind=IndexKind.HNSW)]
tags: Annotated[list[str], VectorStoreField('data', 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; }
}
Gorjeta
Para obter mais informações sobre como anotar seu modelo de dados, consulte Definindo seu modelo de dados.
Gorjeta
Para obter uma alternativa à anotação do seu modelo de dados, consulte definir o seu esquema com uma definição de registo.
Conecte-se ao seu banco de dados e selecione uma coleção
Depois de definir seu modelo de dados, a próxima etapa é criar uma instância VectorStore para o banco de dados de sua escolha e selecionar uma coleção de registros.
Neste exemplo, usaremos o Qdrant. Portanto, você precisará importar o pacote nuget Qdrant.
dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease
Se você quiser executar o Qdrant localmente usando o Docker, use o seguinte comando para iniciar o contêiner Qdrant com as configurações usadas neste exemplo.
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant:latest
Para verificar se sua instância do Qdrant está ativada e funcionando corretamente, visite o painel do Qdrant integrado ao contêiner do docker do Qdrant: http://localhost:6333/dashboard
Como os bancos de dados suportam muitos tipos diferentes de chaves e registros, permitimos que você especifique o tipo de chave e registro para sua coleção usando genéricos.
No nosso caso, o tipo de registo será a Hotel
classe que já definimos, e o tipo de chave será ulong
, uma vez que a HotelId
propriedade é a ulong
e Qdrant apenas suporta Guid
ou ulong
chaves.
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");
Como os bancos de dados suportam muitos tipos diferentes de chaves e registros, permitimos que você especifique o tipo de chave e registro para sua coleção usando genéricos.
No nosso caso, o tipo de registo será a Hotel
classe que já definimos, e o tipo de chave será str
, uma vez que a HotelId
propriedade é a str
e Qdrant apenas suporta str
ou int
chaves.
from semantic_kernel.connectors.qdrant import QdrantCollection
# Create a collection specify the type of key and record stored in it via Generic parameters.
collection: QdrantCollection[str, Hotel] = QdrantCollection(
record_type=Hotel,
collection_name="skhotels" # this is optional, you can also specify the collection_name in the vectorstoremodel decorator.
)
Como os bancos de dados suportam muitos tipos diferentes de chaves e registros, permitimos que você especifique o tipo de chave e registro para sua coleção usando genéricos.
No nosso caso, o tipo de registro será a Hotel
classe que já definimos, e o tipo de chave será String
, já que a hotelId
propriedade é uma String
e o armazenamento JDBC só suporta String
chaves.
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()
);
}
}
Gorjeta
Para obter mais informações sobre quais tipos de chave e campo cada implementação do Vetor Store suporta, consulte a documentação de cada implementação.
Criar a coleção e adicionar registros
// 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);
Criar a coleção e adicionar registros
# Create the collection if it doesn't exist yet.
await collection.ensure_collection_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();
Gorjeta
Para obter mais informações sobre como gerar incorporações, consulte Geração de incorporação.
Faça uma pesquisa vetorial
// 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);
}
Faça uma pesquisa vetorial
O método de pesquisa pode ser usado para procurar registros na coleção. Ou aceita uma sequência de caracteres, que é então vetorizada usando a configuração de geração de embeddings no modelo ou coleção, ou um vetor que já está gerado.
# Do a search.
search_result = await collection.search("I'm looking for a hotel where customer happiness is the priority.", vector_property_name="description_embedding", top=3)
# Inspect the returned hotels.
async for result in search_result.results:
print(f"Found hotel description: {result.record.description}")
Criar uma função de pesquisa
Para criar uma função de pesquisa simples que pode ser usada para pesquisar hotéis, você pode usar o create_search_function
método na coleção.
O nome e a descrição, bem como os nomes e descrições dos parâmetros, são usados para gerar uma assinatura de função que é enviada para o LLM quando a chamada de função é usada. Isso significa que ajustar isso pode ser útil para fazer com que o LLM gere a chamada de função correta.
collection.create_search_function(
function_name="hotel_search",
description="A hotel search engine, allows searching for hotels in specific cities, "
"you do not have to specify that you are searching for hotels, for all, use `*`."
)
Há muitos outros parâmetros, por exemplo, é assim que uma versão mais complexa se parece, observe a personalização dos parâmetros e a string_mapper
função que é usada para converter o registro em uma cadeia de caracteres.
from semantic_kernel.function import KernelParameterMetadata
collection.create_search_function(
function_name="hotel_search",
description="A hotel search engine, allows searching for hotels in specific cities, "
"you do not have to specify that you are searching for hotels, for all, use `*`.",
search_type="keyword_hybrid", # default is "vector"
parameters=[
KernelParameterMetadata(
name="query",
description="The terms you want to search for in the hotel database.",
type="str",
is_required=True,
type_object=str,
),
KernelParameterMetadata(
name="tags",
description="The tags you want to search for in the hotel database, use `*` to match all.",
type="str",
type_object=str,
default_value="*",
),
KernelParameterMetadata(
name="top",
description="Number of results to return.",
type="int",
default_value=5,
type_object=int,
),
],
# finally, we specify the `string_mapper` function that is used to convert the record to a string.
# This is used to make sure the relevant information from the record is passed to the LLM.
string_mapper=lambda x: f"Hotel {x.record.hotel_name}: {x.record.description}. Tags: {x.record.tags} (hotel_id: {x.record.hotel_id}) ",
)
Gorjeta
Para obter mais exemplos, incluindo exemplos de ponta a ponta, consulte o repositório Semantic Kernel Samples.
// 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());
Gorjeta
Para obter mais informações sobre como gerar incorporações, consulte Geração de incorporação.