From 05b8db8547eaf69fa801325c52ed3fa2531373b7 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 5 Sep 2023 22:19:36 -0500 Subject: [PATCH] Support states from inbound api. --- docs/architecture/assets/diagram.drawio | 43 +++++---- docs/architecture/assets/overview.drawio | 73 +++++++++++++++ .../assets/routing-reasoning.drawio | 92 +++++++++++++++++++ docs/architecture/assets/routing.drawio | 59 ++++++++++++ .../Conversations/IConversationService.cs | 5 +- .../IConversationStateService.cs | 6 +- .../Conversations/IConversationStorage.cs | 2 - .../Routing/Models/RetrievalArgs.cs | 4 +- .../Agents/Services/AgentService.LoadAgent.cs | 6 +- .../ConversationService.CallFunctions.cs | 3 +- ...vice.GetChatCompletionsAsyncRecursively.cs | 5 +- .../ConversationService.SendMessage.cs | 54 +++++------ .../Services/ConversationService.cs | 22 ++++- .../Services/ConversationStateService.cs | 47 ++++------ .../BotSharp.Core/Routing/Simulator.cs | 4 +- .../Controllers/ConversationController.cs | 6 +- .../Conversations/NewMessageModel.cs | 5 + .../ChatbotUiController.cs | 14 +-- .../ViewModels/OpenAiMessageInput.cs | 4 + .../Controllers/WebhookController.cs | 7 +- .../WeChatBackgroundService.cs | 7 +- .../Functions/GetBakingTimeFn.cs | 14 +++ .../Functions/GetPizzaPricesFn.cs | 1 - .../{MakeOrderFn.cs => PlaceOrderFn.cs} | 4 +- .../Hooks/PizzaBotAgentHook.cs | 2 +- .../PizzaBotPlugin.cs | 3 +- 26 files changed, 372 insertions(+), 120 deletions(-) create mode 100644 docs/architecture/assets/overview.drawio create mode 100644 docs/architecture/assets/routing-reasoning.drawio create mode 100644 docs/architecture/assets/routing.drawio create mode 100644 tests/BotSharp.Plugin.PizzaBot/Functions/GetBakingTimeFn.cs rename tests/BotSharp.Plugin.PizzaBot/Functions/{MakeOrderFn.cs => PlaceOrderFn.cs} (74%) diff --git a/docs/architecture/assets/diagram.drawio b/docs/architecture/assets/diagram.drawio index 1170e476..291cd8f2 100644 --- a/docs/architecture/assets/diagram.drawio +++ b/docs/architecture/assets/diagram.drawio @@ -1,69 +1,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + diff --git a/docs/architecture/assets/overview.drawio b/docs/architecture/assets/overview.drawio new file mode 100644 index 00000000..b6dacd1a --- /dev/null +++ b/docs/architecture/assets/overview.drawio @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/architecture/assets/routing-reasoning.drawio b/docs/architecture/assets/routing-reasoning.drawio new file mode 100644 index 00000000..cc9b5643 --- /dev/null +++ b/docs/architecture/assets/routing-reasoning.drawio @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/architecture/assets/routing.drawio b/docs/architecture/assets/routing.drawio new file mode 100644 index 00000000..7df280ab --- /dev/null +++ b/docs/architecture/assets/routing.drawio @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index 48107244..7ddf8ad8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -4,7 +4,9 @@ namespace BotSharp.Abstraction.Conversations; public interface IConversationService { + IConversationStateService States { get; } Task NewConversation(Conversation conversation); + void SetConversationId(string conversationId, string channel); Task GetConversation(string id); Task> GetConversations(); Task DeleteConversation(string id); @@ -22,13 +24,12 @@ public interface IConversationService /// This delegate is useful when you want to report progress on UI /// Task SendMessage(string agentId, - string conversationId, RoleDialogModel lastDalog, Func onMessageReceived, Func onFunctionExecuting, Func onFunctionExecuted); - List GetDialogHistory(string conversationId, int lastCount = 20); + List GetDialogHistory(int lastCount = 20); Task CleanHistory(string agentId); Task CallFunctions(RoleDialogModel msg); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs index 420f1191..72dc54f2 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs @@ -1,5 +1,3 @@ -using BotSharp.Abstraction.Conversations.Models; - namespace BotSharp.Abstraction.Conversations; /// @@ -7,9 +5,9 @@ namespace BotSharp.Abstraction.Conversations; /// public interface IConversationStateService { - void SetConversation(string conversationId); - ConversationState Load(); + ConversationState Load(string conversationId); string GetState(string name); + ConversationState GetStates(); void SetState(string name, string value); void CleanState(); void Save(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStorage.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStorage.cs index ed5044b0..1805bbe0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStorage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStorage.cs @@ -1,5 +1,3 @@ -using BotSharp.Abstraction.Conversations.Models; - namespace BotSharp.Abstraction.Conversations; public interface IConversationStorage diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RetrievalArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RetrievalArgs.cs index e0b3f9a1..5786b73f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RetrievalArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RetrievalArgs.cs @@ -11,8 +11,8 @@ public class RetrievalArgs : RoutingArgs [JsonPropertyName("answer")] public string Answer { get; set; } - [JsonPropertyName("reason")] - public string Reason { get; set; } + [JsonPropertyName("response")] + public string Response { get; set; } [JsonPropertyName("args")] public JsonDocument Arguments { get; set; } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index e2f13567..7ea90864 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -1,6 +1,5 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Templating; -using BotSharp.Core.Templating; namespace BotSharp.Core.Agents.Services; @@ -56,9 +55,8 @@ public partial class AgentService private void PopulateState(Dictionary dict) { - var stateService = _services.GetRequiredService(); - var state = stateService.Load(); - foreach (var t in state) + var conv = _services.GetRequiredService(); + foreach (var t in conv.States.GetStates()) { dict[t.Key] = t.Value; } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.CallFunctions.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.CallFunctions.cs index 01b3444b..5c3f941a 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.CallFunctions.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.CallFunctions.cs @@ -7,7 +7,8 @@ public partial class ConversationService public async Task CallFunctions(RoleDialogModel msg) { var hooks = _services.GetServices() - .OrderBy(x => x.Priority).ToList(); + .OrderBy(x => x.Priority) + .ToList(); // Invoke functions var functions = _services.GetServices() diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs index 21e8950c..c1780c60 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs @@ -10,7 +10,6 @@ public partial class ConversationService int currentRecursiveDepth = 0; private async Task GetChatCompletionsAsyncRecursively(IChatCompletion chatCompletion, - string conversationId, Agent agent, List wholeDialogs, Func onMessageReceived, @@ -43,7 +42,7 @@ public partial class ConversationService await HandleAssistantMessage(msg, onMessageReceived); // Add to dialog history - _storage.Append(conversationId, agent.Id, msg); + _storage.Append(_conversationId, agent.Id, msg); }, async fn => { var preAgentId = agent.Id; @@ -72,7 +71,6 @@ public partial class ConversationService wholeDialogs.Add(fn); await GetChatCompletionsAsyncRecursively(chatCompletion, - conversationId, agent, wholeDialogs, onMessageReceived, @@ -103,7 +101,6 @@ public partial class ConversationService wholeDialogs.Add(fn); await GetChatCompletionsAsyncRecursively(chatCompletion, - conversationId, agent, wholeDialogs, onMessageReceived, diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index d44eb56a..d9ce0967 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -1,6 +1,5 @@ using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Models; -using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.Routing.Settings; using BotSharp.Core.Routing; @@ -9,30 +8,13 @@ namespace BotSharp.Core.Conversations.Services; public partial class ConversationService { - public async Task SendMessage(string agentId, string conversationId, + public async Task SendMessage(string agentId, RoleDialogModel lastDialog, Func onMessageReceived, Func onFunctionExecuting, Func onFunctionExecuted) { - var converation = await GetConversation(conversationId); - - // Create conversation if this conversation not exists - if (converation == null) - { - var sess = new Conversation - { - Id = conversationId, - AgentId = agentId - }; - converation = await NewConversation(sess); - } - - // conversation state - var stateService = _services.GetRequiredService(); - stateService.SetConversation(conversationId); - stateService.Load(); - stateService.SetState("channel", lastDialog.Channel); + var conversation = await GetConversationRecord(agentId); var agentService = _services.GetRequiredService(); Agent agent = await agentService.LoadAgent(agentId); @@ -41,10 +23,10 @@ public partial class ConversationService lastDialog.CurrentAgentId = agent.Id; - var wholeDialogs = GetDialogHistory(conversationId); + var wholeDialogs = GetDialogHistory(); wholeDialogs.Add(lastDialog); - _storage.Append(conversationId, agent.Id, lastDialog); + _storage.Append(_conversationId, agent.Id, lastDialog); // Get relevant domain knowledge /*if (_settings.EnableKnowledgeBase) @@ -63,7 +45,7 @@ public partial class ConversationService foreach (var hook in hooks) { hook.SetAgent(agent) - .SetConversation(converation); + .SetConversation(conversation); await hook.OnDialogsLoaded(wholeDialogs); await hook.BeforeCompletion(lastDialog); @@ -73,7 +55,7 @@ public partial class ConversationService { var response = new RoleDialogModel(AgentRole.Assistant, lastDialog.Content); await onMessageReceived(response); - _storage.Append(conversationId, agent.Id, response); + _storage.Append(_conversationId, agent.Id, response); return true; } } @@ -114,13 +96,15 @@ public partial class ConversationService simulator.Dialogs.ForEach(x => { wholeDialogs.Add(x); - _storage.Append(conversationId, agent.Id, x); + if (x.Content != null) + { + _storage.Append(_conversationId, agent.Id, x); + } }); } var chatCompletion = GetChatCompletion(); var result = await GetChatCompletionsAsyncRecursively(chatCompletion, - conversationId, agent, wholeDialogs, onMessageReceived, @@ -130,6 +114,24 @@ public partial class ConversationService return result; } + private async Task GetConversationRecord(string agentId) + { + var converation = await GetConversation(_conversationId); + + // Create conversation if this conversation not exists + if (converation == null) + { + var sess = new Conversation + { + Id = _conversationId, + AgentId = agentId + }; + converation = await NewConversation(sess); + } + + return converation; + } + private void SaveStateByArgs(string args) { var stateService = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 299ad8a6..6f409ce8 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -1,5 +1,3 @@ -using BotSharp.Abstraction.Conversations.Models; - namespace BotSharp.Core.Conversations.Services; public partial class ConversationService : IConversationService @@ -9,17 +7,23 @@ public partial class ConversationService : IConversationService private readonly IUserIdentity _user; private readonly ConversationSetting _settings; private readonly IConversationStorage _storage; + private readonly IConversationStateService _state; + private string _conversationId; + + public IConversationStateService States => _state; public ConversationService(IServiceProvider services, IUserIdentity user, ConversationSetting settings, IConversationStorage storage, + IConversationStateService state, ILogger logger) { _services = services; _user = user; _settings = settings; _storage = storage; + _state = state; _logger = logger; } @@ -72,11 +76,19 @@ public partial class ConversationService : IConversationService throw new NotImplementedException(); } - public List GetDialogHistory(string conversationId, int lastCount = 20) + public List GetDialogHistory(int lastCount = 20) { - var dialogs = _storage.GetDialogs(conversationId); + var dialogs = _storage.GetDialogs(_conversationId); return dialogs .Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-8)) - .TakeLast(lastCount).ToList(); + .TakeLast(lastCount) + .ToList(); + } + + public void SetConversationId(string conversationId, string channel) + { + _conversationId = conversationId; + _state.Load(_conversationId); + _state.SetState("channel", channel); } } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index 98f2bedf..65f37fa7 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Conversations.Models; using System.IO; namespace BotSharp.Core.Conversations.Services; @@ -10,7 +9,7 @@ public class ConversationStateService : IConversationStateService, IDisposable { private readonly ILogger _logger; private readonly IServiceProvider _services; - private ConversationState _state; + private ConversationState _states; private MyDatabaseSettings _dbSettings; private string _conversationId; private string _file; @@ -22,16 +21,17 @@ public class ConversationStateService : IConversationStateService, IDisposable _logger = logger; _services = services; _dbSettings = dbSettings; + _states = new ConversationState(); } public void SetState(string name, string value) { var hooks = _services.GetServices(); - string preValue = _state.ContainsKey(name) ? _state[name] : ""; - if (!_state.ContainsKey(name) || _state[name] != value) + string preValue = _states.ContainsKey(name) ? _states[name] : ""; + if (!_states.ContainsKey(name) || _states[name] != value) { var currentValue = value; - _state[name] = currentValue; + _states[name] = currentValue; _logger.LogInformation($"Set state: {name} = {value}"); foreach (var hook in hooks) { @@ -40,24 +40,9 @@ public class ConversationStateService : IConversationStateService, IDisposable } } - public void SetConversation(string conversationId) + public ConversationState Load(string conversationId) { _conversationId = conversationId; - } - - public ConversationState Load() - { - if (_state != null) - { - return _state; - } - - _state = new ConversationState(); - - if (_conversationId == null) - { - return _state; - } _file = GetStorageFile(_conversationId); @@ -66,18 +51,19 @@ public class ConversationStateService : IConversationStateService, IDisposable var dict = File.ReadAllLines(_file); foreach (var line in dict) { - _state[line.Split('=')[0]] = line.Split('=')[1]; + _states[line.Split('=')[0]] = line.Split('=')[1]; + _logger.LogInformation($"Loaded state: {line}"); } } - _logger.LogInformation($"Loaded state {_conversationId}"); + _logger.LogInformation($"Loaded conversation states: {_conversationId}"); var hooks = _services.GetServices(); foreach (var hook in hooks) { - hook.OnStateLoaded(_state).Wait(); + hook.OnStateLoaded(_states).Wait(); } - return _state; + return _states; } public void Save() @@ -89,7 +75,7 @@ public class ConversationStateService : IConversationStateService, IDisposable var states = new List(); - foreach (var dic in _state) + foreach (var dic in _states) { states.Add($"{dic.Key}={dic.Value}"); } @@ -112,13 +98,16 @@ public class ConversationStateService : IConversationStateService, IDisposable return Path.Combine(dir, "state.dict"); } + public ConversationState GetStates() + => _states; + public string GetState(string name) { - if (!_state.ContainsKey(name)) + if (!_states.ContainsKey(name)) { - _state[name] = ""; + _states[name] = ""; } - return _state[name]; + return _states[name]; } public void Dispose() diff --git a/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs b/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs index 6e88bc7d..3bbbf8ff 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs @@ -45,8 +45,8 @@ public class Simulator } else if (args.Function == "interrupt_task_execution") { - response.Content = args.Parameters.Reason; - response.ExecutionResult = args.Parameters.Reason; + response.Content = args.Parameters.Response; + response.ExecutionResult = args.Parameters.Response; } else if (args.Function == "response_to_user") { diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index 364416cd..5ad55c78 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -44,11 +44,13 @@ public class ConversationController : ControllerBase, IApiAdapter [FromQuery] string? channel = "openapi") { var conv = _services.GetRequiredService(); - + conv.SetConversationId(conversationId, channel); + input.States.ForEach(x => conv.States.SetState(x.Split('=')[0], x.Split('=')[1])); + var response = new MessageResponseModel(); var stackMsg = new List(); - await conv.SendMessage(agentId, conversationId, + await conv.SendMessage(agentId, new RoleDialogModel("user", input.Text) { Channel = channel diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/NewMessageModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/NewMessageModel.cs index 45716e21..0f66d7be 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/NewMessageModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/NewMessageModel.cs @@ -3,4 +3,9 @@ namespace BotSharp.OpenAPI.ViewModels.Conversations; public class NewMessageModel { public string Text { get; set; } + + /// + /// Conversation states from input + /// + public List States { get; set; } = new List(); } diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs index 89bd7a95..cee7428d 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs @@ -16,7 +16,6 @@ using Microsoft.Extensions.DependencyInjection; using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations.Models; using Microsoft.AspNetCore.Authorization; -using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Agents.Enums; namespace BotSharp.Plugin.ChatbotUI.Controllers; @@ -62,18 +61,19 @@ public class ChatbotUiController : ControllerBase, IApiAdapter Response.Headers.Add(HeaderNames.Connection, "keep-alive"); var outputStream = Response.Body; + var channel = "webchat"; var conversation = input.Messages .Where(x => x.Role == AgentRole.User) .Select(x => new RoleDialogModel(x.Role, x.Content) { - Channel = "webchat" - }) - .Last(); + Channel = channel + }).Last(); - var conversationService = _services.GetRequiredService(); + var conv = _services.GetRequiredService(); + conv.SetConversationId(input.ConversationId, channel); + input.States.ForEach(x => conv.States.SetState(x.Split('=')[0], x.Split('=')[1])); - var result = await conversationService.SendMessage(input.AgentId, - input.ConversationId, + var result = await conv.SendMessage(input.AgentId, conversation, async msg => await OnChunkReceived(outputStream, msg), diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs b/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs index 419ccc6c..76771738 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ViewModels/OpenAiMessageInput.cs @@ -14,6 +14,10 @@ public class OpenAiMessageInput public int MaxTokens { get; set; } = 4000; public bool Stream { get; set; } = true; public float Temperature { get; set; } = 0.9f; + /// + /// Conversation states from input + /// + public List States { get; set; } = new List(); public override string ToString() { diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs b/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs index a83e424a..6440ac9f 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs @@ -67,8 +67,6 @@ public class WebhookController : ControllerBase // received message if (req.Entry[0].Messaging[0].Message != null) { - var conv = _services.GetRequiredService(); - var reply = new QuickReplyMessage(); var senderId = req.Entry[0].Messaging[0].Sender.Id; var input = req.Entry[0].Messaging[0].Message.Text; @@ -99,7 +97,10 @@ public class WebhookController : ControllerBase }); // Go to LLM - var result = await conv.SendMessage(agentId, senderId, new RoleDialogModel("user", input) + var conv = _services.GetRequiredService(); + conv.SetConversationId(senderId, "messenger"); + + var result = await conv.SendMessage(agentId, new RoleDialogModel("user", input) { Channel = "messenger" }, async msg => diff --git a/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs b/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs index ac0dab42..529b2142 100644 --- a/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs +++ b/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs @@ -48,7 +48,10 @@ namespace BotSharp.Plugin.WeChat var conversationService = scoped.GetRequiredService(); - var latestConversationId = (await conversationService.GetConversations()).OrderByDescending(_ => _.CreatedTime).FirstOrDefault()?.Id; + var latestConversationId = (await conversationService.GetConversations()) + .OrderByDescending(_ => _.CreatedTime) + .FirstOrDefault()?.Id; + conversationService.SetConversationId(latestConversationId, "wechat"); latestConversationId ??= (await conversationService.NewConversation(new Conversation() { @@ -56,7 +59,7 @@ namespace BotSharp.Plugin.WeChat AgentId = AgentId }))?.Id; - var result = await conversationService.SendMessage(AgentId, latestConversationId, new RoleDialogModel("user", message), async msg => + var result = await conversationService.SendMessage(AgentId, new RoleDialogModel("user", message), async msg => { await ReplyTextMessageAsync(openid, msg.Content); }, async functionExecuting => diff --git a/tests/BotSharp.Plugin.PizzaBot/Functions/GetBakingTimeFn.cs b/tests/BotSharp.Plugin.PizzaBot/Functions/GetBakingTimeFn.cs new file mode 100644 index 00000000..1d72dfbb --- /dev/null +++ b/tests/BotSharp.Plugin.PizzaBot/Functions/GetBakingTimeFn.cs @@ -0,0 +1,14 @@ +using BotSharp.Abstraction.Conversations.Models; + +namespace BotSharp.Plugin.PizzaBot.Functions; + +public class GetBakingTimeFn : IFunctionCallback +{ + public string Name => "get_cooking_remaing_time"; + + public async Task Execute(RoleDialogModel message) + { + message.ExecutionResult = "15 minutes remaining"; + return true; + } +} diff --git a/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs b/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs index 625e9ec4..4852d4dd 100644 --- a/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs +++ b/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Conversations.Models; -using System.Text.Json; namespace BotSharp.Plugin.PizzaBot.Functions; diff --git a/tests/BotSharp.Plugin.PizzaBot/Functions/MakeOrderFn.cs b/tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs similarity index 74% rename from tests/BotSharp.Plugin.PizzaBot/Functions/MakeOrderFn.cs rename to tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs index 68405157..bc398dbd 100644 --- a/tests/BotSharp.Plugin.PizzaBot/Functions/MakeOrderFn.cs +++ b/tests/BotSharp.Plugin.PizzaBot/Functions/PlaceOrderFn.cs @@ -2,9 +2,9 @@ using BotSharp.Abstraction.Conversations.Models; namespace BotSharp.Plugin.PizzaBot.Functions; -public class MakeOrderFn : IFunctionCallback +public class PlaceOrderFn : IFunctionCallback { - public string Name => "make_order"; + public string Name => "place_an_order"; public async Task Execute(RoleDialogModel message) { diff --git a/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaBotAgentHook.cs b/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaBotAgentHook.cs index be1bbe6f..8ee49399 100644 --- a/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaBotAgentHook.cs +++ b/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaBotAgentHook.cs @@ -10,7 +10,7 @@ public class PizzaBotAgentHook : AgentHookBase public override bool OnInstructionLoaded(string template, Dictionary dict) { dict["current_date"] = $"{DateTime.Now:MMM dd, yyyy}"; - dict["current_time"] = $"{DateTime.Now:hh:mm t}"; + dict["current_time"] = $"{DateTime.Now:hh:mm tt}"; dict["current_weekday"] = $"{DateTime.Now:dddd}"; return true; } diff --git a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs index 87b2c7ae..fbd3a6a2 100644 --- a/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs +++ b/tests/BotSharp.Plugin.PizzaBot/PizzaBotPlugin.cs @@ -10,8 +10,9 @@ public class PizzaBotPlugin : IBotSharpPlugin // Register callback function services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); + services.AddScoped(); // Register hooks services.AddScoped();