diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs index cdd30b99..6d832fe6 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs @@ -1,8 +1,9 @@ using BotSharp.Abstraction.Conversations.Models; +using BotSharp.Abstraction.MLTasks; namespace BotSharp.Abstraction.Conversations; -public abstract class ConversationCompletionHookBase +public abstract class ConversationCompletionHookBase : IConversationCompletionHook { protected Agent _agent; public Agent Agent => _agent; @@ -13,11 +14,40 @@ public abstract class ConversationCompletionHookBase protected List _dialogs; public List Dialogs => _dialogs; - public IConversationCompletionHook SetContexts(Agent agent, Conversation conversation, List dialogs) + protected IChatCompletion _chatCompletion; + public IChatCompletion ChatCompletion => _chatCompletion; + + public IConversationCompletionHook SetAgent(Agent agent) { _agent = agent; + return this; + } + + public IConversationCompletionHook SetConversation(Conversation conversation) + { _conversation = conversation; + return this; + } + + public IConversationCompletionHook SetDialogs(List dialogs) + { _dialogs = dialogs; - return this as IConversationCompletionHook; + return this; + } + + public IConversationCompletionHook SetChatCompletion(IChatCompletion chatCompletion) + { + _chatCompletion = chatCompletion; + return this; + } + + public virtual Task BeforeCompletion() + { + return Task.CompletedTask; + } + + public virtual Task AfterCompletion(string response) + { + return Task.FromResult(response); } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationCompletionHook.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationCompletionHook.cs index 866b5fc9..fadc055f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationCompletionHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationCompletionHook.cs @@ -1,13 +1,22 @@ using BotSharp.Abstraction.Conversations.Models; +using BotSharp.Abstraction.MLTasks; namespace BotSharp.Abstraction.Conversations; public interface IConversationCompletionHook { Agent Agent { get; } + IConversationCompletionHook SetAgent(Agent agent); + Conversation Conversation { get; } + IConversationCompletionHook SetConversation(Conversation conversation); + List Dialogs { get; } - IConversationCompletionHook SetContexts(Agent agent, Conversation conversation, List dialogs); + IConversationCompletionHook SetDialogs(List dialogs); + + IChatCompletion ChatCompletion { get; } + IConversationCompletionHook SetChatCompletion(IChatCompletion chatCompletion); + Task BeforeCompletion(); Task AfterCompletion(string response); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index 250d5c06..f8a3ecae 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -8,6 +8,12 @@ public class RoleDialogModel public string Role { get; set; } public string Text { get; set; } + public RoleDialogModel(string role, string text) + { + Role = role; + Text = text; + } + public override string ToString() { return $"{Role}: {Text}"; diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs index 6b70558b..3cc82b0c 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs @@ -45,11 +45,7 @@ public class ConversationController : ControllerBase, IApiAdapter { var conv = _services.GetRequiredService(); - var result = await conv.SendMessage(agentId, conversationId, new RoleDialogModel - { - Role = "user", - Text = input.Text - }); + var result = await conv.SendMessage(agentId, conversationId, new RoleDialogModel("user", input.Text)); return new MessageResponseModel { diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 9b820f2a..03ab2b36 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -53,8 +53,8 @@ public class ConversationService : IConversationService var db = _services.GetRequiredService(); var record = ConversationRecord.FromConversation(sess); - record.Id = Guid.NewGuid().ToString(); - record.UserId = _user.Id; + record.Id = sess.Id ?? Guid.NewGuid().ToString(); + record.UserId = sess.UserId ?? _user.Id; record.Title = "New Conversation"; db.Transaction(delegate @@ -75,11 +75,7 @@ public class ConversationService : IConversationService var response = await SendMessage(agentId, conversationId, wholeDialogs); - _storage.Append(agentId, conversationId, new RoleDialogModel - { - Role = "assistant", - Text = response - }); + _storage.Append(agentId, conversationId, new RoleDialogModel("assistant", response)); return response; } @@ -107,7 +103,10 @@ public class ConversationService : IConversationService hooks.ForEach(hook => { - hook.SetContexts(agent, converation, wholeDialogs) + hook.SetAgent(agent) + .SetConversation(converation) + .SetDialogs(wholeDialogs) + .SetChatCompletion(chatCompletion) .BeforeCompletion(); }); diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs index d486f947..34d8f7a3 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs @@ -26,11 +26,7 @@ public class ConversationStorage : IConversationStorage var pos = x.IndexOf(':'); var role = x.Substring(0, pos); var text = x.Substring(pos + 1); - return new RoleDialogModel - { - Role = role, - Text = text - }; + return new RoleDialogModel(role, text); }).ToList(); } diff --git a/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs b/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs index c58b903e..1b30a92d 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/DataContextHelper.cs @@ -30,10 +30,10 @@ public static class DataContextHelper dc.BindDbContext(new DatabaseBind { ServiceProvider = serviceProvider, - MasterConnection = new SqlConnection(settings.Agent.Master), - SlaveConnections = settings.Agent.Slavers.Length == 0 ? - new List { new SqlConnection(settings.Agent.Master) } : - settings.Agent.Slavers.Select(x => new SqlConnection(x) as DbConnection).ToList(), + MasterConnection = new SqlConnection(settings.BotSharp.Master), + SlaveConnections = settings.BotSharp.Slavers.Length == 0 ? + new List { new SqlConnection(settings.BotSharp.Master) } : + settings.BotSharp.Slavers.Select(x => new SqlConnection(x) as DbConnection).ToList(), CreateDbIfNotExist = true }); } diff --git a/src/Infrastructure/BotSharp.Core/Repository/MyDatabaseSettings.cs b/src/Infrastructure/BotSharp.Core/Repository/MyDatabaseSettings.cs index 1b68b80e..cadf7206 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/MyDatabaseSettings.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/MyDatabaseSettings.cs @@ -1,10 +1,8 @@ -using EntityFrameworkCore.BootKit; - namespace BotSharp.Core.Repository; public class MyDatabaseSettings : DatabaseSettings { public string[] Assemblies { get; set; } public DbConnectionSetting MongoDb { get; set; } - public DbConnectionSetting Agent { get; set; } + public DbConnectionSetting BotSharp { get; set; } } diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/AzureOpenAiPlugin.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/AzureOpenAiPlugin.cs index 49aa3bde..dfc3d00b 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/AzureOpenAiPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/AzureOpenAiPlugin.cs @@ -15,7 +15,7 @@ public class AzureOpenAiPlugin : IBotSharpPlugin config.Bind("AzureOpenAi", settings); services.AddSingleton(x => settings); - services.AddSingleton(); + services.AddScoped(); services.AddScoped(); } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs index 2b1e3f23..22b8c2fc 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs @@ -48,22 +48,31 @@ public class ChatCompletionProvider : IChatCompletion public List GetChatSamples(string sampleText) { var samples = new List(); - if (!string.IsNullOrEmpty(sampleText)) + if (string.IsNullOrEmpty(sampleText)) { - var lines = sampleText.Split('\n'); - for (int i = 0; i < lines.Length; i += 3) - { - var line = lines[i]; - var role = line.Substring(0, line.IndexOf(' ') - 1).Trim(); - var content = line.Substring(line.IndexOf(' ') + 1).Trim(); - - samples.Add(new RoleDialogModel - { - Role = role, - Text = content - }); - } + return samples; } + + var lines = sampleText.Split('\n'); + for (int i = 0; i < lines.Length; i++) + { + var line = lines[i]; + if (string.IsNullOrEmpty(line.Trim())) + { + continue; + } + var role = line.Substring(0, line.IndexOf(' ') - 1).Trim(); + var content = line.Substring(line.IndexOf(' ') + 1).Trim(); + + // comments + if (role == "##") + { + continue; + } + + samples.Add(new RoleDialogModel(role, content)); + } + return samples; } @@ -104,8 +113,9 @@ public class ChatCompletionProvider : IChatCompletion { chatCompletionsOptions.Messages.Add(new ChatMessage(ChatRole.System, agent.Knowledges)); } - - foreach (var message in GetChatSamples(agent.Samples)) + + var samples = GetChatSamples(agent.Samples); + foreach (var message in samples) { chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Text)); } diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs index 8cefdeef..ab671a2f 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs @@ -59,23 +59,26 @@ public class ChatbotUiController : ControllerBase, IApiAdapter Response.Headers.Add(HeaderNames.Connection, "keep-alive"); var outputStream = Response.Body; - var conversations = input.Messages.Select(x => new RoleDialogModel - { - Role = x.Role, - Text = x.Content - }).ToList(); + var conversations = input.Messages + .Select(x => new RoleDialogModel(x.Role, x.Content)) + .ToList(); - var conv = _services.GetRequiredService(); + var conversationService = _services.GetRequiredService(); // Check if this conversation exists - var converation = await conv.GetConversation(input.ConversationId); - var sess = new Conversation + var converation = await conversationService.GetConversation(input.ConversationId); + if(converation == null) { - AgentId = input.AgentId - }; - sess = await conv.NewConversation(sess); + var sess = new Conversation + { + Id = input.ConversationId, + UserId = Guid.Empty.ToString(), + AgentId = input.AgentId + }; + converation = await conversationService.NewConversation(sess); + } - var result = await conv.SendMessage(input.AgentId, input.ConversationId, conversations); + var result = await conversationService.SendMessage(input.AgentId, input.ConversationId, conversations); await OnChunkReceived(outputStream, result); await OnEventCompleted(outputStream); diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs b/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs index 8bff419d..419ccc6c 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs @@ -13,7 +13,6 @@ public class OpenAiMessageInput [JsonPropertyName("max_tokens")] public int MaxTokens { get; set; } = 4000; public bool Stream { get; set; } = true; - public string? SystemPrompt { get; set; } public float Temperature { get; set; } = 0.9f; public override string ToString()