Skip to content

Commit

Permalink
Implemented Gemini
Browse files Browse the repository at this point in the history
  • Loading branch information
ronnygunawan committed Jan 31, 2024
1 parent d520f21 commit b6229b3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 72 deletions.
96 changes: 25 additions & 71 deletions BotNet.CommandHandlers/AI/Gemini/GeminiTextPromptHandler.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -20,7 +16,6 @@ namespace BotNet.CommandHandlers.AI.Gemini {
public sealed class GeminiTextPromptHandler(
ITelegramBotClient telegramBotClient,
GeminiClient geminiClient,
ICommandQueue commandQueue,
ITelegramMessageCache telegramMessageCache,
CommandPriorityCategorizer commandPriorityCategorizer,
ILogger<GeminiTextPromptHandler> logger
Expand All @@ -29,7 +24,6 @@ ILogger<GeminiTextPromptHandler> 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<GeminiTextPromptHandler> _logger = logger;
Expand Down Expand Up @@ -62,17 +56,33 @@ public Task Handle(GeminiTextPrompt textPrompt, CancellationToken cancellationTo

// Fire and forget
Task.Run(async () => {
List<Content> 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<Content> 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)
Expand All @@ -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(
Expand Down
8 changes: 7 additions & 1 deletion BotNet.Services/Gemini/Models/Content.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace BotNet.Services.Gemini.Models {
Expand All @@ -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!);
}
}
}

0 comments on commit b6229b3

Please sign in to comment.