From 3bf7bcb1b0e62b5ab08bda8a38570e56eb4b8a66 Mon Sep 17 00:00:00 2001 From: token <239573049@qq.com> Date: Thu, 1 Aug 2024 01:30:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=A1=86=E6=9E=B6=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=20=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Build.props | 6 +- mem0.NET.sln | 14 --- src/mem0.Core/mem0.Core.csproj | 13 --- .../ServiceCollectionExtensions.cs | 20 ---- .../mem0.NET.EntityFramework.csproj | 19 ---- .../ServiceCollectionExtensions.cs | 9 +- .../Services/QdrantVectorStoresService.cs | 1 + src/mem0.NET.Qdrant/mem0.NET.Qdrant.csproj | 6 +- src/mem0.NET.Service/Program.cs | 35 +++---- .../Services/MemoryService.cs | 44 +++------ src/mem0.NET.Service/appsettings.json | 13 +++ src/mem0.NET.Service/mem0.NET.Service.csproj | 2 - .../ApplicationContext.cs} | 2 +- .../DataAccess/Mem0DbContext.cs | 0 src/{mem0.Core => mem0.NET}/Distance.cs | 0 .../Dto/CreateMemoryInput.cs | 0 .../Dto/CreateMemoryToolInput.cs | 0 .../Dto/UpdateMemoryInput.cs | 0 src/mem0.NET/Functions/MemoryTool.cs | 78 ++------------- src/{mem0.Core => mem0.NET}/Mem0Builder.cs | 0 src/{mem0.Core => mem0.NET}/Model/History.cs | 0 .../Model/SearchHit.cs | 0 .../Model/VectorData.cs | 13 ++- .../Model/VectorInfo.cs | 0 .../{Mem0DotNetOptions.cs => Mem0Options.cs} | 5 +- src/mem0.NET/ServiceCollectionExtensions.cs | 32 +++--- .../Services/HistoryService.cs | 28 +++++- src/mem0.NET/Services/IMemoryService.cs | 50 ---------- src/mem0.NET/Services/MemoryService.cs | 98 +++++++++---------- .../VectorInfoStatus.cs | 0 .../VectorStores/IHistoryService.cs | 0 .../VectorStores/IVectorStoreService.cs | 0 src/mem0.NET/mem0.NET.csproj | 6 +- 33 files changed, 166 insertions(+), 328 deletions(-) delete mode 100644 src/mem0.Core/mem0.Core.csproj delete mode 100644 src/mem0.NET.EntityFramework/ServiceCollectionExtensions.cs delete mode 100644 src/mem0.NET.EntityFramework/mem0.NET.EntityFramework.csproj rename src/{mem0.Core/Mem0Context.cs => mem0.NET/ApplicationContext.cs} (86%) rename src/{mem0.NET.EntityFramework => mem0.NET}/DataAccess/Mem0DbContext.cs (100%) rename src/{mem0.Core => mem0.NET}/Distance.cs (100%) rename src/{mem0.Core => mem0.NET}/Dto/CreateMemoryInput.cs (100%) rename src/{mem0.Core => mem0.NET}/Dto/CreateMemoryToolInput.cs (100%) rename src/{mem0.Core => mem0.NET}/Dto/UpdateMemoryInput.cs (100%) rename src/{mem0.Core => mem0.NET}/Mem0Builder.cs (100%) rename src/{mem0.Core => mem0.NET}/Model/History.cs (100%) rename src/{mem0.Core => mem0.NET}/Model/SearchHit.cs (100%) rename src/{mem0.Core => mem0.NET}/Model/VectorData.cs (75%) rename src/{mem0.Core => mem0.NET}/Model/VectorInfo.cs (100%) rename src/mem0.NET/Options/{Mem0DotNetOptions.cs => Mem0Options.cs} (89%) rename src/{mem0.NET.EntityFramework => mem0.NET}/Services/HistoryService.cs (52%) delete mode 100644 src/mem0.NET/Services/IMemoryService.cs rename src/{mem0.Core => mem0.NET}/VectorInfoStatus.cs (100%) rename src/{mem0.Core => mem0.NET}/VectorStores/IHistoryService.cs (100%) rename src/{mem0.Core => mem0.NET}/VectorStores/IVectorStoreService.cs (100%) diff --git a/Directory.Build.props b/Directory.Build.props index 8a706b5..84131b3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 0.1.3 - 0.1.3 + 0.1.4 + 0.1.4 AIDotNet AIDotNet $(AssemblyName) @@ -12,7 +12,7 @@ Apache-2.0 1.16.1 8.0.0 - 8.0.7 + 8.0.0 1.10.0 True diff --git a/mem0.NET.sln b/mem0.NET.sln index 36c2b45..815a5b7 100644 --- a/mem0.NET.sln +++ b/mem0.NET.sln @@ -15,12 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mem0.NET.Qdrant", "src\mem0.NET.Qdrant\mem0.NET.Qdrant.csproj", "{F6D8FF6D-7376-479B-B673-DCC0BE715336}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mem0.Core", "src\mem0.Core\mem0.Core.csproj", "{89EA032E-1A1B-4B19-9121-7258C818FD00}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mem0.NET.Service", "src\mem0.NET.Service\mem0.NET.Service.csproj", "{4755664B-6109-441B-97D6-1EE3117533EF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mem0.NET.EntityFramework", "src\mem0.NET.EntityFramework\mem0.NET.EntityFramework.csproj", "{7DC30AE7-0C55-4CFF-9C30-33B12296B4CE}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,18 +31,10 @@ Global {F6D8FF6D-7376-479B-B673-DCC0BE715336}.Debug|Any CPU.Build.0 = Debug|Any CPU {F6D8FF6D-7376-479B-B673-DCC0BE715336}.Release|Any CPU.ActiveCfg = Release|Any CPU {F6D8FF6D-7376-479B-B673-DCC0BE715336}.Release|Any CPU.Build.0 = Release|Any CPU - {89EA032E-1A1B-4B19-9121-7258C818FD00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89EA032E-1A1B-4B19-9121-7258C818FD00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89EA032E-1A1B-4B19-9121-7258C818FD00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89EA032E-1A1B-4B19-9121-7258C818FD00}.Release|Any CPU.Build.0 = Release|Any CPU {4755664B-6109-441B-97D6-1EE3117533EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4755664B-6109-441B-97D6-1EE3117533EF}.Debug|Any CPU.Build.0 = Debug|Any CPU {4755664B-6109-441B-97D6-1EE3117533EF}.Release|Any CPU.ActiveCfg = Release|Any CPU {4755664B-6109-441B-97D6-1EE3117533EF}.Release|Any CPU.Build.0 = Release|Any CPU - {7DC30AE7-0C55-4CFF-9C30-33B12296B4CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7DC30AE7-0C55-4CFF-9C30-33B12296B4CE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7DC30AE7-0C55-4CFF-9C30-33B12296B4CE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7DC30AE7-0C55-4CFF-9C30-33B12296B4CE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -54,8 +42,6 @@ Global GlobalSection(NestedProjects) = preSolution {E33A18E4-609D-4565-89B3-03F83D8810D3} = {D2C48892-B1D7-4C7E-B82E-B059CAD9B95F} {F6D8FF6D-7376-479B-B673-DCC0BE715336} = {D2C48892-B1D7-4C7E-B82E-B059CAD9B95F} - {89EA032E-1A1B-4B19-9121-7258C818FD00} = {D2C48892-B1D7-4C7E-B82E-B059CAD9B95F} {4755664B-6109-441B-97D6-1EE3117533EF} = {D2C48892-B1D7-4C7E-B82E-B059CAD9B95F} - {7DC30AE7-0C55-4CFF-9C30-33B12296B4CE} = {D2C48892-B1D7-4C7E-B82E-B059CAD9B95F} EndGlobalSection EndGlobal diff --git a/src/mem0.Core/mem0.Core.csproj b/src/mem0.Core/mem0.Core.csproj deleted file mode 100644 index 70450b2..0000000 --- a/src/mem0.Core/mem0.Core.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net8.0 - enable - enable - true - - - - - - diff --git a/src/mem0.NET.EntityFramework/ServiceCollectionExtensions.cs b/src/mem0.NET.EntityFramework/ServiceCollectionExtensions.cs deleted file mode 100644 index d20abd4..0000000 --- a/src/mem0.NET.EntityFramework/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using mem0.Core; -using mem0.Core.VectorStores; -using mem0.NET.EntityFramework.Services; -using mem0.NET.Service.DataAccess; -using Microsoft.EntityFrameworkCore; - -namespace Microsoft.Extensions.DependencyInjection; - -public static class ServiceCollectionExtensions -{ - public static IServiceCollection AddMem0DotNetEntityFramework(this IServiceCollection services, - Action? optionsAction = null) - { - services.AddDbContext(optionsAction); - - services.AddScoped(); - - return services; - } -} \ No newline at end of file diff --git a/src/mem0.NET.EntityFramework/mem0.NET.EntityFramework.csproj b/src/mem0.NET.EntityFramework/mem0.NET.EntityFramework.csproj deleted file mode 100644 index 82e7949..0000000 --- a/src/mem0.NET.EntityFramework/mem0.NET.EntityFramework.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net8.0 - enable - enable - true - - - - - - - - - - - - diff --git a/src/mem0.NET.Qdrant/ServiceCollectionExtensions.cs b/src/mem0.NET.Qdrant/ServiceCollectionExtensions.cs index 83d98ae..bb2f199 100644 --- a/src/mem0.NET.Qdrant/ServiceCollectionExtensions.cs +++ b/src/mem0.NET.Qdrant/ServiceCollectionExtensions.cs @@ -11,14 +11,11 @@ public static class ServiceCollectionExtensions /// 注册Vector Qdrant实现 /// /// - /// + /// /// public static Mem0Builder AddVectorQdrant(this Mem0Builder services, - Action qdrantOptions) + QdrantOptions options) { - var options = new QdrantOptions(); - qdrantOptions.Invoke(options); - services.Services.AddSingleton(_ => { var client = new QdrantClient(options.Host, options.Port, options.Https, options.ApiKey, @@ -27,7 +24,7 @@ public static Mem0Builder AddVectorQdrant(this Mem0Builder services, return client; }); - services.Services.AddScoped(); + services.Services.AddSingleton(); return services; } diff --git a/src/mem0.NET.Qdrant/Services/QdrantVectorStoresService.cs b/src/mem0.NET.Qdrant/Services/QdrantVectorStoresService.cs index a12aa0f..a3aed00 100644 --- a/src/mem0.NET.Qdrant/Services/QdrantVectorStoresService.cs +++ b/src/mem0.NET.Qdrant/Services/QdrantVectorStoresService.cs @@ -114,6 +114,7 @@ public async Task> Search(string name, float[] query, ulong limi var filter = CreateFilter(filters); var hits = await client.SearchAsync(name, query.ToArray(), filter, limit: limit); + return hits.Select(hit => new SearchHit { Id = hit.Id, diff --git a/src/mem0.NET.Qdrant/mem0.NET.Qdrant.csproj b/src/mem0.NET.Qdrant/mem0.NET.Qdrant.csproj index 3f0d322..641039e 100644 --- a/src/mem0.NET.Qdrant/mem0.NET.Qdrant.csproj +++ b/src/mem0.NET.Qdrant/mem0.NET.Qdrant.csproj @@ -14,11 +14,7 @@ - - - - - + diff --git a/src/mem0.NET.Service/Program.cs b/src/mem0.NET.Service/Program.cs index 94dc0ab..c8e6273 100644 --- a/src/mem0.NET.Service/Program.cs +++ b/src/mem0.NET.Service/Program.cs @@ -1,6 +1,8 @@ +using mem0.NET.Options; using mem0.NET.Service.DataAccess; using mem0.NET.Service.Services; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection.Options; namespace mem0.NET.Service; @@ -10,28 +12,23 @@ public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - builder.Services.AddMem0DotNetEntityFramework(options => - { - options.UseNpgsql(builder.Configuration.GetConnectionString("Default")); - }); - builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - builder.Services.AddMem0DotNet(options => - { - options.OpenAIEndpoint = "https://api.token-ai.cn"; - options.OpenAIKey = "请在 https://api.token-ai.cn 注册获取"; - options.OpenAIChatCompletionModel = "gpt-4o-mini"; - options.OpenAITextEmbeddingModel = "text-embedding-ada-002"; - options.CollectionName = "mem0.NET"; - }).AddVectorQdrant(options => - { - options.Host = "localhost"; - options.Port = 6334; - options.Https = false; - options.ApiKey = "dd666666"; - }); + builder.Services.AddOptions() + .Bind(builder.Configuration.GetSection("Mem0")); + + builder.Services.AddOptions() + .Bind(builder.Configuration.GetSection("Qdrant")); + + var options = builder.Configuration.GetSection("Mem0") + .Get(); + var qdrantOptions = builder.Configuration.GetSection("Qdrant") + .Get(); + + builder.Services.AddMem0DotNet(options, + optionsBuilder => { optionsBuilder.UseNpgsql(builder.Configuration.GetConnectionString("Default")); }) + .AddVectorQdrant(qdrantOptions); var app = builder.Build(); diff --git a/src/mem0.NET.Service/Services/MemoryService.cs b/src/mem0.NET.Service/Services/MemoryService.cs index 425ccda..9f81607 100644 --- a/src/mem0.NET.Service/Services/MemoryService.cs +++ b/src/mem0.NET.Service/Services/MemoryService.cs @@ -3,9 +3,6 @@ using mem0.NET.Functions; using mem0.NET.Options; using mem0.NET.Services; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.ChatCompletion; -using Microsoft.SemanticKernel.Embeddings; #pragma warning disable SKEXP0001 @@ -21,76 +18,67 @@ public static WebApplication MapMemoryService(this WebApplication app) .WithDisplayName("Memory"); memoryService.MapPost("/memory", async (MemoryService memoryService, - CreateMemoryInput input, - Mem0DotNetOptions mem0DotNetOptions) => + CreateMemoryInput input) => { - await memoryService.CreateMemoryAsync(input, - mem0DotNetOptions); + await memoryService.CreateMemoryAsync(input); }).WithDescription("创建记忆").WithDisplayName("创建记忆").WithTags("记忆").WithName("CreateMemory"); memoryService.MapPost("memory_tool", async (MemoryService memoryService, - CreateMemoryToolInput input, - Mem0DotNetOptions mem0DotNetOptions) => + CreateMemoryToolInput input) => { - await memoryService.CreateMemoryToolAsync(input, - mem0DotNetOptions); + await memoryService.CreateMemoryToolAsync(input); }).WithDescription("创建记忆工具").WithDisplayName("创建记忆工具").WithTags("记忆"); memoryService.MapGet("history/{memoryId}", async (MemoryService memoryService, string memoryId) => await memoryService.GetHistory(memoryId)) .WithDescription("获取历史").WithDisplayName("获取历史").WithTags("记忆"); - memoryService.MapGet("memory/{memoryId}", async (MemoryService memoryService, string memoryId, - Mem0DotNetOptions options) => - await memoryService.GetMemory(memoryId, options)) + memoryService.MapGet("memory/{memoryId}", async (MemoryService memoryService, string memoryId) => + await memoryService.GetMemory(memoryId)) .WithDescription("获取记忆") .WithDisplayName("获取记忆") .WithTags("记忆"); memoryService.MapGet("memory", async (MemoryService memoryService, - Mem0DotNetOptions options, string? userId, string? agentId, string? runId, uint limit) => - await memoryService.GetMemoryAll(options, userId, agentId, runId, limit)) + await memoryService.GetMemoryAll(userId, agentId, runId, limit)) .WithDescription("获取所有记忆") .WithDisplayName("获取所有记忆") .WithTags("记忆"); memoryService.MapGet("search", async (MemoryService memoryService, - Mem0DotNetOptions options, string query, string? userId, string? agentId, string? runId, uint limit) => - await memoryService.SearchMemory(options, query, + await memoryService.SearchMemory(query, userId, agentId, runId, limit)) .WithDescription("搜索记忆") .WithDisplayName("搜索记忆") .WithTags("记忆"); - memoryService.MapPut("memory", async (MemoryService memoryService, UpdateMemoryInput input, - MemoryTool memoryTool) => await memoryService.Update(input, memoryTool)) + memoryService.MapPut("memory", + async (MemoryService memoryService, UpdateMemoryInput input) => await memoryService.Update(input)) .WithDescription("更新记忆") .WithDisplayName("更新记忆") .WithTags("记忆"); - memoryService.MapDelete("memory/{memoryId}", async (MemoryService memoryService, string memoryId, - MemoryTool memoryTool) => await memoryService.Delete(memoryId, memoryTool)) + memoryService.MapDelete("memory/{memoryId}", + async (MemoryService memoryService, string memoryId) => await memoryService.Delete(memoryId)) .WithDescription("删除记忆") .WithDisplayName("删除记忆") .WithTags("记忆"); memoryService.MapDelete("memory", async (MemoryService memoryService, string? userId, - string? agentId, string? runId, - Mem0DotNetOptions options, MemoryTool memoryTool) => - await memoryService.DeleteAll(userId, agentId, runId, options, memoryTool)) + string? agentId, string? runId) => + await memoryService.DeleteAll(userId, agentId, runId)) .WithDescription("删除所有记忆") .WithDisplayName("删除所有记忆") .WithTags("记忆"); - memoryService.MapDelete("reset", async (MemoryService memoryService, IVectorStoreService vectorStoreService, - Mem0DotNetOptions mem0DotNetOptions, IHistoryService historyService) => - await memoryService.Reset(vectorStoreService, mem0DotNetOptions, historyService)) + memoryService.MapDelete("reset", async (MemoryService memoryService) => + await memoryService.Reset()) .WithDescription("重置记忆") .WithDisplayName("重置记忆") .WithTags("记忆"); diff --git a/src/mem0.NET.Service/appsettings.json b/src/mem0.NET.Service/appsettings.json index 45bf372..b663d18 100644 --- a/src/mem0.NET.Service/appsettings.json +++ b/src/mem0.NET.Service/appsettings.json @@ -8,5 +8,18 @@ "AllowedHosts": "*", "ConnectionStrings": { "Default": "Host=localhost;Port=5432;Database=mem0;Username=token;Password=dd666666" + }, + "Mem0": { + "OpenAIEndpoint": "https://api.token-ai.cn", + "OpenAIKey": "", + "OpenAIChatCompletionModel": "gpt-4o-mini", + "OpenAITextEmbeddingModel": "text-embedding-ada-002", + "CollectionName": "mem0" + }, + "Qdrant": { + "Host": "127.0.0.1", + "Port": 6334, + "Https": false, + "ApiKey": "dd666666" } } diff --git a/src/mem0.NET.Service/mem0.NET.Service.csproj b/src/mem0.NET.Service/mem0.NET.Service.csproj index 2c66c5a..23ce3f5 100644 --- a/src/mem0.NET.Service/mem0.NET.Service.csproj +++ b/src/mem0.NET.Service/mem0.NET.Service.csproj @@ -8,8 +8,6 @@ - - diff --git a/src/mem0.Core/Mem0Context.cs b/src/mem0.NET/ApplicationContext.cs similarity index 86% rename from src/mem0.Core/Mem0Context.cs rename to src/mem0.NET/ApplicationContext.cs index 0a67615..b0a9ccd 100644 --- a/src/mem0.Core/Mem0Context.cs +++ b/src/mem0.NET/ApplicationContext.cs @@ -1,6 +1,6 @@ namespace mem0.Core; -public class Mem0Context +public class ApplicationContext { /// /// 用于存储当前上下文的对象 diff --git a/src/mem0.NET.EntityFramework/DataAccess/Mem0DbContext.cs b/src/mem0.NET/DataAccess/Mem0DbContext.cs similarity index 100% rename from src/mem0.NET.EntityFramework/DataAccess/Mem0DbContext.cs rename to src/mem0.NET/DataAccess/Mem0DbContext.cs diff --git a/src/mem0.Core/Distance.cs b/src/mem0.NET/Distance.cs similarity index 100% rename from src/mem0.Core/Distance.cs rename to src/mem0.NET/Distance.cs diff --git a/src/mem0.Core/Dto/CreateMemoryInput.cs b/src/mem0.NET/Dto/CreateMemoryInput.cs similarity index 100% rename from src/mem0.Core/Dto/CreateMemoryInput.cs rename to src/mem0.NET/Dto/CreateMemoryInput.cs diff --git a/src/mem0.Core/Dto/CreateMemoryToolInput.cs b/src/mem0.NET/Dto/CreateMemoryToolInput.cs similarity index 100% rename from src/mem0.Core/Dto/CreateMemoryToolInput.cs rename to src/mem0.NET/Dto/CreateMemoryToolInput.cs diff --git a/src/mem0.Core/Dto/UpdateMemoryInput.cs b/src/mem0.NET/Dto/UpdateMemoryInput.cs similarity index 100% rename from src/mem0.Core/Dto/UpdateMemoryInput.cs rename to src/mem0.NET/Dto/UpdateMemoryInput.cs diff --git a/src/mem0.NET/Functions/MemoryTool.cs b/src/mem0.NET/Functions/MemoryTool.cs index 62a296b..b9c04f7 100644 --- a/src/mem0.NET/Functions/MemoryTool.cs +++ b/src/mem0.NET/Functions/MemoryTool.cs @@ -1,49 +1,19 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; -using mem0.Core; -using mem0.Core.VectorStores; -using mem0.NET.Options; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; +using mem0.NET.Services; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Embeddings; #pragma warning disable SKEXP0001 namespace mem0.NET.Functions; -public class MemoryTool( - IServiceProvider serviceProvider, - ILogger logger) +public sealed class MemoryTool( + MemoryToolService memoryToolService) { [KernelFunction, Description("add a memory")] public async Task AddMemory([Required] [Description("Data to add to memory")] string data) { - var currentValue = Mem0Context.Current.Value; - - await using var scope = serviceProvider.CreateAsyncScope(); - var options = scope.ServiceProvider.GetRequiredService(); - var vectorStoreService = scope.ServiceProvider.GetService(); - var historyService = scope.ServiceProvider.GetService(); - var textEmbeddingGenerationService = scope.ServiceProvider.GetService(); - var embeddings = await textEmbeddingGenerationService.GenerateEmbeddingAsync(data); - var memoryId = Guid.NewGuid().ToString(); - var metadata = new Dictionary - { - { "data", data }, - { "created_at", DateTime.Now }, - { "user_id", currentValue["userId"] }, - { "run_id", currentValue["runId"] } - }; - await vectorStoreService.Insert(options.CollectionName, - [[..embeddings.ToArray()]], - [metadata], [memoryId]); - - await historyService.AddHistory(memoryId, string.Empty, data, "add"); - - logger.LogInformation("添加缓存" + data + " memoryId:" + memoryId); - - await Task.CompletedTask; + await memoryToolService.AddMemory(data); } [KernelFunction, Description("Update memory provided Id and data")] @@ -51,49 +21,13 @@ public async Task UpdateMemory([Required] [Description("memoryid of the memory t [Required] [Description("Updated data for the memory")] string data) { - await using var scope = serviceProvider.CreateAsyncScope(); - var options = scope.ServiceProvider.GetRequiredService(); - var vectorStoreService = scope.ServiceProvider.GetService(); - var historyService = scope.ServiceProvider.GetService(); - var existingMemory = await vectorStoreService.Get(options.CollectionName, memoryId); - - var prevValue = existingMemory.MetaData["data"]; - var newMetadata = new Dictionary - { - { "data", prevValue }, - { "updated_at", DateTime.Now }, - }; - - foreach (var o in existingMemory.MetaData) - { - if (o.Key != "data") - newMetadata.Add(o.Key, o.Value); - } - - await vectorStoreService.Update(options.CollectionName, memoryId, - [..existingMemory.Vector.ToArray()], newMetadata); - - await historyService.AddHistory(memoryId, prevValue.ToString(), data, "update"); - - logger.LogInformation("更新缓存 memoryId:" + memoryId + " data:" + data); + await memoryToolService.UpdateMemory(memoryId, data); } [KernelFunction, Description("Delete memory by memory_id")] public async Task DeleteMemory([Required] [Description("memoryid of the memory to update")] string memoryId) { - await using var scope = serviceProvider.CreateAsyncScope(); - var options = scope.ServiceProvider.GetRequiredService(); - var vectorStoreService = scope.ServiceProvider.GetService(); - var historyService = scope.ServiceProvider.GetService(); - var existingMemory = await vectorStoreService.Get(options.CollectionName, memoryId); - - var prevValue = existingMemory.MetaData["data"]; - - await vectorStoreService.Delete(options.CollectionName, memoryId); - - logger.LogInformation("删除缓存 memoryId:" + memoryId); - - await historyService.AddHistory(memoryId, prevValue.ToString(), string.Empty, "delete", true); + await memoryToolService.DeleteMemory(memoryId); } } \ No newline at end of file diff --git a/src/mem0.Core/Mem0Builder.cs b/src/mem0.NET/Mem0Builder.cs similarity index 100% rename from src/mem0.Core/Mem0Builder.cs rename to src/mem0.NET/Mem0Builder.cs diff --git a/src/mem0.Core/Model/History.cs b/src/mem0.NET/Model/History.cs similarity index 100% rename from src/mem0.Core/Model/History.cs rename to src/mem0.NET/Model/History.cs diff --git a/src/mem0.Core/Model/SearchHit.cs b/src/mem0.NET/Model/SearchHit.cs similarity index 100% rename from src/mem0.Core/Model/SearchHit.cs rename to src/mem0.NET/Model/SearchHit.cs diff --git a/src/mem0.Core/Model/VectorData.cs b/src/mem0.NET/Model/VectorData.cs similarity index 75% rename from src/mem0.Core/Model/VectorData.cs rename to src/mem0.NET/Model/VectorData.cs index 685f00b..37c20ce 100644 --- a/src/mem0.Core/Model/VectorData.cs +++ b/src/mem0.NET/Model/VectorData.cs @@ -1,4 +1,7 @@ -namespace mem0.Core.Model; +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace mem0.Core.Model; public class VectorData { @@ -7,9 +10,8 @@ public class VectorData public float Score { get; set; } // 向量 public IReadOnlyList Vector { get; set; } - - public Dictionary MetaData { get; set; } // 有效载荷 + public Dictionary MetaData { get; set; } // 有效载荷 public string? Text { @@ -23,4 +25,9 @@ public string? Text return string.Empty; } } // 文本 +} + +public class VectorDataPayload +{ + public string stringValue { get; set; } } \ No newline at end of file diff --git a/src/mem0.Core/Model/VectorInfo.cs b/src/mem0.NET/Model/VectorInfo.cs similarity index 100% rename from src/mem0.Core/Model/VectorInfo.cs rename to src/mem0.NET/Model/VectorInfo.cs diff --git a/src/mem0.NET/Options/Mem0DotNetOptions.cs b/src/mem0.NET/Options/Mem0Options.cs similarity index 89% rename from src/mem0.NET/Options/Mem0DotNetOptions.cs rename to src/mem0.NET/Options/Mem0Options.cs index a6760e4..22d48f6 100644 --- a/src/mem0.NET/Options/Mem0DotNetOptions.cs +++ b/src/mem0.NET/Options/Mem0Options.cs @@ -1,6 +1,9 @@ namespace mem0.NET.Options; -public class Mem0DotNetOptions +/// +/// mem0 配置 +/// +public class Mem0Options { /// /// OpenAI Endpoint https://api.token-ai.cn diff --git a/src/mem0.NET/ServiceCollectionExtensions.cs b/src/mem0.NET/ServiceCollectionExtensions.cs index da32cad..13eb4d6 100644 --- a/src/mem0.NET/ServiceCollectionExtensions.cs +++ b/src/mem0.NET/ServiceCollectionExtensions.cs @@ -1,37 +1,41 @@ using mem0.Core; +using mem0.Core.VectorStores; using mem0.NET; +using mem0.NET.EntityFramework.Services; using mem0.NET.Functions; using mem0.NET.Options; +using mem0.NET.Service.DataAccess; using mem0.NET.Services; +using Microsoft.EntityFrameworkCore; using Microsoft.SemanticKernel; +#pragma warning disable SKEXP0010 + namespace Microsoft.Extensions.DependencyInjection; public static class ServiceCollectionExtensions { - public static Mem0Builder AddMem0DotNet(this IServiceCollection services, - Action mem0DotNetOptions) + public static Mem0Builder AddMem0DotNet(this IServiceCollection services, Mem0Options value, + Action optionsAction) { - var options = new Mem0DotNetOptions(); - mem0DotNetOptions(options); - - services.AddScoped(); - - services.AddScoped((_) => options); - var openAiHttpClientHandler = new OpenAIHttpClientHandler(options.OpenAIEndpoint); + services.AddSingleton(); + services.AddSingleton(); - var openAiHttpClient = new HttpClient(openAiHttpClientHandler); + var openAiHttpClient = new HttpClient(new OpenAIHttpClientHandler(value.OpenAIEndpoint)); -#pragma warning disable SKEXP0010 var kernelBuilder = services.AddKernel() - .AddOpenAIChatCompletion(options.OpenAIChatCompletionModel, options.OpenAIKey, + .AddOpenAIChatCompletion(value.OpenAIChatCompletionModel, value.OpenAIKey, httpClient: openAiHttpClient) - .AddOpenAITextEmbeddingGeneration(options.OpenAITextEmbeddingModel, options.OpenAIKey, + .AddOpenAITextEmbeddingGeneration(value.OpenAITextEmbeddingModel, value.OpenAIKey, httpClient: openAiHttpClient); + kernelBuilder.Services.AddSingleton(); + kernelBuilder.Plugins.AddFromType(); -#pragma warning restore SKEXP0010 + services.AddDbContext(optionsAction); + + services.AddSingleton(); return new Mem0Builder(services); } diff --git a/src/mem0.NET.EntityFramework/Services/HistoryService.cs b/src/mem0.NET/Services/HistoryService.cs similarity index 52% rename from src/mem0.NET.EntityFramework/Services/HistoryService.cs rename to src/mem0.NET/Services/HistoryService.cs index 818ef9d..c6e042e 100644 --- a/src/mem0.NET.EntityFramework/Services/HistoryService.cs +++ b/src/mem0.NET/Services/HistoryService.cs @@ -2,14 +2,37 @@ using mem0.Core.VectorStores; using mem0.NET.Service.DataAccess; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace mem0.NET.EntityFramework.Services; -public sealed class HistoryService(Mem0DbContext dbContext) : IHistoryService +public sealed class HistoryService(IServiceProvider serviceProvider) : IHistoryService { + AsyncLocal<(IServiceScope, Mem0DbContext)?> dbContext = new((args => + { + if (args.PreviousValue != null) + { + args.PreviousValue.Value.Item2.Dispose(); + args.PreviousValue.Value.Item1.Dispose(); + } + })); + + public Mem0DbContext GetDbContext() + { + if (dbContext.Value == null) + { + var scope = serviceProvider.CreateScope(); + dbContext.Value = (scope, scope.ServiceProvider.GetRequiredService()); + } + + return dbContext.Value.Value.Item2; + } + public async Task AddHistory(string memoryId, string prevValue, string newValue, string @event, bool isDeleted = false) { + var dbContext = GetDbContext(); + await dbContext.Histories.AddAsync(new History { MemoryId = memoryId, @@ -23,6 +46,8 @@ await dbContext.Histories.AddAsync(new History public async Task> GetHistories(string memoryId) { + var dbContext = GetDbContext(); + var histories = await dbContext.Histories.Where(h => h.MemoryId == memoryId).ToListAsync(); return histories; @@ -30,6 +55,7 @@ public async Task> GetHistories(string memoryId) public async Task ResetHistory() { + var dbContext = GetDbContext(); await dbContext.Histories .ExecuteDeleteAsync(); } diff --git a/src/mem0.NET/Services/IMemoryService.cs b/src/mem0.NET/Services/IMemoryService.cs deleted file mode 100644 index 3618c6f..0000000 --- a/src/mem0.NET/Services/IMemoryService.cs +++ /dev/null @@ -1,50 +0,0 @@ -using mem0.Core; -using mem0.Core.Model; -using mem0.Core.VectorStores; -using mem0.NET.Functions; -using mem0.NET.Options; -using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.ChatCompletion; -using Microsoft.SemanticKernel.Embeddings; - -#pragma warning disable SKEXP0001 - -namespace mem0.NET.Services; - -public interface IMemoryService -{ - Task CreateMemoryAsync(CreateMemoryInput input, - ITextEmbeddingGenerationService textEmbeddingGenerationService, - IChatCompletionService chatCompletionService, - Kernel kernel, - Mem0DotNetOptions mem0DotNetOptions); - - Task CreateMemoryToolAsync(CreateMemoryToolInput input, - ITextEmbeddingGenerationService textEmbeddingGenerationService, - IChatCompletionService chatCompletionService, - Mem0DotNetOptions mem0DotNetOptions); - - Task GetMemory(string memoryId, - Mem0DotNetOptions options); - - Task> GetMemoryAll(Mem0DotNetOptions options, - string? userId, - string? agentId, string? runId, uint limit = 100); - - Task> SearchMemory(Mem0DotNetOptions options, - ITextEmbeddingGenerationService textEmbeddingGenerationService, - IChatCompletionService chatCompletionService, - string query, string? userId, - string? agentId, string? runId, uint limit = 100); - - Task Update(UpdateMemoryInput input, MemoryTool memoryTool); - - Task Delete(string memoryId, MemoryTool memoryTool); - - Task DeleteAll(string? userId, string? agentId, string? runId, - Mem0DotNetOptions options, MemoryTool memoryTool); - - Task> GetHistory(string memoryId, IHistoryService historyService); - - Task Reset(Mem0DotNetOptions mem0DotNetOptions); -} \ No newline at end of file diff --git a/src/mem0.NET/Services/MemoryService.cs b/src/mem0.NET/Services/MemoryService.cs index 9056cfe..8c08896 100644 --- a/src/mem0.NET/Services/MemoryService.cs +++ b/src/mem0.NET/Services/MemoryService.cs @@ -5,6 +5,7 @@ using mem0.Core.VectorStores; using mem0.NET.Functions; using mem0.NET.Options; +using Microsoft.Extensions.Options; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.OpenAI; @@ -21,20 +22,25 @@ namespace mem0.NET.Services; /// public class MemoryService( IVectorStoreService vectorStoreService, - IHistoryService historyService) : IMemoryService + MemoryToolService memoryToolService, + ITextEmbeddingGenerationService textEmbeddingGenerationService, + IChatCompletionService chatCompletionService, + IOptions options, + Kernel kernel, + IHistoryService historyService) { private const string MemoryDeductionPrompt = """ - Output in the original language of the content Deduce the facts, preferences, and memories from the provided text. Just return the facts, preferences, and memories in bullet points: Natural language text: {user_input} User/Agent details: {metadata} - + Constraint for deducing facts, preferences, and memories: - The facts, preferences, and memories should be concise and informative. - Don't start by "The person likes Pizza". Instead, start with "Likes Pizza". - Don't remember the user/agent details provided. Only remember the facts, preferences, and memories. - + - Output content in the original language + Deduced facts, preferences, and memories: """; @@ -61,15 +67,7 @@ Output in the original language of the content /// 创建记忆 /// /// - /// - /// - /// - /// - public async Task CreateMemoryAsync(CreateMemoryInput input, - ITextEmbeddingGenerationService textEmbeddingGenerationService, - IChatCompletionService chatCompletionService, - Kernel kernel, - Mem0DotNetOptions mem0DotNetOptions) + public async Task CreateMemoryAsync(CreateMemoryInput input) { var embeddings = await textEmbeddingGenerationService.GenerateEmbeddingAsync(input.Data); @@ -100,14 +98,14 @@ public async Task CreateMemoryAsync(CreateMemoryInput input, var extracted_memories = await chatCompletionService.GetChatMessageContentAsync(new ChatHistory() { new(AuthorRole.System, - "你是一个从非结构化文本中推断事实、偏好和记忆的专家。"), + "You are an expert at deducing facts, preferences and memories from unstructured text."), new(AuthorRole.User, input.Prompt) }); - await vectorStoreService.CreateCol(mem0DotNetOptions.CollectionName, 1536); + await vectorStoreService.CreateCol(options.Value.CollectionName, 1536); var existing_memories = ( - await vectorStoreService.Search(mem0DotNetOptions.CollectionName, embeddings.ToArray(), 5, filters)) + await vectorStoreService.Search(options.Value.CollectionName, embeddings.ToArray(), 5, filters)) .Select(x => new { id = x.Id, @@ -132,7 +130,6 @@ await vectorStoreService.Search(mem0DotNetOptions.CollectionName, embeddings.ToA { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions, }, kernel); - } private List get_update_memory_messages(object serializedExistingMemories, @@ -155,11 +152,7 @@ private List get_update_memory_messages(object serializedExi /// 创建记忆工具 /// /// - /// - public async Task CreateMemoryToolAsync(CreateMemoryToolInput input, - ITextEmbeddingGenerationService textEmbeddingGenerationService, - IChatCompletionService chatCompletionService, - Mem0DotNetOptions mem0DotNetOptions) + public async Task CreateMemoryToolAsync(CreateMemoryToolInput input) { var embeddings = await textEmbeddingGenerationService.GenerateEmbeddingAsync(input.Data); @@ -167,7 +160,7 @@ public async Task CreateMemoryToolAsync(CreateMemoryToolInput input, input.MetaData.Add("data", input.Data); input.MetaData.Add("created_at", DateTime.Now); - await vectorStoreService.Insert(mem0DotNetOptions.CollectionName, [[..embeddings.ToArray()]], + await vectorStoreService.Insert(options.Value.CollectionName, [[..embeddings.ToArray()]], [input.MetaData], [memoryId]); } @@ -176,12 +169,10 @@ await vectorStoreService.Insert(mem0DotNetOptions.CollectionName, [[..embeddings /// 获取缓存 /// /// - /// /// - public async Task GetMemory(string memoryId, - Mem0DotNetOptions options) + public async Task GetMemory(string memoryId) { - var memory = await vectorStoreService.Get(options.CollectionName, memoryId); + var memory = await vectorStoreService.Get(options.Value.CollectionName, memoryId); if (memory == null) { @@ -194,14 +185,12 @@ public async Task GetMemory(string memoryId, /// /// 获取所有记忆 /// - /// /// /// /// /// /// - public async Task> GetMemoryAll(Mem0DotNetOptions options, - string? userId, + public async Task> GetMemoryAll(string? userId, string? agentId, string? runId, uint limit = 100) { var filters = new Dictionary(); @@ -220,7 +209,7 @@ public async Task> GetMemoryAll(Mem0DotNetOptions options, filters.Add("run_id", runId); } - var memories = await vectorStoreService.List(options.CollectionName, filters, limit); + var memories = await vectorStoreService.List(options.Value.CollectionName, filters, limit); return memories; } @@ -228,17 +217,13 @@ public async Task> GetMemoryAll(Mem0DotNetOptions options, /// /// 搜索记忆 /// - /// /// /// /// /// /// /// - public async Task> SearchMemory(Mem0DotNetOptions options, - ITextEmbeddingGenerationService textEmbeddingGenerationService, - IChatCompletionService chatCompletionService, - string query, string? userId, + public async Task> SearchMemory(string query, string? userId, string? agentId, string? runId, uint limit = 100) { var embeddings = await textEmbeddingGenerationService.GenerateEmbeddingAsync(query); @@ -259,7 +244,20 @@ public async Task> SearchMemory(Mem0DotNetOptions options, filters.Add("run_id", runId); } - var memories = await vectorStoreService.Search(options.CollectionName, embeddings.ToArray(), limit, filters); + var memories = + await vectorStoreService.Search(options.Value.CollectionName, embeddings.ToArray(), limit, filters); + + memories.ForEach(x => + { + foreach (var o in x.Payload) + { + var str = o.Value.ToString(); + if (!string.IsNullOrEmpty(str)) + { + x.Payload[o.Key] = JsonSerializer.Deserialize(str).stringValue; + } + } + }); return memories.Select(x => new VectorData() { @@ -273,20 +271,18 @@ public async Task> SearchMemory(Mem0DotNetOptions options, /// 更新记忆 /// /// - /// - public async Task Update(UpdateMemoryInput input, MemoryTool memoryTool) + public async Task Update(UpdateMemoryInput input) { - await memoryTool.UpdateMemory(input.MemoryId, input.Data); + await memoryToolService.UpdateMemory(input.MemoryId, input.Data); } /// /// 删除指定记忆 /// /// - /// - public async Task Delete(string memoryId, MemoryTool memoryTool) + public async Task Delete(string memoryId) { - await memoryTool.DeleteMemory(memoryId); + await memoryToolService.DeleteMemory(memoryId); } /// @@ -295,11 +291,8 @@ public async Task Delete(string memoryId, MemoryTool memoryTool) /// /// /// - /// - /// /// - public async Task DeleteAll(string? userId, string? agentId, string? runId, - Mem0DotNetOptions options, MemoryTool memoryTool) + public async Task DeleteAll(string? userId, string? agentId, string? runId) { var filters = new Dictionary(); if (!string.IsNullOrEmpty(userId)) @@ -323,11 +316,11 @@ public async Task DeleteAll(string? userId, string? agentId, string? runId, "At least one filter is required to delete all memories. If you want to delete all memories, use the `reset()` method."); } - var memories = await vectorStoreService.List(options.CollectionName, filters); + var memories = await vectorStoreService.List(options.Value.CollectionName, filters); foreach (var memory in memories) { - await memoryTool.DeleteMemory(memory.Id.ToString()); + await memoryToolService.DeleteMemory(memory.Id.ToString()); } } @@ -336,7 +329,7 @@ public async Task DeleteAll(string? userId, string? agentId, string? runId, /// /// /// - public async Task> GetHistory(string memoryId, IHistoryService historyService) + public async Task> GetHistory(string memoryId) { var histories = await historyService.GetHistories(memoryId); @@ -346,10 +339,9 @@ public async Task> GetHistory(string memoryId, IHistoryService his /// /// 重置记忆 /// - /// - public async Task Reset(Mem0DotNetOptions mem0DotNetOptions) + public async Task Reset() { - await vectorStoreService.DeleteCol(mem0DotNetOptions.CollectionName); + await vectorStoreService.DeleteCol(options.Value.CollectionName); await historyService.ResetHistory(); } diff --git a/src/mem0.Core/VectorInfoStatus.cs b/src/mem0.NET/VectorInfoStatus.cs similarity index 100% rename from src/mem0.Core/VectorInfoStatus.cs rename to src/mem0.NET/VectorInfoStatus.cs diff --git a/src/mem0.Core/VectorStores/IHistoryService.cs b/src/mem0.NET/VectorStores/IHistoryService.cs similarity index 100% rename from src/mem0.Core/VectorStores/IHistoryService.cs rename to src/mem0.NET/VectorStores/IHistoryService.cs diff --git a/src/mem0.Core/VectorStores/IVectorStoreService.cs b/src/mem0.NET/VectorStores/IVectorStoreService.cs similarity index 100% rename from src/mem0.Core/VectorStores/IVectorStoreService.cs rename to src/mem0.NET/VectorStores/IVectorStoreService.cs diff --git a/src/mem0.NET/mem0.NET.csproj b/src/mem0.NET/mem0.NET.csproj index 4e2ea86..2dd7125 100644 --- a/src/mem0.NET/mem0.NET.csproj +++ b/src/mem0.NET/mem0.NET.csproj @@ -8,12 +8,10 @@ + + - - - -