diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs index 8c836645..0881b1d3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs @@ -5,7 +5,7 @@ namespace BotSharp.Abstraction.Routing; public interface IRoutingService { List Dialogs { get; } - Task GetNextInstruction(string prompt); + Task GetNextInstruction(); Task InvokeAgent(string agentId); Task InstructLoop(); Task ExecuteOnce(Agent agent); diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs index d3c1bb65..3499b6e9 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs @@ -6,13 +6,16 @@ public class RoutingArgs public string Function { get; set; } = string.Empty; [JsonPropertyName("reason")] - public string Reason { get; set; } = string.Empty; + public string Reason { get; set; } = "the reason why you select this function or agent"; [JsonPropertyName("answer")] public string Answer { get; set; } = string.Empty; - [JsonPropertyName("agent")] - public string AgentName { get; set; } = string.Empty; + [JsonPropertyName("next_action_agent")] + public string AgentName { get; set; } = "agent for next action based on user's latest response"; + + [JsonPropertyName("user_goal_agent")] + public string OriginalAgent { get; set; } = "agent who can achieve user's original goal"; public override string ToString() { diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index 7068b0b6..47cfcd2b 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -19,6 +19,11 @@ public partial class AgentService } var agent = await GetAgent(id); + if (agent == null) + { + throw new Exception($"Can't load agent by id: {id}"); + } + var templateDict = new Dictionary(); PopulateState(templateDict); diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index cc495f4a..1b789f1f 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -63,8 +63,4 @@ - - - - diff --git a/src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs similarity index 90% rename from src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs rename to src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs index bdba221a..aaeba5d7 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RouteToAgentFn.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs @@ -25,8 +25,21 @@ public class RouteToAgentFn : IFunctionCallback { var args = JsonSerializer.Deserialize(message.FunctionArgs); - // Push to routing stack - _context.Push(message.CurrentAgentId); + // Push original task agent + if (!string.IsNullOrEmpty(args.OriginalAgent) && args.OriginalAgent.Length < 32) + { + var db = _services.GetRequiredService(); + var originalAgent = db.Agents.FirstOrDefault(x => x.Name.ToLower() == args.OriginalAgent.ToLower()); + if (originalAgent != null) + { + _context.Push(originalAgent.Id); + } + } + else + { + // Push current agent to routing stack + _context.Push(message.CurrentAgentId); + } if (string.IsNullOrEmpty(args.AgentName)) { diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index b1e279a2..cca712bc 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -15,8 +15,9 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler public List Parameters => new List { - new NameDesc("agent", "the name of the agent"), - new NameDesc("reason", "why route to this agent"), + new NameDesc("next_action_agent", "the name of the next action's agent"), + new NameDesc("user_goal_agent", "the agent who can achieve user's original goal"), + new NameDesc("reason", "the reason why you select this function or agent"), new NameDesc("args", "the agent required parameters") }; @@ -33,10 +34,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler var message = new RoleDialogModel(AgentRole.Function, inst.Question) { FunctionName = inst.Function, - FunctionArgs = JsonSerializer.Serialize(new RoutingArgs - { - AgentName = inst.AgentName - }), + FunctionArgs = JsonSerializer.Serialize(inst), CurrentAgentId = routing.Dialogs.Last().CurrentAgentId }; @@ -44,7 +42,8 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler var context = _services.GetRequiredService(); var result = await routing.InvokeAgent(context.CurrentAgentId); - + // Keep last message data for debug + result.ExecutionData = result.ExecutionData ?? message.ExecutionData; return result; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs index cd3c8de5..1cf9b1d1 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetNextInstruction.cs @@ -7,8 +7,9 @@ namespace BotSharp.Core.Routing; public partial class RoutingService { - public async Task GetNextInstruction(string prompt) + public async Task GetNextInstruction() { + var prompt = "Which is the next step based on the CONVERSATION? Or you can handle without asking specific agent."; var responseFormat = _settings.EnableReasoning ? JsonSerializer.Serialize(new FunctionCallFromLlm()) : JsonSerializer.Serialize(new RoutingArgs diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index ca4f11ea..5c1b3f1d 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -76,9 +76,7 @@ public partial class RoutingService : IRoutingService { loopCount++; - var prompt = _settings.EnableReasoning ? "Tell me the next step?" : "Which agent is suitable to handle user's request based on the CONVERSATION?"; - prompt += " Or you can handle without asking specific agent."; - var inst = await GetNextInstruction(prompt); + var inst = await GetNextInstruction(); inst.Question = inst.Question ?? message; var handler = handlers.FirstOrDefault(x => x.Name == inst.Function); diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs index 40adcf9d..536337dd 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs @@ -81,14 +81,14 @@ public class MemVectorDatabase : IVectorDb return simiMatix; } - public int[] CalCosineSimilarityTopK(float[] vec, List records, int topK = 10, float filterProb = 0.75f) + public (int, float)[] CalCosineSimilarityTopK(float[] vec, List records, int topK = 10, float filterProb = 0.75f) { var simiMatix = CalCosineSimilarity(vec, records); topK = Math.Min(topK, records.Count); var topIndex = np.argsort(simiMatix)["::-1"][$":{topK}"]; - var resIndex = new List(); + var resIndex = new List<(int, float)>(); for (int i = 0; i < topK; i++) { @@ -97,7 +97,7 @@ public class MemVectorDatabase : IVectorDb if (value > filterProb) { - resIndex.Add(topIndex[i]); + resIndex.Add((topIndex[i], value)); } }