diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentRole.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentRole.cs
index 4cab43d6..f9547d5a 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentRole.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentRole.cs
@@ -3,21 +3,7 @@ namespace BotSharp.Abstraction.Agents.Enums;
public class AgentRole
{
public const string System = "system";
-
- ///
- /// AI Assistant
- ///
public const string Assistant = "assistant";
-
- ///
- /// Client
- ///
public const string User = "user";
-
public const string Function = "function";
-
- ///
- /// Customer service representative (CSR)
- ///
- public const string CSR = "csr";
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/UserAgent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/UserAgent.cs
index 55033a04..b6eab94d 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/UserAgent.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/UserAgent.cs
@@ -5,6 +5,7 @@ public class UserAgent
public string Id { get; set; } = string.Empty;
public string UserId { get; set; } = string.Empty;
public string AgentId { get; set; } = string.Empty;
+ public bool Editable { get; set; }
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
index f13466b7..3d82500c 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
@@ -77,7 +77,7 @@ public abstract class ConversationHookBase : IConversationHook
return Task.CompletedTask;
}
- public virtual Task OnConversationInitialized(Conversation message)
+ public virtual Task OnConversationInitialized(Conversation conversation)
{
return Task.CompletedTask;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
index 4cc6af36..66342ffb 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
@@ -9,7 +9,7 @@ public interface IBotSharpRepository
#region User
User? GetUserByEmail(string email);
- User? GetUserByExternalId(string externalId);
+ User? GetUserById(string id);
void CreateUser(User user);
#endregion
diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs
index f54782ce..35d74aa4 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs
@@ -4,6 +4,7 @@ namespace BotSharp.Abstraction.Users;
public interface IUserService
{
+ Task GetUser(string id);
Task CreateUser(User user);
Task GetToken(string authorization);
Task GetMyProfile();
diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
index 7253f4db..a56e505f 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
@@ -1,3 +1,5 @@
+using BotSharp.Abstraction.Users.Enums;
+
namespace BotSharp.Abstraction.Users.Models;
public class User
@@ -9,6 +11,7 @@ public class User
public string Salt { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string? ExternalId { get; set; }
+ public string Role { get; set; } = UserRole.Client;
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
}
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs
index 5e29d9a8..2253710c 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs
@@ -42,7 +42,7 @@ public partial class AgentService
.SetResponses(foundAgent.Responses);
}
- var user = _db.GetUserByExternalId(_user.Id);
+ var user = _db.GetUserById(_user.Id);
var userAgentRecord = new UserAgent
{
Id = Guid.NewGuid().ToString(),
diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs
index fa24f404..7d0d4ced 100644
--- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs
+++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs
@@ -13,7 +13,7 @@ public partial class AgentService
var dbSettings = _services.GetRequiredService();
var agentDir = Path.Combine(dbSettings.FileRepository, _agentSettings.DataDir);
- var user = _db.GetUserByExternalId(_user.Id);
+ var user = _db.GetUserById(_user.Id);
var agents = new List();
var userAgents = new List();
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
index 20bfb7cf..92022dca 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
@@ -1,4 +1,6 @@
using BotSharp.Abstraction.Repositories;
+using BotSharp.Abstraction.Users.Enums;
+using BotSharp.Abstraction.Users.Models;
namespace BotSharp.Core.Conversations.Services;
@@ -46,15 +48,15 @@ public partial class ConversationService : IConversationService
public async Task> GetConversations()
{
var db = _services.GetRequiredService();
- var user = db.GetUserByExternalId(_user.Id);
- var conversations = db.GetConversations(user?.Id);
+ var user = db.GetUserById(_user.Id);
+ var conversations = db.GetConversations(user.Role == UserRole.CSR ? null : user?.Id);
return conversations.OrderByDescending(x => x.CreatedTime).ToList();
}
public async Task NewConversation(Conversation sess)
{
var db = _services.GetRequiredService();
- var user = db.GetUserByExternalId(_user.Id);
+ var user = db.GetUserById(_user.Id);
var foundUserId = user?.Id ?? string.Empty;
var record = sess;
diff --git a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs
index 4b2383bc..93339d3d 100644
--- a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs
+++ b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs
@@ -169,7 +169,7 @@ public class BotSharpDbContext : Database, IBotSharpRepository
throw new NotImplementedException();
}
- public User? GetUserByExternalId(string externalId)
+ public User? GetUserById(string id)
{
throw new NotImplementedException();
}
diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs
index 517bd0f7..e77e160a 100644
--- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs
+++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs
@@ -726,7 +726,7 @@ public class FileRepository : IBotSharpRepository
var json = File.ReadAllText(path);
var record = JsonSerializer.Deserialize(json, _options);
- if (record != null && record.UserId == userId)
+ if (record != null && (record.UserId == userId || userId == null))
{
records.Add(record);
}
@@ -769,9 +769,9 @@ public class FileRepository : IBotSharpRepository
return Users.FirstOrDefault(x => x.Email == email);
}
- public User? GetUserByExternalId(string externalId)
+ public User? GetUserById(string id = null)
{
- return Users.FirstOrDefault(x => x.ExternalId == externalId);
+ return Users.FirstOrDefault(x => x.ExternalId == id || x.Id == id);
}
public void CreateUser(User user)
diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
index 30fa131f..d832cc13 100644
--- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
+++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
@@ -97,7 +97,15 @@ public class UserService : IUserService
public async Task GetMyProfile()
{
var db = _services.GetRequiredService();
- var user = db.GetUserByExternalId(_user.Id);
+ var user = db.GetUserById(_user.Id);
+ return user;
+ }
+
+ [MemoryCache(60)]
+ public async Task GetUser(string id)
+ {
+ var db = _services.GetRequiredService();
+ var user = db.GetUserById(id);
return user;
}
}
diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs
index 7b5d83b0..39fc861a 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs
@@ -2,6 +2,7 @@ using BotSharp.Abstraction.ApiAdapters;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Models;
using BotSharp.OpenAPI.ViewModels.Conversations;
+using BotSharp.OpenAPI.ViewModels.Users;
using Microsoft.AspNetCore.Http;
using System.Net.Http.Headers;
@@ -27,7 +28,8 @@ public class ConversationController : ControllerBase, IApiAdapter
var service = _services.GetRequiredService();
var conv = new Conversation
{
- AgentId = agentId
+ AgentId = agentId,
+ UserId = _user.Id
};
conv = await service.NewConversation(conv);
config.States.ForEach(x => conv.States[x.Split('=')[0]] = x.Split('=')[1]);
@@ -35,6 +37,34 @@ public class ConversationController : ControllerBase, IApiAdapter
return ConversationViewModel.FromSession(conv);
}
+ [HttpGet("/conversations/{agentId}")]
+ public async Task> GetConversations()
+ {
+ var service = _services.GetRequiredService();
+ var conversations = await service.GetConversations();
+ var userService = _services.GetRequiredService();
+ var list = conversations.Select(x => new ConversationViewModel
+ {
+ Id = x.Id,
+ AgentId = x.AgentId,
+ Title = x.Title,
+ User = new UserViewModel
+ {
+ Id = x.UserId,
+ },
+ CreatedTime = x.CreatedTime,
+ UpdatedTime = x.UpdatedTime
+ }).ToList();
+
+ foreach (var item in list)
+ {
+ var user = await userService.GetUser(item.User.Id);
+ item.User = UserViewModel.FromUser(user);
+ }
+
+ return list;
+ }
+
[HttpDelete("/conversation/{agentId}/{conversationId}")]
public async Task DeleteConversation([FromRoute] string agentId, [FromRoute] string conversationId)
{
diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs
index f47c5cd6..ee819cf1 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs
@@ -1,4 +1,5 @@
using BotSharp.Abstraction.Conversations.Models;
+using BotSharp.OpenAPI.ViewModels.Users;
namespace BotSharp.OpenAPI.ViewModels.Conversations;
@@ -7,6 +8,7 @@ public class ConversationViewModel
public string Id { get; set; }
public string AgentId { get; set; }
public string Title { get; set; } = string.Empty;
+ public UserViewModel User { get; set; } = new UserViewModel();
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
@@ -15,6 +17,10 @@ public class ConversationViewModel
return new ConversationViewModel
{
Id = sess.Id,
+ User = new UserViewModel
+ {
+ Id = sess.UserId
+ },
AgentId = sess.AgentId,
Title = sess.Title,
CreatedTime = sess.CreatedTime,
diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs
index 4e452334..5bed438e 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs
@@ -9,6 +9,8 @@ public class UserViewModel
public string LastName { get; set; }
public string Email { get; set; }
+ public string FullName => $"{FirstName} {LastName}";
+
public static UserViewModel FromUser(User user)
{
return new UserViewModel
diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs
index 0009e0aa..aacd623b 100644
--- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs
+++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs
@@ -768,9 +768,9 @@ public class MongoRepository : IBotSharpRepository
} : null;
}
- public User? GetUserByExternalId(string externalId)
+ public User? GetUserById(string id)
{
- var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.ExternalId == externalId);
+ var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.Id == id || x.ExternalId == id);
return user != null ? new User
{
Id = user.Id,
diff --git a/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj b/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj
index aa9ca00d..e8f32d39 100644
--- a/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj
+++ b/src/Plugins/BotSharp.Plugin.Qdrant/BotSharp.Plugin.Qdrant.csproj
@@ -1,4 +1,4 @@
-
+
netstandard2.1
@@ -10,7 +10,7 @@
-
+
diff --git a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs
index 1d7aac14..3bc4e8fb 100644
--- a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs
+++ b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs
@@ -1,9 +1,8 @@
using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.VectorStorage;
using Microsoft.Extensions.DependencyInjection;
-using QdrantCSharp;
-using QdrantCSharp.Enums;
-using QdrantCSharp.Models;
+using Qdrant.Client;
+using Qdrant.Client.Grpc;
using System;
using System.Collections.Generic;
using System.IO;
@@ -14,7 +13,7 @@ namespace BotSharp.Plugin.Qdrant;
public class QdrantDb : IVectorDb
{
- private readonly QdrantHttpClient _client;
+ private readonly QdrantClient _client;
private readonly QdrantSetting _setting;
private readonly IServiceProvider _services;
@@ -23,9 +22,9 @@ public class QdrantDb : IVectorDb
{
_setting = setting;
_services = services;
- _client = new QdrantHttpClient
+ _client = new QdrantClient
(
- url: _setting.Url,
+ host: _setting.Url,
apiKey: _setting.ApiKey
);
}
@@ -33,8 +32,8 @@ public class QdrantDb : IVectorDb
public async Task> GetCollections()
{
// List all the collections
- var collections = await _client.GetCollections();
- return collections.Result.Collections.Select(x => x.Name).ToList();
+ var collections = await _client.ListCollectionsAsync();
+ return collections.ToList();
}
public async Task CreateCollection(string collectionName, int dim)
@@ -43,7 +42,11 @@ public class QdrantDb : IVectorDb
if (!collections.Contains(collectionName))
{
// Create a new collection
- await _client.CreateCollection(collectionName, new VectorParams(size: dim, distance: Distance.COSINE));
+ await _client.CreateCollectionAsync(collectionName, new VectorParams()
+ {
+ Size = (ulong)dim,
+ Distance = Distance.Cosine
+ });
var agentService = _services.GetRequiredService();
var agentDataDir = agentService.GetAgentDataDir(collectionName);
@@ -52,7 +55,7 @@ public class QdrantDb : IVectorDb
}
// Get collection info
- var collectionInfo = await _client.GetCollection(collectionName);
+ var collectionInfo = await _client.GetCollectionInfoAsync(collectionName);
if (collectionInfo == null)
{
throw new Exception($"Create {collectionName} failed.");
@@ -62,9 +65,16 @@ public class QdrantDb : IVectorDb
public async Task Upsert(string collectionName, int id, float[] vector, string text)
{
// Insert vectors
- await _client.Upsert(collectionName, points: new List
+ await _client.UpsertAsync(collectionName, points: new List
{
- new PointStruct(id: id, vector: vector)
+ new PointStruct()
+ {
+ Id = new PointId()
+ {
+ Num = (ulong)id,
+ },
+ Vectors = vector
+ }
});
// Store chunks in local file system
@@ -76,13 +86,13 @@ public class QdrantDb : IVectorDb
public async Task> Search(string collectionName, float[] vector, int limit = 5)
{
- var result = await _client.Search(collectionName, vector, limit);
+ var result = await _client.SearchAsync(collectionName, vector, limit: (ulong)limit);
var agentService = _services.GetRequiredService();
var agentDataDir = agentService.GetAgentDataDir(collectionName);
var knowledgePath = Path.Combine(agentDataDir, "knowledge.txt");
var texts = File.ReadAllLines(knowledgePath);
- return result.Result.Select(x => texts[x.Id]).ToList();
+ return result.Select(x => texts[x.Id.Num]).ToList();
}
}