From 509c5cf87b6074b149662e560fdbc063de7584f3 Mon Sep 17 00:00:00 2001 From: mostlikely4r Date: Sun, 17 Nov 2024 20:09:33 +0100 Subject: [PATCH] LLM: Test implementation of LLM interface. Mostly for compilation testing. --- playerbot/PlayerbotLLMInterface.cpp | 134 +++++++++++++++++++++ playerbot/PlayerbotLLMInterface.h | 11 ++ playerbot/strategy/actions/DebugAction.cpp | 25 ++++ 3 files changed, 170 insertions(+) create mode 100644 playerbot/PlayerbotLLMInterface.cpp create mode 100644 playerbot/PlayerbotLLMInterface.h diff --git a/playerbot/PlayerbotLLMInterface.cpp b/playerbot/PlayerbotLLMInterface.cpp new file mode 100644 index 00000000..ab2d241c --- /dev/null +++ b/playerbot/PlayerbotLLMInterface.cpp @@ -0,0 +1,134 @@ + +#include "PlayerbotLLMInterface.h" +#include +#include +#include + +#ifdef _WIN32 +// Windows-specific headers +#include +#include +#pragma comment(lib, "ws2_32.lib") // Link with Ws2_32.lib +#else +// Linux/Unix-specific headers +#include +#include +#include +#include +#include +#endif + +std::string PlayerbotLLMInterface::Generate(const std::string& prompt) { + std::string serverIp = "127.0.0.1"; // Replace with KoboldCpp server IP + int serverPort = 5001; // Replace with KoboldCpp server port + + const int bufferSize = 4096; + char buffer[bufferSize]; + std::string response; + +#ifdef _WIN32 + // Initialize Winsock + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + return "WSAStartup failed"; + } +#endif + + // Create a socket + int sock; +#ifdef _WIN32 + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + WSACleanup(); + return "Socket creation failed"; + } +#else + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + return "Socket creation failed"; + } +#endif + + // Server address setup + struct sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(serverPort); +#ifdef _WIN32 + if (InetPton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) { + closesocket(sock); + WSACleanup(); + return "Invalid server IP address"; + } +#else + if (inet_pton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) { + close(sock); + return "Invalid server IP address"; + } +#endif + + // Connect to the server +#ifdef _WIN32 + if (connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { + closesocket(sock); + WSACleanup(); + return "Connection to server failed"; + } +#else + if (connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { + close(sock); + return "Connection to server failed"; + } +#endif + + // Create the HTTP POST request + std::ostringstream request; + request << "POST /api/v1/generate HTTP/1.1\r\n"; + request << "Host: " << serverIp << ":" << serverPort << "\r\n"; + request << "Content-Type: application/json\r\n"; + std::string body = "{\"prompt\": \"" + prompt + "\"}"; + request << "Content-Length: " << body.size() << "\r\n"; + request << "\r\n"; + request << body; + + // Send the request +#ifdef _WIN32 + if (send(sock, request.str().c_str(), request.str().size(), 0) == SOCKET_ERROR) { + closesocket(sock); + WSACleanup(); + return "Failed to send request"; + } +#else + if (send(sock, request.str().c_str(), request.str().size(), 0) < 0) { + close(sock); + return "Failed to send request"; + } +#endif + + // Read the response + int bytesRead; + while ((bytesRead = recv(sock, buffer, bufferSize - 1, 0)) > 0) { + buffer[bytesRead] = '\0'; + response += buffer; + } + +#ifdef _WIN32 + if (bytesRead == SOCKET_ERROR) { + response += "Error reading response"; + } + closesocket(sock); + WSACleanup(); +#else + if (bytesRead < 0) { + response += "Error reading response"; + } + close(sock); +#endif + + // Extract the response body (optional: depending on KoboldCpp response format) + size_t pos = response.find("\r\n\r\n"); + if (pos != std::string::npos) { + response = response.substr(pos + 4); + } + + return response; +} \ No newline at end of file diff --git a/playerbot/PlayerbotLLMInterface.h b/playerbot/PlayerbotLLMInterface.h new file mode 100644 index 00000000..9acbe44d --- /dev/null +++ b/playerbot/PlayerbotLLMInterface.h @@ -0,0 +1,11 @@ +namespace ai +{ + class PlayerbotLLMInterface + { + public: + PlayerbotLLMInterface() {} + static std::string Generate(const std::string& prompt); + private: + + }; +} \ No newline at end of file diff --git a/playerbot/strategy/actions/DebugAction.cpp b/playerbot/strategy/actions/DebugAction.cpp index b739d911..8210391b 100644 --- a/playerbot/strategy/actions/DebugAction.cpp +++ b/playerbot/strategy/actions/DebugAction.cpp @@ -11,6 +11,7 @@ #include "playerbot/PlayerbotHelpMgr.h" #include "Entities/Transports.h" #include "MotionGenerators/PathFinder.h" +#include "playerbot/PlayerbotLLMInterface.h" #include @@ -96,6 +97,30 @@ bool DebugAction::Execute(Event& event) return true; } + else if (text.find("llm ") == 0) + { + + std::thread t([text, requester]() { + WorldPacket new_packet(Opcodes(CMSG_MESSAGECHAT), 4096); + + uint32 type = CHAT_MSG_SAY; + uint32 lang = LANG_UNIVERSAL; + + new_packet << type; + new_packet << lang; + + std::string string = PlayerbotLLMInterface::Generate(text.substr(4)); + + new_packet << string; + + std::unique_ptr packet(new WorldPacket(new_packet.GetOpcode())); + *packet = new_packet; + requester->GetSession()->QueuePacket(std::move(packet)); + + return; }); + t.detach(); + return true; + } else if (text == "gy" && isMod) { for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i)