From 08b96c24755be87a988a5669360313b863142abc Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Mon, 12 Jun 2023 08:28:49 -0500 Subject: [PATCH] Support conversation session partially. --- .../Agents/IAgentService.cs | 2 +- .../Conversations/ISessionService.cs | 6 +-- .../Conversations/Models/Session.cs | 11 ++++ .../Conversations/Models/SessionModel.cs | 7 --- .../BotSharp.Core/Agents/AgentController.cs | 5 +- .../Agents/Services/AgentService.cs | 27 ++++++---- .../Agents/ViewModels/AgentViewModel.cs | 16 +++++- .../BotSharpServiceCollectionExtensions.cs | 7 ++- .../Conversations/ConversationController.cs | 34 ++++++++++++ .../{ => Services}/ConversationService.cs | 2 +- .../Conversations/Services/SessionService.cs | 49 +++++++++++++++++ .../Conversations/SessionService.cs | 50 ------------------ .../ViewModels/SessionCreationModel.cs | 16 ++++++ .../ViewModels/SessionViewModel.cs | 24 +++++++++ .../Repository/AgentDbContext.cs | 3 +- .../Repository/DbTables/AgentRecord.cs | 13 +++++ .../Repository/DbTables/SessionRecord.cs | 52 +++++++++++++++++++ src/Infrastructure/BotSharp.Core/Using.cs | 6 ++- 18 files changed, 248 insertions(+), 82 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Session.cs delete mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Models/SessionModel.cs create mode 100644 src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs rename src/Infrastructure/BotSharp.Core/Conversations/{ => Services}/ConversationService.cs (95%) create mode 100644 src/Infrastructure/BotSharp.Core/Conversations/Services/SessionService.cs delete mode 100644 src/Infrastructure/BotSharp.Core/Conversations/SessionService.cs create mode 100644 src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionCreationModel.cs create mode 100644 src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionViewModel.cs create mode 100644 src/Infrastructure/BotSharp.Core/Repository/DbTables/SessionRecord.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 28757dff..a914ce42 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -7,7 +7,7 @@ namespace BotSharp.Abstraction.Agents; /// public interface IAgentService { - Task CreateAgent(Agent agent); + Task CreateAgent(Agent agent); Task DeleteAgent(string id); Task UpdateAgent(Agent agent); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ISessionService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ISessionService.cs index 99e61e6d..8e869182 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ISessionService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ISessionService.cs @@ -4,7 +4,7 @@ namespace BotSharp.Abstraction.Conversations; public interface ISessionService { - Task NewSession(string userId); - List GetAllSessions(string userId); - void DeleteSession(string sessionId); + Task NewSession(Session sess); + Task> GetSessions(); + Task DeleteSession(string sessionId); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Session.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Session.cs new file mode 100644 index 00000000..1048c807 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Session.cs @@ -0,0 +1,11 @@ +namespace BotSharp.Abstraction.Conversations.Models; + +public class Session +{ + public string Id { get; set; } = string.Empty; + public string AgentId { get; set; } = string.Empty; + public string UserId { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public DateTime UpdatedTime { get; set; } = DateTime.UtcNow; + public DateTime CreatedTime { get; set; } = DateTime.UtcNow; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/SessionModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/SessionModel.cs deleted file mode 100644 index 5852c93d..00000000 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/SessionModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace BotSharp.Abstraction.Conversations.Models; - -public class SessionModel -{ - public string UserId { get; set; } = string.Empty; - public string SessionId { get; set; } = string.Empty; -} diff --git a/src/Infrastructure/BotSharp.Core/Agents/AgentController.cs b/src/Infrastructure/BotSharp.Core/Agents/AgentController.cs index 09d3cc24..0db3a1de 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/AgentController.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/AgentController.cs @@ -17,8 +17,9 @@ public class AgentController : ControllerBase, IApiAdapter } [HttpPost("/agent")] - public async Task CreateAgent(AgentCreationModel agent) + public async Task CreateAgent(AgentCreationModel agent) { - return await _agentService.CreateAgent(agent.ToAgent()); + var createdAgent = await _agentService.CreateAgent(agent.ToAgent()); + return AgentViewModel.FromAgent(createdAgent); } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs index 574f483d..4a521a75 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs @@ -1,32 +1,41 @@ using BotSharp.Abstraction.Agents; using BotSharp.Abstraction.Agents.Models; -using BotSharp.Core.Repository; -using BotSharp.Core.Repository.Abstraction; -using BotSharp.Core.Repository.DbTables; -using EntityFrameworkCore.BootKit; -using Microsoft.Extensions.DependencyInjection; +using BotSharp.Abstraction.Users; namespace BotSharp.Core.Agents.Services; public class AgentService : IAgentService { private readonly IServiceProvider _services; - public AgentService(IServiceProvider services) + private readonly ICurrentUser _user; + + public AgentService(IServiceProvider services, ICurrentUser user) { _services = services; + _user = user; } - public async Task CreateAgent(Agent agent) + public async Task CreateAgent(Agent agent) { var db = _services.GetRequiredService(); - var record = AgentRecord.FromAgent(agent); + var record = db.Agent.FirstOrDefault(x => x.OwnerId == _user.Id && x.Name == agent.Name); + if (record != null) + { + return record.ToAgent(); + } + + record = AgentRecord.FromAgent(agent); + record.Id = Guid.NewGuid().ToString(); + record.OwnerId = _user.Id; + record.CreatedDateTime = DateTime.UtcNow; + record.UpdatedDateTime = DateTime.UtcNow; db.Transaction(delegate { db.Add(record); }); - return record.Id; + return record.ToAgent(); } public Task DeleteAgent(string id) diff --git a/src/Infrastructure/BotSharp.Core/Agents/ViewModels/AgentViewModel.cs b/src/Infrastructure/BotSharp.Core/Agents/ViewModels/AgentViewModel.cs index 168525ae..1115d582 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/ViewModels/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/ViewModels/AgentViewModel.cs @@ -1,8 +1,22 @@ +using BotSharp.Abstraction.Agents.Models; + namespace BotSharp.Core.Agents.ViewModels; public class AgentViewModel { public string Id { get; set; } public string Name { get; set; } - public string Description { get; set; } + public string Description { get; set; } + public DateTime UpdatedDateTime { get; set; } + + public static AgentViewModel FromAgent(Agent agent) + { + return new AgentViewModel + { + Id = agent.Id, + Name = agent.Name, + Description = agent.Description, + UpdatedDateTime = agent.UpdatedDateTime + }; + } } diff --git a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs index 9296ec35..f46a1f31 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs +++ b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs @@ -2,12 +2,11 @@ using BotSharp.Abstraction.Agents; using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Users; using BotSharp.Core.Agents.Services; -using BotSharp.Core.Conversations; +using BotSharp.Core.Conversations.Services; using BotSharp.Core.Users.Services; using BotSharp.Plugins.LLamaSharp; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; namespace BotSharp.Core; @@ -18,8 +17,8 @@ public static class BotSharpServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddSingleton(); - services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); RegisterRepository(services, config); diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs new file mode 100644 index 00000000..52d4a822 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs @@ -0,0 +1,34 @@ +using BotSharp.Abstraction.ApiAdapters; +using BotSharp.Abstraction.Conversations; +using BotSharp.Core.Conversations.ViewModels; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace BotSharp.Core.Conversations; + +[Authorize] +[ApiController] +public class ConversationController : ControllerBase, IApiAdapter +{ + private readonly IServiceProvider _services; + + public ConversationController(IServiceProvider services) + { + _services = services; + } + + [HttpPost("/conversation/session")] + public async Task NewSession([FromBody] SessionCreationModel session) + { + var service = _services.GetRequiredService(); + var sess = session.ToSession(); + sess = await service.NewSession(sess); + return SessionViewModel.FromSession(sess); + } + + [HttpDelete("/conversation/session/{sessionId}")] + public async Task DeleteSession([FromRoute] string sessionId) + { + var service = _services.GetRequiredService(); + } +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs similarity index 95% rename from src/Infrastructure/BotSharp.Core/Conversations/ConversationService.cs rename to src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 507d0db5..f8357c5b 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Text; -namespace BotSharp.Core.Conversations; +namespace BotSharp.Core.Conversations.Services; public class ConversationService : IConversationService { diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/SessionService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/SessionService.cs new file mode 100644 index 00000000..f950c5f0 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/SessionService.cs @@ -0,0 +1,49 @@ +using BotSharp.Abstraction.Conversations; +using BotSharp.Abstraction.Conversations.Models; +using BotSharp.Abstraction.Users; + +namespace BotSharp.Core.Conversations.Services; + +public class SessionService : ISessionService +{ + private readonly IServiceProvider _services; + private readonly ICurrentUser _user; + + public SessionService(IServiceProvider services, ICurrentUser user) + { + _services = services; + _user = user; + } + + public Task DeleteSession(string sessionId) + { + throw new NotImplementedException(); + } + + public async Task> GetSessions() + { + var db = _services.GetRequiredService(); + var query = from sess in db.Session + where sess.UserId == _user.Id + orderby sess.CreatedTime descending + select sess.ToSession(); + return query.ToList(); + } + + public async Task NewSession(Session sess) + { + var db = _services.GetRequiredService(); + + var record = SessionRecord.FromSession(sess); + record.Id = Guid.NewGuid().ToString(); + record.UserId = _user.Id; + record.Title = "New Session"; + + db.Transaction(delegate + { + db.Add(record); + }); + + return record.ToSession(); + } +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/SessionService.cs b/src/Infrastructure/BotSharp.Core/Conversations/SessionService.cs deleted file mode 100644 index 7278f7ea..00000000 --- a/src/Infrastructure/BotSharp.Core/Conversations/SessionService.cs +++ /dev/null @@ -1,50 +0,0 @@ -using BotSharp.Abstraction.Conversations; -using BotSharp.Abstraction.Conversations.Models; -using BotSharp.Core.Repository; -using BotSharp.Core.Repository.Collections; -using EntityFrameworkCore.BootKit; -using Microsoft.Extensions.DependencyInjection; -using MongoDB.Bson; -using MongoDB.Driver; - -namespace BotSharp.Core.Conversations; - -public class SessionService : ISessionService -{ - private readonly IServiceProvider _services; - - public SessionService(IServiceProvider services) - { - _services = services; - } - - public void DeleteSession(string sessionId) - { - throw new NotImplementedException(); - } - - public List GetAllSessions(string userId) - { - throw new NotImplementedException(); - } - - public async Task NewSession(string userId) - { - var mongo = _services.CreateScope().ServiceProvider.GetRequiredService(); - - var record = new Conversation - { - CreatedAt = DateTime.UtcNow, - Messages = new List(), - UserId = "anonymous", - Model = "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5" - }; - await mongo.Conversations.InsertOneAsync(record); - - return new SessionModel - { - SessionId = record.Id.ToString(), - UserId = record.UserId - }; - } -} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionCreationModel.cs b/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionCreationModel.cs new file mode 100644 index 00000000..948e1d6b --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionCreationModel.cs @@ -0,0 +1,16 @@ +using BotSharp.Abstraction.Conversations.Models; + +namespace BotSharp.Core.Conversations.ViewModels; + +public class SessionCreationModel +{ + public string AgentId { get; set; } + + public Session ToSession() + { + return new Session + { + AgentId = AgentId + }; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionViewModel.cs b/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionViewModel.cs new file mode 100644 index 00000000..267e8ffd --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/SessionViewModel.cs @@ -0,0 +1,24 @@ +using BotSharp.Abstraction.Conversations.Models; + +namespace BotSharp.Core.Conversations.ViewModels; + +public class SessionViewModel +{ + public string Id { get; set; } + public string AgentId { get; set; } + public string Title { get; set; } = string.Empty; + public DateTime UpdatedTime { get; set; } = DateTime.UtcNow; + public DateTime CreatedTime { get; set; } = DateTime.UtcNow; + + public static SessionViewModel FromSession(Session sess) + { + return new SessionViewModel + { + Id = sess.Id, + AgentId = sess.AgentId, + Title = sess.Title, + CreatedTime = sess.CreatedTime, + UpdatedTime = sess.UpdatedTime + }; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Repository/AgentDbContext.cs b/src/Infrastructure/BotSharp.Core/Repository/AgentDbContext.cs index 97072369..1c0d1c96 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/AgentDbContext.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/AgentDbContext.cs @@ -1,9 +1,8 @@ -using BotSharp.Core.Repository.DbTables; - namespace BotSharp.Core.Repository; public class AgentDbContext : Database { public IQueryable User => Table(); public IQueryable Agent => Table(); + public IQueryable Session => Table(); } diff --git a/src/Infrastructure/BotSharp.Core/Repository/DbTables/AgentRecord.cs b/src/Infrastructure/BotSharp.Core/Repository/DbTables/AgentRecord.cs index fcfe3e41..11cfbfa7 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/DbTables/AgentRecord.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/DbTables/AgentRecord.cs @@ -34,4 +34,17 @@ public class AgentRecord : DbRecord, IAgentTable OwnerId = agent.OwerId }; } + + public Agent ToAgent() + { + return new Agent + { + Id = Id, + Name = Name, + Description = Description, + OwerId = OwnerId, + CreatedDateTime = CreatedDateTime, + UpdatedDateTime = UpdatedDateTime + }; + } } diff --git a/src/Infrastructure/BotSharp.Core/Repository/DbTables/SessionRecord.cs b/src/Infrastructure/BotSharp.Core/Repository/DbTables/SessionRecord.cs new file mode 100644 index 00000000..eb37bcd0 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Repository/DbTables/SessionRecord.cs @@ -0,0 +1,52 @@ +using BotSharp.Abstraction.Conversations.Models; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace BotSharp.Core.Repository.DbTables; + +[Table("Session")] +public class SessionRecord : DbRecord, IAgentTable +{ + [Required] + [MaxLength(36)] + public string AgentId { get; set; } = string.Empty; + + [Required] + [MaxLength(36)] + public string UserId { get; set; } = string.Empty; + + [MaxLength(64)] + public string Title { get; set; } = string.Empty; + + [Required] + public DateTime UpdatedTime { get; set; } = DateTime.UtcNow; + + [Required] + public DateTime CreatedTime { get; set; } = DateTime.UtcNow; + + public static SessionRecord FromSession(Session sess) + { + return new SessionRecord + { + AgentId = sess.AgentId, + UserId = sess.UserId, + Id = sess.Id, + Title = sess.Title, + CreatedTime = sess.CreatedTime, + UpdatedTime = sess.UpdatedTime + }; + } + + public Session ToSession() + { + return new Session + { + Id = Id, + Title = Title, + UserId = UserId, + AgentId = AgentId, + CreatedTime = CreatedTime, + UpdatedTime = UpdatedTime + }; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Using.cs b/src/Infrastructure/BotSharp.Core/Using.cs index a12f7db8..0e2fb894 100644 --- a/src/Infrastructure/BotSharp.Core/Using.cs +++ b/src/Infrastructure/BotSharp.Core/Using.cs @@ -2,9 +2,11 @@ global using System; global using System.Collections.Generic; global using System.Text; global using System.Threading.Tasks; -global using BotSharp.Abstraction; global using System.Linq; +global using Microsoft.Extensions.DependencyInjection; global using BotSharp.Abstraction.Plugins; global using EntityFrameworkCore.BootKit; +global using BotSharp.Abstraction; global using BotSharp.Core.Repository; -global using BotSharp.Core.Repository.Abstraction; \ No newline at end of file +global using BotSharp.Core.Repository.Abstraction; +global using BotSharp.Core.Repository.DbTables; \ No newline at end of file