diff --git a/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs b/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs index e0751c2..cec7729 100644 --- a/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs +++ b/BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs @@ -1,12 +1,8 @@ -using BotNet.CommandHandlers.Art; -using BotNet.Commands; +using BotNet.Commands; using BotNet.Commands.AI.Gemini; -using BotNet.Commands.AI.OpenAI; -using BotNet.Commands.AI.Stability; using BotNet.Commands.BotUpdate.Message; using BotNet.Commands.ChatAggregate; using BotNet.Commands.CommandPrioritization; -using BotNet.Commands.SenderAggregate; using BotNet.Services.Gemini; using BotNet.Services.Gemini.Models; using BotNet.Services.MarkdownV2; @@ -20,7 +16,6 @@ namespace BotNet.CommandHandlers.AI.Gemini { public sealed class GeminiTextPromptHandler( ITelegramBotClient telegramBotClient, GeminiClient geminiClient, - ICommandQueue commandQueue, ITelegramMessageCache telegramMessageCache, CommandPriorityCategorizer commandPriorityCategorizer, ILogger logger @@ -29,7 +24,6 @@ ILogger logger private readonly ITelegramBotClient _telegramBotClient = telegramBotClient; private readonly GeminiClient _geminiClient = geminiClient; - private readonly ICommandQueue _commandQueue = commandQueue; private readonly ITelegramMessageCache _telegramMessageCache = telegramMessageCache; private readonly CommandPriorityCategorizer _commandPriorityCategorizer = commandPriorityCategorizer; private readonly ILogger _logger = logger; @@ -62,17 +56,33 @@ public Task Handle(GeminiTextPrompt textPrompt, CancellationToken cancellationTo // Fire and forget Task.Run(async () => { - List messages = [ - Content.FromText("model", "The following is a conversation with an AI assistant. The assistant is helpful, creative, direct, concise, and always get to the point. When user asks for an image to be generated, the AI assistant should respond with \"ImageGeneration:\" followed by comma separated list of features to be expected from the generated image.") - ]; + List messages = []; - messages.AddRange( - from message in textPrompt.Thread.Take(10).Reverse() - select Content.FromText( + // Merge adjacent messages from same role + foreach (MessageBase message in textPrompt.Thread.Reverse()) { + Content content = Content.FromText( role: message.Sender.GeminiRole, text: message.Text - ) - ); + ); + + if (messages.Count > 0 + && messages[^1].Role == message.Sender.GeminiRole) { + messages[^1].Add(content); + } else { + messages.Add(content); + } + } + + // Trim thread longer than 10 messages + while (messages.Count > 10) { + messages.RemoveAt(0); + } + + // Thread must start with user message + while (messages.Count > 0 + && messages[0].Role != "user") { + messages.RemoveAt(0); + } messages.Add( Content.FromText("user", textPrompt.Prompt) @@ -91,62 +101,6 @@ select Content.FromText( cancellationToken: cancellationToken ); - // Handle image generation intent - if (response.StartsWith("ImageGeneration:")) { - if (textPrompt.Command.Sender is not VIPSender) { - try { - ArtCommandHandler.IMAGE_GENERATION_RATE_LIMITER.ValidateActionRate(textPrompt.Command.Chat.Id, textPrompt.Command.Sender.Id); - } catch (RateLimitExceededException exc) { - await _telegramBotClient.SendTextMessageAsync( - chatId: textPrompt.Command.Chat.Id, - text: $"Anda belum mendapat giliran. Coba lagi {exc.Cooldown}.", - parseMode: ParseMode.Html, - replyToMessageId: textPrompt.Command.MessageId, - cancellationToken: cancellationToken - ); - return; - } - } - - string imageGenerationPrompt = response.Substring(response.IndexOf(':') + 1).Trim(); - switch (textPrompt.Command) { - case { Sender: VIPSender }: - await _commandQueue.DispatchAsync( - command: new OpenAIImageGenerationPrompt( - callSign: "Gemini", - prompt: imageGenerationPrompt, - promptMessageId: textPrompt.Command.MessageId, - responseMessageId: new(responseMessage.MessageId), - chat: textPrompt.Command.Chat, - sender: textPrompt.Command.Sender - ) - ); - break; - case { Chat: HomeGroupChat }: - await _commandQueue.DispatchAsync( - command: new StabilityTextToImagePrompt( - callSign: "Gemini", - prompt: imageGenerationPrompt, - promptMessageId: textPrompt.Command.MessageId, - responseMessageId: new(responseMessage.MessageId), - chat: textPrompt.Command.Chat, - sender: textPrompt.Command.Sender - ) - ); - break; - default: - await _telegramBotClient.EditMessageTextAsync( - chatId: textPrompt.Command.Chat.Id, - messageId: responseMessage.MessageId, - text: MarkdownV2Sanitizer.Sanitize("Image generation tidak bisa dipakai di sini."), - parseMode: ParseMode.MarkdownV2, - cancellationToken: cancellationToken - ); - break; - } - return; - } - // Finalize message try { responseMessage = await telegramBotClient.EditMessageTextAsync( diff --git a/BotNet.Services/Gemini/Models/Content.cs b/BotNet.Services/Gemini/Models/Content.cs index bdf6c60..36197b6 100644 --- a/BotNet.Services/Gemini/Models/Content.cs +++ b/BotNet.Services/Gemini/Models/Content.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Text.Json.Serialization; namespace BotNet.Services.Gemini.Models { @@ -12,5 +13,10 @@ public record Content( new(Text: text) ] ); + + public void Add(Content content) { + if (content.Role != Role) throw new InvalidOperationException(); + Parts!.AddRange(content.Parts!); + } } }