// 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;
}
}