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 4046cda4..00000000 --- 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 00000000..e02b1c7b --- /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 00000000..b8ecdf6b --- /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 00000000..2feedcf8 --- /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 71698ebd..c1fd2e30 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 @@ public partial class ConversationService 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 c8cd625d..bae33c7e 100644 --- a/src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs +++ b/src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs @@ -2,6 +2,8 @@ using BotSharp.Abstraction.Agents.Models; 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 class RouteToAgentFn : IFunctionCallback 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; } }