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.
Suporte integrado para a geração de embeddings no repositório de vetores
A atualização de abril de 2025 introduz suporte integrado para geração de embeddings diretamente no repositório de vetores. Ao configurar um gerador de incorporação, agora você pode gerar automaticamente incorporações para propriedades vetoriais sem a necessidade de pré-calculá-las externamente. Esse recurso simplifica os fluxos de trabalho e reduz a necessidade de etapas adicionais de pré-processamento.
Configurando um gerador de incorporação
Os geradores de incorporação que implementam as Microsoft.Extensions.AI abstrações são suportados e podem ser configurados em vários níveis:
No Vetor Store: Você pode definir um gerador de incorporação padrão para todo o repositório de vetores. Este gerador será usado para todas as coleções e propriedades, a menos que seja substituído.
using Microsoft.Extensions.AI; using Microsoft.SemanticKernel.Connectors.Qdrant; using OpenAI; using Qdrant.Client; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var vectorStore = new QdrantVectorStore(new QdrantClient("localhost"), new QdrantVectorStoreOptions { EmbeddingGenerator = embeddingGenerator });Em uma coleção: pode configurar um gerador de inserção para uma coleção específica, sobrescrevendo o gerador ao nível da loja.
using Microsoft.Extensions.AI; using Microsoft.SemanticKernel.Connectors.Qdrant; using OpenAI; using Qdrant.Client; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var collectionOptions = new QdrantVectorStoreRecordCollectionOptions<MyRecord> { EmbeddingGenerator = embeddingGenerator }; var collection = new QdrantVectorStoreRecordCollection<ulong, MyRecord>(new QdrantClient("localhost"), "myCollection", collectionOptions);Em uma definição de registro: ao definir propriedades programaticamente usando
VectorStoreRecordDefinitiono , você pode especificar um gerador de incorporação para todas as propriedades.using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using Microsoft.SemanticKernel.Connectors.Qdrant; using OpenAI; using Qdrant.Client; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var recordDefinition = new VectorStoreRecordDefinition { EmbeddingGenerator = embeddingGenerator, Properties = new List<VectorStoreRecordProperty> { new VectorStoreRecordKeyProperty("Key", typeof(ulong)), new VectorStoreRecordVectorProperty("DescriptionEmbedding", typeof(string), dimensions: 1536) } }; var collectionOptions = new QdrantVectorStoreRecordCollectionOptions<MyRecord> { VectorStoreRecordDefinition = recordDefinition }; var collection = new QdrantVectorStoreRecordCollection<ulong, MyRecord>(new QdrantClient("localhost"), "myCollection", collectionOptions);Em uma definição de propriedade vetorial: Ao definir propriedades programaticamente, você pode definir um gerador de incorporação diretamente na propriedade.
using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using OpenAI; var embeddingGenerator = new OpenAIClient("your key") .GetEmbeddingClient("your chosen model") .AsIEmbeddingGenerator(); var vectorProperty = new VectorStoreRecordVectorProperty("DescriptionEmbedding", typeof(string), dimensions: 1536) { EmbeddingGenerator = embeddingGenerator };
Exemplo de Utilização
O exemplo a seguir demonstra como usar o gerador de embebimento para gerar vetores automaticamente durante tanto as operações de upsert quanto de pesquisa. Essa abordagem simplifica os fluxos de trabalho, eliminando a necessidade de pré-calcular incorporações manualmente.
// The data model
internal class FinanceInfo
{
[VectorStoreRecordKey]
public string Key { get; set; } = string.Empty;
[VectorStoreRecordData]
public string Text { get; set; } = string.Empty;
// Note that the vector property is typed as a string, and
// its value is derived from the Text property. The string
// value will however be converted to a vector on upsert and
// stored in the database as a vector.
[VectorStoreRecordVector(1536)]
public string Embedding => this.Text;
}
// Create an OpenAI embedding generator.
var embeddingGenerator = new OpenAIClient("your key")
.GetEmbeddingClient("your chosen model")
.AsIEmbeddingGenerator();
// Use the embedding generator with the vector store.
var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
var collection = vectorStore.GetCollection<string, FinanceInfo>("finances");
await collection.CreateCollectionAsync();
// Create some test data.
string[] budgetInfo =
{
"The budget for 2020 is EUR 100 000",
"The budget for 2021 is EUR 120 000",
"The budget for 2022 is EUR 150 000",
"The budget for 2023 is EUR 200 000",
"The budget for 2024 is EUR 364 000"
};
// Embeddings are generated automatically on upsert.
var records = budgetInfo.Select((input, index) => new FinanceInfo { Key = index.ToString(), Text = input });
await collection.UpsertAsync(records);
// Embeddings for the search is automatically generated on search.
var searchResult = collection.SearchAsync(
"What is my budget for 2024?",
top: 1);
// Output the matching result.
await foreach (var result in searchResult)
{
Console.WriteLine($"Key: {result.Record.Key}, Text: {result.Record.Text}");
}
Transição de IVectorizableTextSearch e IVectorizedSearch para IVectorSearch
As IVectorizableTextSearch interfaces e IVectorizedSearch foram marcadas como obsoletas e substituídas pela interface mais unificada e flexível IVectorSearch .
Essa alteração simplifica a superfície da API e fornece uma abordagem mais consistente para operações de pesquisa vetorial.
Alterações de Chaves
Interface unificada:
- A
IVectorSearchinterface consolida a funcionalidade de ambosIVectorizableTextSearcheIVectorizedSearchem uma única interface.
- A
Renomeação de métodos:
-
VectorizableTextSearchAsyncdeIVectorizableTextSearchfoi substituído porSearchAsyncinIVectorSearch. -
VectorizedSearchAsyncdeIVectorizedSearchfoi substituído porSearchEmbeddingAsyncinIVectorSearch.
-
Flexibilidade melhorada:
- O
SearchAsyncmétodo emIVectorSearchgerencia a geração de incorporações, suportando a incorporação local, se um gerador de incorporações estiver configurado, ou a incorporação no lado do servidor. - O método
SearchEmbeddingAsyncemIVectorSearchpermite pesquisas baseadas diretamente em incorporação, fornecendo uma API de baixo nível para casos de uso avançados.
- O
Alteração de tipo de retorno para métodos de pesquisa
Além da alteração na nomenclatura dos métodos de pesquisa, o tipo de retorno para todos os métodos de pesquisa foi alterado para simplificar o uso.
O tipo de resultado dos métodos de pesquisa é agora IAsyncEnumerable<VectorSearchResult<TRecord>>, o que permite percorrer os resultados diretamente. Anteriormente, o objeto retornado continha uma propriedade IAsyncEnumerable.
Suporte para pesquisa sem vetores / obtenção filtrada
A atualização de abril de 2025 introduz suporte para localizar registros usando um filtro e retornar os resultados com uma ordem de classificação configurável. Isso permite enumerar registros em uma ordem previsível, o que é particularmente útil quando é necessário sincronizar o armazenamento vetorial com uma fonte de dados externa.
Exemplo: Usando o filtro GetAsync
O exemplo a seguir demonstra como usar o GetAsync método com um filtro e opções para recuperar registros de uma coleção de armazenamento de vetores. Essa abordagem permite aplicar critérios de filtragem e classificar os resultados em uma ordem previsível.
// Define a filter to retrieve products priced above $600
Expression<Func<ProductInfo, bool>> filter = product => product.Price > 600;
// Define the options with a sort order
var options = new GetFilteredRecordOptions<ProductInfo>();
options.OrderBy.Descending(product => product.Price);
// Use GetAsync with the filter and sort order
var filteredProducts = await collection.GetAsync(filter, top: 10, options)
.ToListAsync();
Este exemplo demonstra como usar o GetAsync método para recuperar registros filtrados e classificá-los com base em critérios específicos, como preço.
Novos métodos em IVectorStore
Alguns novos métodos estão disponíveis na IVectorStore interface que permitem que você execute mais operações diretamente sem precisar de um objeto VectorStoreRecordCollection.
Verificar se existe uma coleção
Agora você pode verificar se uma coleção existe no repositório de vetores sem precisar criar um objeto VectorStoreRecordCollection.
// Example: Check if a collection exists
bool exists = await vectorStore.CollectionExistsAsync("myCollection", cancellationToken);
if (exists)
{
Console.WriteLine("The collection exists.");
}
else
{
Console.WriteLine("The collection does not exist.");
}
Excluir uma coleção
Um novo método permite excluir uma coleção do repositório de vetores sem ter que criar um objeto VectorStoreRecordCollection.
// Example: Delete a collection
await vectorStore.DeleteCollectionAsync("myCollection", cancellationToken);
Console.WriteLine("The collection has been deleted.");
Substituição de VectorStoreGenericDataModel<TKey> por Dictionary<string, object?>
As abstrações de dados vetoriais suportam o trabalho com bancos de dados onde o esquema de uma coleção não é conhecido no momento da compilação.
Anteriormente, isso era suportado através do VectorStoreGenericDataModel<TKey> tipo, onde este modelo pode ser usado no lugar de um modelo de dados personalizado.
Nesta versão, o VectorStoreGenericDataModel<TKey> foi obsoleto, e a abordagem recomendada é usar um Dictionary<string, object?> em vez disso.
Como antes, uma definição de registro precisa ser fornecida para determinar o esquema da coleção. Observe também que o tipo de chave necessário ao obter a instância de coleta é object, enquanto no esquema ele é corrigido como string.
var recordDefinition = new VectorStoreRecordDefinition
{
Properties = new List<VectorStoreRecordProperty>
{
new VectorStoreRecordKeyProperty("Key", typeof(string)),
new VectorStoreRecordDataProperty("Text", typeof(string)),
new VectorStoreRecordVectorProperty("Embedding", typeof(ReadOnlyMemory<float>), 1536)
}
};
var collection = vectorStore.GetCollection<object, Dictionary<string, object?>>("finances", recordDefinition);
var record = new Dictionary<string, object?>
{
{ "Key", "1" },
{ "Text", "The budget for 2024 is EUR 364 000" },
{ "Embedding", vector }
};
await collection.UpsertAsync(record);
var retrievedRecord = await collection.GetAsync("1");
Console.WriteLine(retrievedRecord["Text"]);
Alteração na convenção de nomenclatura do método Batch
A IVectorStoreRecordCollection interface foi atualizada para melhorar a consistência nas convenções de nomenclatura de métodos.
Especificamente, os métodos de lote foram renomeados para remover a parte "Lote" de seus nomes. Esta alteração alinha-se com uma convenção de nomenclatura mais concisa.
Exemplos de renomeação
Método antigo:
GetBatchAsync(IEnumerable<TKey> keys, ...)
Novo método:GetAsync(IEnumerable<TKey> keys, ...)Método antigo:
DeleteBatchAsync(IEnumerable<TKey> keys, ...)
Novo método:DeleteAsync(IEnumerable<TKey> keys, ...)Método antigo:
UpsertBatchAsync(IEnumerable<TRecord> records, ...)
Novo método:UpsertAsync(IEnumerable<TRecord> records, ...)
Alteração de tipo de retorno para o método Upsert em lote
O tipo de retorno para o método batch upsert foi alterado de IAsyncEnumerable<TKey> para Task<IReadOnlyList<TKey>>.
Essa alteração afeta a forma como o método é consumido. Agora você pode simplesmente aguardar o resultado e obter de volta uma lista de chaves.
Anteriormente, para garantir que todos os upserts fossem concluídos, era necessário enumerar completamente o IAsyncEnumerable.
Isso simplifica a experiência do desenvolvedor ao usar o método batch upsert.
A propriedade CollectionName foi alterada para Name
A CollectionName propriedade na IVectorStoreRecordCollection interface foi renomeada para Name.
Os nomes IsFilterable e IsFullTextSearchable foram alterados para IsIndexed e IsFullTextIndexed.
As propriedades IsFilterable e IsFullTextSearchable nas classes VectorStoreRecordDataAttribute e VectorStoreRecordDataProperty foram renomeadas para IsIndexed e IsFullTextIndexed respectivamente.
As dimensões agora são necessárias para atributos vetoriais e definições
Na atualização de abril de 2025, a especificação do número de dimensões tornou-se obrigatória ao usar atributos de vetor ou definições de propriedade de vetor. Isso garante que o armazenamento de vetores sempre tenha as informações necessárias para lidar com incorporações corretamente.
Alterações ao VectorStoreRecordVectorAttribute
Anteriormente, o VectorStoreRecordVectorAttribute permitia que você omitisse o Dimensions parâmetro. Isso não é mais permitido, e o Dimensions parâmetro agora deve ser explicitamente fornecido.
Antes:
[VectorStoreRecordVector]
public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }
Depois:
[VectorStoreRecordVector(Dimensions: 1536)]
public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }
Alterações ao VectorStoreRecordVectorProperty
Da mesma forma, ao definir uma propriedade vetorial programaticamente usando VectorStoreRecordVectorProperty, o parâmetro dimensions agora é necessário.
Antes:
var vectorProperty = new VectorStoreRecordVectorProperty("DefinitionEmbedding", typeof(ReadOnlyMemory<float>));
Depois:
var vectorProperty = new VectorStoreRecordVectorProperty("DefinitionEmbedding", typeof(ReadOnlyMemory<float>), dimensions: 1536);
Todas as coleções exigem que o tipo de chave seja passado como um parâmetro de tipo genérico
Ao construir uma coleção diretamente, agora é necessário fornecer o TKey parâmetro de tipo genérico.
Anteriormente, em alguns bancos de dados, apenas um tipo de chave era permitido. Agora, tornou-se um parâmetro necessário, mas para permitir o uso de coleções com um tipo `Dictionary<string, object?>` e um tipo de chave `object`, `TKey` deve sempre ser fornecido.
Não Aplicável
Atualmente, estas alterações só são aplicáveis em C#
Não Aplicável
Atualmente, estas alterações só são aplicáveis em C#