Download backend/src/utils/stream.ts from picklefried706/NEON: direct link, hf CLI and curl.
- Browser
- Download file 1.81 kB
-
https://huggingface.co/picklefried706/NEON/resolve/main/backend/src/utils/stream.ts
- Command line
-
hf download hf://picklefried706/NEON/backend/src/utils/stream.ts
-
curl -L -o stream.ts https://huggingface.co/picklefried706/NEON/resolve/main/backend/src/utils/stream.ts
1.81 kB
| 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"); | |
| } | |
| } | |
| } | |