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%
3.8 KB · 84 lines typescript
Raw Blame History
1// Probe 01: per model — (a) tiny generateContent with systemInstruction, (b) generateContentStream chunk shape,2// usage arrival pattern, part.thought flag, finishReason, modelVersion. Also raw REST SSE for one model.3import { ai, MODELS, KEY, SUFFIX, save, errInfo, shortText, withRetry, sleep, PACE_MS } from "./lib.js";45const results: any = {};67for (const model of MODELS) {8  const r: any = (results[model] = {});9  // (a) + (i) non-streaming with systemInstruction10  try {11    const res = await withRetry(() => ai.models.generateContent({12      model,13      contents: "Reply with exactly one word: what colour is the sky on a clear day?",14      config: { systemInstruction: "You are terse. Always answer in UPPERCASE.", maxOutputTokens: 400 },15    }));16    r.generate = {17      ok: true,18      text: shortText(res),19      modelVersion: res.modelVersion,20      responseId: res.responseId,21      finishReason: res.candidates?.[0]?.finishReason,22      partKeys: res.candidates?.[0]?.content?.parts?.map((p: any) => Object.keys(p)),23      role: res.candidates?.[0]?.content?.role,24      usage: res.usageMetadata,25      topLevelKeys: Object.keys(res).filter((k) => !k.startsWith("_")),26    };27  } catch (e) {28    r.generate = { ok: false, error: errInfo(e) };29  }3031  // (b) streaming32  try {33    await sleep(PACE_MS);34    const stream = await withRetry(() => ai.models.generateContentStream({35      model,36      contents: "Count from 1 to 12 separated by spaces, then say DONE.",37      config: { maxOutputTokens: 2000, thinkingConfig: { includeThoughts: true } },38    }));39    const chunks: any[] = [];40    for await (const c of stream) {41      chunks.push({42        parts: c.candidates?.[0]?.content?.parts?.map((p: any) => ({43          keys: Object.keys(p), thought: p.thought ?? undefined, textLen: p.text?.length, hasSig: !!p.thoughtSignature,44        })),45        role: c.candidates?.[0]?.content?.role,46        finishReason: c.candidates?.[0]?.finishReason,47        usage: c.usageMetadata,48        modelVersion: c.modelVersion,49        responseId: c.responseId,50        keys: Object.keys(c).filter((k) => !k.startsWith("_") && (c as any)[k] !== undefined),51      });52    }53    r.stream = {54      ok: true,55      chunkCount: chunks.length,56      usageOnChunks: chunks.map((c) => (c.usage ? (c.usage.candidatesTokenCount != null ? "full" : "partial") : "none")),57      thoughtChunks: chunks.filter((c) => c.parts?.some((p: any) => p.thought)).length,58      lastUsage: chunks.at(-1)?.usage,59      finishReasons: chunks.map((c) => c.finishReason ?? null),60      sampleFirst: chunks[0],61      sampleLast: chunks.at(-1),62    };63  } catch (e) {64    r.stream = { ok: false, error: errInfo(e) };65  }66  await sleep(PACE_MS);67  console.log(model, JSON.stringify({ gen: r.generate.ok ? r.generate.text : r.generate.error, stream: r.stream.ok ? { n: r.stream.chunkCount, usage: r.stream.usageOnChunks, thoughts: r.stream.thoughtChunks } : r.stream.error }));68}6970// Raw REST SSE protocol sample (one model)71if (!process.argv[2]) {72  const model = "gemini-3.5-flash-lite";73  const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse`, {74    method: "POST",75    headers: { "x-goog-api-key": KEY, "content-type": "application/json" },76    body: JSON.stringify({ contents: [{ role: "user", parts: [{ text: "Say hello in three words." }] }], generationConfig: { maxOutputTokens: 50, thinkingConfig: { thinkingBudget: 0 } } }),77  });78  const raw = await res.text();79  results.restSse = { status: res.status, contentType: res.headers.get("content-type"), rawFirst1200: raw.slice(0, 1200), eventCount: raw.split("\n\n").filter((s) => s.trim()).length };80  console.log("REST SSE", res.status, res.headers.get("content-type"), "events:", results.restSse.eventCount);81}8283save(`01-basic-stream${SUFFIX}.json`, results);84