// Copyright (c) Microsoft. All rights reserved. using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using Microsoft.SemanticKernel.Data; namespace Memory; /// /// Extension methods for which allow: /// 1. Creating an instance of from a list of strings. /// internal static class VectorStoreExtensions { /// /// Delegate to create a record from a string. /// /// Type of the record key. /// Type of the record. internal delegate TRecord CreateRecordFromString(string text, ReadOnlyMemory vector) where TKey : notnull; /// /// Delegate to create a record from a . /// /// Type of the record key. /// Type of the record. internal delegate TRecord CreateRecordFromTextSearchResult(TextSearchResult searchResult, ReadOnlyMemory vector) where TKey : notnull; /// /// Create a from a list of strings by: /// 1. Getting an instance of /// 2. Generating embeddings for each string. /// 3. Creating a record with a valid key for each string and it's embedding. /// 4. Insert the records into the collection. /// /// Instance of used to created the collection. /// The collection name. /// A list of strings. /// An embedding generator. /// A delegate which can create a record with a valid key for each string and it's embedding. internal static async Task> CreateCollectionFromListAsync( this VectorStore vectorStore, string collectionName, string[] entries, IEmbeddingGenerator> embeddingGenerator, CreateRecordFromString createRecord) where TKey : notnull where TRecord : class { // Get and create collection if it doesn't exist. var collection = vectorStore.GetCollection(collectionName); await collection.EnsureCollectionExistsAsync().ConfigureAwait(false); // Create records and generate embeddings for them. var tasks = entries.Select(entry => Task.Run(async () => { var record = createRecord(entry, (await embeddingGenerator.GenerateAsync(entry).ConfigureAwait(false)).Vector); await collection.UpsertAsync(record).ConfigureAwait(false); })); await Task.WhenAll(tasks).ConfigureAwait(false); return collection; } /// /// Create a from a list of strings by: /// 1. Getting an instance of /// 2. Generating embeddings for each string. /// 3. Creating a record with a valid key for each string and it's embedding. /// 4. Insert the records into the collection. /// /// Instance of used to created the collection. /// The collection name. /// A list of s. /// An embedding generator service. /// A delegate which can create a record with a valid key for each string and it's embedding. internal static async Task> CreateCollectionFromTextSearchResultsAsync( this VectorStore vectorStore, string collectionName, IList searchResults, IEmbeddingGenerator> embeddingGenerator, CreateRecordFromTextSearchResult createRecord) where TKey : notnull where TRecord : class { // Get and create collection if it doesn't exist. var collection = vectorStore.GetCollection(collectionName); await collection.EnsureCollectionExistsAsync().ConfigureAwait(false); // Create records and generate embeddings for them. var tasks = searchResults.Select(searchResult => Task.Run(async () => { var record = createRecord(searchResult, (await embeddingGenerator.GenerateAsync(searchResult.Value!).ConfigureAwait(false)).Vector); await collection.UpsertAsync(record).ConfigureAwait(false); })); await Task.WhenAll(tasks).ConfigureAwait(false); return collection; } }