From 2d04226a14bc31224fb82bc3b34d9498e2b20227 Mon Sep 17 00:00:00 2001 From: hchen Date: Mon, 21 Aug 2023 15:43:03 -0500 Subject: [PATCH 1/3] Fix QuickReplies. --- .../Controllers/WebhookController.cs | 5 ++++- .../MessagingModels/QuickReplyMessage.cs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs b/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs index 47e87dc33..a83e424a4 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs @@ -124,7 +124,10 @@ public async Task> Messages([FromRoute] string age try { var parsed = JsonSerializer.Deserialize(json, jsonOpt); - reply.QuickReplies = parsed; + if (parsed.Length > 0) + { + reply.QuickReplies = parsed; + } } catch(Exception ex) { diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/QuickReplyMessage.cs b/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/QuickReplyMessage.cs index e0db69250..9d577143f 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/QuickReplyMessage.cs +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/QuickReplyMessage.cs @@ -13,5 +13,6 @@ public class QuickReplyMessage : IResponseMessage public string Text { get; set; } [JsonPropertyName("quick_replies")] - public QuickReplyMessageItem[] QuickReplies { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public QuickReplyMessageItem[]? QuickReplies { get; set; } } From 36f0f2771b1cc71cc5fd5144ef8ea767d60093b2 Mon Sep 17 00:00:00 2001 From: hchen2020 <101423@smsassist.com> Date: Mon, 21 Aug 2023 23:48:17 -0500 Subject: [PATCH 2/3] Ignore state if the value is empty. --- .../Services/ConversationService.SendMessage.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index 521f30546..45ede9dc0 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -85,7 +85,10 @@ private void SaveStateByArgs(string args) { foreach (JsonProperty property in root.EnumerateObject()) { - stateService.SetState(property.Name, property.Value.ToString()); + if (!string.IsNullOrEmpty(property.Value.ToString())) + { + stateService.SetState(property.Name, property.Value.ToString()); + } } } } From 78b33bd4de746e770dcd0ec6b5cb61e458d845cf Mon Sep 17 00:00:00 2001 From: hchen2020 <101423@smsassist.com> Date: Mon, 21 Aug 2023 23:49:42 -0500 Subject: [PATCH 3/3] Apply centralized routing by routing table. --- .../Agents/Models/AgentRoutingArgs.cs | 9 ---- .../Agents/Models/RoutingArgs.cs | 14 ++++++ .../Agents/Models/RoutingResult.cs | 11 +++++ .../Agents/Models/RoutingTable.cs | 20 ++++++++ ...vice.GetChatCompletionsAsyncRecursively.cs | 7 +-- .../BotSharp.Core/Functions/RouteToAgentFn.cs | 47 ++++++++++++++++--- 6 files changed, 89 insertions(+), 19 deletions(-) delete mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRoutingArgs.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingArgs.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingResult.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingTable.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRoutingArgs.cs deleted file mode 100644 index 4046cda44..000000000 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentRoutingArgs.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Text.Json.Serialization; - -namespace BotSharp.Abstraction.Agents.Models; - -public class AgentRoutingArgs -{ - [JsonPropertyName("agent_id")] - public string AgentId { get; set; } -} diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingArgs.cs new file mode 100644 index 000000000..e02b1c7b9 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingArgs.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; + +namespace BotSharp.Abstraction.Agents.Models; + +public class RoutingArgs +{ + [JsonPropertyName("agent_name")] + public string AgentName { get; set; } + + public override string ToString() + { + return AgentName; + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingResult.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingResult.cs new file mode 100644 index 000000000..b8ecdf6b6 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingResult.cs @@ -0,0 +1,11 @@ +namespace BotSharp.Abstraction.Agents.Models; + +public class RoutingResult +{ + public string Result { get; set; } + + public RoutingResult(string result) + { + Result = result; + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingTable.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingTable.cs new file mode 100644 index 000000000..2feedcf83 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/RoutingTable.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; + +namespace BotSharp.Abstraction.Agents.Models; + +public class RoutingTable +{ + [JsonPropertyName("agent_id")] + public string AgentId { get; set; } + + [JsonPropertyName("name")] + public string AgentName { get; set; } + + [JsonPropertyName("required")] + public List RequiredFields { get; set; } + + public override string ToString() + { + return AgentName; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs index 71698ebdc..c1fd2e307 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs @@ -53,18 +53,19 @@ await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, fn.Content return; } - fn.Content = fn.ExecutionResult; + fn.Content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.ExecutionResult; // Agent has been transferred + var agentSettings = _services.GetRequiredService(); if (fn.CurrentAgentId != preAgentId) { - var agentSettings = _services.GetRequiredService(); var agentService = _services.GetRequiredService(); agent = await agentService.LoadAgent(fn.CurrentAgentId); } // Add to dialog history - _storage.Append(conversationId, preAgentId, fn); + // The server had an error processing your request. Sorry about that! + // _storage.Append(conversationId, preAgentId, fn); // After function is executed, pass the result to LLM to get a natural response wholeDialogs.Add(fn); diff --git a/src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs index c8cd625d8..bae33c7e8 100644 --- a/src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs +++ b/src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs @@ -2,6 +2,8 @@ using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.Functions; using BotSharp.Abstraction.Functions.Models; +using Microsoft.Extensions.Logging; +using System.IO; namespace BotSharp.Core.Functions; @@ -17,20 +19,51 @@ public RouteToAgentFn(IServiceProvider services) public async Task Execute(RoleDialogModel message) { - var args = JsonSerializer.Deserialize(message.FunctionArgs); + var args = JsonSerializer.Deserialize(message.FunctionArgs); + var result = new RoutingResult($"Routed to {args.AgentName}"); - if (string.IsNullOrEmpty(args.AgentId)) + if (string.IsNullOrEmpty(args.AgentName)) { - var result = new FunctionExecutionValidationResult("false", "agent_id can't be parsed."); - message.ExecutionResult = JsonSerializer.Serialize(result); + result = new RoutingResult($"Can't find {args.AgentName}"); } else { - var result = new FunctionExecutionValidationResult("true"); - message.ExecutionResult = JsonSerializer.Serialize(result); - message.CurrentAgentId = args.AgentId; + var agentSettings = _services.GetRequiredService(); + var dbSettings = _services.GetRequiredService(); + var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir, agentSettings.RouterId, "route.json"); + var routes = JsonSerializer.Deserialize(File.ReadAllText(filePath)); + + var agent = routes.FirstOrDefault(x => x.AgentName.ToLower() == args.AgentName.ToLower()); + if (agent == null) + { + result = new RoutingResult($"Can't find agent {args.AgentName}."); + } + else + { + // Check required fields + var jo = JsonSerializer.Deserialize(message.FunctionArgs); + bool hasMissingField = false; + foreach (var field in agent.RequiredFields) + { + if (jo is JsonElement root) + { + if (!root.EnumerateObject().Any(x => x.Name == field)) + { + result = new RoutingResult($"Please provide {field}."); + hasMissingField = true; + break; + } + } + } + + if (!hasMissingField) + { + message.CurrentAgentId = agent.AgentId; + } + } } + message.ExecutionResult = JsonSerializer.Serialize(result); return true; } }