diff --git a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj
index 1419d509..98449d96 100644
--- a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj
+++ b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj
@@ -8,6 +8,12 @@
Icon.png
+
+
+
+
+
+
True
@@ -22,8 +28,4 @@
-
-
-
-
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs
new file mode 100644
index 00000000..6d832fe6
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationCompletionHookBase.cs
@@ -0,0 +1,53 @@
+using BotSharp.Abstraction.Conversations.Models;
+using BotSharp.Abstraction.MLTasks;
+
+namespace BotSharp.Abstraction.Conversations;
+
+public abstract class ConversationCompletionHookBase : IConversationCompletionHook
+{
+ protected Agent _agent;
+ public Agent Agent => _agent;
+
+ protected Conversation _conversation;
+ public Conversation Conversation => _conversation;
+
+ protected List _dialogs;
+ public List Dialogs => _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;
+ }
+
+ 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 be68b6d6..fadc055f 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationCompletionHook.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationCompletionHook.cs
@@ -1,9 +1,22 @@
using BotSharp.Abstraction.Conversations.Models;
+using BotSharp.Abstraction.MLTasks;
namespace BotSharp.Abstraction.Conversations;
public interface IConversationCompletionHook
{
- Task BeforeCompletion(Agent agent, List conversations);
- Task AfterCompletion(Agent agent, string response);
+ Agent Agent { get; }
+ IConversationCompletionHook SetAgent(Agent agent);
+
+ Conversation Conversation { get; }
+ IConversationCompletionHook SetConversation(Conversation conversation);
+
+ List Dialogs { get; }
+ 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/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs
index 72d2b3ae..8d87c51e 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs
@@ -5,6 +5,7 @@ namespace BotSharp.Abstraction.Conversations;
public interface IConversationService
{
Task NewConversation(Conversation conversation);
+ Task GetConversation(string id);
Task> GetConversations();
Task DeleteConversation(string id);
Task SendMessage(string agentId, string conversationId, RoleDialogModel lastDalog);
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.Abstraction/Utilities/StringExtensions.cs b/src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs
new file mode 100644
index 00000000..8352bcff
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Utilities/StringExtensions.cs
@@ -0,0 +1,7 @@
+namespace BotSharp.Abstraction.Utilities;
+
+public static class StringExtensions
+{
+ public static string IfNullOrEmptyAs(this string str, string defaultValue)
+ => string.IsNullOrEmpty(str) ? defaultValue : str;
+}
diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
index 4f5e5df0..5d00e58d 100644
--- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
+++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj
@@ -34,14 +34,25 @@
https://raw.githubusercontent.com/SciSharp/BotSharp/master/docs/static/logos/BotSharp.png
https://raw.githubusercontent.com/SciSharp/BotSharp/master/LICENSE
Icon.png
+ enable
TRACE;DEBUG
+ 1701;1702
TRACE;
+ 1701;1702
+
+
+
+ 1701;1702
+
+
+
+ 1701;1702
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs
index 6b70558b..debb5db3 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationController.cs
@@ -26,6 +26,7 @@ public class ConversationController : ControllerBase, IApiAdapter
var service = _services.GetRequiredService();
var sess = new Conversation
{
+ UserId = _user.Id,
AgentId = agentId
};
sess = await service.NewConversation(sess);
@@ -45,15 +46,11 @@ 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
{
- Content = result
+ Text = result
};
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
index 5f5c1d33..9f89a15f 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
@@ -28,6 +28,16 @@ public class ConversationService : IConversationService
throw new NotImplementedException();
}
+ public async Task GetConversation(string id)
+ {
+ var db = _services.GetRequiredService();
+ var query = from sess in db.Conversation
+ where sess.Id == id
+ orderby sess.CreatedTime descending
+ select sess.ToConversation();
+ return query.FirstOrDefault();
+ }
+
public async Task> GetConversations()
{
var db = _services.GetRequiredService();
@@ -43,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.IfNullOrEmptyAs(Guid.NewGuid().ToString());
+ record.UserId = sess.UserId.IfNullOrEmptyAs(_user.Id);
record.Title = "New Conversation";
db.Transaction(delegate
@@ -65,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;
}
@@ -77,6 +83,7 @@ public class ConversationService : IConversationService
public async Task SendMessage(string agentId, string conversationId, List wholeDialogs)
{
var agent = await _services.GetRequiredService().GetAgent(agentId);
+ var converation = await GetConversation(conversationId);
// Get relevant domain knowledge
if (_settings.EnableKnowledgeBase)
@@ -94,14 +101,21 @@ public class ConversationService : IConversationService
// Before chat completion hook
var hooks = _services.GetServices().ToList();
- hooks.ForEach(hook => hook.BeforeCompletion(agent, wholeDialogs));
+ hooks.ForEach(hook =>
+ {
+ hook.SetAgent(agent)
+ .SetConversation(converation)
+ .SetDialogs(wholeDialogs)
+ .SetChatCompletion(chatCompletion)
+ .BeforeCompletion();
+ });
var response = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs);
// After chat completion hook
hooks.ForEach(async hook =>
{
- response = await hook.AfterCompletion(agent, response);
+ response = await hook.AfterCompletion(response);
});
return response;
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/Conversations/ViewModels/MessageResponseModel.cs b/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/MessageResponseModel.cs
index 2a2f050d..68f58a5f 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/MessageResponseModel.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/ViewModels/MessageResponseModel.cs
@@ -2,5 +2,5 @@ namespace BotSharp.Core.Conversations.ViewModels;
public class MessageResponseModel
{
- public string Content { get; set; }
+ public string Text { get; set; }
}
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/Infrastructure/BotSharp.Core/Using.cs b/src/Infrastructure/BotSharp.Core/Using.cs
index 28976df7..304bcf8c 100644
--- a/src/Infrastructure/BotSharp.Core/Using.cs
+++ b/src/Infrastructure/BotSharp.Core/Using.cs
@@ -10,6 +10,7 @@ global using BotSharp.Abstraction.Agents;
global using BotSharp.Abstraction.Conversations;
global using BotSharp.Abstraction.Knowledges;
global using BotSharp.Abstraction.Users;
+global using BotSharp.Abstraction.Utilities;
global using BotSharp.Core.Repository;
global using BotSharp.Core.Repository.Abstraction;
global using BotSharp.Core.Repository.DbTables;
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 cb11d9a5..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++)
- {
- var line = lines[i];
- var role = line.Substring(0, line.IndexOf(' ') - 1);
- var content = line.Substring(line.IndexOf(' ') + 1);
-
- 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 18975e5b..0337c983 100644
--- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs
+++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs
@@ -16,9 +16,11 @@ using BotSharp.Plugin.ChatbotUI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Conversations.Models;
+using Microsoft.AspNetCore.Authorization;
namespace BotSharp.Plugin.ChatbotUI.Controllers;
+[Authorize]
[ApiController]
public class ChatbotUiController : ControllerBase, IApiAdapter
{
@@ -59,15 +61,25 @@ public class ChatbotUiController : ControllerBase, IApiAdapter
Response.Headers.Add(HeaderNames.Connection, "keep-alive");
var outputStream = Response.Body;
- var conversations = input.Messages.Skip(1).Select(x => new RoleDialogModel
+ var conversations = input.Messages
+ .Select(x => new RoleDialogModel(x.Role, x.Content))
+ .ToList();
+
+ var conversationService = _services.GetRequiredService();
+
+ // Check if this conversation exists
+ var converation = await conversationService.GetConversation(input.ConversationId);
+ if(converation == null)
{
- Role = x.Role,
- Text = x.Content
- }).ToList();
+ var sess = new Conversation
+ {
+ Id = input.ConversationId,
+ AgentId = input.AgentId
+ };
+ converation = await conversationService.NewConversation(sess);
+ }
- var conv = _services.GetRequiredService();
-
- var result = await conv.SendMessage("", "", conversations.Last());
+ 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 2cbbf286..419ccc6c 100644
--- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs
+++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs
@@ -6,6 +6,8 @@ namespace BotSharp.Plugin.ChatbotUI.ViewModels;
public class OpenAiMessageInput
{
+ public string AgentId { get; set; }
+ public string ConversationId { get; set; }
public string Model { get; set; } = string.Empty;
public List Messages { get; set; } = new List();
[JsonPropertyName("max_tokens")]