using OpenAI.Chat; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; using TelegramBot; using File = System.IO.File; string baseUrl = Env.Get("OPENAI_BASE_URL"); string apiKey = Env.Get("OPENAI_API_KEY"); string model = Env.Get("OPENAI_MODEL"); var oaiAgent = new OpenAiAgent(baseUrl, apiKey, model); oaiAgent.ContextSize = Int32.Parse(Env.Get("CONTEXT_SIZE")); Console.WriteLine("Starting the bot..."); string nemesisPrompt = File.ReadAllText($"prompt/{Env.Get("NEMESIS_PROMPT_FILE")}"); string krolikPrompt = File.ReadAllText($"prompt/{Env.Get("KROLIK_PROMPT_FILE")}"); //Ratelimit TimeSpan rateLimit = new(0, 0, 0, 10); Dictionary lastMessage = new(); HashSet unlimitedChats = new(); bool IsRateLimited(long chatId) { if (lastMessage.ContainsKey(chatId) && DateTime.Now - lastMessage[chatId] < rateLimit) return true; lastMessage[chatId] = DateTime.Now; return false; } #region TelegramBot Startup string nemesisToken = Env.Get("NEMESIS_BOT_TOKEN"); string krolikToken = Env.Get("KROLIK_BOT_TOKEN"); using var nemcts = new CancellationTokenSource(); using var krocts = new CancellationTokenSource(); var nemesisBot = new TelegramBotClient(nemesisToken, cancellationToken:nemcts.Token); var krolikBot = new TelegramBotClient(krolikToken, cancellationToken:krocts.Token); var nemProfile = nemesisBot.GetMe(); Agent Nemesis = new( Actor.Nemesis, nemProfile.Result.Id, nemProfile.Result.FirstName, nemProfile.Result.Username!, nemesisBot, nemesisPrompt, oaiAgent.GetTokenLenght(nemesisPrompt) ); var kroProfile = krolikBot.GetMe(); Agent Krolik = new( Actor.Krolik, kroProfile.Result.Id, kroProfile.Result.FirstName, kroProfile.Result.Username!, krolikBot, krolikPrompt, oaiAgent.GetTokenLenght(krolikPrompt) ); nemesisBot.OnMessage += OnNemMessage; krolikBot.OnMessage += OnKroMessage; await nemesisBot.DropPendingUpdates(); Console.WriteLine("Nemesis Bot running"); await krolikBot.DropPendingUpdates(); Console.WriteLine("Krolik Bot running"); Thread.Sleep(Timeout.Infinite); nemcts.Cancel(); // stop nembot krocts.Cancel(); // stop krobot #endregion async Task OnNemMessage(Message msg, UpdateType type) { //Discard any message that is not a text message if (msg.Type != MessageType.Text) return; await OnMessage(msg, Nemesis); } async Task OnKroMessage(Message msg, UpdateType type) { //Discard any message that is not a text message if (msg.Type != MessageType.Text) return; await OnMessage(msg, Krolik); } //TODO: currently we only take in account private messages and messages directed to the bot/mentioning them. // We should also take in account the last x messages in groups to add more context async Task OnMessage(Message msg, Agent agent) { var chatid = msg.Chat.Id; //Check if the message is a reset command if (msg.Text == "/reset" || msg.Text == "/reset@" + agent.Username) { oaiAgent.ResetChat(chatid); await agent.Bot.SendMessage(chatid, "Chat context has been reset"); return; } if (msg.Text == "/history @"+agent.Username) { var history = oaiAgent.GetChatHistory(chatid, agent.Actor); var historyText = string.Join("\n", history.Select(x => x.Item1.Content[0].Text)); await agent.Bot.SendMessage(chatid, historyText); return; } var text = $"{msg.From?.FirstName} {msg.From?.LastName}: {msg.Text}"; var tokenlenght = oaiAgent.GetTokenLenght(msg.Text!); Console.WriteLine( $""" {agent.Name} has received message from {chatid} TokenLenght: {tokenlenght} Message: {msg.Text} """); //Add the message to the chat history oaiAgent.ChatHistoryAppend(agent.Actor, chatid, text); //Check if the message contains the bot's username or a reply to a message sent by the bot or a private chat // Otherwise process it normally if (msg.Text!.Contains(agent.Name, StringComparison.OrdinalIgnoreCase) || msg.ReplyToMessage?.From?.Id == agent.TelegramId || msg.Chat.Type == ChatType.Private) { //Check if the chat (group) is rate limited /*if (IsRateLimited(chatid)) { Console.WriteLine("No response due to ratelimit."); return; } */ await AnswerChat(chatid, agent); } } async Task AnswerChat(long chatId, Agent agent) { //Get the response from the OpenAI API var result = oaiAgent.GetChatResponse(chatId, agent); Console.WriteLine( $""" {agent.Name} has responded with: {result} """); //Send the response to the user await agent.Bot.SendMessage(chatId, result); }