Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Prise en charge intégrée pour la génération d'embeddings dans le stockage vectoriel
La mise à jour d'avril 2025 introduit la prise en charge intégrée de la génération d'intégrations directement dans le stockage vectoriel. En configurant un générateur d’incorporation, vous pouvez désormais générer automatiquement des incorporations pour les propriétés vectorielles sans avoir à les précomputer en externe. Cette fonctionnalité simplifie les flux de travail et réduit le besoin d’étapes de prétraitement supplémentaires.
Configuration d’un générateur d’incorporation
Les générateurs d’incorporation implémentant les Microsoft.Extensions.AI
abstractions sont pris en charge et peuvent être configurés à différents niveaux :
Dans le magasin de vecteurs : vous pouvez définir un générateur d’incorporation par défaut pour l’intégralité du magasin vectoriel. Ce générateur sera utilisé pour toutes les collections et propriétés, sauf en cas de substitution.
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 });
Dans une collection : vous pouvez configurer un générateur d'intégration pour une collection spécifique, en remplaçant le générateur au niveau du magasin.
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);
Sur une définition d’enregistrement : lors de la définition des propriétés par programmation
VectorStoreRecordDefinition
, vous pouvez spécifier un générateur d’incorporation pour toutes les propriétés.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);
Sur une définition de propriété vectorielle : lorsque vous définissez des propriétés par programmation, vous pouvez définir un générateur d’incorporation directement sur la propriété.
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 };
Exemple d’utilisation
L’exemple suivant montre comment utiliser le générateur d’incorporation pour générer automatiquement des vecteurs pendant les opérations upsert et de recherche. Cette approche simplifie les flux de travail en éliminant la nécessité de précomputer manuellement les incorporations.
// 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}");
}
Transition depuis IVectorizableTextSearch
et IVectorizedSearch
vers IVectorSearch
Les interfaces IVectorizableTextSearch
et IVectorizedSearch
ont été déclarées obsolètes et remplacées par l’interface plus unifiée et flexible IVectorSearch
.
Cette modification simplifie la surface de l’API et offre une approche plus cohérente des opérations de recherche vectorielle.
Modifications clés
Interface unifiée :
- L’interface
IVectorSearch
consolide les fonctionnalités des deuxIVectorizableTextSearch
etIVectorizedSearch
dans une seule interface.
- L’interface
Renommage de la méthode :
-
VectorizableTextSearchAsync
deIVectorizableTextSearch
a été remplacé parSearchAsync
inIVectorSearch
. -
VectorizedSearchAsync
deIVectorizedSearch
a été remplacé parSearchEmbeddingAsync
inIVectorSearch
.
-
Flexibilité améliorée :
- Méthode
SearchAsync
dansIVectorSearch
gère la génération d’incorporations, en prenant en charge soit l’incorporation locale, si un générateur d’incorporation est configuré, soit l’incorporation côté serveur. - La méthode
SearchEmbeddingAsync
dansIVectorSearch
permet des recherches basées sur les embeddings, fournissant une API de bas niveau pour des cas d'utilisation avancés.
- Méthode
Modification du type de retour pour les méthodes de recherche
Outre le changement de nommage des méthodes de recherche, le type de retour de toutes les méthodes de recherche a été modifié pour simplifier l’utilisation.
Le type de résultats des méthodes de recherche est maintenant IAsyncEnumerable<VectorSearchResult<TRecord>>
, ce qui permet de parcourir directement les résultats. Auparavant, l’objet retourné contenait une propriété IAsyncEnumerable.
Prise en charge de la recherche sans vecteurs / récupération filtrée
La mise à jour d’avril 2025 introduit la prise en charge de la recherche d’enregistrements à l’aide d’un filtre et le retour des résultats avec un ordre de tri configurable. Cela permet d’énumérer des enregistrements dans un ordre prévisible, ce qui est particulièrement utile lors de la synchronisation du magasin vectoriel avec une source de données externe.
Exemple : utilisation de filtres GetAsync
L’exemple suivant montre comment utiliser la GetAsync
méthode avec un filtre et des options pour récupérer des enregistrements d’une collection de magasins vectoriels. Cette approche vous permet d’appliquer des critères de filtrage et de trier les résultats dans un ordre prévisible.
// 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();
Cet exemple montre comment utiliser la GetAsync
méthode pour récupérer des enregistrements filtrés et les trier en fonction de critères spécifiques, tels que le prix.
Nouvelles méthodes sur IVectorStore
Certaines nouvelles méthodes sont disponibles sur l’interface IVectorStore
qui vous permettent d’effectuer plus d’opérations directement sans avoir besoin d’un objet VectorStoreRecordCollection.
Vérifier si une collection existe
Vous pouvez maintenant vérifier si une collection existe dans le magasin de vecteurs sans avoir à créer d’objet 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.");
}
Supprimer une collection
Une nouvelle méthode vous permet de supprimer une collection du magasin vectoriel sans avoir à créer d’objet VectorStoreRecordCollection.
// Example: Delete a collection
await vectorStore.DeleteCollectionAsync("myCollection", cancellationToken);
Console.WriteLine("The collection has been deleted.");
Remplacement de VectorStoreGenericDataModel<TKey>
par Dictionary<string, object?>
Les abstractions de données vectorielles prennent en charge l’utilisation de bases de données où le schéma d’une collection n’est pas connu au moment de la génération.
Auparavant, cela a été pris en charge via le VectorStoreGenericDataModel<TKey>
type, où ce modèle peut être utilisé à la place d’un modèle de données personnalisé.
Dans cette version, le VectorStoreGenericDataModel<TKey>
est devenu obsolète, et l'approche recommandée consiste à utiliser un Dictionary<string, object?>
à la place.
Comme précédemment, une définition d’enregistrement doit être fournie pour déterminer le schéma de la collection. Notez également que le type de clé requis lors de l’obtention de l’instance de collection est object
, tandis que dans le schéma, il est fixe à 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"]);
Modification de la convention d’affectation de noms de méthode Batch
L’interface IVectorStoreRecordCollection
a été mise à jour pour améliorer la cohérence dans les conventions d’affectation de noms de méthodes.
Plus précisément, les méthodes de traitement par lots ont été renommées pour supprimer la partie « Batch » de leurs noms. Cette modification s’aligne sur une convention d’affectation de noms plus concise.
Renommer les exemples
Ancienne méthode :
GetBatchAsync(IEnumerable<TKey> keys, ...)
Nouvelle méthode :GetAsync(IEnumerable<TKey> keys, ...)
Ancienne méthode :
DeleteBatchAsync(IEnumerable<TKey> keys, ...)
Nouvelle méthode :DeleteAsync(IEnumerable<TKey> keys, ...)
Ancienne méthode :
UpsertBatchAsync(IEnumerable<TRecord> records, ...)
Nouvelle méthode :UpsertAsync(IEnumerable<TRecord> records, ...)
Modification du type de retour pour la méthode Upsert batch
Le type de retour de la méthode batch upsert a été remplacé de IAsyncEnumerable<TKey>
à Task<IReadOnlyList<TKey>>
.
Cette modification a un impact sur la façon dont la méthode est consommée. Vous pouvez maintenant simplement attendre le résultat et récupérer une liste de clés.
Auparavant, pour s’assurer que tous les upserts étaient terminés, l’IAsyncEnumerable devait être entièrement énuméré.
Cela simplifie l’expérience du développeur lors de l’utilisation de la méthode batch upsert.
La propriété CollectionName a été remplacée par Name
La propriété CollectionName
de l’interface IVectorStoreRecordCollection
a été renommée en Name
.
IsFilterable et IsFullTextSearchable ont été renommés en IsIndexed et IsFullTextIndexed
Les propriétés IsFilterable
et IsFullTextSearchable
des classes VectorStoreRecordDataAttribute
et VectorStoreRecordDataProperty
ont été renommées respectivement IsIndexed
et IsFullTextIndexed
.
Les dimensions sont désormais requises pour les attributs et définitions de vecteurs
Dans la mise à jour d’avril 2025, la spécification du nombre de dimensions est devenue obligatoire lors de l’utilisation d’attributs vectoriels ou de définitions de propriétés vectorielles. Cela garantit que le magasin de vecteurs dispose toujours des informations nécessaires pour gérer correctement les incorporations.
Modifications apportées à VectorStoreRecordVectorAttribute
Précédemment, le VectorStoreRecordVectorAttribute
vous permettait d'omettre le paramètre Dimensions
. Cela n’est plus autorisé, et le Dimensions
paramètre doit maintenant être fourni explicitement.
Avant :
[VectorStoreRecordVector]
public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }
Après :
[VectorStoreRecordVector(Dimensions: 1536)]
public ReadOnlyMemory<float> DefinitionEmbedding { get; set; }
Modifications apportées à VectorStoreRecordVectorProperty
De même, lors de la définition d’une propriété vectorielle de manière programmatique en utilisant VectorStoreRecordVectorProperty
, le paramètre dimensions
est désormais requis.
Avant :
var vectorProperty = new VectorStoreRecordVectorProperty("DefinitionEmbedding", typeof(ReadOnlyMemory<float>));
Après :
var vectorProperty = new VectorStoreRecordVectorProperty("DefinitionEmbedding", typeof(ReadOnlyMemory<float>), dimensions: 1536);
Toutes les collections nécessitent que le type de clé soit transmis en tant que paramètre de type générique
Lors de la construction directe d’une collection, il est maintenant nécessaire de fournir le TKey
paramètre de type générique.
Auparavant, où certaines bases de données n’autorisaient qu’un seul type de clé, il s’agissait maintenant d’un paramètre obligatoire, mais pour autoriser l’utilisation de collections avec un Dictionary<string, object?>
type et un object
type de clé, TKey
doivent maintenant toujours être fournies.
Sans objet
Ces modifications sont actuellement applicables uniquement en C#
Sans objet
Ces modifications sont actuellement applicables uniquement en C#