#pragma once #include "ofMain.h" #include "ofThread.h" #include #include #include #include #include "ofxNetwork.h" class LLMRequestThread : public ofThread { public: LLMRequestThread() {} ~LLMRequestThread() { stop(); waitForThread(false); } void setup(std::string url_) { url = url_; resultReady = false; startThread(); } void requestPromptTest(std::string newPrompt) { std::unique_lock lock(mutex); prompt = newPrompt; resultReady = false; hasNewPrompt = true; condition.notify_all(); // wake thread to start processing } void requestPrompt(const std::string& speaker_, const std::string& text_, const std::string& emotion_, const float temp_) { std::unique_lock lock(mutex); speaker = speaker_; text = text_; emotion = emotion_; llmTemperature = temp_; resultReady = false; hasNewPrompt = true; condition.notify_all(); // wake thread to start processing } std::string getResult() { std::unique_lock lock(mutex); return result; } bool isResultReady() { return resultReady.load(); } void stop() { std::unique_lock lock(mutex); stopThread(); condition.notify_all(); } protected: void threadedFunction() override { while (isThreadRunning()) { std::unique_lock lock(mutex); condition.wait(lock, [this] { return hasNewPrompt || !isThreadRunning(); }); if (!isThreadRunning()) break; std::string localSpeaker = speaker; std::string localBody = text; std::string localEmotion = emotion; float localTemp = llmTemperature; hasNewPrompt = false; lock.unlock(); // unlock during HTTP request // Do HTTP POST request to FastAPI std::string responseText = makeRequest(localSpeaker, localBody, localEmotion, localTemp); lock.lock(); result = responseText; resultReady = true; } } std::string makeRequest(const std::string& speaker_, const std::string& text_, const std::string& emotion_, const float temp_) { ofxTCPClient client; std::string host = "127.0.0.1"; // or extract from your url int port = 8000; // or extract from your url // Connect to server if (!client.setup(host, port, false)) { return "Error: Could not connect"; } // Prepare HTTP POST request // Build JSON body with all fields std::string body = "{\"speaker\":\"" + speaker_ + "\"," "\"sentence\":\"" + text_ + "\"," "\"emotion\":\"" + emotion_ + "\"," "\"temp\":" + ofToString(temp_) + "}"; ofLog() << body; std::string request = "POST /generate HTTP/1.1\r\n" "Host: " + host + "\r\n" "Content-Type: application/json\r\n" "Content-Length: " + std::to_string(body.size()) + "\r\n" "Connection: close\r\n" "\r\n" + body; client.sendRaw(request); // Wait for response (simple, not robust) std::string response; uint64_t startTime = ofGetElapsedTimeMillis(); while (ofGetElapsedTimeMillis() - startTime < 3000) { // 3s timeout std::string received = client.receiveRaw(); if (!received.empty()) { response += received; } if (response.find("\r\n\r\n") != std::string::npos) break; // End of headers ofSleepMillis(10); } client.close(); // Extract body (after \r\n\r\n) size_t pos = response.find("\r\n\r\n"); if (pos != std::string::npos) { std::string body = response.substr(pos + 4); // Optionally parse JSON here return body; } else { return "Error: No response body"; } } private: std::string url; std::string prompt; std::string speaker; std::string text; std::string emotion; float llmTemperature; std::string result; std::condition_variable condition; std::mutex mutex; std::atomic resultReady; bool hasNewPrompt = false; };