They can now answer

This commit is contained in:
Samuele Lorefice
2024-12-26 20:19:59 +01:00
parent 124a4c66fe
commit 773203127f
6 changed files with 79 additions and 46 deletions

1
.env
View File

@@ -1,2 +1,3 @@
MODEL_PATH=./model MODEL_PATH=./model
MODEL_NAME=Qwen2.5-7B-Instruct-Q8.gguf MODEL_NAME=Qwen2.5-7B-Instruct-Q8.gguf
CONTEXT_SIZE=4096

View File

@@ -5,7 +5,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0C9A5F05-7CED-450F-9757-C641D75F8787}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0C9A5F05-7CED-450F-9757-C641D75F8787}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
compose.yaml = compose.yaml compose.yaml = compose.yaml
prompt\nemesis.txt = prompt\nemesis.txt
EndProjectSection EndProjectSection
EndProject EndProject
Global Global

View File

@@ -2,10 +2,12 @@
namespace TelegramBot; namespace TelegramBot;
public class Agent(Actor actor, long telegramId, string name, string username, TelegramBotClient bot) { public class Agent(Actor actor, long telegramId, string name, string username, TelegramBotClient bot, string systemPrompt, int tokenLenght) {
public Actor Actor { get; } = actor; public Actor Actor { get; } = actor;
public long TelegramId { get; } = telegramId; public long TelegramId { get; } = telegramId;
public string Username { get; } = username; public string Username { get; } = username;
public string Name { get; } = name; public string Name { get; } = name;
public TelegramBotClient Bot { get; } = bot; public TelegramBotClient Bot { get; } = bot;
public string SystemPrompt { get; } = systemPrompt;
public int SystemPromptLength { get; } = tokenLenght;
} }

View File

@@ -6,14 +6,16 @@ using OpenAI.Chat;
namespace TelegramBot; namespace TelegramBot;
public class OpenAiAgent public class OpenAiAgent {
{
private ApiKeyCredential apikey; private ApiKeyCredential apikey;
private OpenAIClient oaiClient; private OpenAIClient oaiClient;
private ChatClient chatClient; private ChatClient chatClient;
private HttpClient httpClient; private HttpClient httpClient;
private Dictionary<(long, Actor), List<(ChatMessage, int)>> oaiChats = new(); private Dictionary<(long, Actor), List<(ChatMessage, int)>> oaiChats = new();
public int ContextSize { get; set; } = 4096;
public OpenAiAgent(string baseUrl, string apiKey, string model) { public OpenAiAgent(string baseUrl, string apiKey, string model) {
OpenAIClientOptions options = new OpenAIClientOptions() { OpenAIClientOptions options = new OpenAIClientOptions() {
Endpoint = new(baseUrl), Endpoint = new(baseUrl),
@@ -79,8 +81,29 @@ public class OpenAiAgent
return chat!; return chat!;
} }
public string GetChatResponse(long chatId, Actor actor) { public string GetChatResponse(long chatId, Agent agent) {
return String.Empty; int currentContextSize = agent.SystemPromptLength;
List<ChatMessage> chatHistory = new();
chatHistory.Add(new SystemChatMessage(agent.SystemPrompt));
//Fetch the chat history from the dictionary trimming to the context size
var history = GetChatHistory(chatId, agent.Actor).ToList();
history.Reverse();
//Add the chat history to the list until the context size is reached
foreach (var (message, tokenLenght) in history) {
if (currentContextSize + tokenLenght > ContextSize) break;
chatHistory.Add(message);
currentContextSize += tokenLenght;
}
//Reverse the chat history to get the correct order
chatHistory.Reverse(1, chatHistory.Count - 1);
var completion = chatClient.CompleteChat(chatHistory).Value.Content[0].Text;
//Add the response to the chat history
ChatHistoryAppend(agent.Actor, chatId, completion);
return completion;
} }
public void AddChatToDictionary(long id) { public void AddChatToDictionary(long id) {

View File

@@ -1,13 +1,15 @@
using OpenAI.Chat; using OpenAI.Chat;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;using TelegramBot; using Telegram.Bot.Types.Enums;
using TelegramBot;
using File = System.IO.File; using File = System.IO.File;
string baseUrl = Env.Get("OPENAI_BASE_URL"); string baseUrl = Env.Get("OPENAI_BASE_URL");
string apiKey = Env.Get("OPENAI_API_KEY"); string apiKey = Env.Get("OPENAI_API_KEY");
string model = Env.Get("OPENAI_MODEL"); string model = Env.Get("OPENAI_MODEL");
var oaiAgent = new OpenAiAgent(baseUrl, apiKey, model); var oaiAgent = new OpenAiAgent(baseUrl, apiKey, model);
oaiAgent.ContextSize = Int32.Parse(Env.Get("CONTEXT_SIZE"));
Console.WriteLine("Starting the bot..."); Console.WriteLine("Starting the bot...");
@@ -43,7 +45,9 @@ Agent Nemesis = new(
nemProfile.Result.Id, nemProfile.Result.Id,
nemProfile.Result.FirstName, nemProfile.Result.FirstName,
nemProfile.Result.Username!, nemProfile.Result.Username!,
nemesisBot nemesisBot,
nemesisPrompt,
oaiAgent.GetTokenLenght(nemesisPrompt)
); );
var kroProfile = krolikBot.GetMe(); var kroProfile = krolikBot.GetMe();
@@ -52,7 +56,9 @@ Agent Krolik = new(
kroProfile.Result.Id, kroProfile.Result.Id,
kroProfile.Result.FirstName, kroProfile.Result.FirstName,
kroProfile.Result.Username!, kroProfile.Result.Username!,
krolikBot krolikBot,
krolikPrompt,
oaiAgent.GetTokenLenght(krolikPrompt)
); );
nemesisBot.OnMessage += OnNemMessage; nemesisBot.OnMessage += OnNemMessage;
@@ -107,25 +113,26 @@ async Task OnMessage(Message msg, Agent agent) {
// Otherwise process it normally // Otherwise process it normally
if (msg.Text!.Contains(agent.Name, StringComparison.OrdinalIgnoreCase) || if (msg.Text!.Contains(agent.Name, StringComparison.OrdinalIgnoreCase) ||
msg.ReplyToMessage?.From?.Id == agent.TelegramId || msg.Chat.Type == ChatType.Private) { msg.ReplyToMessage?.From?.Id == agent.TelegramId ||
msg.Chat.Type == ChatType.Private) {
//Check if the chat (group) is rate limited //Check if the chat (group) is rate limited
if (IsRateLimited(chatid)) { /*if (IsRateLimited(chatid)) {
Console.WriteLine("No response due to ratelimit."); Console.WriteLine("No response due to ratelimit.");
return; return;
} }
await AnswerChat(chatid, msg.Text, tokenlenght, agent.Actor); */
await AnswerChat(chatid, agent);
} }
} }
async Task AnswerChat(long chatId, string input, int tokenLenght, Actor actor) { async Task AnswerChat(long chatId, Agent agent) {
//Limit the message to 1024 characters to avoid out of context jump
string text = input;
if (input.Length > 1024) text = input.Substring(0, 1024);
//Get the response from the OpenAI API //Get the response from the OpenAI API
var result = oaiAgent.GetChatResponse(chatId, actor); var result = oaiAgent.GetChatResponse(chatId, agent);
Console.WriteLine(
$"""
{agent.Name} has responded with: {result}
""");
//Send the response to the user //Send the response to the user
await krolikBot.SendMessage(chatId, result); await agent.Bot.SendMessage(chatId, result);
} }

View File

@@ -6,6 +6,7 @@
context: . context: .
dockerfile: TelegramBot/Dockerfile dockerfile: TelegramBot/Dockerfile
env_file: env_file:
- .env
- TelegramBot/.env - TelegramBot/.env
llm-server: llm-server:
@@ -15,7 +16,7 @@
- ${MODEL_PATH}:/models - ${MODEL_PATH}:/models
ports: ports:
- "80:80" - "80:80"
command: -m /models/${MODEL_NAME} --port 80 --host 0.0.0.0 -n 128 -c 4096 --no-mmap -ngl 50 -fa -np 4 command: -m /models/${MODEL_NAME} --port 80 --host 0.0.0.0 -n 128 -c ${CONTEXT_SIZE} --no-mmap -ngl 50 -fa -np 4
deploy: deploy:
resources: resources:
reservations: reservations: