chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Memory.VectorStoreLangchainInterop;
/// <summary>
/// Data model class that matches the data model used by Langchain.
/// This data model is not decorated with vector store attributes since instead
/// a different record definition is used with each vector store implementation.
/// </summary>
/// <remarks>
/// This class is used with the <see cref="VectorStore_Langchain_Interop"/> sample.
/// </remarks>
public class LangchainDocument<TKey>
{
/// <summary>
/// The unique identifier of the record.
/// </summary>
public TKey Key { get; set; }
/// <summary>
/// The text content for which embeddings have been generated.
/// </summary>
public string Content { get; set; }
/// <summary>
/// The source of the content. E.g. where to find the original content.
/// </summary>
public string Source { get; set; }
/// <summary>
/// The embedding for the <see cref="Content"/>.
/// </summary>
public ReadOnlyMemory<float> Embedding { get; set; }
}
@@ -0,0 +1,87 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.Pinecone;
using Pinecone;
namespace Memory.VectorStoreLangchainInterop;
/// <summary>
/// Contains a factory method that can be used to create a Pinecone vector store that is compatible with datasets ingested using Langchain.
/// </summary>
/// <remarks>
/// This class is used with the <see cref="VectorStore_Langchain_Interop"/> sample.
/// </remarks>
public static class PineconeFactory
{
/// <summary>
/// Record definition that matches the storage format used by Langchain for Pinecone.
/// </summary>
private static readonly VectorStoreCollectionDefinition s_definition = new()
{
Properties =
[
new VectorStoreKeyProperty("Key", typeof(string)),
new VectorStoreDataProperty("Content", typeof(string)) { StorageName = "text" },
new VectorStoreDataProperty("Source", typeof(string)) { StorageName = "source" },
new VectorStoreVectorProperty("Embedding", typeof(ReadOnlyMemory<float>), 1536) { StorageName = "embedding" }
]
};
/// <summary>
/// Create a new Pinecone-backed <see cref="VectorStore"/> that can be used to read data that was ingested using Langchain.
/// </summary>
/// <param name="pineconeClient">Pinecone client that can be used to manage the collections and points in a Pinecone store.</param>
/// <returns>The <see cref="VectorStore"/>.</returns>
public static VectorStore CreatePineconeLangchainInteropVectorStore(PineconeClient pineconeClient)
=> new PineconeLangchainInteropVectorStore(new PineconeVectorStore(pineconeClient), pineconeClient);
private sealed class PineconeLangchainInteropVectorStore(
VectorStore innerStore,
PineconeClient pineconeClient)
: VectorStore
{
private readonly PineconeClient _pineconeClient = pineconeClient;
public override VectorStoreCollection<TKey, TRecord> GetCollection<TKey, TRecord>(string name, VectorStoreCollectionDefinition? definition = null)
{
if (typeof(TKey) != typeof(string) || typeof(TRecord) != typeof(LangchainDocument<string>))
{
throw new NotSupportedException("This VectorStore is only usable with string keys and LangchainDocument<string> record types");
}
// Create a Pinecone collection and pass in our custom record definition that matches
// the schema used by Langchain so that the default mapper can use the storage names
// in it, to map to the storage scheme.
return (new PineconeCollection<TKey, TRecord>(
_pineconeClient,
name,
new()
{
Definition = s_definition
}) as VectorStoreCollection<TKey, TRecord>)!;
}
public override VectorStoreCollection<object, Dictionary<string, object?>> GetDynamicCollection(string name, VectorStoreCollectionDefinition? definition = null)
{
// Create a Pinecone collection and pass in our custom record definition that matches
// the schema used by Langchain so that the default mapper can use the storage names
// in it, to map to the storage scheme.
return new PineconeDynamicCollection(
_pineconeClient,
name,
new()
{
Definition = s_definition
});
}
public override object? GetService(Type serviceType, object? serviceKey = null) => innerStore.GetService(serviceType, serviceKey);
public override IAsyncEnumerable<string> ListCollectionNamesAsync(CancellationToken cancellationToken = default) => innerStore.ListCollectionNamesAsync(cancellationToken);
public override Task<bool> CollectionExistsAsync(string name, CancellationToken cancellationToken = default) => innerStore.CollectionExistsAsync(name, cancellationToken);
public override Task EnsureCollectionDeletedAsync(string name, CancellationToken cancellationToken = default) => innerStore.EnsureCollectionDeletedAsync(name, cancellationToken);
}
}
@@ -0,0 +1,89 @@
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.Redis;
using StackExchange.Redis;
namespace Memory.VectorStoreLangchainInterop;
/// <summary>
/// Contains a factory method that can be used to create a Redis vector store that is compatible with datasets ingested using Langchain.
/// </summary>
/// <remarks>
/// This class is used with the <see cref="VectorStore_Langchain_Interop"/> sample.
/// </remarks>
public static class RedisFactory
{
/// <summary>
/// Record definition that matches the storage format used by Langchain for Redis.
/// </summary>
private static readonly VectorStoreCollectionDefinition s_definition = new()
{
Properties =
[
new VectorStoreKeyProperty("Key", typeof(string)),
new VectorStoreDataProperty("Content", typeof(string)) { StorageName = "text" },
new VectorStoreDataProperty("Source", typeof(string)) { StorageName = "source" },
new VectorStoreVectorProperty("Embedding", typeof(ReadOnlyMemory<float>), 1536) { StorageName = "embedding" }
]
};
/// <summary>
/// Create a new Redis-backed <see cref="VectorStore"/> that can be used to read data that was ingested using Langchain.
/// </summary>
/// <param name="database">The redis database to read/write from.</param>
/// <returns>The <see cref="VectorStore"/>.</returns>
public static VectorStore CreateRedisLangchainInteropVectorStore(IDatabase database)
=> new RedisLangchainInteropVectorStore(new RedisVectorStore(database), database);
private sealed class RedisLangchainInteropVectorStore(
VectorStore innerStore,
IDatabase database)
: VectorStore
{
private readonly IDatabase _database = database;
public override VectorStoreCollection<TKey, TRecord> GetCollection<TKey, TRecord>(string name, VectorStoreCollectionDefinition? definition = null)
{
if (typeof(TKey) != typeof(string) || typeof(TRecord) != typeof(LangchainDocument<string>))
{
throw new NotSupportedException("This VectorStore is only usable with string keys and LangchainDocument<string> record types");
}
// Create a hash set collection, since Langchain uses redis hashes for storing records.
// Also pass in our custom record definition that matches the schema used by Langchain
// so that the default mapper can use the storage names in it, to map to the storage
// scheme.
return (new RedisHashSetCollection<TKey, TRecord>(
_database,
name,
new()
{
Definition = s_definition
}) as VectorStoreCollection<TKey, TRecord>)!;
}
public override VectorStoreCollection<object, Dictionary<string, object?>> GetDynamicCollection(string name, VectorStoreCollectionDefinition? definition = null)
{
// Create a hash set collection, since Langchain uses redis hashes for storing records.
// Also pass in our custom record definition that matches the schema used by Langchain
// so that the default mapper can use the storage names in it, to map to the storage
// scheme.
return new RedisHashSetDynamicCollection(
_database,
name,
new()
{
Definition = s_definition
});
}
public override object? GetService(Type serviceType, object? serviceKey = null) => innerStore.GetService(serviceType, serviceKey);
public override IAsyncEnumerable<string> ListCollectionNamesAsync(CancellationToken cancellationToken = default) => innerStore.ListCollectionNamesAsync(cancellationToken);
public override Task<bool> CollectionExistsAsync(string name, CancellationToken cancellationToken = default) => innerStore.CollectionExistsAsync(name, cancellationToken);
public override Task EnsureCollectionDeletedAsync(string name, CancellationToken cancellationToken = default) => innerStore.EnsureCollectionDeletedAsync(name, cancellationToken);
}
}