NEON / backend /src /utils /stream.ts
picklefried706's picture
Upload folder using huggingface_hub
40a9423 verified
import { request } from "undici";
const API_BASE = process.env.LLM_API_BASE ?? "https://api.openai.com";
const API_KEY = process.env.LLM_API_KEY ?? "";
const MODEL = process.env.LLM_MODEL ?? "gpt-4o-mini";
export async function streamChatCompletion(
messages: Array<{ role: string; content: string }>,
onToken: (token: string) => void
) {
if (!API_KEY) {
throw new Error("Missing LLM_API_KEY environment variable.");
}
const payload = {
model: MODEL,
messages,
stream: true,
temperature: 0.3
};
const { body, statusCode } = await request(`${API_BASE}/v1/chat/completions`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
if (statusCode < 200 || statusCode >= 300) {
const errorText = await body.text();
throw new Error(`LLM request failed (${statusCode}): ${errorText.slice(0, 200)}`);
}
const reader = body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
let boundary = buffer.indexOf("\n\n");
while (boundary !== -1) {
const chunk = buffer.slice(0, boundary).trim();
buffer = buffer.slice(boundary + 2);
if (chunk.startsWith("data:")) {
const data = chunk.replace(/^data:\s*/, "").trim();
if (data === "[DONE]") return;
try {
const parsed = JSON.parse(data);
const delta = parsed.choices?.[0]?.delta?.content;
if (delta) onToken(delta);
} catch {
// Ignore JSON parse errors in partial chunks
}
}
boundary = buffer.indexOf("\n\n");
}
}
}