4 changed files with 232 additions and 11 deletions
@ -0,0 +1,152 @@ |
|||
#pragma once |
|||
#include "ofMain.h" |
|||
#include "ofThread.h" |
|||
#include <condition_variable> |
|||
#include <mutex> |
|||
#include <atomic> |
|||
#include <string> |
|||
#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<std::mutex> 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<std::mutex> 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<std::mutex> lock(mutex); |
|||
return result; |
|||
} |
|||
|
|||
bool isResultReady() { |
|||
return resultReady.load(); |
|||
} |
|||
|
|||
void stop() { |
|||
std::unique_lock<std::mutex> lock(mutex); |
|||
stopThread(); |
|||
condition.notify_all(); |
|||
} |
|||
|
|||
protected: |
|||
void threadedFunction() override { |
|||
while (isThreadRunning()) { |
|||
std::unique_lock<std::mutex> 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<bool> resultReady; |
|||
bool hasNewPrompt = false; |
|||
}; |
Loading…
Reference in new issue