diff --git a/Conversation.cpp b/Conversation.cpp index b2b7463..c70838e 100644 --- a/Conversation.cpp +++ b/Conversation.cpp @@ -23,6 +23,13 @@ Conversation::Conversation(BHandler* replyTo) { Conversation::~Conversation() { } + + +void Conversation::PrintAsJsonArray(const std::vector& models) { + json output = models; // implicit conversion to JSON array + std::cout << output.dump(2) << std::endl; // pretty-print with 2-space indent +} + void Conversation::sendReply(BMessage message) { BLooper* looper = replyTarget->Looper(); // get the looper it's attached to @@ -34,6 +41,25 @@ void Conversation::sendReply(BMessage message) { } } + +std::vector Conversation::FilterTextModels(const json& modelsJson) { + std::vector result; + std::regex pattern("gpt|text|davinci|curie|babbage|ada"); + + for (const auto& model : modelsJson["data"]) { + std::string id = model["id"]; + if (std::regex_search(id, pattern) && + id.find("audio") == std::string::npos && + id.find("vision") == std::string::npos && + id.find("dall-e") == std::string::npos) { + result.push_back(id); + } + } + + return result; +} + + void Conversation::MessageReceived(BMessage* message) { switch (message->what) { //.. case B_HTTP_DATA_RECEIVED: { @@ -78,12 +104,35 @@ void Conversation::MessageReceived(BMessage* message) { BHttpBody body = _lastResult->Body(); if (body.text.has_value()) { + //printf("full Reply as text:%s",body.text.value().String()); json parsed = json::parse(body.text.value().String()); - std::string content = parsed["choices"][0]["message"]["content"]; -// printf("we got content:%s",content.c_str()); - BMessage message(kSendReply); - message.AddString("text", BString(content.c_str())); - sendReply(message); + printf("Parsed..\n"); + + std::string objType = parsed["object"]; + printf("Reply of type object :%s\n",objType.c_str()); + + if (objType == "list") + { + //printf("full Reply as text:%s",body.text.value().String()); + + std::vector validModels = FilterTextModels(parsed); + PrintAsJsonArray(validModels); + + +// std::string content = parsed["choices"][0]["message"]["content"]; + + } + + else + if (objType == "chat.completion") + { + std::string content = parsed["choices"][0]["message"]["content"]; + + // printf("we got content:%s",content.c_str()); + BMessage message(kSendReply); + message.AddString("text", BString(content.c_str())); + sendReply(message); + } } else { @@ -132,18 +181,7 @@ void Conversation::MessageReceived(BMessage* message) { } } -void Conversation::ask(const std::string& prompt) { - - printf("Asking prompt: %s",prompt.c_str()); - - if (_lastResult) - - _sharedSession.Cancel(_lastResult->Identity()); - - - auto url = BUrl("https://api.openai.com/v1/chat/completions"); - BHttpRequest request = BHttpRequest(url); - request.SetMethod(BHttpMethod::Post); +std::string Conversation::buildBearerKey() { // if the API key file contains a new line bhttpfields will crash with invalid // content .end() requires include algorithm @@ -152,9 +190,49 @@ void Conversation::ask(const std::string& prompt) { key.erase(std::remove(key.begin(), key.end(), '\r'), key.end()); std::string bearer = std::string("Bearer ") + std::string(key); + return bearer; + +} + +void Conversation::loadModels() { + + auto url = BUrl("https://api.openai.com/v1/models"); + BHttpRequest request = BHttpRequest(url); + request.SetMethod(BHttpMethod::Get); + BHttpFields fields = BHttpFields(); - fields.AddField("Authorization", bearer); + fields.AddField("Authorization", buildBearerKey()); + request.SetFields(fields); + + BString mime = BString("application/json"); + + printf("Sending Prompt to server: %s\n", url.UrlString().String()); + _lastResult = _sharedSession.Execute(std::move(request), nullptr, this); + + if (_lastResult) { + printf("Result has identity: %d\n", _lastResult->Identity()); + } + + + +} + +void Conversation::ask(const std::string& prompt) { + +// printf("Asking prompt: %s",prompt.c_str()); + + if (_lastResult) + _sharedSession.Cancel(_lastResult->Identity()); + + + auto url = BUrl("https://api.openai.com/v1/chat/completions"); + BHttpRequest request = BHttpRequest(url); + request.SetMethod(BHttpMethod::Post); + + + BHttpFields fields = BHttpFields(); + fields.AddField("Authorization", buildBearerKey()); // fields.AddField("Content-Type", "application/json"); //NO, this will // crash, we set it in request request.SetFields(fields); @@ -184,14 +262,13 @@ void Conversation::ask(const std::string& prompt) { BString Conversation::ReadOpenAIKey() { - // /boot/home/config/openai_key - // or ~/.config/openai_key on linux BPath configPath; if (find_directory(B_USER_SETTINGS_DIRECTORY, &configPath) != B_OK) return "error: couldn't find config directory"; - - configPath.Append("openai_keyxxx"); + + // /boot/home/config/openai_key + configPath.Append("openai_key"); BFile file(configPath.Path(), B_READ_ONLY); diff --git a/Conversation.h b/Conversation.h index 7e8fd8b..4b8162a 100644 --- a/Conversation.h +++ b/Conversation.h @@ -6,9 +6,13 @@ #include #include +#include #include #include #include +#include +#include +#include @@ -51,10 +55,18 @@ public: Conversation(BHandler* replyTo); virtual ~Conversation() ; - virtual void ask(const std::string& prompt); virtual void MessageReceived(BMessage *msg); + + std::vector FilterTextModels(const json& modelsJson); + + void ask(const std::string& prompt); + void loadModels(); + void PrintAsJsonArray(const std::vector& models) ; + private: + + std::string buildBearerKey(); void sendReply(BMessage message); diff --git a/DumBer b/DumBer index 8ac83e7..e04ac0e 100755 Binary files a/DumBer and b/DumBer differ diff --git a/MainWindow.cpp b/MainWindow.cpp index 1bbe758..c022834 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -135,7 +135,10 @@ void MainWindow::checkValidKey() { return; } else + { _infoView->SetText("API Key loaded."); + _conversation->loadModels(); + } }