diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index 6b8624f9..f08e5a66 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Models; namespace BotSharp.Abstraction.Conversations.Models; @@ -38,6 +39,8 @@ public class RoleDialogModel : ITrackableMessage [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool StopCompletion { get; set; } + public FunctionCallFromLlm Instruction { get; set; } + private RoleDialogModel() { } diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs index d86c6298..6c8ae94e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Functions.Models; -using BotSharp.Abstraction.Models; namespace BotSharp.Abstraction.Routing; @@ -19,5 +18,5 @@ public interface IRoutingHandler void SetDialogs(List dialogs) { } - Task Handle(IRoutingService routing, FunctionCallFromLlm inst); + Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs index 802f8f73..47744957 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs @@ -8,7 +8,7 @@ public interface IRoutingService void ResetRecursiveCounter(); void RefreshDialogs(); Task GetNextInstruction(); - Task InvokeAgent(string agentId); - Task InstructLoop(); - Task ExecuteOnce(Agent agent); + Task InvokeAgent(string agentId, RoleDialogModel message); + Task InstructLoop(RoleDialogModel message); + Task ExecuteOnce(Agent agent, RoleDialogModel message); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs index 96e133d9..bca8018e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs @@ -1,10 +1,7 @@ namespace BotSharp.Abstraction.Routing.Models; -public class RoutingArgs : ITrackableMessage +public class RoutingArgs { - [JsonPropertyName("message_id")] - public string MessageId { get; set; } - [JsonPropertyName("function")] public string Function { get; set; } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index e80b5b1e..387a18e7 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -8,7 +8,7 @@ namespace BotSharp.Core.Conversations.Services; public partial class ConversationService { public async Task SendMessage(string agentId, - RoleDialogModel incoming, + RoleDialogModel message, Func onMessageReceived, Func onFunctionExecuting, Func onFunctionExecuted) @@ -18,16 +18,16 @@ public partial class ConversationService var agentService = _services.GetRequiredService(); Agent agent = await agentService.LoadAgent(agentId); - var message = $"Received [{agent.Name}] {incoming.Role}: {incoming.Content}"; + var content = $"Received [{agent.Name}] {message.Role}: {message.Content}"; #if DEBUG - Console.WriteLine(message, Color.OrangeRed); + Console.WriteLine(content, Color.OrangeRed); #else - _logger.LogInformation(message); + _logger.LogInformation(content); #endif - incoming.CurrentAgentId = agent.Id; + message.CurrentAgentId = agent.Id; - _storage.Append(_conversationId, incoming); + _storage.Append(_conversationId, message); var hooks = _services.GetServices().ToList(); @@ -37,13 +37,13 @@ public partial class ConversationService hook.SetAgent(agent) .SetConversation(conversation); - await hook.OnMessageReceived(incoming); + await hook.OnMessageReceived(message); // Interrupted by hook - if (incoming.StopCompletion) + if (message.StopCompletion) { - await onMessageReceived(incoming); - _storage.Append(_conversationId, incoming); + await onMessageReceived(message); + _storage.Append(_conversationId, message); return true; } } @@ -52,11 +52,11 @@ public partial class ConversationService var routing = _services.GetRequiredService(); var settings = _services.GetRequiredService(); - var response = agentId == settings.RouterId ? - await routing.InstructLoop() : - await routing.ExecuteOnce(agent); + var ret = agentId == settings.RouterId ? + await routing.InstructLoop(message) : + await routing.ExecuteOnce(agent, message); - await HandleAssistantMessage(response, onMessageReceived); + await HandleAssistantMessage(message, onMessageReceived); var statistics = _services.GetRequiredService(); statistics.PrintStatistics(); @@ -64,7 +64,7 @@ public partial class ConversationService routing.ResetRecursiveCounter(); routing.RefreshDialogs(); - return true; + return ret; } private async Task GetConversationRecord(string agentId) diff --git a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs index dcfe47e4..fd916b12 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs @@ -66,14 +66,11 @@ public class RouteToAgentFn : IFunctionCallback else { message.CurrentAgentId = targetAgent.Id; - message.Content = $"Routing to {args.AgentName}"; } } _context.Push(message.CurrentAgentId); - // Set default execution data - message.Data = JsonSerializer.Deserialize(message.FunctionArgs); return true; } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs index 8e167855..1c809ef4 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs @@ -26,19 +26,15 @@ public class ContinueExecuteTaskRoutingHandler : RoutingHandlerBase, IRoutingHan { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { var db = _services.GetRequiredService(); var record = db.GetAgents(inst.AgentName).FirstOrDefault(); - var result = new RoleDialogModel(AgentRole.Function, inst.Question) - { - MessageId = inst.MessageId, - FunctionName = inst.Function, - FunctionArgs = JsonSerializer.Serialize(inst.Arguments), - CurrentAgentId = record.Id - }; + message.FunctionName = inst.Function; + message.CurrentAgentId = record.Id; + message.FunctionArgs = JsonSerializer.Serialize(inst.Arguments); - return result; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs index 69a5c9f7..97eafa46 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs @@ -24,15 +24,11 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var result = new RoleDialogModel(AgentRole.Assistant, inst.Response) - { - MessageId = inst.MessageId, - CurrentAgentId = _settings.RouterId, - FunctionName = inst.Function, - Data = inst - }; + message.Content = inst.Response; + message.FunctionName = inst.Function; var hooks = _services.GetServices() .OrderBy(x => x.Priority) @@ -40,9 +36,9 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler foreach (var hook in hooks) { - await hook.OnConversationEnding(result); + await hook.OnConversationEnding(message); } - return result; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs index 1ebf9c43..671dc644 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs @@ -11,8 +11,6 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle public string Description => "Reach out to human being, customer service or customer representative."; - private readonly RoutingSettings _settings; - public List Parameters => new List { new NameDesc("reason", "why need customer service"), @@ -22,18 +20,13 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle public HumanInterventionNeededHandler(IServiceProvider services, ILogger logger, RoutingSettings settings) : base(services, logger, settings) { - _settings = settings; + } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var result = new RoleDialogModel(AgentRole.Assistant, inst.Response) - { - MessageId = inst.MessageId, - CurrentAgentId = _settings.RouterId, - FunctionName = inst.Function, - Data = inst - }; + message.Role = AgentRole.Assistant; + message.Content = inst.Response; var hooks = _services.GetServices() .OrderBy(x => x.Priority) @@ -41,9 +34,9 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle foreach (var hook in hooks) { - await hook.OnHumanInterventionNeeded(result); + await hook.OnHumanInterventionNeeded(message); } - return result; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs index c62102e2..76d18be3 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs @@ -24,15 +24,11 @@ public class InterruptTaskExecutionRoutingHandler : RoutingHandlerBase, IRouting { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var result = new RoleDialogModel(AgentRole.User, inst.Reason) - { - MessageId = inst.MessageId, - FunctionName = inst.Function, - StopCompletion = true - }; + message.FunctionName = inst.Function; + message.StopCompletion = true; - return result; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs index 9da370b8..cb480e56 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs @@ -24,16 +24,11 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var result = new RoleDialogModel(AgentRole.Assistant, inst.Response) - { - MessageId = inst.MessageId, - CurrentAgentId = _settings.RouterId, - FunctionName = inst.Function, - Data = inst, - StopCompletion = true - }; - return result; + message.Content = inst.Response; + message.StopCompletion = true; + message.Role = AgentRole.Assistant; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs index 04d78bdb..3b30c19d 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs @@ -27,14 +27,12 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { // Retrieve information from specific agent var db = _services.GetRequiredService(); var record = db.GetAgents(inst.AgentName).FirstOrDefault(); - var response = await routing.InvokeAgent(record.Id); - - inst.Response = response.Content; + var ret = await routing.InvokeAgent(record.Id, message); /*_dialogs.Add(new RoleDialogModel(AgentRole.Assistant, inst.Parameters.Question) { @@ -53,11 +51,11 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH CurrentAgentId = record.Id });*/ - _router.Instruction += $"\r\n{AgentRole.Function}: {response.Content}"; + _router.Instruction += $"\r\n{AgentRole.Function}: {message.Content}"; // Got the response from agent, then send to reasoner again to make the decision // inst = await GetNextInstructionFromReasoner($"What's the next step based on user's original goal and function result?"); - return null; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index 52766548..daa4e734 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -28,26 +28,15 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { var context = _services.GetRequiredService(); - var function = _services.GetServices().FirstOrDefault(x => x.Name == inst.Function); - var message = new RoleDialogModel(AgentRole.Function, inst.Question) - { - MessageId = inst.MessageId, - FunctionName = inst.Function, - FunctionArgs = JsonSerializer.Serialize(inst), - CurrentAgentId = context.GetCurrentAgentId(), - }; - + message.FunctionArgs = JsonSerializer.Serialize(inst); var ret = await function.Execute(message); - var result = await routing.InvokeAgent(context.GetCurrentAgentId()); - // Keep last message data for debug - result.Data = result.Data ?? message.Data; - result.FunctionName = result.FunctionName ?? message.FunctionName; + ret = await routing.InvokeAgent(context.GetCurrentAgentId(), message); - return result; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs index ba7f2e2c..edb2cfc9 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs @@ -23,25 +23,17 @@ public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler { } - public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst) + public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var result = new RoleDialogModel(AgentRole.Assistant, inst.Response) - { - MessageId = inst.MessageId, - CurrentAgentId = _settings.RouterId, - FunctionName = inst.Function, - Data = inst - }; - var hooks = _services.GetServices() .OrderBy(x => x.Priority) .ToList(); foreach (var hook in hooks) { - await hook.OnCurrentTaskEnding(result); + await hook.OnCurrentTaskEnding(message); } - return result; + return true; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs index 10541e4c..e217dd89 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs @@ -57,6 +57,7 @@ public partial class RoutingService int retryCount = 0; var agentService = _services.GetRequiredService(); + var dialogs = Dialogs; while (retryCount < 3) { @@ -64,7 +65,7 @@ public partial class RoutingService { var conversation = ""; - foreach (var dialog in _dialogs.TakeLast(20)) + foreach (var dialog in dialogs.TakeLast(50)) { var role = dialog.Role; if (role != AgentRole.User) @@ -120,9 +121,6 @@ public partial class RoutingService return args; } -#if !DEBUG - [MemoryCache(10 * 60)] -#endif private string GetNextStepPrompt() { var template = _routerInstance.Router.Templates.First(x => x.Name == "next_step_prompt").Content; diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 8147f437..f19bee3f 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -8,13 +8,13 @@ public partial class RoutingService { const int MAXIMUM_RECURSION_DEPTH = 3; private int _currentRecursionDepth = 0; - public async Task InvokeAgent(string agentId) + public async Task InvokeAgent(string agentId, RoleDialogModel message) { _currentRecursionDepth++; if (_currentRecursionDepth > MAXIMUM_RECURSION_DEPTH) { _logger.LogWarning($"Current recursive call depth greater than {MAXIMUM_RECURSION_DEPTH}, which will cause unexpected result."); - return Dialogs.Last(); + return false; } var agentService = _services.GetRequiredService(); @@ -23,50 +23,56 @@ public partial class RoutingService var settings = _services.GetRequiredService(); var chatCompletion = CompletionProvider.GetChatCompletion(_services, provider: settings.Provider, model: settings.Model); RoleDialogModel response = chatCompletion.GetChatCompletions(agent, Dialogs); + message.Role = response.Role; if (response.Role == AgentRole.Function) { - return await InvokeFunction(agent, response); + message.FunctionName = response.FunctionName; + message.FunctionArgs = response.FunctionArgs; + + await InvokeFunction(agent, message); } else { - return response; + message.Content = response.Content; } + + return true; } - private async Task InvokeFunction(Agent agent, RoleDialogModel response) + private async Task InvokeFunction(Agent agent, RoleDialogModel message) { // execute function // Save states - SaveStateByArgs(JsonSerializer.Deserialize(response.FunctionArgs)); + SaveStateByArgs(JsonSerializer.Deserialize(message.FunctionArgs)); var conversationService = _services.GetRequiredService(); // Call functions - await conversationService.CallFunctions(response); + await conversationService.CallFunctions(message); - Dialogs.Add(response); + Dialogs.Add(message); // Pass execution result to LLM to get response - if (!response.StopCompletion) + if (!message.StopCompletion) { // Find response template var templateService = _services.GetRequiredService(); - var responseTemplate = await templateService.RenderFunctionResponse(agent.Id, response); + var responseTemplate = await templateService.RenderFunctionResponse(agent.Id, message); if (!string.IsNullOrEmpty(responseTemplate)) { - response.Role = AgentRole.Assistant; - response.Content = responseTemplate.Trim(); + message.Role = AgentRole.Assistant; + message.Content = responseTemplate.Trim(); } else { - response = await InvokeAgent(response.CurrentAgentId); + await InvokeAgent(message.CurrentAgentId, message); } } else { - response.Role = AgentRole.Assistant; + message.Role = AgentRole.Assistant; } - return response; + return message; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index ba4f8f1b..b7073f04 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -46,38 +46,29 @@ public partial class RoutingService : IRoutingService _routerInstance = routerInstance; } - - public async Task ExecuteOnce(Agent agent) + public async Task ExecuteOnce(Agent agent, RoleDialogModel message) { - var message = Dialogs.Last().Content; - var handlers = _services.GetServices(); var handler = handlers.FirstOrDefault(x => x.Name == "route_to_agent"); handler.SetDialogs(Dialogs); + var result = await handler.Handle(this, new FunctionCallFromLlm { Function = "route_to_agent", - Question = message, - Reason = message, + Question = message.Content, + Reason = message.Content, AgentName = agent.Name - }); + }, message); return result; } - public async Task InstructLoop() + public async Task InstructLoop(RoleDialogModel message) { _routerInstance.Load(); var router = _routerInstance.Router; - var result = new RoleDialogModel(AgentRole.Assistant, "Can you repeat your request again?") - { - CurrentAgentId = router.Id - }; - - var inputMsg = Dialogs.Last(); - var handlers = _services.GetServices(); int loopCount = 0; @@ -87,8 +78,8 @@ public partial class RoutingService : IRoutingService loopCount++; var inst = await GetNextInstruction(); - inst.MessageId = inputMsg.MessageId; - inst.Question = inst.Question ?? inputMsg.Content; + message.Instruction = inst; + inst.Question = message.Content; var handler = handlers.FirstOrDefault(x => x.Name == inst.Function); if (handler == null) @@ -99,13 +90,18 @@ public partial class RoutingService : IRoutingService handler.SetRouter(router); handler.SetDialogs(Dialogs); - result = await handler.Handle(this, inst); - result.MessageId = inputMsg.MessageId; + message.FunctionName = inst.Function; + message.Role = AgentRole.Function; + message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments); + + await handler.Handle(this, inst, message); + + inst.Response = message.Content; stop = !_settings.EnableReasoning; } - return result; + return true; } protected void SaveStateByArgs(JsonDocument args) diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index 4fd4be21..5fb5cd7c 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -53,12 +53,11 @@ public class ConversationController : ControllerBase, IApiAdapter .SetState("sampling_factor", input.SamplingFactor); var response = new MessageResponseModel(); - var stackMsg = new List(); var inputMsg = new RoleDialogModel("user", input.Text); await conv.SendMessage(agentId, inputMsg, async msg => { - stackMsg.Add(msg); + }, async fnExecuting => { @@ -66,14 +65,14 @@ public class ConversationController : ControllerBase, IApiAdapter }, async fnExecuted => { - response.Function = fnExecuted.FunctionName; - response.Data = fnExecuted.Data; + }); - response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content)); - response.Data = response.Data ?? stackMsg.Last().Data; - response.Function = stackMsg.Last().FunctionName; response.MessageId = inputMsg.MessageId; + response.Text = inputMsg.Content; + response.Data = inputMsg.Data; + response.Function = inputMsg.FunctionName; + response.Instruction = inputMsg.Instruction; return response; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs index dc88faaf..4dcf0c58 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs @@ -1,4 +1,6 @@ +using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Models; +using BotSharp.Abstraction.Routing.Models; namespace BotSharp.OpenAPI.ViewModels.Conversations; @@ -8,4 +10,5 @@ public class MessageResponseModel : ITrackableMessage public string Text { get; set; } public string Function { get; set; } public object Data { get; set; } + public FunctionCallFromLlm Instruction { get; set; } } diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj index b05729a7..6723a4da 100644 --- a/src/WebStarter/WebStarter.csproj +++ b/src/WebStarter/WebStarter.csproj @@ -5,6 +5,7 @@ enable enable 4fb8c9df-7975-4926-ba73-46c8ca440691 + False diff --git a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid index d9c0515b..67cd6d1a 100644 --- a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid +++ b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instruction.liquid @@ -2,7 +2,7 @@ You're {{router.name}} ({{router.description}}). Follow these steps to handle us 1. Read the [CONVERSATION] content. 2. Select a appropriate function from [FUNCTIONS]. 3. Determine which agent is suitable to handle this conversation. -4. If user wants to talk with human being, you will transfer to customer representative. +4. Re-think on whether the function you chose matches the reason. 5. For agent required arguments, leave it as blank object if user doesn't provide it. [FUNCTIONS] diff --git a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/next_step_prompt.liquid b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/next_step_prompt.liquid index 41bcd63d..12de3ffd 100644 --- a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/next_step_prompt.liquid +++ b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/next_step_prompt.liquid @@ -1 +1,4 @@ -What is the next step based on the CONVERSATION? Response must be in appropriate JSON format. Route to the Agent that last handled the conversation if necessary. \ No newline at end of file +What is the next step based on the CONVERSATION? +Response must be in appropriate JSON format. +Route to the Agent that last handled the conversation if necessary. +If user wants to speak to customer service, use function human_intervention_needed. \ No newline at end of file diff --git a/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs b/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs index 9e39a155..4fa39c7c 100644 --- a/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs +++ b/tests/BotSharp.Plugin.PizzaBot/Functions/GetPizzaPricesFn.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Conversations.Models; +using System.Text.Json; namespace BotSharp.Plugin.PizzaBot.Functions; @@ -14,6 +15,7 @@ public class GetPizzaPricesFn : IFunctionCallback cheese_unit_price = 3.5, margherita_unit_price = 3.8, }; + message.Content = JsonSerializer.Serialize(message.Data); return true; } }