diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs index 5bceefaf..4cf63cdf 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs @@ -59,6 +59,9 @@ public abstract class ConversationHookBase : IConversationHook public virtual Task OnMessageReceived(RoleDialogModel message) => Task.CompletedTask; + public virtual Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg) + => Task.CompletedTask; + public virtual Task OnResponseGenerated(RoleDialogModel message) => Task.CompletedTask; diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs index 8552aa20..1143c492 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs @@ -46,6 +46,7 @@ public interface IConversationHook Task OnStateChanged(string name, string preValue, string currentValue); Task OnMessageReceived(RoleDialogModel message); + Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg); /// /// Triggered before LLM calls function. diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index 203e9053..884ba9c0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -30,6 +30,7 @@ public interface IConversationService /// Task SendMessage(string agentId, RoleDialogModel lastDalog, + PostbackMessageModel? replyMessage, Func onResponseReceived, Func onFunctionExecuting, Func onFunctionExecuted); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs index 005cb0b2..2176c7fa 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs @@ -4,4 +4,9 @@ public class IncomingMessageModel : MessageConfig { public string Text { get; set; } = string.Empty; public virtual string Channel { get; set; } = string.Empty; + + /// + /// Postback message + /// + public PostbackMessageModel? Postback { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/PostbackMessageModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/PostbackMessageModel.cs new file mode 100644 index 00000000..afa1d6d3 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/PostbackMessageModel.cs @@ -0,0 +1,11 @@ +namespace BotSharp.Abstraction.Conversations.Models; + +public class PostbackMessageModel +{ + public string FunctionName { get; set; } = string.Empty; + public string Payload { get; set; } = string.Empty; + /// + /// Parent message id + /// + public string ParentId { get; set; } = string.Empty; +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index ae5a803b..9aaa75ef 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -10,6 +10,7 @@ public partial class ConversationService { public async Task SendMessage(string agentId, RoleDialogModel message, + PostbackMessageModel? replyMessage, Func onMessageReceived, Func onFunctionExecuting, Func onFunctionExecuted) @@ -51,7 +52,14 @@ public partial class ConversationService hook.SetAgent(agent) .SetConversation(conversation); - await hook.OnMessageReceived(message); + if (replyMessage == null) + { + await hook.OnMessageReceived(message); + } + else + { + await hook.OnPostbackMessageReceived(message, replyMessage); + } // Interrupted by hook if (message.StopCompletion) diff --git a/src/Infrastructure/BotSharp.Core/Evaluations/EvaluatingService.cs b/src/Infrastructure/BotSharp.Core/Evaluations/EvaluatingService.cs index 340b8f7e..a87bc950 100644 --- a/src/Infrastructure/BotSharp.Core/Evaluations/EvaluatingService.cs +++ b/src/Infrastructure/BotSharp.Core/Evaluations/EvaluatingService.cs @@ -97,9 +97,10 @@ public class EvaluatingService : IEvaluatingService await conv.SendMessage(agentId, new RoleDialogModel(AgentRole.User, text), + replyMessage: null, async msg => response = msg, - fnExecuting => Task.CompletedTask, - fnExecuted => Task.CompletedTask); + _ => Task.CompletedTask, + _ => Task.CompletedTask); return response; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index fee57e18..8ef208af 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -171,6 +171,7 @@ public class ConversationController : ControllerBase var response = new ChatResponseModel(); await conv.SendMessage(agentId, inputMsg, + replyMessage: input.Postback, async msg => { response.Text = msg.Content; @@ -179,14 +180,8 @@ public class ConversationController : ControllerBase response.Instruction = msg.Instruction; response.Data = msg.Data; }, - async fnExecuting => - { - - }, - async fnExecuted => - { - - }); + _ => Task.CompletedTask, + _ => Task.CompletedTask); var state = _services.GetRequiredService(); response.States = state.GetStates(); diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs index 254520e7..1dac0af1 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs @@ -59,6 +59,22 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input)); } + public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg) + { + var conversationId = _state.GetConversationId(); + var log = $"{message.Content}"; + var replyContent = JsonSerializer.Serialize(replyMsg, _serializerOptions); + log += $"\r\n```json\r\n{replyContent}\r\n```"; + + var input = new ContentLogInputModel(conversationId, message) + { + Name = _user.UserName, + Source = ContentLogSource.UserInput, + Log = log + }; + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input)); + } + public async Task BeforeGenerating(Agent agent, List conversations) { if (!_convSettings.ShowVerboseLog) return; diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs index 4dbf304d..132856b9 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs @@ -80,13 +80,12 @@ public class ChatbotUiController : ControllerBase .SetState("sampling_factor", input.SamplingFactor); var result = await conv.SendMessage(input.AgentId, - message, + message, + replyMessage: null, async msg => await OnChunkReceived(outputStream, msg), - async fn - => await Task.CompletedTask, - async fn - => await Task.CompletedTask); + _ => Task.CompletedTask, + _ => Task.CompletedTask); await OnEventCompleted(outputStream); } diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/Services/MessageHandleService.cs b/src/Plugins/BotSharp.Plugin.MetaMessenger/Services/MessageHandleService.cs index 164c38f0..e6aa19e2 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/Services/MessageHandleService.cs +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/Services/MessageHandleService.cs @@ -60,7 +60,9 @@ public class MessageHandleService var replies = new List(); var result = await conv.SendMessage(agentId, - new RoleDialogModel(AgentRole.User, message), async msg => + new RoleDialogModel(AgentRole.User, message), + replyMessage: null, + async msg => { if (msg.RichContent != null) { diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs index acea5752..0dc43aa6 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs @@ -59,6 +59,7 @@ public class TwilioVoiceController : TwilioController var result = await conv.SendMessage(agentId, new RoleDialogModel(AgentRole.User, input.SpeechResult), + replyMessage: null, async msg => { response = twilio.ReturnInstructions(msg.Content); diff --git a/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs b/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs index 5013100e..0e1057dd 100644 --- a/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs +++ b/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs @@ -61,16 +61,15 @@ namespace BotSharp.Plugin.WeChat AgentId = AgentId }))?.Id; - var result = await conversationService.SendMessage(AgentId, new RoleDialogModel("user", message), async msg => - { - await ReplyTextMessageAsync(openid, msg.Content); - }, async functionExecuting => - { - - }, async functionExecuted => - { - - }); + var result = await conversationService.SendMessage(AgentId, + new RoleDialogModel("user", message), + replyMessage: null, + async msg => + { + await ReplyTextMessageAsync(openid, msg.Content); + }, + _ => Task.CompletedTask, + _ => Task.CompletedTask); } private async Task GetWeChatAccountUserAsync(string openId, IServiceProvider service) diff --git a/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs b/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs new file mode 100644 index 00000000..558fa047 --- /dev/null +++ b/tests/BotSharp.Plugin.PizzaBot/Hooks/PizzaTypeConversationHook.cs @@ -0,0 +1,16 @@ +using BotSharp.Abstraction.Conversations; +using BotSharp.Abstraction.Conversations.Models; + +namespace BotSharp.Plugin.PizzaBot.Hooks; + +public class PizzaTypeConversationHook : ConversationHookBase +{ + public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg) + { + if (replyMsg.FunctionName == "get_pizza_types") + { + // message.StopCompletion = true; + } + return; + } +}