optimize hook

This commit is contained in:
nick.yi 2025-05-16 09:19:55 +08:00
parent 9cdf9179c0
commit 37f860d897
29 changed files with 98 additions and 76 deletions

View file

@ -1,20 +0,0 @@
namespace BotSharp.Abstraction.Conversations;
public class ConversationHookProvider
{
public IEnumerable<IConversationHook> Hooks { get; }
private readonly Lazy<IEnumerable<IConversationHook>> _hooksOrderByPriority;
public IEnumerable<IConversationHook> HooksOrderByPriority
=> _hooksOrderByPriority.Value;
public ConversationHookProvider(IEnumerable<IConversationHook> conversationHooks)
{
Hooks = conversationHooks;
_hooksOrderByPriority = new Lazy<IEnumerable<IConversationHook>>(() =>
{
return conversationHooks.OrderBy(hook => hook.Priority).ToArray();
});
}
}

View file

@ -0,0 +1,25 @@
using BotSharp.Abstraction.Conversations;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BotSharp.Abstraction.Hooks
{
public static class HookProvider
{
public static List<T> GetHooks<T>(this IServiceProvider services, string agentId) where T : IHookBase
{
var hooks = services.GetServices<T>().Where(p => p.IsMatch(agentId));
return hooks.ToList();
}
public static List<T> GetHooksOrderByPriority<T>(this IServiceProvider services, string agentId) where T: IConversationHook
{
var hooks = services.GetServices<T>().Where(p => p.IsMatch(agentId));
return hooks.OrderBy(p => p.Priority).ToList();
}
}
}

View file

@ -12,6 +12,6 @@ namespace BotSharp.Abstraction.Hooks
/// Agent Id /// Agent Id
/// </summary> /// </summary>
string SelfId => string.Empty; string SelfId => string.Empty;
bool IsMatch(string id) => string.IsNullOrEmpty(SelfId) || SelfId == id; bool IsMatch(string agentId) => string.IsNullOrEmpty(SelfId) || SelfId == agentId;
} }
} }

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Options; using BotSharp.Abstraction.Options;
using BotSharp.Core.Infrastructures; using BotSharp.Core.Infrastructures;
@ -23,7 +24,6 @@ public class RealtimeHub : IRealtimeHub
public async Task ConnectToModel(Func<string, Task>? responseToUser = null, Func<string, Task>? init = null) public async Task ConnectToModel(Func<string, Task>? responseToUser = null, Func<string, Task>? init = null)
{ {
var hookProvider = _services.GetService<ConversationHookProvider>();
var convService = _services.GetRequiredService<IConversationService>(); var convService = _services.GetRequiredService<IConversationService>();
convService.SetConversationId(_conn.ConversationId, []); convService.SetConversationId(_conn.ConversationId, []);
var conversation = await convService.GetConversation(_conn.ConversationId); var conversation = await convService.GetConversation(_conn.ConversationId);
@ -105,7 +105,8 @@ public class RealtimeHub : IRealtimeHub
dialogs.Add(message); dialogs.Add(message);
storage.Append(_conn.ConversationId, message); storage.Append(_conn.ConversationId, message);
foreach (var hook in hookProvider?.HooksOrderByPriority ?? []) var hooks = _services.GetHooksOrderByPriority<IConversationHook>(_conn.CurrentAgentId);
foreach (var hook in hooks)
{ {
hook.SetAgent(agent) hook.SetAgent(agent)
.SetConversation(conversation); .SetConversation(conversation);
@ -126,7 +127,8 @@ public class RealtimeHub : IRealtimeHub
storage.Append(_conn.ConversationId, message); storage.Append(_conn.ConversationId, message);
routing.Context.SetMessageId(_conn.ConversationId, message.MessageId); routing.Context.SetMessageId(_conn.ConversationId, message.MessageId);
foreach (var hook in hookProvider?.HooksOrderByPriority ?? []) var hooks = _services.GetHooksOrderByPriority<IConversationHook>(_conn.CurrentAgentId);
foreach (var hook in hooks)
{ {
hook.SetAgent(agent) hook.SetAgent(agent)
.SetConversation(conversation); .SetConversation(conversation);

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Infrastructures.Enums; using BotSharp.Abstraction.Infrastructures.Enums;
using BotSharp.Abstraction.Messaging; using BotSharp.Abstraction.Messaging;
using BotSharp.Abstraction.Messaging.Models.RichContent; using BotSharp.Abstraction.Messaging.Models.RichContent;
@ -29,7 +30,6 @@ public partial class ConversationService
var dialogs = conv.GetDialogHistory(); var dialogs = conv.GetDialogHistory();
var statistics = _services.GetRequiredService<ITokenStatistics>(); var statistics = _services.GetRequiredService<ITokenStatistics>();
var hookProvider = _services.GetRequiredService<ConversationHookProvider>();
RoleDialogModel response = message; RoleDialogModel response = message;
bool stopCompletion = false; bool stopCompletion = false;
@ -44,7 +44,8 @@ public partial class ConversationService
message.Payload = replyMessage.Payload; message.Payload = replyMessage.Payload;
} }
foreach (var hook in hookProvider.HooksOrderByPriority) var hooks = _services.GetHooksOrderByPriority<IConversationHook>(message.CurrentAgentId);
foreach (var hook in hooks)
{ {
hook.SetAgent(agent) hook.SetAgent(agent)
.SetConversation(conversation); .SetConversation(conversation);

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Infrastructures.Enums; using BotSharp.Abstraction.Infrastructures.Enums;
namespace BotSharp.Core.Conversations.Services; namespace BotSharp.Core.Conversations.Services;
@ -31,9 +32,7 @@ public partial class ConversationService
states.CleanStates(excludedStates); states.CleanStates(excludedStates);
} }
var hooks = _services var hooks = _services.GetHooksOrderByPriority<IConversationHook>(routingCtx.GetCurrentAgentId());
.GetRequiredService<ConversationHookProvider>()
.HooksOrderByPriority;
// Before executing functions // Before executing functions
foreach (var hook in hooks) foreach (var hook in hooks)

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Conversations.Enums;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Models;
namespace BotSharp.Core.Conversations.Services; namespace BotSharp.Core.Conversations.Services;
@ -116,7 +117,7 @@ public partial class ConversationService : IConversationService
db.CreateNewConversation(record); db.CreateNewConversation(record);
var hooks = _services.GetServices<IConversationHook>(); var hooks = _services.GetHooks<IConversationHook>(record.AgentId);
foreach (var hook in hooks) foreach (var hook in hooks)
{ {

View file

@ -15,6 +15,7 @@
******************************************************************************/ ******************************************************************************/
using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Conversations.Enums;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Options; using BotSharp.Abstraction.Options;
using BotSharp.Abstraction.SideCar; using BotSharp.Abstraction.SideCar;
@ -28,6 +29,7 @@ public class ConversationStateService : IConversationStateService
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IServiceProvider _services; private readonly IServiceProvider _services;
private readonly IBotSharpRepository _db; private readonly IBotSharpRepository _db;
private readonly IRoutingContext _routingContext;
private readonly IConversationSideCar? _sidecar; private readonly IConversationSideCar? _sidecar;
private string _conversationId; private string _conversationId;
/// <summary> /// <summary>
@ -42,10 +44,12 @@ public class ConversationStateService : IConversationStateService
public ConversationStateService( public ConversationStateService(
IServiceProvider services, IServiceProvider services,
IBotSharpRepository db, IBotSharpRepository db,
IRoutingContext routingContext,
ILogger<ConversationStateService> logger) ILogger<ConversationStateService> logger)
{ {
_services = services; _services = services;
_db = db; _db = db;
_routingContext = routingContext;
_logger = logger; _logger = logger;
_curStates = new ConversationState(); _curStates = new ConversationState();
_historyStates = new ConversationState(); _historyStates = new ConversationState();
@ -87,7 +91,6 @@ public class ConversationStateService : IConversationStateService
} }
_logger.LogDebug($"[STATE] {name} = {value}"); _logger.LogDebug($"[STATE] {name} = {value}");
var routingCtx = _services.GetRequiredService<IRoutingContext>();
var isNoChange = ContainsState(name) var isNoChange = ContainsState(name)
&& preValue == currentValue && preValue == currentValue
@ -98,7 +101,7 @@ public class ConversationStateService : IConversationStateService
&& prevLeafNode?.Active == curActive && prevLeafNode?.Active == curActive
&& pair?.Readonly == readOnly; && pair?.Readonly == readOnly;
var hooks = _services.GetServices<IConversationHook>(); var hooks = _services.GetHooks<IConversationHook>(_routingContext.GetCurrentAgentId());
if (!ContainsState(name) || preValue != currentValue || prevLeafNode?.ActiveRounds != curActiveRounds) if (!ContainsState(name) || preValue != currentValue || prevLeafNode?.ActiveRounds != curActiveRounds)
{ {
foreach (var hook in hooks) foreach (var hook in hooks)
@ -106,7 +109,7 @@ public class ConversationStateService : IConversationStateService
hook.OnStateChanged(new StateChangeModel hook.OnStateChanged(new StateChangeModel
{ {
ConversationId = _conversationId, ConversationId = _conversationId,
MessageId = routingCtx.MessageId, MessageId = _routingContext.MessageId,
Name = name, Name = name,
BeforeValue = preValue, BeforeValue = preValue,
BeforeActiveRounds = prevLeafNode?.ActiveRounds, BeforeActiveRounds = prevLeafNode?.ActiveRounds,
@ -129,7 +132,7 @@ public class ConversationStateService : IConversationStateService
var newValue = new StateValue var newValue = new StateValue
{ {
Data = currentValue, Data = currentValue,
MessageId = routingCtx.MessageId, MessageId = _routingContext.MessageId,
Active = curActive, Active = curActive,
ActiveRounds = curActiveRounds, ActiveRounds = curActiveRounds,
DataType = valueType, DataType = valueType,
@ -171,8 +174,8 @@ public class ConversationStateService : IConversationStateService
return endNodes; return endNodes;
} }
var routingCtx = _services.GetRequiredService<IRoutingContext>(); var _routingContext = _services.GetRequiredService<IRoutingContext>();
var curMsgId = routingCtx.MessageId; var curMsgId = _routingContext.MessageId;
var dialogs = _db.GetConversationDialogs(conversationId); var dialogs = _db.GetConversationDialogs(conversationId);
var userDialogs = dialogs.Where(x => x.MetaData?.Role == AgentRole.User) var userDialogs = dialogs.Where(x => x.MetaData?.Role == AgentRole.User)
.GroupBy(x => x.MetaData?.MessageId) .GroupBy(x => x.MetaData?.MessageId)
@ -225,7 +228,7 @@ public class ConversationStateService : IConversationStateService
} }
_logger.LogInformation($"Loaded conversation states: {conversationId}"); _logger.LogInformation($"Loaded conversation states: {conversationId}");
var hooks = _services.GetServices<IConversationHook>(); var hooks = _services.GetHooks<IConversationHook>(_routingContext.GetCurrentAgentId());
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
hook.OnStateLoaded(_curStates).Wait(); hook.OnStateLoaded(_curStates).Wait();
@ -277,7 +280,6 @@ public class ConversationStateService : IConversationStateService
{ {
if (!ContainsState(name)) return false; if (!ContainsState(name)) return false;
var routingCtx = _services.GetRequiredService<IRoutingContext>();
var value = _curStates[name]; var value = _curStates[name];
var leafNode = value?.Values?.LastOrDefault(); var leafNode = value?.Values?.LastOrDefault();
if (value == null || !value.Versioning || leafNode == null) return false; if (value == null || !value.Versioning || leafNode == null) return false;
@ -285,7 +287,7 @@ public class ConversationStateService : IConversationStateService
_curStates[name].Values.Add(new StateValue _curStates[name].Values.Add(new StateValue
{ {
Data = leafNode.Data, Data = leafNode.Data,
MessageId = routingCtx.MessageId, MessageId = _routingContext.MessageId,
Active = false, Active = false,
ActiveRounds = leafNode.ActiveRounds, ActiveRounds = leafNode.ActiveRounds,
DataType = leafNode.DataType, DataType = leafNode.DataType,
@ -293,13 +295,13 @@ public class ConversationStateService : IConversationStateService
UpdateTime = DateTime.UtcNow UpdateTime = DateTime.UtcNow
}); });
var hooks = _services.GetServices<IConversationHook>(); var hooks = _services.GetHooks<IConversationHook>(_routingContext.GetCurrentAgentId());
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
hook.OnStateChanged(new StateChangeModel hook.OnStateChanged(new StateChangeModel
{ {
ConversationId = _conversationId, ConversationId = _conversationId,
MessageId = routingCtx.MessageId, MessageId = _routingContext.MessageId,
Name = name, Name = name,
BeforeValue = leafNode.Data, BeforeValue = leafNode.Data,
BeforeActiveRounds = leafNode.ActiveRounds, BeforeActiveRounds = leafNode.ActiveRounds,
@ -316,8 +318,7 @@ public class ConversationStateService : IConversationStateService
public void CleanStates(params string[] excludedStates) public void CleanStates(params string[] excludedStates)
{ {
var routingCtx = _services.GetRequiredService<IRoutingContext>(); var curMsgId = _routingContext.MessageId;
var curMsgId = routingCtx.MessageId;
var utcNow = DateTime.UtcNow; var utcNow = DateTime.UtcNow;
foreach (var key in _curStates.Keys) foreach (var key in _curStates.Keys)

View file

@ -9,7 +9,7 @@ public static class HookEmitter
{ {
var logger = services.GetRequiredService<ILogger<T>>(); var logger = services.GetRequiredService<ILogger<T>>();
var result = new HookEmittedResult(); var result = new HookEmittedResult();
var hooks = services.GetServices<T>().Where(p => p.IsMatch(agentId)); var hooks = services.GetHooks<T>(agentId);
option = option ?? new(); option = option ?? new();
foreach (var hook in hooks) foreach (var hook in hooks)
@ -40,7 +40,7 @@ public static class HookEmitter
{ {
var logger = services.GetRequiredService<ILogger<T>>(); var logger = services.GetRequiredService<ILogger<T>>();
var result = new HookEmittedResult(); var result = new HookEmittedResult();
var hooks = services.GetServices<T>().Where(p => p.IsMatch(agentId)); var hooks = services.GetHooks<T>(agentId);
option = option ?? new(); option = option ?? new();
foreach (var hook in hooks) foreach (var hook in hooks)

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Instructs; using BotSharp.Abstraction.Instructs;
using BotSharp.Abstraction.Instructs.Models; using BotSharp.Abstraction.Instructs.Models;
using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.MLTasks;
@ -23,7 +24,7 @@ public partial class InstructService
} }
// Trigger before completion hooks // Trigger before completion hooks
var hooks = _services.GetServices<IInstructHook>().Where(p => p.IsMatch(agentId)); var hooks = _services.GetHooks<IInstructHook>(agentId);
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
await hook.BeforeCompletion(agent, message); await hook.BeforeCompletion(agent, message);

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Functions; using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Hooks;
namespace BotSharp.Core.Routing.Functions; namespace BotSharp.Core.Routing.Functions;
@ -15,9 +16,7 @@ public class HumanInterventionNeededFn : IFunctionCallback
public async Task<bool> Execute(RoleDialogModel message) public async Task<bool> Execute(RoleDialogModel message)
{ {
var hooks = _services var hooks = _services.GetHooksOrderByPriority<IConversationHook>(message.CurrentAgentId);
.GetRequiredService<ConversationHookProvider>()
.HooksOrderByPriority;
foreach (var hook in hooks) foreach (var hook in hooks)
{ {

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Functions; using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Templating; using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Routing; namespace BotSharp.Core.Routing;
@ -28,10 +29,6 @@ public partial class RoutingService
var clonedMessage = RoleDialogModel.From(message); var clonedMessage = RoleDialogModel.From(message);
clonedMessage.FunctionName = name; clonedMessage.FunctionName = name;
var hooks = _services
.GetRequiredService<ConversationHookProvider>()
.HooksOrderByPriority;
var progressService = _services.GetService<IConversationProgressService>(); var progressService = _services.GetService<IConversationProgressService>();
// Before executing functions // Before executing functions
@ -51,6 +48,7 @@ public partial class RoutingService
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.GetAgent(clonedMessage.CurrentAgentId); var agent = await agentService.GetAgent(clonedMessage.CurrentAgentId);
var hooks = _services.GetHooksOrderByPriority<IConversationHook>(clonedMessage.CurrentAgentId);
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
hook.SetAgent(agent); hook.SetAgent(agent);

View file

@ -1,5 +1,6 @@
using Anthropic.SDK.Common; using Anthropic.SDK.Common;
using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.MLTasks.Settings; using BotSharp.Abstraction.MLTasks.Settings;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -29,7 +30,7 @@ public class ChatCompletionProvider : IChatCompletion
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations) public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)

View file

@ -1,5 +1,6 @@
using Azure; using Azure;
using BotSharp.Abstraction.Files.Utilities; using BotSharp.Abstraction.Files.Utilities;
using BotSharp.Abstraction.Hooks;
using OpenAI.Chat; using OpenAI.Chat;
using System.ClientModel; using System.ClientModel;
@ -29,7 +30,7 @@ public class ChatCompletionProvider : IChatCompletion
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations) public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)
@ -128,7 +129,7 @@ public class ChatCompletionProvider : IChatCompletion
Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onMessageReceived,
Func<RoleDialogModel, Task> onFunctionExecuting) Func<RoleDialogModel, Task> onFunctionExecuting)
{ {
var hooks = _services.GetServices<IContentGeneratingHook>().ToList(); var hooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in hooks) foreach (var hook in hooks)

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.MLTasks.Settings; using BotSharp.Abstraction.MLTasks.Settings;
using System.Net.Http; using System.Net.Http;
using System.Net.Mime; using System.Net.Mime;
@ -36,7 +37,7 @@ public class TextCompletionProvider : ITextCompletion
public async Task<string> GetCompletion(string text, string agentId, string messageId) public async Task<string> GetCompletion(string text, string agentId, string messageId)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agentId);
// Before chat completion hook // Before chat completion hook
var agent = new Agent() var agent = new Agent()

View file

@ -24,7 +24,6 @@ public class ChatHubPlugin : IBotSharpPlugin
services.AddScoped<IConversationHook, ChatHubConversationHook>(); services.AddScoped<IConversationHook, ChatHubConversationHook>();
services.AddScoped<IConversationHook, StreamingLogHook>(); services.AddScoped<IConversationHook, StreamingLogHook>();
services.AddScoped<IConversationHook, WelcomeHook>(); services.AddScoped<IConversationHook, WelcomeHook>();
services.AddScoped<ConversationHookProvider>();
services.AddScoped<IRoutingHook, StreamingLogHook>(); services.AddScoped<IRoutingHook, StreamingLogHook>();
services.AddScoped<IContentGeneratingHook, StreamingLogHook>(); services.AddScoped<IContentGeneratingHook, StreamingLogHook>();
services.AddScoped<ICrontabHook, ChatHubCrontabHook>(); services.AddScoped<ICrontabHook, ChatHubCrontabHook>();

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
@ -26,7 +27,6 @@ public class SignalRHub : Hub
{ {
_logger.LogInformation($"SignalR Hub: {_user.FirstName} {_user.LastName} ({Context.User.Identity.Name}) connected in {Context.ConnectionId}"); _logger.LogInformation($"SignalR Hub: {_user.FirstName} {_user.LastName} ({Context.User.Identity.Name}) connected in {Context.ConnectionId}");
var hooks = _services.GetServices<IConversationHook>();
var convService = _services.GetRequiredService<IConversationService>(); var convService = _services.GetRequiredService<IConversationService>();
_context.HttpContext.Request.Query.TryGetValue("conversationId", out var conversationId); _context.HttpContext.Request.Query.TryGetValue("conversationId", out var conversationId);
@ -38,6 +38,7 @@ public class SignalRHub : Hub
var conv = await convService.GetConversation(conversationId); var conv = await convService.GetConversation(conversationId);
if (conv != null) if (conv != null)
{ {
var hooks = _services.GetHooks<IConversationHook>(conv.AgentId);
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
// Check if user connected with agent is the first time. // Check if user connected with agent is the first time.

View file

@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging;
using OpenAI.Chat; using OpenAI.Chat;
using BotSharp.Abstraction.Files; using BotSharp.Abstraction.Files;
using BotSharp.Plugin.DeepSeek.Providers; using BotSharp.Plugin.DeepSeek.Providers;
using BotSharp.Abstraction.Hooks;
namespace BotSharp.Plugin.DeepSeekAI.Providers.Chat; namespace BotSharp.Plugin.DeepSeekAI.Providers.Chat;
@ -25,7 +26,7 @@ public class ChatCompletionProvider : IChatCompletion
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations) public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)
@ -95,7 +96,7 @@ public class ChatCompletionProvider : IChatCompletion
public async Task<bool> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onFunctionExecuting) public async Task<bool> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onFunctionExecuting)
{ {
var hooks = _services.GetServices<IContentGeneratingHook>().ToList(); var hooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in hooks) foreach (var hook in hooks)

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenAI.Chat; using OpenAI.Chat;
@ -22,7 +23,7 @@ public class TextCompletionProvider : ITextCompletion
public async Task<string> GetCompletion(string text, string agentId, string messageId) public async Task<string> GetCompletion(string text, string agentId, string messageId)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agentId);
var state = _services.GetRequiredService<IConversationStateService>(); var state = _services.GetRequiredService<IConversationStateService>();
// Before chat completion hook // Before chat completion hook

View file

@ -2,6 +2,7 @@ using System.Text.Json.Nodes;
using BotSharp.Abstraction.Agents; using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Loggers;
using GenerativeAI; using GenerativeAI;
using GenerativeAI.Core; using GenerativeAI.Core;
@ -33,7 +34,7 @@ public class GeminiChatCompletionProvider : IChatCompletion
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations) public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)
@ -91,7 +92,7 @@ public class GeminiChatCompletionProvider : IChatCompletion
public async Task<bool> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onFunctionExecuting) public async Task<bool> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onFunctionExecuting)
{ {
var hooks = _services.GetServices<IContentGeneratingHook>().ToList(); var hooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in hooks) foreach (var hook in hooks)

View file

@ -5,6 +5,7 @@ using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing;
using LLMSharp.Google.Palm; using LLMSharp.Google.Palm;
using LLMSharp.Google.Palm.DiscussService; using LLMSharp.Google.Palm.DiscussService;
using BotSharp.Abstraction.Hooks;
namespace BotSharp.Plugin.GoogleAi.Providers.Chat; namespace BotSharp.Plugin.GoogleAi.Providers.Chat;
@ -29,7 +30,7 @@ public class PalmChatCompletionProvider : IChatCompletion
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations) public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using GenerativeAI; using GenerativeAI;
using GenerativeAI.Core; using GenerativeAI.Core;
using GenerativeAI.Live; using GenerativeAI.Live;
@ -216,7 +217,7 @@ public class GoogleRealTimeProvider : IRealTimeCompletion
} }
} }
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(conn.CurrentAgentId);
// After chat completion hook // After chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)
{ {

View file

@ -1,5 +1,6 @@
using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Loggers;
using GenerativeAI; using GenerativeAI;
using GenerativeAI.Core; using GenerativeAI.Core;
@ -32,7 +33,7 @@ public class GeminiTextCompletionProvider : ITextCompletion
public async Task<string> GetCompletion(string text, string agentId, string messageId) public async Task<string> GetCompletion(string text, string agentId, string messageId)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agentId);
// Before completion hook // Before completion hook
var agent = new Agent() var agent = new Agent()

View file

@ -1,5 +1,6 @@
using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Loggers;
namespace BotSharp.Plugin.GoogleAi.Providers.Text; namespace BotSharp.Plugin.GoogleAi.Providers.Text;
@ -27,7 +28,7 @@ public class PalmTextCompletionProvider : ITextCompletion
public async Task<string> GetCompletion(string text, string agentId, string messageId) public async Task<string> GetCompletion(string text, string agentId, string messageId)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agentId);
// Before completion hook // Before completion hook
var agent = new Agent() { Id = agentId }; var agent = new Agent() { Id = agentId };

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Hooks;
using OpenAI.Chat; using OpenAI.Chat;
namespace BotSharp.Plugin.OpenAI.Providers.Chat; namespace BotSharp.Plugin.OpenAI.Providers.Chat;
@ -32,7 +33,7 @@ public class ChatCompletionProvider : IChatCompletion
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations) public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in contentHooks) foreach (var hook in contentHooks)
@ -105,7 +106,7 @@ public class ChatCompletionProvider : IChatCompletion
Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onMessageReceived,
Func<RoleDialogModel, Task> onFunctionExecuting) Func<RoleDialogModel, Task> onFunctionExecuting)
{ {
var hooks = _services.GetServices<IContentGeneratingHook>().ToList(); var hooks = _services.GetHooks<IContentGeneratingHook>(agent.Id);
// Before chat completion hook // Before chat completion hook
foreach (var hook in hooks) foreach (var hook in hooks)

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Plugin.OpenAI.Models.Realtime; using BotSharp.Plugin.OpenAI.Models.Realtime;
using OpenAI.Chat; using OpenAI.Chat;
@ -609,7 +610,7 @@ public class RealTimeCompletionProvider : IRealTimeCompletion
return []; return [];
} }
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(conn.CurrentAgentId);
var prompts = new List<string>(); var prompts = new List<string>();
var inputTokenDetails = data.Usage?.InputTokenDetails; var inputTokenDetails = data.Usage?.InputTokenDetails;

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using System.Net.Http; using System.Net.Http;
using System.Net.Mime; using System.Net.Mime;
@ -25,7 +26,7 @@ public class TextCompletionProvider : ITextCompletion
public async Task<string> GetCompletion(string text, string agentId, string messageId) public async Task<string> GetCompletion(string text, string agentId, string messageId)
{ {
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList(); var contentHooks = _services.GetHooks<IContentGeneratingHook>(agentId);
// Before chat completion hook // Before chat completion hook
var agent = new Agent() var agent = new Agent()

View file

@ -3,6 +3,7 @@ using Task = System.Threading.Tasks.Task;
using Twilio.Rest.Api.V2010.Account; using Twilio.Rest.Api.V2010.Account;
using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Interfaces;
using BotSharp.Plugin.Twilio.Models; using BotSharp.Plugin.Twilio.Models;
using BotSharp.Abstraction.Hooks;
namespace BotSharp.Plugin.Twilio.Hooks; namespace BotSharp.Plugin.Twilio.Hooks;
@ -23,7 +24,7 @@ public class TwilioConversationHook : ConversationHookBase, IConversationHook
public override async Task OnFunctionExecuted(RoleDialogModel message) public override async Task OnFunctionExecuted(RoleDialogModel message)
{ {
var hooks = _services.GetServices<ITwilioSessionHook>(); var hooks = _services.GetHooks<ITwilioSessionHook>(message.CurrentAgentId);
var routing = _services.GetRequiredService<IRoutingService>(); var routing = _services.GetRequiredService<IRoutingService>();
var conversationId = routing.Context.ConversationId; var conversationId = routing.Context.ConversationId;

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Realtime; using BotSharp.Abstraction.Realtime;
using BotSharp.Abstraction.Realtime.Models; using BotSharp.Abstraction.Realtime.Models;
@ -63,7 +64,7 @@ public class TwilioStreamMiddleware
// load conversation and state // load conversation and state
var convService = services.GetRequiredService<IConversationService>(); var convService = services.GetRequiredService<IConversationService>();
convService.SetConversationId(conversationId, []); convService.SetConversationId(conversationId, []);
var hooks = services.GetServices<ITwilioSessionHook>(); var hooks = services.GetHooks<ITwilioSessionHook>(agentId);
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
await hook.OnStreamingStarted(conn); await hook.OnStreamingStarted(conn);
@ -229,7 +230,6 @@ public class TwilioStreamMiddleware
private async Task HandleUserDtmfReceived(IServiceProvider _services, RealtimeHubConnection conn, IRealTimeCompletion completer, string data) private async Task HandleUserDtmfReceived(IServiceProvider _services, RealtimeHubConnection conn, IRealTimeCompletion completer, string data)
{ {
var routing = _services.GetRequiredService<IRoutingService>(); var routing = _services.GetRequiredService<IRoutingService>();
var hookProvider = _services.GetRequiredService<ConversationHookProvider>();
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.GetAgent(conn.CurrentAgentId); var agent = await agentService.GetAgent(conn.CurrentAgentId);
var dialogs = routing.Context.GetDialogs(); var dialogs = routing.Context.GetDialogs();
@ -245,7 +245,8 @@ public class TwilioStreamMiddleware
var storage = _services.GetRequiredService<IConversationStorage>(); var storage = _services.GetRequiredService<IConversationStorage>();
storage.Append(conn.ConversationId, message); storage.Append(conn.ConversationId, message);
foreach (var hook in hookProvider.HooksOrderByPriority) var hooks = _services.GetHooksOrderByPriority<IConversationHook>(conn.CurrentAgentId);
foreach (var hook in hooks)
{ {
hook.SetAgent(agent) hook.SetAgent(agent)
.SetConversation(conversation); .SetConversation(conversation);