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%
2.8 KB · 79 lines typescript
Raw Blame History
1// Probe 05: vision with a 32x32 PNG data URL on every probe model (incl. the text-only one to see the error shape).2import { deflateSync } from "node:zlib";3import { raw, save, short } from "./lib.ts";4import { MODELS, byId } from "./models.ts";56function crc32(buf: Buffer) {7  let c: number;8  const table: number[] = [];9  for (let n = 0; n < 256; n++) {10    c = n;11    for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;12    table[n] = c >>> 0;13  }14  let crc = 0xffffffff;15  for (const b of buf) crc = table[(crc ^ b) & 0xff] ^ (crc >>> 8);16  return (crc ^ 0xffffffff) >>> 0;17}18function chunk(type: string, data: Buffer) {19  const len = Buffer.alloc(4);20  len.writeUInt32BE(data.length);21  const td = Buffer.concat([Buffer.from(type, "ascii"), data]);22  const crc = Buffer.alloc(4);23  crc.writeUInt32BE(crc32(td));24  return Buffer.concat([len, td, crc]);25}26/** Solid red square with a blue diagonal, size×size, RGB PNG. */27function png(size: number) {28  const ihdr = Buffer.alloc(13);29  ihdr.writeUInt32BE(size, 0);30  ihdr.writeUInt32BE(size, 4);31  ihdr[8] = 8; // bit depth32  ihdr[9] = 2; // RGB33  const rows: Buffer[] = [];34  for (let y = 0; y < size; y++) {35    const row = Buffer.alloc(1 + size * 3);36    for (let x = 0; x < size; x++) {37      const diag = Math.abs(x - y) < 2;38      row[1 + x * 3] = diag ? 0 : 220;39      row[2 + x * 3] = 0;40      row[3 + x * 3] = diag ? 220 : 0;41    }42    rows.push(row);43  }44  const idat = deflateSync(Buffer.concat(rows));45  return Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", ihdr), chunk("IDAT", idat), chunk("IEND", Buffer.alloc(0))]);46}4748const dataUrl = `data:image/png;base64,${png(32).toString("base64")}`;49const results: any = {};50for (const model of MODELS) {51  const body: any = {52    model,53    messages: [54      {55        role: "user",56        content: [57          { type: "text", text: "Describe this image in one sentence: main colour and any shape." },58          { type: "image_url", image_url: { url: dataUrl, detail: "low" } },59        ],60      },61    ],62    max_tokens: 100,63    usage: { include: true },64    ...(byId.get(model)?.reasoning ? { reasoning: { effort: "low" } } : {}),65  };66  const r = await raw("/chat/completions", { method: "POST", body: JSON.stringify(body) });67  const b: any = r.body;68  results[model] = {69    status: r.status,70    supportsImage: (byId.get(model)?.architecture?.input_modalities ?? []).includes("image"),71    provider: b?.provider,72    content: b?.choices?.[0]?.message?.content,73    usage: b?.usage,74    error: b?.error,75  };76  console.log(`[${model}] ${r.status} img=${results[model].supportsImage} provider=${b?.provider} prompt_tokens=${b?.usage?.prompt_tokens} cost=${b?.usage?.cost} ${short(b?.choices?.[0]?.message?.content, 140)} ${b?.error ? "ERR=" + short(b.error, 300) : ""}`);77}78save("05-vision.json", results);79