94 lines
2.5 KiB
D
94 lines
2.5 KiB
D
#!/usr/bin/env rdmd
|
|
|
|
// Hermes AI Streaming Example in D
|
|
// Uses std.net.curl with byChunk for streaming SSE responses
|
|
|
|
import std.stdio;
|
|
import std.net.curl;
|
|
import std.json;
|
|
import std.string;
|
|
import std.algorithm;
|
|
import std.array;
|
|
|
|
void main()
|
|
{
|
|
immutable baseUrl = "https://hermes.ai.unturf.com/v1/chat/completions";
|
|
immutable model = "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic";
|
|
|
|
try
|
|
{
|
|
writeln("Streaming from Hermes AI...\n");
|
|
|
|
// Create JSON payload
|
|
JSONValue payload;
|
|
payload.object = [
|
|
"model": model,
|
|
"messages": [
|
|
[
|
|
"role": "user",
|
|
"content": "Give a Python Fizzbuzz solution in one line of code?"
|
|
]
|
|
],
|
|
"temperature": 0.5,
|
|
"max_tokens": 150,
|
|
"stream": true
|
|
];
|
|
|
|
// Make streaming POST request
|
|
auto http = HTTP();
|
|
http.addRequestHeader("Content-Type", "application/json");
|
|
http.method = HTTP.Method.post;
|
|
http.url = baseUrl;
|
|
http.postData = payload.toString();
|
|
|
|
string buffer = "";
|
|
|
|
// Process chunks as they arrive
|
|
http.onReceive = (ubyte[] data)
|
|
{
|
|
buffer ~= cast(string)data;
|
|
|
|
// Process complete lines
|
|
while (true)
|
|
{
|
|
auto idx = buffer.indexOf("\n");
|
|
if (idx == -1) break;
|
|
|
|
auto line = buffer[0..idx].strip();
|
|
buffer = buffer[idx+1..$];
|
|
|
|
// Process SSE data lines
|
|
if (line.startsWith("data: "))
|
|
{
|
|
auto jsonData = line[6..$];
|
|
if (jsonData == "[DONE]") continue;
|
|
|
|
try
|
|
{
|
|
auto parsed = parseJSON(jsonData);
|
|
if ("choices" in parsed && parsed["choices"].array.length > 0)
|
|
{
|
|
auto delta = parsed["choices"][0]["delta"];
|
|
if ("content" in delta)
|
|
{
|
|
write(delta["content"].str);
|
|
stdout.flush();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception) {}
|
|
}
|
|
}
|
|
|
|
return data.length;
|
|
};
|
|
|
|
http.perform();
|
|
|
|
writeln("\n\nDone!");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
writeln("\nError: ", e.msg);
|
|
}
|
|
}
|