Merge pull request #657 from iceljc/master

add collection exist
This commit is contained in:
iceljc 2024-09-24 15:37:37 -05:00 committed by GitHub
commit ec6db642de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 81 additions and 33 deletions

View file

@ -6,6 +6,7 @@ namespace BotSharp.Abstraction.Knowledges;
public interface IKnowledgeService public interface IKnowledgeService
{ {
#region Vector #region Vector
Task<bool> ExistVectorCollection(string collectionName);
Task<bool> CreateVectorCollection(string collectionName, string collectionType, int dimension, string provider, string model); Task<bool> CreateVectorCollection(string collectionName, string collectionType, int dimension, string provider, string model);
Task<bool> DeleteVectorCollection(string collectionName); Task<bool> DeleteVectorCollection(string collectionName);
Task<IEnumerable<string>> GetVectorCollections(string type); Task<IEnumerable<string>> GetVectorCollections(string type);

View file

@ -116,7 +116,6 @@ public interface IBotSharpRepository
bool AddKnowledgeCollectionConfigs(List<VectorCollectionConfig> configs, bool reset = false); bool AddKnowledgeCollectionConfigs(List<VectorCollectionConfig> configs, bool reset = false);
bool DeleteKnowledgeCollectionConfig(string collectionName); bool DeleteKnowledgeCollectionConfig(string collectionName);
IEnumerable<VectorCollectionConfig> GetKnowledgeCollectionConfigs(VectorCollectionConfigFilter filter); IEnumerable<VectorCollectionConfig> GetKnowledgeCollectionConfigs(VectorCollectionConfigFilter filter);
bool SaveKnolwedgeBaseFileMeta(KnowledgeDocMetaData metaData); bool SaveKnolwedgeBaseFileMeta(KnowledgeDocMetaData metaData);
/// <summary> /// <summary>
/// Delete file meta data in a knowledge collection, given the vector store provider. If "fileId" is null, delete all in the collection. /// Delete file meta data in a knowledge collection, given the vector store provider. If "fileId" is null, delete all in the collection.

View file

@ -5,7 +5,8 @@ namespace BotSharp.Abstraction.VectorStorage;
public interface IVectorDb public interface IVectorDb
{ {
string Provider { get; } string Provider { get; }
Task<bool> DoesCollectionExist(string collectionName);
Task<IEnumerable<string>> GetCollections(); Task<IEnumerable<string>> GetCollections();
Task<StringIdPagedItems<VectorCollectionData>> GetPagedCollectionData(string collectionName, VectorFilter filter); Task<StringIdPagedItems<VectorCollectionData>> GetPagedCollectionData(string collectionName, VectorFilter filter);
Task<IEnumerable<VectorCollectionData>> GetCollectionData(string collectionName, IEnumerable<Guid> ids, bool withPayload = false, bool withVector = false); Task<IEnumerable<VectorCollectionData>> GetCollectionData(string collectionName, IEnumerable<Guid> ids, bool withPayload = false, bool withVector = false);

View file

@ -213,7 +213,7 @@ public partial class FileRepository
return new PagedItems<KnowledgeDocMetaData> return new PagedItems<KnowledgeDocMetaData>
{ {
Items = records.Skip(filter.Offset).Take(filter.Size), Items = records.OrderByDescending(x => x.CreateDate).Skip(filter.Offset).Take(filter.Size),
Count = records.Count Count = records.Count
}; };
} }

View file

@ -1,6 +1,5 @@
using BotSharp.Abstraction.Files.Utilities; using BotSharp.Abstraction.Files.Utilities;
using BotSharp.Abstraction.Graph.Models; using BotSharp.Abstraction.Graph.Models;
using BotSharp.Abstraction.Knowledges.Models;
using BotSharp.Abstraction.VectorStorage.Models; using BotSharp.Abstraction.VectorStorage.Models;
using BotSharp.OpenAPI.ViewModels.Knowledges; using BotSharp.OpenAPI.ViewModels.Knowledges;
@ -20,6 +19,12 @@ public class KnowledgeBaseController : ControllerBase
} }
#region Vector #region Vector
[HttpGet("knowledge/vector/{collection}/exist")]
public async Task<bool> ExistVectorCollection([FromRoute] string collection)
{
return await _knowledgeService.ExistVectorCollection(collection);
}
[HttpGet("knowledge/vector/collections")] [HttpGet("knowledge/vector/collections")]
public async Task<IEnumerable<string>> GetVectorCollections([FromQuery] string type) public async Task<IEnumerable<string>> GetVectorCollections([FromQuery] string type)
{ {

View file

@ -10,6 +10,12 @@ public class MemoryVectorDb : IVectorDb
public string Provider => "MemoryVector"; public string Provider => "MemoryVector";
public async Task<bool> DoesCollectionExist(string collectionName)
{
return false;
}
public async Task<bool> CreateCollection(string collectionName, int dimension) public async Task<bool> CreateCollection(string collectionName, int dimension)
{ {
_collections[collectionName] = dimension; _collections[collectionName] = dimension;

View file

@ -3,7 +3,6 @@ using BotSharp.Abstraction.Files.Models;
using BotSharp.Abstraction.Files.Utilities; using BotSharp.Abstraction.Files.Utilities;
using BotSharp.Abstraction.Knowledges.Helpers; using BotSharp.Abstraction.Knowledges.Helpers;
using BotSharp.Abstraction.VectorStorage.Enums; using BotSharp.Abstraction.VectorStorage.Enums;
using System.Collections;
using System.Net.Http; using System.Net.Http;
using System.Net.Mime; using System.Net.Mime;
@ -13,13 +12,21 @@ public partial class KnowledgeService
{ {
public async Task<UploadKnowledgeResponse> UploadDocumentsToKnowledge(string collectionName, IEnumerable<ExternalFileModel> files) public async Task<UploadKnowledgeResponse> UploadDocumentsToKnowledge(string collectionName, IEnumerable<ExternalFileModel> files)
{ {
var res = new UploadKnowledgeResponse
{
Success = [],
Failed = files?.Select(x => x.FileName) ?? new List<string>()
};
if (string.IsNullOrWhiteSpace(collectionName) || files.IsNullOrEmpty()) if (string.IsNullOrWhiteSpace(collectionName) || files.IsNullOrEmpty())
{ {
return new UploadKnowledgeResponse return res;
{ }
Success = [],
Failed = files?.Select(x => x.FileName) ?? new List<string>() var exist = await ExistVectorCollection(collectionName);
}; if (!exist)
{
return res;
} }
var db = _services.GetRequiredService<IBotSharpRepository>(); var db = _services.GetRequiredService<IBotSharpRepository>();
@ -103,6 +110,9 @@ public partial class KnowledgeService
try try
{ {
var exist = await ExistVectorCollection(collectionName);
if (!exist) return false;
var db = _services.GetRequiredService<IBotSharpRepository>(); var db = _services.GetRequiredService<IBotSharpRepository>();
var userId = await GetUserId(); var userId = await GetUserId();
var vectorStoreProvider = _settings.VectorDb.Provider; var vectorStoreProvider = _settings.VectorDb.Provider;

View file

@ -7,6 +7,23 @@ namespace BotSharp.Plugin.KnowledgeBase.Services;
public partial class KnowledgeService public partial class KnowledgeService
{ {
#region Collection #region Collection
public async Task<bool> ExistVectorCollection(string collectionName)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var vectorDb = GetVectorDb();
var exist = await vectorDb.DoesCollectionExist(collectionName);
if (exist) return true;
var configs = db.GetKnowledgeCollectionConfigs(new VectorCollectionConfigFilter
{
CollectionNames = [collectionName],
VectorStroageProviders = [_settings.VectorDb.Provider]
});
return !configs.IsNullOrEmpty();
}
public async Task<bool> CreateVectorCollection(string collectionName, string collectionType, int dimension, string provider, string model) public async Task<bool> CreateVectorCollection(string collectionName, string collectionType, int dimension, string provider, string model)
{ {
try try

View file

@ -39,16 +39,22 @@ public class QdrantDb : IVectorDb
return _client; return _client;
} }
public async Task<bool> CreateCollection(string collectionName, int dimension) public async Task<bool> DoesCollectionExist(string collectionName)
{ {
var client = GetClient(); var client = GetClient();
var exist = await DoesCollectionExist(client, collectionName); return await client.CollectionExistsAsync(collectionName);
}
public async Task<bool> CreateCollection(string collectionName, int dimension)
{
var exist = await DoesCollectionExist(collectionName);
if (exist) return false; if (exist) return false;
try try
{ {
// Create a new collection // Create a new collection
var client = GetClient();
await client.CreateCollectionAsync(collectionName, new VectorParams() await client.CreateCollectionAsync(collectionName, new VectorParams()
{ {
Size = (ulong)dimension, Size = (ulong)dimension,
@ -65,11 +71,11 @@ public class QdrantDb : IVectorDb
public async Task<bool> DeleteCollection(string collectionName) public async Task<bool> DeleteCollection(string collectionName)
{ {
var client = GetClient(); var exist = await DoesCollectionExist(collectionName);
var exist = await DoesCollectionExist(client, collectionName);
if (!exist) return false; if (!exist) return false;
var client = GetClient();
await client.DeleteCollectionAsync(collectionName); await client.DeleteCollectionAsync(collectionName);
return true; return true;
} }
@ -83,8 +89,7 @@ public class QdrantDb : IVectorDb
public async Task<StringIdPagedItems<VectorCollectionData>> GetPagedCollectionData(string collectionName, VectorFilter filter) public async Task<StringIdPagedItems<VectorCollectionData>> GetPagedCollectionData(string collectionName, VectorFilter filter)
{ {
var client = GetClient(); var exist = await DoesCollectionExist(collectionName);
var exist = await DoesCollectionExist(client, collectionName);
if (!exist) if (!exist)
{ {
return new StringIdPagedItems<VectorCollectionData>(); return new StringIdPagedItems<VectorCollectionData>();
@ -126,6 +131,7 @@ public class QdrantDb : IVectorDb
}; };
} }
var client = GetClient();
var totalPointCount = await client.CountAsync(collectionName, filter: queryFilter); var totalPointCount = await client.CountAsync(collectionName, filter: queryFilter);
var response = await client.ScrollAsync(collectionName, limit: (uint)filter.Size, var response = await client.ScrollAsync(collectionName, limit: (uint)filter.Size,
offset: !string.IsNullOrWhiteSpace(filter.StartId) ? new PointId { Uuid = filter.StartId } : null, offset: !string.IsNullOrWhiteSpace(filter.StartId) ? new PointId { Uuid = filter.StartId } : null,
@ -152,15 +158,18 @@ public class QdrantDb : IVectorDb
public async Task<IEnumerable<VectorCollectionData>> GetCollectionData(string collectionName, IEnumerable<Guid> ids, public async Task<IEnumerable<VectorCollectionData>> GetCollectionData(string collectionName, IEnumerable<Guid> ids,
bool withPayload = false, bool withVector = false) bool withPayload = false, bool withVector = false)
{ {
if (ids.IsNullOrEmpty()) return Enumerable.Empty<VectorCollectionData>(); if (ids.IsNullOrEmpty())
{
var client = GetClient(); return Enumerable.Empty<VectorCollectionData>();
var exist = await DoesCollectionExist(client, collectionName); }
var exist = await DoesCollectionExist(collectionName);
if (!exist) if (!exist)
{ {
return Enumerable.Empty<VectorCollectionData>(); return Enumerable.Empty<VectorCollectionData>();
} }
var client = GetClient();
var pointIds = ids.Select(x => new PointId { Uuid = x.ToString() }).Distinct().ToList(); var pointIds = ids.Select(x => new PointId { Uuid = x.ToString() }).Distinct().ToList();
var points = await client.RetrieveAsync(collectionName, pointIds, withPayload, withVector); var points = await client.RetrieveAsync(collectionName, pointIds, withPayload, withVector);
return points.Select(x => new VectorCollectionData return points.Select(x => new VectorCollectionData
@ -209,8 +218,7 @@ public class QdrantDb : IVectorDb
{ {
var results = new List<VectorCollectionData>(); var results = new List<VectorCollectionData>();
var client = GetClient(); var exist = await DoesCollectionExist(collectionName);
var exist = await DoesCollectionExist(client, collectionName);
if (!exist) if (!exist)
{ {
return results; return results;
@ -221,7 +229,8 @@ public class QdrantDb : IVectorDb
{ {
payloadSelector.Include = new PayloadIncludeSelector { Fields = { fields.ToArray() } }; payloadSelector.Include = new PayloadIncludeSelector { Fields = { fields.ToArray() } };
} }
var client = GetClient();
var points = await client.SearchAsync(collectionName, var points = await client.SearchAsync(collectionName,
vector, vector,
limit: (ulong)limit, limit: (ulong)limit,
@ -244,33 +253,27 @@ public class QdrantDb : IVectorDb
{ {
if (ids.IsNullOrEmpty()) return false; if (ids.IsNullOrEmpty()) return false;
var client = GetClient(); var exist = await DoesCollectionExist(collectionName);
var exist = await DoesCollectionExist(client, collectionName);
if (!exist) if (!exist)
{ {
return false; return false;
} }
var client = GetClient();
var result = await client.DeleteAsync(collectionName, ids); var result = await client.DeleteAsync(collectionName, ids);
return result.Status == UpdateStatus.Completed; return result.Status == UpdateStatus.Completed;
} }
public async Task<bool> DeleteCollectionAllData(string collectionName) public async Task<bool> DeleteCollectionAllData(string collectionName)
{ {
var client = GetClient(); var exist = await DoesCollectionExist(collectionName);
var exist = await DoesCollectionExist(client, collectionName);
if (!exist) if (!exist)
{ {
return false; return false;
} }
var client = GetClient();
var result = await client.DeleteAsync(collectionName, new Filter()); var result = await client.DeleteAsync(collectionName, new Filter());
return result.Status == UpdateStatus.Completed; return result.Status == UpdateStatus.Completed;
} }
private async Task<bool> DoesCollectionExist(QdrantClient client, string collectionName)
{
return await client.CollectionExistsAsync(collectionName);
}
} }

View file

@ -25,6 +25,12 @@ namespace BotSharp.Plugin.SemanticKernel
public string Provider => "SemanticKernel"; public string Provider => "SemanticKernel";
public async Task<bool> DoesCollectionExist(string collectionName)
{
return false;
}
public async Task<bool> CreateCollection(string collectionName, int dimension) public async Task<bool> CreateCollection(string collectionName, int dimension)
{ {
await _memoryStore.CreateCollectionAsync(collectionName); await _memoryStore.CreateCollectionAsync(collectionName);