From ac40aa645f5b110c0b85834f74783bf1ef1a7334 Mon Sep 17 00:00:00 2001 From: Haiping Chen <101423@smsassist.com> Date: Wed, 28 Feb 2024 10:21:14 -0600 Subject: [PATCH] Stream Routing context log. --- .../BotSharp.Abstraction.csproj | 6 - .../Conversations/ConversationHookBase.cs | 6 - .../Conversations/IConversationHook.cs | 16 --- .../Infrastructures/HookEmittedResult.cs | 5 + .../Routing/IRoutingContext.cs | 13 +++ .../Routing/IRoutingHook.cs | 30 +++++ .../Infrastructures/HookEmitter.cs | 27 +++++ .../Routing/Functions/FallbackToRouterFn.cs | 2 +- .../Routing/Functions/RouteToAgentFn.cs | 12 +- .../RetrieveDataFromAgentRoutingHandler.cs | 2 +- .../Handlers/RouteToAgentRoutingHandler.cs | 2 +- .../Routing/Planning/HFPlanner.cs | 6 +- .../Routing/Planning/NaivePlanner.cs | 2 +- .../Routing/Planning/SequentialPlanner.cs | 2 +- .../TwoStagePlanner/TwoStagePlanner.cs | 2 +- .../Routing}/RoutingContext.cs | 39 ++++++- .../BotSharp.Core/Routing/RoutingPlugin.cs | 2 +- .../Routing/RoutingService.InvokeAgent.cs | 2 +- .../BotSharp.Core/Routing/RoutingService.cs | 10 +- .../Templating/ResponseTemplateService.cs | 4 +- src/Infrastructure/BotSharp.Core/Using.cs | 2 + .../BotSharp.Plugin.ChatHub/ChatHubPlugin.cs | 2 + .../Hooks/StreamingLogHook.cs | 108 ++++++++++++++---- .../RoutingConversationHook.cs | 3 +- .../agent.json | 2 + 25 files changed, 224 insertions(+), 83 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Infrastructures/HookEmittedResult.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingContext.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHook.cs create mode 100644 src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs rename src/Infrastructure/{BotSharp.Abstraction/Routing/Models => BotSharp.Core/Routing}/RoutingContext.cs (63%) diff --git a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj index 285cb0b8..bbade11e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj +++ b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj @@ -10,12 +10,6 @@ $(SolutionDir)packages - - - - - - True diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs index 569ac4e1..ea6a03d8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs @@ -69,10 +69,4 @@ public abstract class ConversationHookBase : IConversationHook public virtual Task OnUserAgentConnectedInitially(Conversation conversation) => Task.CompletedTask; - - public virtual Task OnConversationRedirected(string toAgentId, RoleDialogModel message) - => Task.CompletedTask; - - public virtual Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message) - => Task.CompletedTask; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs index 68360bed..95afaab4 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs @@ -84,20 +84,4 @@ public interface IConversationHook /// /// Task OnHumanInterventionNeeded(RoleDialogModel message); - - /// - /// Conversation is redirected to another agent - /// - /// - /// - /// - Task OnConversationRedirected(string toAgentId, RoleDialogModel message); - - /// - /// Routing instruction is received from Router - /// - /// routing instruction - /// message - /// - Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/HookEmittedResult.cs b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/HookEmittedResult.cs new file mode 100644 index 00000000..5084b412 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/HookEmittedResult.cs @@ -0,0 +1,5 @@ +namespace BotSharp.Abstraction.Infrastructures; + +public class HookEmittedResult +{ +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingContext.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingContext.cs new file mode 100644 index 00000000..01da8e31 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingContext.cs @@ -0,0 +1,13 @@ +namespace BotSharp.Abstraction.Routing; + +public interface IRoutingContext +{ + string GetCurrentAgentId(); + string OriginAgentId { get; } + bool IsEmpty { get; } + string IntentName { get; set; } + void Push(string agentId); + void Pop(); + void Replace(string agentId); + void Empty(); +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHook.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHook.cs new file mode 100644 index 00000000..34a07162 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHook.cs @@ -0,0 +1,30 @@ +using BotSharp.Abstraction.Functions.Models; + +namespace BotSharp.Abstraction.Routing; + +public interface IRoutingHook +{ + /// + /// Conversation is redirected to another agent + /// + /// + /// + /// + Task OnConversationRedirected(string toAgentId, RoleDialogModel message); + + /// + /// Routing instruction is received from Router + /// + /// routing instruction + /// message + /// + Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message); + + Task OnAgentEnqueued(string agentId, string preAgentId); + + Task OnAgentDequeued(string agentId, string currentAgentId); + + Task OnAgentReplaced(string fromAgentId, string toAgentId); + + Task OnAgentQueueEmptied(string agentId); +} diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs new file mode 100644 index 00000000..988863ac --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/HookEmitter.cs @@ -0,0 +1,27 @@ +using BotSharp.Abstraction.Infrastructures; + +namespace BotSharp.Core.Infrastructures; + +public static class HookEmitter +{ + public static async Task Emit(IServiceProvider services, Action action) + { + var logger = services.GetRequiredService>(); + var result = new HookEmittedResult(); + var hooks = services.GetServices(); + + foreach (var hook in hooks) + { + try + { + action(hook); + } + catch (Exception ex) + { + logger.LogError(ex.ToString()); + } + } + + return result; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Routing/Functions/FallbackToRouterFn.cs b/src/Infrastructure/BotSharp.Core/Routing/Functions/FallbackToRouterFn.cs index d6fb3dcb..4d51113f 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Functions/FallbackToRouterFn.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Functions/FallbackToRouterFn.cs @@ -29,7 +29,7 @@ public class FallbackToRouterFn : IFunctionCallback return false; } - var routing = _services.GetRequiredService(); + var routing = _services.GetRequiredService(); routing.Replace(targetAgent.Id); var router = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs index ee78fd1b..c8085cf3 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs @@ -14,9 +14,9 @@ public class RouteToAgentFn : IFunctionCallback { public string Name => "route_to_agent"; private readonly IServiceProvider _services; - private readonly RoutingContext _context; + private readonly IRoutingContext _context; - public RouteToAgentFn(IServiceProvider services, RoutingContext context) + public RouteToAgentFn(IServiceProvider services, IRoutingContext context) { _services = services; _context = context; @@ -153,11 +153,9 @@ public class RouteToAgentFn : IFunctionCallback #else logger.LogInformation($"*** Routing redirect to {record.Name.ToUpper()} ***"); #endif - var hooks = _services.GetServices(); - foreach (var hook in hooks) - { - hook.OnConversationRedirected(routingRule.RedirectTo, message).Wait(); - } + HookEmitter.Emit(_services, async hook => + await hook.OnConversationRedirected(routingRule.RedirectTo, message) + ).Wait(); } else { diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs index 54f3e66c..24a048ae 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs @@ -39,7 +39,7 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); var agentId = context.GetCurrentAgentId(); var dialogs = new List { diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index 2404e896..4aae20db 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -39,7 +39,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler public async Task Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message) { - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); var function = _services.GetServices().FirstOrDefault(x => x.Name == inst.Function); message.FunctionArgs = JsonSerializer.Serialize(inst); var ret = await function.Execute(message); diff --git a/src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs index ccb4f274..6f49c933 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs @@ -2,7 +2,7 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Repositories.Filters; -using BotSharp.Abstraction.Routing.Models; +using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Planning; using BotSharp.Abstraction.Templating; @@ -75,7 +75,7 @@ public class HFPlanner : IPlaner var filter = new AgentFilter { AgentName = inst.AgentName }; var agent = db.GetAgents(filter).FirstOrDefault(); - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); context.Push(agent.Id); } @@ -84,7 +84,7 @@ public class HFPlanner : IPlaner public async Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List dialogs) { - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); context.Empty(); return true; } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs index 91f35801..684c947c 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs @@ -87,7 +87,7 @@ public class NaivePlanner : IPlaner public async Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List dialogs) { - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); if (inst.UnmatchedAgent) { var unmatchedAgentId = context.GetCurrentAgentId(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs index 84246d40..24cc2aa7 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs @@ -140,7 +140,7 @@ public class SequentialPlanner : IPlaner public async Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List dialogs) { - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); if (message.StopCompletion) { diff --git a/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/TwoStagePlanner.cs b/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/TwoStagePlanner.cs index 5688fce4..8dfa2f69 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/TwoStagePlanner.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/TwoStagePlanner.cs @@ -155,7 +155,7 @@ public partial class TwoStagePlanner : IPlaner public async Task AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List dialogs) { - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); if (message.StopCompletion || _isTaskCompleted) { diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs similarity index 63% rename from src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs rename to src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs index d09658d8..6b39978e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs @@ -1,11 +1,9 @@ -using BotSharp.Abstraction.Agents; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing.Settings; -using Microsoft.Extensions.DependencyInjection; -namespace BotSharp.Abstraction.Routing.Models; +namespace BotSharp.Core.Routing; -public class RoutingContext +public class RoutingContext : IRoutingContext { private readonly IServiceProvider _services; private readonly RoutingSettings _setting; @@ -56,7 +54,12 @@ public class RoutingContext { if (_stack.Count == 0 || _stack.Peek() != agentId) { + var preAgentId = _stack.Count == 0 ? agentId : _stack.Peek(); _stack.Push(agentId); + + HookEmitter.Emit(_services, async hook => + await hook.OnAgentEnqueued(agentId, preAgentId) + ).Wait(); } } @@ -65,24 +68,50 @@ public class RoutingContext /// public void Pop() { - _stack.Pop(); + if (_stack.Count == 0) + { + return; + } + + var agentId = _stack.Pop(); + + HookEmitter.Emit(_services, async hook => + await hook.OnAgentDequeued(agentId, _stack.Peek()) + ).Wait(); } public void Replace(string agentId) { + var fromAgent = agentId; + var toAgent = agentId; + if (_stack.Count == 0) { _stack.Push(agentId); } else if (_stack.Peek() != agentId) { + fromAgent = _stack.Peek(); _stack.Pop(); _stack.Push(agentId); + + HookEmitter.Emit(_services, async hook => + await hook.OnAgentReplaced(fromAgent, toAgent) + ).Wait(); } } public void Empty() { + if (_stack.Count == 0) + { + return; + } + + var agentId = GetCurrentAgentId(); _stack.Clear(); + HookEmitter.Emit(_services, async hook => + await hook.OnAgentQueueEmptied(agentId) + ).Wait(); } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs index 410070d1..1ee1d732 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs @@ -23,7 +23,7 @@ public class RoutingPlugin : IBotSharpPlugin public void RegisterDI(IServiceCollection services, IConfiguration config) { - services.AddScoped(); + services.AddScoped(); // Register router services.AddScoped(provider => diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index 9ea133fa..ede6ee42 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -64,7 +64,7 @@ public partial class RoutingService // Pass execution result to LLM to get response if (!message.StopCompletion) { - var routing = _services.GetRequiredService(); + var routing = _services.GetRequiredService(); // Find response template var templateService = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index d9c4e21b..8d93b420 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -80,7 +80,7 @@ public partial class RoutingService : IRoutingService var conv = _services.GetRequiredService(); var dialogs = conv.GetDialogHistory(); - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); var executor = _services.GetRequiredService(); var planner = GetPlanner(_router); @@ -98,11 +98,9 @@ public partial class RoutingService : IRoutingService // Get instruction from Planner var inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs); - var hooks = _services.GetServices(); - foreach (var hook in hooks) - { - await hook.OnConversationRouting(inst, message); - } + await HookEmitter.Emit(_services, async hook => + await hook.OnConversationRouting(inst, message) + ); // Save states states.SaveStateByArgs(inst.Arguments); diff --git a/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs b/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs index 6bde9ce6..5119bc91 100644 --- a/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs +++ b/src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs @@ -68,8 +68,8 @@ public class ResponseTemplateService : IResponseTemplateService // .ToList(); var db = _services.GetRequiredService(); - var context = _services.GetRequiredService(); - var responses = db.GetAgentResponses(agentId, "intent", context.IntentName); + var routing = _services.GetRequiredService(); + var responses = db.GetAgentResponses(agentId, "intent", routing.IntentName); if (responses.Count == 0) { diff --git a/src/Infrastructure/BotSharp.Core/Using.cs b/src/Infrastructure/BotSharp.Core/Using.cs index 4571da54..c55585e5 100644 --- a/src/Infrastructure/BotSharp.Core/Using.cs +++ b/src/Infrastructure/BotSharp.Core/Using.cs @@ -7,6 +7,7 @@ global using System.Text.Json; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.Logging; global using EntityFrameworkCore.BootKit; +global using BotSharp.Abstraction.Routing; global using BotSharp.Abstraction.Plugins; global using BotSharp.Abstraction.Agents; global using BotSharp.Abstraction.Conversations; @@ -18,6 +19,7 @@ global using BotSharp.Abstraction.Agents.Settings; global using BotSharp.Abstraction.Conversations.Settings; global using BotSharp.Abstraction.Agents.Enums; global using BotSharp.Core.Repository; +global using BotSharp.Core.Routing; global using BotSharp.Core.Agents.Services; global using BotSharp.Core.Conversations.Services; global using BotSharp.Core.Infrastructures; diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs b/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs index bec0a01a..7825f0f1 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Loggers; +using BotSharp.Abstraction.Routing; using BotSharp.Plugin.ChatHub.Hooks; using Microsoft.Extensions.Configuration; @@ -20,5 +21,6 @@ public class ChatHubPlugin : IBotSharpPlugin services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); } } diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs index 90fbcefa..5b7f65fc 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs @@ -4,11 +4,12 @@ using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Loggers.Enums; using BotSharp.Abstraction.Loggers.Models; using BotSharp.Abstraction.Repositories; +using BotSharp.Abstraction.Routing; using Microsoft.AspNetCore.SignalR; namespace BotSharp.Plugin.ChatHub.Hooks; -public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook +public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IRoutingHook { private readonly ConversationSetting _convSettings; private readonly JsonSerializerOptions _serializerOptions; @@ -17,6 +18,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook private readonly IConversationStateService _state; private readonly IUserIdentity _user; private readonly IAgentService _agentService; + private string _messageId; public StreamingLogHook( ConversationSetting convSettings, @@ -43,32 +45,13 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook public override async Task OnMessageReceived(RoleDialogModel message) { + _messageId = message.MessageId; var conversationId = _state.GetConversationId(); - var log = $"{message.Role}: {message.Content}"; + var log = $"{message.Content}"; await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(conversationId, _user.UserName, log, ContentLogSource.UserInput, message)); } - public override async Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message) - { - var conversationId = _state.GetConversationId(); - var agent = await _agentService.LoadAgent(message.CurrentAgentId); - var log = JsonSerializer.Serialize(instruct, _serializerOptions); - await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", - BuildContentLog(conversationId, agent?.Name, log, ContentLogSource.AgentResponse, message)); - } - - public override async Task OnConversationRedirected(string toAgentId, RoleDialogModel message) - { - var conversationId = _state.GetConversationId(); - var fromAgent = await _agentService.LoadAgent(message.CurrentAgentId); - var toAgent = await _agentService.LoadAgent(toAgentId); - - var log = $"{message.Content}\r\n=====\r\nREDIRECTED TO {toAgent.Name}"; - await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", - BuildContentLog(conversationId, fromAgent.Name, log, ContentLogSource.HardRule, message)); - } - public async Task BeforeGenerating(Agent agent, List conversations) { if (!_convSettings.ShowVerboseLog) return; @@ -147,6 +130,8 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook CreateTime = DateTime.UtcNow }; + var json = JsonSerializer.Serialize(log, _serializerOptions); + var convSettings = _services.GetRequiredService(); if (convSettings.EnableContentLog) { @@ -154,7 +139,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook db.SaveConversationContentLog(log); } - return JsonSerializer.Serialize(log, _serializerOptions); + return json; } private string BuildStateLog(string conversationId, Dictionary states, RoleDialogModel message) @@ -176,4 +161,81 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook return JsonSerializer.Serialize(log, _serializerOptions); } + + #region IRoutingHook + public async Task OnAgentEnqueued(string agentId, string preAgentId) + { + var conversationId = _state.GetConversationId(); + var agent = await _agentService.LoadAgent(agentId); + var preAgent = await _agentService.LoadAgent(preAgentId); + + var log = $"{agent.Name} is enqueued"; + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", + BuildContentLog(conversationId, preAgent.Name, log, ContentLogSource.HardRule, new RoleDialogModel(AgentRole.System, log) + { + MessageId = _messageId + })); + } + + public async Task OnAgentDequeued(string agentId, string currentAgentId) + { + var conversationId = _state.GetConversationId(); + var agent = await _agentService.LoadAgent(agentId); + var currentAgent = await _agentService.LoadAgent(currentAgentId); + + var log = $"{agent.Name} is dequeued"; + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", + BuildContentLog(conversationId, currentAgent.Name, log, ContentLogSource.HardRule, new RoleDialogModel(AgentRole.System, log) + { + MessageId = _messageId + })); + } + + public async Task OnAgentReplaced(string fromAgentId, string toAgentId) + { + var conversationId = _state.GetConversationId(); + var fromAgent = await _agentService.LoadAgent(fromAgentId); + var toAgent = await _agentService.LoadAgent(toAgentId); + + var log = $"{fromAgent.Name} is replaced to {toAgent.Name}"; + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", + BuildContentLog(conversationId, toAgent.Name, log, ContentLogSource.HardRule, new RoleDialogModel(AgentRole.System, log) + { + MessageId = _messageId + })); + } + + public async Task OnAgentQueueEmptied(string agentId) + { + var conversationId = _state.GetConversationId(); + var agent = await _agentService.LoadAgent(agentId); + + var log = $"Agent queue is cleared."; + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", + BuildContentLog(conversationId, agent.Name, log, ContentLogSource.HardRule, new RoleDialogModel(AgentRole.System, log) + { + MessageId = _messageId + })); + } + + public async Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message) + { + var conversationId = _state.GetConversationId(); + var agent = await _agentService.LoadAgent(message.CurrentAgentId); + var log = JsonSerializer.Serialize(instruct, _serializerOptions); + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", + BuildContentLog(conversationId, agent?.Name, log, ContentLogSource.AgentResponse, message)); + } + + public async Task OnConversationRedirected(string toAgentId, RoleDialogModel message) + { + var conversationId = _state.GetConversationId(); + var fromAgent = await _agentService.LoadAgent(message.CurrentAgentId); + var toAgent = await _agentService.LoadAgent(toAgentId); + + var log = $"{message.Content}\r\n=====\r\nREDIRECTED TO {toAgent.Name}"; + await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", + BuildContentLog(conversationId, fromAgent.Name, log, ContentLogSource.HardRule, message)); + } + #endregion } diff --git a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs index 8c6d826e..b7fab29e 100644 --- a/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.RoutingSpeeder/RoutingConversationHook.cs @@ -12,6 +12,7 @@ using BotSharp.Abstraction.Agents; using System.IO; using BotSharp.Abstraction.Routing.Settings; using BotSharp.Abstraction.Routing.Models; +using BotSharp.Abstraction.Routing; namespace BotSharp.Plugin.RoutingSpeeder; @@ -31,7 +32,7 @@ public class RoutingConversationHook: ConversationHookBase // intentClassifier.Train(); // Utilize local discriminative model to predict intent - var context = _services.GetRequiredService(); + var context = _services.GetRequiredService(); context.IntentName = intentClassifier.Predict(vector); if (string.IsNullOrEmpty(context.IntentName)) diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/beda4c12-e1ec-4b4b-b328-3df4a6687c4f/agent.json b/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/beda4c12-e1ec-4b4b-b328-3df4a6687c4f/agent.json index 80f66ba9..4f19d591 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/beda4c12-e1ec-4b4b-b328-3df4a6687c4f/agent.json +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/beda4c12-e1ec-4b4b-b328-3df4a6687c4f/agent.json @@ -9,6 +9,8 @@ "isPublic": true, "profiles": [ "tool", "sql" ], "llmConfig": { + "model": "gpt-4-0125", + "model3": "gpt-35-turbo-1106", "max_recursion_depth": 10 } } \ No newline at end of file