This commit is contained in:
Santiago Lema 2025-05-10 04:48:28 -03:00
parent 5360c4f8d0
commit 9c040edca1
5 changed files with 187 additions and 158 deletions

View file

@ -37,17 +37,16 @@ void Conversation::sendReply(BMessage message) {
}
std::string Conversation::buildHistoryInfoLine() {
std::string info = "" + std::to_string(_messageHistory.size()) + " messages";
return info;
std::string info = "" + std::to_string(_messageHistory.size()) + " messages";
return info;
}
void Conversation::ClearHistory() {
printf("Cleared history\n");
_messageHistory.clear();
printf("Cleared history\n");
_messageHistory.clear();
}
std::vector<std::string>
@ -71,7 +70,8 @@ Conversation::FilterTextModels(const json &modelsJson) {
}
}
std::sort(result.begin(), result.end(), std::greater<>()); // inverse alphabetical to get gpt-4 on top
std::sort(result.begin(), result.end(),
std::greater<>()); // inverse alphabetical to get gpt-4 on top
return result;
}
@ -111,24 +111,36 @@ void Conversation::MessageReceived(BMessage *message) {
} 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()) {
try {
//printf("full Reply as text:%s",body.text.value().String());
auto fullBody =body.text.value().String();
// The following call will not block, because we have been notified
// that the request is done.
try {
printf("RequestCompleted\n");
if (!_lastResult) {
printf("No Last Result (no connection?)..\n");
return;
}
auto identifier = message->GetInt32(UrlEventData::Id, -1);
if (_lastResult->Identity() == identifier) {
if (!_lastResult->HasBody()) {
printf("NO Body (no connection)..\n");
return;
}
BHttpBody body = _lastResult->Body();
if (body.text.has_value()) {
// printf("full Reply as text:%s",body.text.value().String());
auto fullBody = body.text.value().String();
json parsed = json::parse(fullBody);
printf("Parsed..\n");
std::string objType = parsed["object"];
// printf("Reply of type object :%s\n", objType.c_str());
// printf("Reply of type object :%s\n", objType.c_str());
if (objType == "list") {
// printf("full Reply as text:%s",body.text.value().String());
@ -143,19 +155,15 @@ void Conversation::MessageReceived(BMessage *message) {
sendReply(msg);
// std::string content =
//parsed["choices"][0]["message"]["content"];
// parsed["choices"][0]["message"]["content"];
}
else if (objType == "chat.completion") {
std::string content = parsed["choices"][0]["message"]["content"];
_messageHistory.push_back({
{"role", "assistant"},
{"content", content}
});
_messageHistory.push_back(
{{"role", "assistant"}, {"content", content}});
// printf("we got content:%s",content.c_str());
BMessage message(kSendReply);
@ -164,23 +172,21 @@ void Conversation::MessageReceived(BMessage *message) {
sendReply(message);
}
} catch (const std::exception &e) {
fprintf(stderr, "Error parsing JSON: %s\n", e.what());
std::string content = "Error parsing JSON, wrong model ?";
} else {
BMessage message(kSendReply);
message.AddString("text", BString(content.c_str()));
message.AddString("text", "EMPTY BODY");
sendReply(message);
}
} else {
BMessage message(kSendReply);
message.AddString("text", "EMPTY BODY");
sendReply(message);
}
} catch (const std::exception &e) {
fprintf(stderr, "Error parsing JSON: %s\n", e.what());
std::string content = "Error parsing JSON, wrong model ?";
BMessage message(kSendReply);
message.AddString("text", BString(content.c_str()));
sendReply(message);
}
}
break;
} break;
case UrlEvent::HttpStatus: {
@ -192,24 +198,24 @@ void Conversation::MessageReceived(BMessage *message) {
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);
}
// 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..");
}
// 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:
@ -259,11 +265,8 @@ void Conversation::setModel(const std::string &model) {
void Conversation::ask(const std::string &prompt) {
_messageHistory.push_back({
{"role", "user"},
{"content", prompt}
});
_messageHistory.push_back({{"role", "user"}, {"content", prompt}});
// printf("Asking prompt: %s",prompt.c_str());
if (_lastResult)
@ -272,23 +275,22 @@ void Conversation::ask(const std::string &prompt) {
auto url = BUrl("https://api.openai.com/v1/chat/completions");
BHttpRequest request = BHttpRequest(url);
request.SetMethod(BHttpMethod::Post);
//Allow up to 2 minute before timeout, it can be long depending on load or complexity of prompt
request.SetTimeout(120*1000000);
// Allow up to 2 minute before timeout, it can be long depending on load or
// complexity of prompt
request.SetTimeout(120 * 1000000);
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);
// WE PASS THE WHOLE HISTORY to keep context, as recommended for this stateless API!
// json bodyJson = {{"model", _activeModel},
// WE PASS THE WHOLE HISTORY to keep context, as recommended for this
// stateless API!
// json bodyJson = {{"model", _activeModel},
// {"messages", {{{"role", "user"}, {"content", prompt}}}}};
json bodyJson = {
{"model", _activeModel},
{"messages", _messageHistory}
};
json bodyJson = {{"model", _activeModel}, {"messages", _messageHistory}};
std::string body = bodyJson.dump();
@ -313,7 +315,7 @@ BString Conversation::ReadOpenAIKey() {
// /boot/home/config/openai_key
configPath.Append("openai_key");
BFile file(configPath.Path(), B_READ_ONLY);
printf("full path:%s\n", configPath.Path());
@ -323,10 +325,10 @@ BString Conversation::ReadOpenAIKey() {
}
off_t size;
file.GetSize(&size);
file.GetSize(&size);
char *buffer = new char[size + 1];
file.Read(buffer, size);
file.Read(buffer, size);
buffer[size] = '\0'; // null-terminate
BString result(buffer);