SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
6.0 KB · 96 lines typescript
Raw Blame History
1import { chat, rawSSE, save, MODELS, short } from "./lib.ts";23const out: Record<string, unknown> = {};45// (1) gpt-oss json_schema streamed: inspect chunks (why invalid in 04?)6{7  const s = await rawSSE("/chat/completions", {8    model: "gpt-oss-120b",9    messages: [{ role: "user", content: "Give the sum of 2 and 2." }],10    max_completion_tokens: 200,11    stream: true,12    response_format: { type: "json_schema", json_schema: { name: "sum", strict: true, schema: { type: "object", properties: { answer: { type: "integer" } }, required: ["answer"], additionalProperties: false } } },13  });14  let content = "";15  let reasoning = "";16  for (const e of s.events) {17    if (e.data === "[DONE]") continue;18    const d = e.data.choices?.[0]?.delta ?? {};19    if (d.content) content += d.content;20    if (d.reasoning) reasoning += d.reasoning;21  }22  const fin = s.events.find((e) => e.data !== "[DONE]" && e.data?.choices?.[0]?.finish_reason)?.data?.choices?.[0]?.finish_reason;23  out.gptOssJsonSchemaStream = { status: s.status, content, reasoning: short(reasoning, 300), finish: fin, usage: s.events.find((e) => e.data !== "[DONE]" && e.data?.usage)?.data?.usage };24  console.log("gpt-oss json_schema stream:", s.status, "finish", fin, "content:", JSON.stringify(content), "reasoning:", short(reasoning, 150));25}2627// (2) reasoning_format raw on gpt-oss and qwen: how are <think>/analysis tags embedded? (non-stream, low effort)28for (const model of ["gpt-oss-120b", "qwen-3.8-27b", "gemma-4-31b"]) {29  const r = await chat({ model, messages: [{ role: "user", content: "Is 7 prime? One word." }], max_completion_tokens: 300, reasoning_format: "raw", reasoning_effort: "low" });30  const b: any = r.body;31  out[`${model}:raw`] = { status: r.status, message: b?.choices?.[0]?.message, usage: b?.usage, error: r.status !== 200 ? b : undefined };32  console.log(model, "reasoning_format raw:", r.status, short(b?.choices?.[0]?.message ?? b, 500));33}3435// (3) gemma with reasoning enabled: is `reasoning` returned & streamed?36{37  const s = await rawSSE("/chat/completions", { model: "gemma-4-31b", messages: [{ role: "user", content: "Is 7 prime? One word." }], max_completion_tokens: 300, stream: true, reasoning_effort: "medium" });38  const keys = new Set<string>();39  let reasoning = "";40  let content = "";41  for (const e of s.events) {42    if (e.data === "[DONE]") continue;43    const d = e.data.choices?.[0]?.delta ?? {};44    Object.keys(d).forEach((k) => keys.add(k));45    if (d.reasoning) reasoning += d.reasoning;46    if (d.content) content += d.content;47  }48  out.gemmaReasoningStream = { status: s.status, deltaKeys: [...keys], reasoning: short(reasoning, 300), content, usage: s.events.find((e) => e.data !== "[DONE]" && e.data?.usage)?.data?.usage, error: s.error };49  console.log("gemma reasoning stream:", s.status, [...keys], "reasoning:", short(reasoning, 150), "content:", content, "usage:", JSON.stringify((out.gemmaReasoningStream as any).usage));50}5152// (4) Context window: ~70k-token prompt (paid: 128k/131k; free: 64k/65k) then ~140k (over limit) to capture error text.53function filler(tokensApprox: number) {54  // "lorem ipsum " ~ 3 tokens per 12 chars → build ~4 chars/token filler of distinct words to avoid weirdness55  const words = ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima"];56  const parts: string[] = [];57  for (let i = 0; i < tokensApprox; i++) parts.push(words[i % words.length]);58  return parts.join(" ");59}60for (const model of MODELS) {61  for (const target of [70_000, 140_000]) {62    const r = await chat({63      model,64      messages: [{ role: "user", content: `Reply with the single word OK. Ignore this filler:\n${filler(target)}` }],65      max_completion_tokens: 10,66      reasoning_effort: model === "gpt-oss-120b" ? "low" : "none",67    });68    const b: any = r.body;69    out[`${model}:ctx${target}`] = { status: r.status, promptTokens: b?.usage?.prompt_tokens, finish: b?.choices?.[0]?.finish_reason, error: r.status !== 200 ? b : undefined, headers: r.headers, ms: r.ms };70    console.log(model, `ctx~${target}:`, r.status, "prompt_tokens", b?.usage?.prompt_tokens, r.ms + "ms", r.status !== 200 ? short(b, 400) : "");71  }72}7374// (5) max_completion_tokens above the per-model cap → error text?75for (const model of MODELS) {76  const r = await chat({ model, messages: [{ role: "user", content: "hi" }], max_completion_tokens: 60_000, reasoning_effort: model === "gpt-oss-120b" ? "low" : "none" });77  out[`${model}:maxout60k`] = { status: r.status, body: r.status !== 200 ? r.body : short((r.body as any)?.choices?.[0]?.message?.content, 80) };78  console.log(model, "max_completion_tokens 60000:", r.status, short(r.body, 300));79}8081// (6) reasoning-heavy probe: gpt-oss high effort, see reasoning_tokens vs completion_tokens & finish on cap82{83  const r = await chat({ model: "gpt-oss-120b", messages: [{ role: "user", content: "How many r's in 'strawberry'? Think carefully." }], max_completion_tokens: 1000, reasoning_effort: "high" });84  const b: any = r.body;85  out.gptOssHigh = { status: r.status, usage: b?.usage, time_info: b?.time_info, finish: b?.choices?.[0]?.finish_reason, content: short(b?.choices?.[0]?.message?.content, 200), reasoningLen: b?.choices?.[0]?.message?.reasoning?.length };86  console.log("gpt-oss high:", r.status, JSON.stringify(b?.usage), "finish", b?.choices?.[0]?.finish_reason, "tps", Math.round(b?.usage?.completion_tokens / b?.time_info?.completion_time));87}88// (7) reasoning cap: qwen with tiny max_completion_tokens while reasoning on → finish_reason length, content empty?89{90  const r = await chat({ model: "qwen-3.8-27b", messages: [{ role: "user", content: "Explain gravity." }], max_completion_tokens: 20 });91  const b: any = r.body;92  out.qwenCap20 = { status: r.status, message: b?.choices?.[0]?.message, finish: b?.choices?.[0]?.finish_reason, usage: b?.usage };93  console.log("qwen cap 20:", r.status, "finish", b?.choices?.[0]?.finish_reason, JSON.stringify(b?.choices?.[0]?.message), JSON.stringify(b?.usage));94}95save("07-context-reasoning.json", out);96