From 5e4c4cec05de0c476ecc26b33469b2750b62949e Mon Sep 17 00:00:00 2001 From: Ronny Gunawan <3048897+ronnygunawan@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:27:01 +0700 Subject: [PATCH] Shared group chat AI rate limiter to reduce group chat noise --- .../AI/Gemini/GeminiTextPromptHandler.cs | 52 +++++++++++++------ .../AI/OpenAI/AskCommandHandler.cs | 51 ++++++++++++------ .../AI/OpenAI/OpenAITextPromptHandler.cs | 49 ++++++++++++----- .../AI/RateLimit/AIRateLimiters.cs | 7 +++ 4 files changed, 114 insertions(+), 45 deletions(-) create mode 100644 BotNet.CommandHandlers/AI/RateLimit/AIRateLimiters.cs diff --git a/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs b/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs index fa5c6ee..2c24002 100644 --- a/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs +++ b/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs @@ -1,4 +1,5 @@ -using BotNet.Commands; +using BotNet.CommandHandlers.AI.RateLimit; +using BotNet.Commands; using BotNet.Commands.AI.Gemini; using BotNet.Commands.BotUpdate.Message; using BotNet.Commands.ChatAggregate; @@ -34,27 +35,46 @@ ILogger logger private readonly ILogger _logger = logger; public Task Handle(GeminiTextPrompt textPrompt, CancellationToken cancellationToken) { - try { - if (textPrompt.Command.Chat is HomeGroupChat - || textPrompt.Command.Sender is VIPSender) { - VIP_CHAT_RATE_LIMITER.ValidateActionRate( + if (textPrompt.Command.Chat is GroupChat) { + try { + AIRateLimiters.GROUP_CHAT_RATE_LIMITER.ValidateActionRate( chatId: textPrompt.Command.Chat.Id, userId: textPrompt.Command.Sender.Id ); - } else { - CHAT_RATE_LIMITER.ValidateActionRate( + } catch (RateLimitExceededException exc) { + return _telegramBotClient.SendTextMessageAsync( chatId: textPrompt.Command.Chat.Id, - userId: textPrompt.Command.Sender.Id + text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown} atau lanjutkan di private chat.", + parseMode: ParseMode.Html, + replyToMessageId: textPrompt.Command.MessageId, + replyMarkup: new InlineKeyboardMarkup( + InlineKeyboardButton.WithUrl("Private chat 💬", "t.me/TeknumBot") + ), + cancellationToken: cancellationToken + ); + } + } else { + try { + if (textPrompt.Command.Sender is VIPSender) { + VIP_CHAT_RATE_LIMITER.ValidateActionRate( + chatId: textPrompt.Command.Chat.Id, + userId: textPrompt.Command.Sender.Id + ); + } else { + CHAT_RATE_LIMITER.ValidateActionRate( + chatId: textPrompt.Command.Chat.Id, + userId: textPrompt.Command.Sender.Id + ); + } + } catch (RateLimitExceededException exc) { + return _telegramBotClient.SendTextMessageAsync( + chatId: textPrompt.Command.Chat.Id, + text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown}.", + parseMode: ParseMode.Html, + replyToMessageId: textPrompt.Command.MessageId, + cancellationToken: cancellationToken ); } - } catch (RateLimitExceededException exc) { - return _telegramBotClient.SendTextMessageAsync( - chatId: textPrompt.Command.Chat.Id, - text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown}.", - parseMode: ParseMode.Html, - replyToMessageId: textPrompt.Command.MessageId, - cancellationToken: cancellationToken - ); } // Fire and forget diff --git a/BotNet.CommandHandlers/AI/OpenAI/AskCommandHandler.cs b/BotNet.CommandHandlers/AI/OpenAI/AskCommandHandler.cs index 7e280d6..de21b8a 100644 --- a/BotNet.CommandHandlers/AI/OpenAI/AskCommandHandler.cs +++ b/BotNet.CommandHandlers/AI/OpenAI/AskCommandHandler.cs @@ -1,4 +1,5 @@ -using BotNet.Commands; +using BotNet.CommandHandlers.AI.RateLimit; +using BotNet.Commands; using BotNet.Commands.AI.OpenAI; using BotNet.Commands.BotUpdate.Message; using BotNet.Commands.ChatAggregate; @@ -30,20 +31,40 @@ ILogger logger private readonly ILogger _logger = logger; public async Task Handle(AskCommand askCommand, CancellationToken cancellationToken) { - try { - OpenAITextPromptHandler.CHAT_RATE_LIMITER.ValidateActionRate( - chatId: askCommand.Command.Chat.Id, - userId: askCommand.Command.Sender.Id - ); - } catch (RateLimitExceededException exc) { - await _telegramBotClient.SendTextMessageAsync( - chatId: askCommand.Command.Chat.Id, - text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown}.", - parseMode: ParseMode.Html, - replyToMessageId: askCommand.Command.MessageId, - cancellationToken: cancellationToken - ); - return; + if (askCommand.Command.Chat is GroupChat) { + try { + AIRateLimiters.GROUP_CHAT_RATE_LIMITER.ValidateActionRate( + chatId: askCommand.Command.Chat.Id, + userId: askCommand.Command.Sender.Id + ); + } catch (RateLimitExceededException exc) { + await _telegramBotClient.SendTextMessageAsync( + chatId: askCommand.Command.Chat.Id, + text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown} atau lanjutkan di private chat.", + parseMode: ParseMode.Html, + replyToMessageId: askCommand.Command.MessageId, + replyMarkup: new InlineKeyboardMarkup( + InlineKeyboardButton.WithUrl("Private chat 💬", "t.me/TeknumBot") + ), + cancellationToken: cancellationToken + ); + } + } else { + try { + OpenAITextPromptHandler.CHAT_RATE_LIMITER.ValidateActionRate( + chatId: askCommand.Command.Chat.Id, + userId: askCommand.Command.Sender.Id + ); + } catch (RateLimitExceededException exc) { + await _telegramBotClient.SendTextMessageAsync( + chatId: askCommand.Command.Chat.Id, + text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown}.", + parseMode: ParseMode.Html, + replyToMessageId: askCommand.Command.MessageId, + cancellationToken: cancellationToken + ); + return; + } } // Fire and forget diff --git a/BotNet.CommandHandlers/AI/OpenAI/OpenAITextPromptHandler.cs b/BotNet.CommandHandlers/AI/OpenAI/OpenAITextPromptHandler.cs index 61e6e0e..494fefe 100644 --- a/BotNet.CommandHandlers/AI/OpenAI/OpenAITextPromptHandler.cs +++ b/BotNet.CommandHandlers/AI/OpenAI/OpenAITextPromptHandler.cs @@ -1,4 +1,5 @@ -using BotNet.CommandHandlers.Art; +using BotNet.CommandHandlers.AI.RateLimit; +using BotNet.CommandHandlers.Art; using BotNet.Commands; using BotNet.Commands.AI.OpenAI; using BotNet.Commands.AI.Stability; @@ -36,19 +37,39 @@ ILogger logger private readonly ILogger _logger = logger; public Task Handle(OpenAITextPrompt textPrompt, CancellationToken cancellationToken) { - try { - CHAT_RATE_LIMITER.ValidateActionRate( - chatId: textPrompt.Command.Chat.Id, - userId: textPrompt.Command.Sender.Id - ); - } catch (RateLimitExceededException exc) { - return _telegramBotClient.SendTextMessageAsync( - chatId: textPrompt.Command.Chat.Id, - text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown}.", - parseMode: ParseMode.Html, - replyToMessageId: textPrompt.Command.MessageId, - cancellationToken: cancellationToken - ); + if (textPrompt.Command.Chat is GroupChat) { + try { + AIRateLimiters.GROUP_CHAT_RATE_LIMITER.ValidateActionRate( + chatId: textPrompt.Command.Chat.Id, + userId: textPrompt.Command.Sender.Id + ); + } catch (RateLimitExceededException exc) { + return _telegramBotClient.SendTextMessageAsync( + chatId: textPrompt.Command.Chat.Id, + text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown} atau lanjutkan di private chat.", + parseMode: ParseMode.Html, + replyToMessageId: textPrompt.Command.MessageId, + replyMarkup: new InlineKeyboardMarkup( + InlineKeyboardButton.WithUrl("Private chat 💬", "t.me/TeknumBot") + ), + cancellationToken: cancellationToken + ); + } + } else { + try { + CHAT_RATE_LIMITER.ValidateActionRate( + chatId: textPrompt.Command.Chat.Id, + userId: textPrompt.Command.Sender.Id + ); + } catch (RateLimitExceededException exc) { + return _telegramBotClient.SendTextMessageAsync( + chatId: textPrompt.Command.Chat.Id, + text: $"Anda terlalu banyak memanggil AI. Coba lagi {exc.Cooldown}.", + parseMode: ParseMode.Html, + replyToMessageId: textPrompt.Command.MessageId, + cancellationToken: cancellationToken + ); + } } // Fire and forget diff --git a/BotNet.CommandHandlers/AI/RateLimit/AIRateLimiters.cs b/BotNet.CommandHandlers/AI/RateLimit/AIRateLimiters.cs new file mode 100644 index 0000000..b00b278 --- /dev/null +++ b/BotNet.CommandHandlers/AI/RateLimit/AIRateLimiters.cs @@ -0,0 +1,7 @@ +using BotNet.Services.RateLimit; + +namespace BotNet.CommandHandlers.AI.RateLimit { + internal static class AIRateLimiters { + internal static readonly RateLimiter GROUP_CHAT_RATE_LIMITER = RateLimiter.PerUserPerChat(4, TimeSpan.FromMinutes(15)); + } +}