Conversation rate limit.

This commit is contained in:
Haiping Chen 2024-03-24 12:33:41 -05:00
parent f7cbbe84de
commit fee89ffb96
10 changed files with 97 additions and 12 deletions

View file

@ -51,6 +51,11 @@ public class DialogElement
Content = content;
RichContent = richContent;
}
public override string ToString()
{
return $"{MetaData.Role}: {Content} [{MetaData.CreateTime}]";
}
}
public class DialogMetaData

View file

@ -12,6 +12,7 @@ public class ConversationSetting
public bool EnableContentLog { get; set; }
public bool EnableStateLog { get; set; }
public CleanConversationSetting CleanSetting { get; set; }
public RateLimitSetting RateLimit { get; set; }
}
public class CleanConversationSetting

View file

@ -0,0 +1,8 @@
namespace BotSharp.Abstraction.Conversations.Settings;
public class RateLimitSetting
{
public int MaxConversationPerDay { get; set; } = 100;
public int MaxInputLengthPerRequest { get; set; } = 256;
public int MinTimeSecondsBetweenMessages { get; set; } = 2;
}

View file

@ -32,7 +32,7 @@ public interface IRoutingService
void ResetRecursiveCounter();
Task<bool> InvokeAgent(string agentId, List<RoleDialogModel> dialogs);
Task<bool> InvokeFunction(string name, RoleDialogModel message);
Task<RoleDialogModel> InstructLoop(RoleDialogModel message);
Task<RoleDialogModel> InstructLoop(RoleDialogModel message, List<RoleDialogModel> dialogs);
/// <summary>
/// Talk to a specific Agent directly, bypassing the Router

View file

@ -34,6 +34,9 @@ public partial class ConversationService
_storage.Append(_conversationId, message);
var conv = _services.GetRequiredService<IConversationService>();
var dialogs = conv.GetDialogHistory();
var statistics = _services.GetRequiredService<ITokenStatistics>();
var hooks = _services.GetServices<IConversationHook>().ToList();
@ -75,7 +78,7 @@ public partial class ConversationService
var settings = _services.GetRequiredService<RoutingSettings>();
response = agent.Type == AgentType.Routing ?
await routing.InstructLoop(message) :
await routing.InstructLoop(message, dialogs) :
await routing.InstructDirect(agent, message);
routing.ResetRecursiveCounter();

View file

@ -1,7 +1,5 @@
using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Repositories.Filters;
using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Routing;
namespace BotSharp.Core.Routing.Functions;
@ -29,12 +27,14 @@ public class FallbackToRouterFn : IFunctionCallback
return false;
}
var routing = _services.GetRequiredService<IRoutingContext>();
routing.Replace(targetAgent.Id);
var conv = _services.GetRequiredService<IConversationService>();
var dialogs = conv.GetDialogHistory();
var router = _services.GetRequiredService<IRoutingService>();
var routing = _services.GetRequiredService<IRoutingService>();
routing.Context.Replace(targetAgent.Id);
message.CurrentAgentId = targetAgent.Id;
var response = await router.InstructLoop(message);
var response = await routing.InstructLoop(message, dialogs);
message.Content = response.Content;
message.StopCompletion = true;

View file

@ -69,7 +69,7 @@ public partial class RoutingService : IRoutingService
return response;
}
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message, List<RoleDialogModel> dialogs)
{
var agentService = _services.GetRequiredService<IAgentService>();
_router = await agentService.LoadAgent(message.CurrentAgentId);
@ -77,9 +77,6 @@ public partial class RoutingService : IRoutingService
RoleDialogModel response = default;
var states = _services.GetRequiredService<IConversationStateService>();
var conv = _services.GetRequiredService<IConversationService>();
var dialogs = conv.GetDialogHistory();
var executor = _services.GetRequiredService<IExecutor>();
var planner = GetPlanner(_router);

View file

@ -13,6 +13,7 @@ public static class BotSharpLoggerExtensions
services.AddScoped<IContentGeneratingHook, CommonContentGeneratingHook>();
services.AddScoped<IContentGeneratingHook, TokenStatsConversationHook>();
services.AddScoped<IContentGeneratingHook, VerboseLogHook>();
services.AddScoped<IConversationHook, RateLimitConversationHook>();
return services;
}
}

View file

@ -0,0 +1,65 @@
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Repositories.Filters;
using BotSharp.Abstraction.Users;
namespace BotSharp.Logger.Hooks;
/// <summary>
/// To prevent users from overusing, if the character limit is exceeded or the sending frequency is too fast,
/// a prompt message will be returned.
/// </summary>
public class RateLimitConversationHook : ConversationHookBase
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public RateLimitConversationHook(IServiceProvider services, ILogger<RateLimitConversationHook> logger)
{
_services = services;
_logger = logger;
}
public override async Task OnMessageReceived(RoleDialogModel message)
{
var settings = _services.GetRequiredService<ConversationSetting>();
var rateLimit = settings.RateLimit;
// Check max input length
var charCount = message.Content.Length;
if (charCount > rateLimit.MaxInputLengthPerRequest)
{
message.Content = $"The number of characters in your message exceeds the system maximum of {rateLimit.MaxInputLengthPerRequest}";
message.StopCompletion = true;
return;
}
// Check message sending frequency
var userSents = _dialogs.Where(x => x.Role == AgentRole.User)
.TakeLast(2).ToList();
if (userSents.Count > 1)
{
var seconds = (DateTime.UtcNow - userSents.First().CreatedAt).TotalSeconds;
if (seconds < rateLimit.MinTimeSecondsBetweenMessages)
{
message.Content = "Your message sending frequency exceeds the frequency specified by the system. Please try again later.";
message.StopCompletion = true;
return;
}
}
// Check the number of conversations
var user = _services.GetRequiredService<IUserIdentity>();
var convService = _services.GetRequiredService<IConversationService>();
var results = await convService.GetConversations(new ConversationFilter
{
UserId = user.Id
});
if (results.Count > rateLimit.MaxConversationPerDay)
{
message.Content = $"The number of conversations you have exceeds the system maximum of {rateLimit.MaxConversationPerDay}";
message.StopCompletion = true;
return;
}
}
}

View file

@ -125,6 +125,11 @@
"BatchSize": 50,
"MessageLimit": 2,
"BufferHours": 12
},
"RateLimit": {
"MaxConversationPerDay": 100,
"MaxInputLengthPerRequest": 256,
"MinTimeSecondsBetweenMessages": 2
}
},