import { chat, rawSSE, save, MODELS, short } from "./lib.ts"; const out: Record = {}; for (const model of MODELS) { // (a) tiny non-streaming const r = await chat({ model, messages: [{ role: "user", content: "What is 2+2? Answer in one short sentence." }], max_completion_tokens: 200, }); const b: any = r.body; const usage = b?.usage; const tps = usage && b?.time_info ? Math.round(usage.completion_tokens / b.time_info.completion_time) : null; out[`${model}:nonstream`] = { ...r, tokensPerSecond: tps }; console.log(model, "nonstream", r.status, r.ms + "ms", "tps=", tps, "\n message keys:", b?.choices?.[0]?.message && Object.keys(b.choices[0].message), "\n content:", short(b?.choices?.[0]?.message?.content, 200), "\n reasoning:", short(b?.choices?.[0]?.message?.reasoning, 120), "\n usage:", JSON.stringify(usage), "\n time_info:", JSON.stringify(b?.time_info), "\n top keys:", b && Object.keys(b)); // (b) streaming with include_usage const s = await rawSSE("/chat/completions", { model, messages: [{ role: "user", content: "Say hello in French, 5 words max." }], max_completion_tokens: 200, stream: true, stream_options: { include_usage: true }, }); const deltaKeys = new Set(); const finishes: string[] = []; let content = ""; let reasoning = ""; const withUsage: number[] = []; const withTimeInfo: number[] = []; const otherKeys = new Set(); s.events.forEach((e, i) => { if (e.data === "[DONE]") return; const d = e.data; Object.keys(d).forEach((k) => otherKeys.add(k)); if (d.usage) withUsage.push(i); if (d.time_info) withTimeInfo.push(i); const c = d.choices?.[0]; if (c?.delta) Object.keys(c.delta).forEach((k) => deltaKeys.add(k)); if (c?.delta?.content) content += c.delta.content; if (c?.delta?.reasoning) reasoning += c.delta.reasoning; if (c?.delta?.reasoning_content) reasoning += "[RC]" + c.delta.reasoning_content; if (c?.finish_reason) finishes.push(`${i}:${c.finish_reason}`); }); out[`${model}:stream`] = { status: s.status, headers: s.headers, ttfbMs: s.ttfbMs, totalMs: s.totalMs, nEvents: s.events.length, deltaKeys: [...deltaKeys], topLevelKeys: [...otherKeys], finishes, withUsage, withTimeInfo, content, reasoning: short(reasoning, 400), hasThinkTag: //.test(content), first3: s.events.slice(0, 3), last3: s.events.slice(-3), error: s.error, }; console.log(model, "stream", s.status, "events", s.events.length, "ttfb", s.ttfbMs, "deltaKeys", [...deltaKeys], "finishes", finishes, "usageAt", withUsage, "timeInfoAt", withTimeInfo, "\n content:", short(content, 150), "\n reasoning:", short(reasoning, 150), "\n last3:", short(s.events.slice(-3), 900)); // (b2) streaming WITHOUT stream_options: is usage still present? const s2 = await rawSSE("/chat/completions", { model, messages: [{ role: "user", content: "Say hi." }], max_completion_tokens: 30, stream: true, }); const usageIdx = s2.events.map((e, i) => (e.data !== "[DONE]" && e.data?.usage ? i : -1)).filter((i) => i >= 0); out[`${model}:stream-no-options`] = { status: s2.status, nEvents: s2.events.length, usageIdx, last2: s2.events.slice(-2) }; console.log(model, "stream w/o stream_options: usage at", usageIdx, "of", s2.events.length); } save("01-chat-stream.json", out);