diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgeDocSource.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgeDocSource.cs new file mode 100644 index 000000000..d033d0779 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgeDocSource.cs @@ -0,0 +1,7 @@ +namespace BotSharp.Abstraction.Knowledges.Enums; + +public static class KnowledgeDocSource +{ + public const string Api = "api"; + public const string User = "user"; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgeDocType.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgeDocType.cs new file mode 100644 index 000000000..39e4f662b --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgeDocType.cs @@ -0,0 +1,7 @@ +namespace BotSharp.Abstraction.Knowledges.Enums; + +public class KnowledgeDocType +{ + public const string File = "file"; + public const string Http = "http"; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgePayloadName.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgePayloadName.cs index 9d95967f6..ac130001a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgePayloadName.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Enums/KnowledgePayloadName.cs @@ -7,4 +7,5 @@ public static class KnowledgePayloadName public static string Answer = "answer"; public static string Request = "request"; public static string Response = "response"; + public static string DataSource = "dataSource"; } diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Enums/VectorDataSource.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Enums/VectorDataSource.cs new file mode 100644 index 000000000..0582492be --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Enums/VectorDataSource.cs @@ -0,0 +1,8 @@ +namespace BotSharp.Abstraction.VectorStorage.Enums; + +public static class VectorDataSource +{ + public const string Api = "api"; + public const string User = "user"; + public const string File = "file"; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs index 3d9cb88c6..59199fb91 100644 --- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorCreateModel.cs @@ -1,7 +1,10 @@ +using BotSharp.Abstraction.VectorStorage.Enums; + namespace BotSharp.Abstraction.VectorStorage.Models; public class VectorCreateModel { public string Text { get; set; } + public string DataSource { get; set; } = VectorDataSource.Api; public Dictionary? Payload { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorFilter.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorFilter.cs index 78eb3691d..584e86534 100644 --- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/Models/VectorFilter.cs @@ -10,4 +10,11 @@ public class VectorFilter : StringIdPagination /// [JsonPropertyName("search_pairs")] public IEnumerable? SearchPairs { get; set; } + + + /// + /// Included payload keys + /// + [JsonPropertyName("included_payloads")] + public IEnumerable? IncludedPayloads { get; set; } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs index 1c1d55c91..5a79a1239 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/KnowledgeBaseController.cs @@ -1,11 +1,8 @@ -using Azure.Core; -using BotSharp.Abstraction.Files.Constants; using BotSharp.Abstraction.Files.Utilities; using BotSharp.Abstraction.Graph.Models; using BotSharp.Abstraction.Knowledges.Models; using BotSharp.Abstraction.VectorStorage.Models; using BotSharp.OpenAPI.ViewModels.Knowledges; -using System.IO; namespace BotSharp.OpenAPI.Controllers; @@ -77,6 +74,7 @@ public async Task CreateVectorKnowledge([FromRoute] string collection, [Fr var create = new VectorCreateModel { Text = request.Text, + DataSource = request.DataSource, Payload = request.Payload }; @@ -91,6 +89,7 @@ public async Task UpdateVectorKnowledge([FromRoute] string collection, [Fr { Id = request.Id, Text = request.Text, + DataSource = request.DataSource, Payload = request.Payload }; @@ -106,24 +105,6 @@ public async Task DeleteVectorCollectionData([FromRoute] string collection #endregion - #region Graph - [HttpPost("/knowledge/graph/search")] - public async Task SearchGraphKnowledge([FromBody] SearchGraphKnowledgeRequest request) - { - var options = new GraphSearchOptions - { - Method = request.Method - }; - - var result = await _knowledgeService.SearchGraphKnowledge(request.Query, options); - return new GraphKnowledgeViewModel - { - Result = result.Result - }; - } - #endregion - - #region Document [HttpPost("/knowledge/document/{collection}/upload")] public async Task UploadKnowledgeDocuments([FromRoute] string collection, [FromBody] VectorKnowledgeUploadRequest request) @@ -181,6 +162,25 @@ public async Task GetKnowledgeDocument([FromRoute] string collect #endregion + + #region Graph + [HttpPost("/knowledge/graph/search")] + public async Task SearchGraphKnowledge([FromBody] SearchGraphKnowledgeRequest request) + { + var options = new GraphSearchOptions + { + Method = request.Method + }; + + var result = await _knowledgeService.SearchGraphKnowledge(request.Query, options); + return new GraphKnowledgeViewModel + { + Result = result.Result + }; + } + #endregion + + #region Common [HttpPost("/knowledge/vector/refresh-configs")] public async Task RefreshVectorCollectionConfigs([FromBody] VectorCollectionConfigsModel request) diff --git a/src/Infrastructure/BotSharp.OpenAPI/Using.cs b/src/Infrastructure/BotSharp.OpenAPI/Using.cs index 8771b81c0..71db10f21 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Using.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Using.cs @@ -26,7 +26,8 @@ global using BotSharp.Abstraction.Repositories.Filters; global using BotSharp.Abstraction.Files.Models; global using BotSharp.Abstraction.Files; +global using BotSharp.Abstraction.VectorStorage.Enums; global using BotSharp.OpenAPI.ViewModels.Conversations; global using BotSharp.OpenAPI.ViewModels.Users; global using BotSharp.OpenAPI.ViewModels.Agents; -global using BotSharp.OpenAPI.ViewModels.Files; \ No newline at end of file +global using BotSharp.OpenAPI.ViewModels.Files; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs index 379483226..fa1c1fb30 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Knowledges/VectorKnowledgeCreateRequest.cs @@ -7,6 +7,9 @@ public class VectorKnowledgeCreateRequest [JsonPropertyName("text")] public string Text { get; set; } + [JsonPropertyName("data_source")] + public string DataSource { get; set; } = VectorDataSource.Api; + [JsonPropertyName("payload")] public Dictionary? Payload { get; set; } } diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/WebSocketsMiddleware.cs b/src/Plugins/BotSharp.Plugin.ChatHub/WebSocketsMiddleware.cs index fb65f150a..ff986be61 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/WebSocketsMiddleware.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/WebSocketsMiddleware.cs @@ -37,7 +37,8 @@ private bool VerifyGetRequest(HttpRequest request) var regexes = new List { new Regex(@"/conversation/(.*?)/message/(.*?)/(.*?)/file/(.*?)/(.*?)", RegexOptions.IgnoreCase), - new Regex(@"/user/avatar", RegexOptions.IgnoreCase) + new Regex(@"/user/avatar", RegexOptions.IgnoreCase), + new Regex(@"/knowledge/document/(.*?)/file/(.*?)", RegexOptions.IgnoreCase) }; return request.Method.IsEqualTo("GET") && regexes.Any(x => x.IsMatch(request.Path.Value ?? string.Empty)); diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs index e4089c570..c50c9ff84 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.Vector.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Files; +using BotSharp.Abstraction.VectorStorage.Enums; namespace BotSharp.Plugin.KnowledgeBase.Services; @@ -119,7 +120,10 @@ public async Task CreateVectorCollectionData(string collectionName, Vector var db = GetVectorDb(); var guid = Guid.NewGuid(); - return await db.Upsert(collectionName, guid, vector, create.Text, create.Payload); + var payload = create.Payload ?? new(); + payload[KnowledgePayloadName.DataSource] = !string.IsNullOrWhiteSpace(create.DataSource) ? create.DataSource : VectorDataSource.Api; + + return await db.Upsert(collectionName, guid, vector, create.Text, payload); } catch (Exception ex) { @@ -146,7 +150,10 @@ public async Task UpdateVectorCollectionData(string collectionName, Vector var textEmbedding = GetTextEmbedding(collectionName); var vector = await textEmbedding.GetVectorAsync(update.Text); - return await db.Upsert(collectionName, guid, vector, update.Text, update.Payload); + var payload = update.Payload ?? new(); + payload[KnowledgePayloadName.DataSource] = !string.IsNullOrWhiteSpace(update.DataSource) ? update.DataSource : VectorDataSource.Api; + + return await db.Upsert(collectionName, guid, vector, update.Text, payload); } catch (Exception ex) { diff --git a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs index b9563a1b9..4a4ff6eea 100644 --- a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs +++ b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Utilities; using BotSharp.Abstraction.VectorStorage.Models; +using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; using Qdrant.Client; using Qdrant.Client.Grpc; @@ -112,10 +113,25 @@ public async Task> GetPagedCollectionDa }; } + // Build payload selector + WithPayloadSelector? payloadSelector = null; + if (!filter.IncludedPayloads.IsNullOrEmpty()) + { + payloadSelector = new WithPayloadSelector + { + Enable = true, + Include = new PayloadIncludeSelector + { + Fields = { filter.IncludedPayloads.ToArray() } + } + }; + } + var totalPointCount = await client.CountAsync(collectionName, filter: queryFilter); var response = await client.ScrollAsync(collectionName, limit: (uint)filter.Size, offset: !string.IsNullOrWhiteSpace(filter.StartId) ? new PointId { Uuid = filter.StartId } : null, filter: queryFilter, + payloadSelector: payloadSelector, vectorsSelector: filter.WithVector); var points = response?.Result?.Select(x => new VectorCollectionData