separated request class
This commit is contained in:
parent
2dd76e787e
commit
c8523bc115
8 changed files with 336 additions and 209 deletions
228
Conversation.cpp
Normal file
228
Conversation.cpp
Normal file
|
@ -0,0 +1,228 @@
|
|||
// Conversation.cpp
|
||||
#include "Conversation.h"
|
||||
|
||||
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Path.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <Url.h>
|
||||
#include <MimeType.h>
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
Conversation::Conversation(BHandler* replyTo) {
|
||||
|
||||
replyTarget = replyTo;
|
||||
_apiKey = ReadOpenAIKey();
|
||||
printf("key is: %s", _apiKey.String());
|
||||
|
||||
}
|
||||
Conversation::~Conversation() {
|
||||
}
|
||||
|
||||
|
||||
void Conversation::MessageReceived(BMessage* message) {
|
||||
switch (message->what) {
|
||||
//.. case B_HTTP_DATA_RECEIVED: {
|
||||
// break;
|
||||
// }
|
||||
|
||||
case UrlEvent::HostNameResolved: {
|
||||
printf("Host name resolved\n");
|
||||
auto name = message->GetString(UrlEventData::HostName);
|
||||
message->PrintToStream();
|
||||
|
||||
//_infoView->SetText("Hostname resolve...");
|
||||
//_infoView->SetText(name);
|
||||
//_progress->SetTo(5);
|
||||
|
||||
} break;
|
||||
|
||||
case UrlEvent::ConnectionOpened: {
|
||||
printf("ConnectionOpened\n");
|
||||
//_progress->SetTo(10);
|
||||
//_infoView->SetText("connection opened...");
|
||||
} break;
|
||||
|
||||
case UrlEvent::ResponseStarted: {
|
||||
printf("ResponseStarted\n");
|
||||
//_progress->SetTo(14);
|
||||
//_infoView->SetText("ResponseStarted...");
|
||||
} break;
|
||||
|
||||
case UrlEvent::HttpRedirect: {
|
||||
printf("HttpRedirect\n");
|
||||
//_progress->SetTo(16);
|
||||
//_infoView->SetText("HttpRedirect...");
|
||||
} break;
|
||||
|
||||
case UrlEvent::RequestCompleted: {
|
||||
printf("RequestCompleted\n");
|
||||
auto identifier = message->GetInt32(UrlEventData::Id, -1);
|
||||
if (_lastResult->Identity() == identifier) {
|
||||
// The following call will not block, because we have been notified
|
||||
// that the request is done.
|
||||
BHttpBody body = _lastResult->Body();
|
||||
if (body.text.has_value())
|
||||
{
|
||||
|
||||
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()));
|
||||
|
||||
|
||||
BLooper* looper = replyTarget->Looper(); // get the looper it's attached to
|
||||
|
||||
if (looper != nullptr) {
|
||||
BMessenger messenger(replyTarget, looper);
|
||||
messenger.SendMessage(&message);
|
||||
} else {
|
||||
printf("Handler not attached to a looper.\n");
|
||||
}
|
||||
|
||||
|
||||
// status_t err = appMessenger.SendMessage(&message);
|
||||
//if (err != B_OK)
|
||||
// printf("SendMessage failed: %s\n", strerror(err));
|
||||
//else
|
||||
//printf("SendMessage OK");
|
||||
|
||||
// _answerView->SetText(content.c_str());
|
||||
|
||||
// _answerView->SetText(body.text.value());
|
||||
|
||||
}
|
||||
// else
|
||||
//_answerView->SetText("nuthin'");
|
||||
}
|
||||
|
||||
//_infoView->SetText("Completed");
|
||||
//_progress->SetMaxValue(100);
|
||||
//_progress->SetTo(100);
|
||||
|
||||
} break;
|
||||
|
||||
case UrlEvent::HttpStatus: {
|
||||
|
||||
printf("HttpStatus\n");
|
||||
//_infoView->SetText("HttpStatus received");
|
||||
//_progress->SetTo(20);
|
||||
|
||||
} break;
|
||||
|
||||
case UrlEvent::BytesWritten: {
|
||||
// _infoView->SetText("Some bytes written..");
|
||||
auto identifier = message->GetInt32(UrlEventData::Id, -1);
|
||||
if (_lastResult->Identity() == identifier) {
|
||||
off_t numBytes = message->GetInt64(UrlEventData::NumBytes, 0);
|
||||
off_t totalBytes = message->GetInt64(UrlEventData::TotalBytes, 0);
|
||||
// _progress->SetTo(numBytes);
|
||||
//_progress->SetMaxValue(totalBytes);
|
||||
}
|
||||
} break;
|
||||
|
||||
case UrlEvent::DownloadProgress: {
|
||||
auto identifier = message->GetInt32(UrlEventData::Id, -1);
|
||||
if (_lastResult->Identity() == identifier) {
|
||||
off_t nn = message->GetInt64(UrlEventData::NumBytes, 0);
|
||||
off_t totalBytes = message->GetInt64(UrlEventData::TotalBytes, 0);
|
||||
//_progress->SetTo(nn);
|
||||
//_progress->SetMaxValue(totalBytes);
|
||||
//_infoView->SetText("Download Progress..");
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
BHandler::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// if the API key file contains a new line bhttpfields will crash with invalid
|
||||
// content .end() requires include algorithm
|
||||
std::string key = _apiKey.String();
|
||||
key.erase(std::remove(key.begin(), key.end(), '\n'), key.end());
|
||||
key.erase(std::remove(key.begin(), key.end(), '\r'), key.end());
|
||||
|
||||
std::string bearer = std::string("Bearer ") + std::string(key);
|
||||
|
||||
BHttpFields fields = BHttpFields();
|
||||
fields.AddField("Authorization", bearer);
|
||||
// fields.AddField("Content-Type", "application/json"); //NO, this will
|
||||
// crash, we set it in request
|
||||
request.SetFields(fields);
|
||||
|
||||
json bodyJson = {
|
||||
{"model", "gpt-4o"},
|
||||
{"messages", {{{"role", "user"}, {"content", prompt}}}}};
|
||||
|
||||
std::string body = bodyJson.dump();
|
||||
|
||||
BString mime = BString("application/json");
|
||||
|
||||
auto memoryIO = std::make_unique<BMemoryIO>(body.c_str(), body.size());
|
||||
request.SetRequestBody(std::move(memoryIO), "application/json", body.size());
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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_key");
|
||||
|
||||
BFile file(configPath.Path(), B_READ_ONLY);
|
||||
|
||||
printf("full path:%s\n", configPath.Path());
|
||||
if (file.InitCheck() != B_OK)
|
||||
return "error: couldn't open key file ";
|
||||
|
||||
off_t size;
|
||||
file.GetSize(&size);
|
||||
|
||||
char *buffer = new char[size + 1];
|
||||
file.Read(buffer, size);
|
||||
buffer[size] = '\0'; // null-terminate
|
||||
|
||||
BString result(buffer);
|
||||
delete[] buffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue