From af484579f5b0927b45465bf826ec54c832fda81e Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sat, 28 Sep 2024 20:00:35 -0500 Subject: [PATCH] Support more data type in Qdrant payload. --- .../VectorStorage/IVectorDb.cs | 2 +- .../Models/VectorCollectionData.cs | 2 +- .../VectorStorage/Models/VectorCreateModel.cs | 2 +- .../VectorKnowledgeCreateRequest.cs | 2 +- .../Knowledges/VectorKnowledgeViewModel.cs | 2 +- .../Functions/MemorizeKnowledgeFn.cs | 2 +- .../MemVecDb/MemoryVectorDb.cs | 4 +- .../Services/KnowledgeService.Document.cs | 2 +- .../Services/KnowledgeService.Vector.cs | 2 +- .../Functions/PrimaryStagePlanFn.cs | 11 ++-- .../BotSharp.Plugin.Qdrant.csproj | 2 +- .../BotSharp.Plugin.Qdrant/QdrantDb.cs | 63 +++++++++++++++++-- .../Services/DbKnowledgeService.cs | 2 +- 13 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs index ae0828de..66f7727a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs +++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs @@ -12,7 +12,7 @@ public interface IVectorDb Task> GetCollectionData(string collectionName, IEnumerable ids, bool withPayload = false, bool withVector = false); Task CreateCollection(string collectionName, int dimension); Task DeleteCollection(string collectionName); - Task Upsert(string collectionName, Guid id, float[] vector, string text, Dictionary? payload = null); + Task Upsert(string collectionName, Guid id, float[] vector, string text, Dictionary? payload = null); Task> Search(string collectionName, float[] vector, IEnumerable? fields, int limit = 5, float confidence = 0.5f, bool withVector = false); Task DeleteCollectionData(string collectionName, List ids); Task DeleteCollectionAllData(string collectionName); diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCollectionData.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCollectionData.cs index ba614c2c..0b075f7e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCollectionData.cs +++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCollectionData.cs @@ -3,7 +3,7 @@ namespace BotSharp.Abstraction.VectorStorage.Models; public class VectorCollectionData { public string Id { get; set; } - public Dictionary Data { get; set; } = new(); + public Dictionary Data { get; set; } = new(); public double? Score { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs index 59199fb9..65641d84 100644 --- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs @@ -6,5 +6,5 @@ public class VectorCreateModel { public string Text { get; set; } public string DataSource { get; set; } = VectorDataSource.Api; - public Dictionary? Payload { get; set; } + public Dictionary? Payload { get; set; } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs index fa1c1fb3..9477d65d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs @@ -11,5 +11,5 @@ public class VectorKnowledgeCreateRequest public string DataSource { get; set; } = VectorDataSource.Api; [JsonPropertyName("payload")] - public Dictionary? Payload { get; set; } + public Dictionary? Payload { get; set; } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeViewModel.cs index dcdf2e57..bbd7dc3a 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeViewModel.cs @@ -9,7 +9,7 @@ public class VectorKnowledgeViewModel public string Id { get; set; } [JsonPropertyName("data")] - public IDictionary Data { get; set; } + public IDictionary Data { get; set; } [JsonPropertyName("score")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs index 62388f19..0af59975 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs @@ -24,7 +24,7 @@ public class MemorizeKnowledgeFn : IFunctionCallback var result = await knowledgeService.CreateVectorCollectionData(collectionName, new VectorCreateModel { Text = args.Question, - Payload = new Dictionary + Payload = new Dictionary { { KnowledgePayloadName.Answer, args.Answer } } diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemoryVectorDb.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemoryVectorDb.cs index 41331c2b..f766bb7e 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemoryVectorDb.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemoryVectorDb.cs @@ -59,7 +59,7 @@ public class MemoryVectorDb : IVectorDb .Take(limit) .Select(i => new VectorCollectionData { - Data = new Dictionary { { "text", _vectors[collectionName][i].Text } }, + Data = new Dictionary { { "text", _vectors[collectionName][i].Text } }, Score = similarities[i], Vector = withVector ? _vectors[collectionName][i].Vector : null, }) @@ -68,7 +68,7 @@ public class MemoryVectorDb : IVectorDb return await Task.FromResult(results); } - public async Task Upsert(string collectionName, Guid id, float[] vector, string text, Dictionary? payload = null) + public async Task Upsert(string collectionName, Guid id, float[] vector, string text, Dictionary? payload = null) { _vectors[collectionName].Add(new VecRecord { diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Document.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Document.cs index bd851eb8..74469177 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Document.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Document.cs @@ -398,7 +398,7 @@ public partial class KnowledgeService var vectorDb = GetVectorDb(); var textEmbedding = GetTextEmbedding(collectionName); - var payload = new Dictionary + var payload = new Dictionary { { KnowledgePayloadName.DataSource, vectorDataSource }, { KnowledgePayloadName.FileId, fileId.ToString() }, diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs index ee46b13e..903eaf69 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs @@ -196,7 +196,7 @@ public partial class KnowledgeService withPayload: true); if (!found.IsNullOrEmpty()) { - if (found.First().Data["text"] == update.Text) + if (found.First().Data["text"].ToString() == update.Text) { // Only update payload return await db.Upsert(collectionName, guid, found.First().Vector, update.Text, update.Payload); diff --git a/src/Plugins/BotSharp.Plugin.Planner/Functions/PrimaryStagePlanFn.cs b/src/Plugins/BotSharp.Plugin.Planner/Functions/PrimaryStagePlanFn.cs index 02d4f3a5..e92c3e8e 100644 --- a/src/Plugins/BotSharp.Plugin.Planner/Functions/PrimaryStagePlanFn.cs +++ b/src/Plugins/BotSharp.Plugin.Planner/Functions/PrimaryStagePlanFn.cs @@ -19,23 +19,23 @@ public class PrimaryStagePlanFn : IFunctionCallback { var agentService = _services.GetRequiredService(); var state = _services.GetRequiredService(); - var knowledgeService = _services.GetRequiredService(); - var knowledgeSettings = _services.GetRequiredService(); + // var knowledgeService = _services.GetRequiredService(); + // var knowledgeSettings = _services.GetRequiredService(); state.SetState("max_tokens", "4096"); var task = JsonSerializer.Deserialize(message.FunctionArgs); - var collectionName = knowledgeSettings.Default.CollectionName ?? KnowledgeCollectionName.BotSharp; + // var collectionName = knowledgeSettings.Default.CollectionName ?? KnowledgeCollectionName.BotSharp; // Get knowledge from vectordb var hooks = _services.GetServices(); var knowledges = new List(); foreach (var question in task.Questions) { - var list = await knowledgeService.SearchVectorKnowledge(question, collectionName, new VectorSearchOptions + /*var list = await knowledgeService.SearchVectorKnowledge(question, collectionName, new VectorSearchOptions { Confidence = 0.4f }); - knowledges.Add(string.Join("\r\n\r\n=====\r\n", list.Select(x => x.ToQuestionAnswer()))); + knowledges.Add(string.Join("\r\n\r\n=====\r\n", list.Select(x => x.ToQuestionAnswer())));*/ foreach (var hook in hooks) { @@ -43,6 +43,7 @@ public class PrimaryStagePlanFn : IFunctionCallback knowledges.AddRange(k); } } + knowledges = knowledges.Distinct().ToList(); // Get first stage planning prompt var currentAgent = await agentService.LoadAgent(message.CurrentAgentId); diff --git a/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj b/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj index 33fae3f9..fb19756b 100644 --- a/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj +++ b/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs index 6c54f60b..9dde5b35 100644 --- a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs +++ b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs @@ -142,7 +142,13 @@ public class QdrantDb : IVectorDb var points = response?.Result?.Select(x => new VectorCollectionData { Id = x.Id?.Uuid ?? string.Empty, - Data = x.Payload.ToDictionary(x => x.Key, x => x.Value.StringValue), + Data = x.Payload.ToDictionary(p => p.Key, p => p.Value.KindCase switch + { + Value.KindOneofCase.StringValue => p.Value.StringValue, + Value.KindOneofCase.BoolValue => p.Value.BoolValue, + Value.KindOneofCase.IntegerValue => p.Value.IntegerValue, + _ => new object() + }), Vector = filter.WithVector ? x.Vectors?.Vector?.Data?.ToArray() : null })?.ToList() ?? new List(); @@ -175,12 +181,18 @@ public class QdrantDb : IVectorDb return points.Select(x => new VectorCollectionData { Id = x.Id?.Uuid ?? string.Empty, - Data = x.Payload?.ToDictionary(x => x.Key, x => x.Value.StringValue) ?? new(), + Data = x.Payload?.ToDictionary(p => p.Key, p => p.Value.KindCase switch + { + Value.KindOneofCase.StringValue => p.Value.StringValue, + Value.KindOneofCase.BoolValue => p.Value.BoolValue, + Value.KindOneofCase.IntegerValue => p.Value.IntegerValue, + _ => new object() + }) ?? new(), Vector = x.Vectors?.Vector?.Data?.ToArray() }); } - public async Task Upsert(string collectionName, Guid id, float[] vector, string text, Dictionary? payload = null) + public async Task Upsert(string collectionName, Guid id, float[] vector, string text, Dictionary? payload = null) { // Insert vectors var point = new PointStruct() @@ -200,7 +212,42 @@ public class QdrantDb : IVectorDb { foreach (var item in payload) { - point.Payload[item.Key] = item.Value; + if (item.Value is string str) + { + point.Payload[item.Key] = str; + } + else if (item.Value is bool b) + { + point.Payload[item.Key] = b; + } + else if (item.Value is byte int8) + { + point.Payload[item.Key] = int8; + } + else if (item.Value is short int16) + { + point.Payload[item.Key] = int16; + } + else if (item.Value is int int32) + { + point.Payload[item.Key] = int32; + } + else if (item.Value is long int64) + { + point.Payload[item.Key] = int64; + } + else if (item.Value is float f32) + { + point.Payload[item.Key] = f32; + } + else if (item.Value is double f64) + { + point.Payload[item.Key] = f64; + } + else if (item.Value is DateTime dt) + { + point.Payload[item.Key] = dt.ToUniversalTime().ToString("o"); + } } } @@ -241,7 +288,13 @@ public class QdrantDb : IVectorDb results = points.Select(x => new VectorCollectionData { Id = x.Id.Uuid, - Data = x.Payload.ToDictionary(x => x.Key, x => x.Value.StringValue), + Data = x.Payload.ToDictionary(p => p.Key, p => p.Value.KindCase switch + { + Value.KindOneofCase.StringValue => p.Value.StringValue, + Value.KindOneofCase.BoolValue => p.Value.BoolValue, + Value.KindOneofCase.IntegerValue => p.Value.IntegerValue, + _ => new object() + }), Score = x.Score, Vector = x.Vectors?.Vector?.Data?.ToArray() }).ToList(); diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/Services/DbKnowledgeService.cs b/src/Plugins/BotSharp.Plugin.SqlDriver/Services/DbKnowledgeService.cs index 129da04c..2402f7ad 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/Services/DbKnowledgeService.cs +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/Services/DbKnowledgeService.cs @@ -69,7 +69,7 @@ public class DbKnowledgeService await knowledgeService.CreateVectorCollectionData(collectionName, new VectorCreateModel { Text = item.Question, - Payload = new Dictionary + Payload = new Dictionary { { KnowledgePayloadName.Answer, item.Answer } }