SPB Git

spb/llmindex Public

The discriminative, contamination-resistant, fully transparent LLM ranking — updated live.

TypeScript 77.9% TeX 15.2% Python 3.7% SQL 1.4% JavaScript 1.1% Shell 0.5%
6.3 KB · 161 lines typescript
Raw Blame History
1/**2 * llmindex.io — vision OCR templates: generated SVG scenes, hostile but unambiguous3 * Author:  Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * License: Proprietary — © Simon-Pierre Boucher, all rights reserved6 *7 * Multimodal reading under load: the target string is embedded in a generated8 * scene among decoy strings, noise strokes, rotation and low-contrast patches.9 * The character set excludes visually ambiguous glyphs (0/O, 1/l/I, 5/S, 8/B,10 * 2/Z) so a perfect reader can always answer with certainty — difficulty comes11 * from clutter and selection, never from unfair glyph ambiguity.12 * The worker rasterizes `svg` to PNG; the prompt text never contains the code.13 */14import { ANSWER_FORMAT_INSTRUCTIONS } from '../answer';15import type { Rng } from '../rng';16import type { ItemTemplate } from '../types';1718/** Unambiguous charset (no 0/O/Q, 1/I/l, 2/Z, 5/S, 8/B, 6/G). */19const GLYPHS = 'ACDEFHJKMNPRTUVWXY3479';2021function code(rng: Rng, len: number): string {22  let out = '';23  for (let i = 0; i < len; i++) out += GLYPHS[rng.int(0, GLYPHS.length - 1)];24  return out;25}2627const PALETTE = [28  { name: 'red', fill: '#d92626' },29  { name: 'blue', fill: '#2563eb' },30  { name: 'green', fill: '#16a34a' },31  { name: 'orange', fill: '#ea8a1a' },32  { name: 'purple', fill: '#9333ea' },33] as const;3435function noise(rng: Rng, w: number, h: number, n: number): string {36  let out = '';37  for (let i = 0; i < n; i++) {38    out += `<line x1="${rng.int(0, w)}" y1="${rng.int(0, h)}" x2="${rng.int(0, w)}" y2="${rng.int(39      0,40      h,41    )}" stroke="#9ca3af" stroke-width="${rng.int(1, 2)}" opacity="0.5"/>`;42  }43  return out;44}4546export const visionCodeHunt: ItemTemplate = {47  id: 'vision.ocr.code-hunt-v1',48  domain: 'vision_ocr',49  description:50    'Transcribe the one code printed in a named color among rotated decoy codes, noise strokes and a low-contrast patch; unambiguous glyph set.',51  paramSpace: 22 ** 8 * 5 * 4 ** 6,52  render(rng: Rng, perturbSeed: string) {53    const W = 560;54    const H = 320;55    const colors = rng.shuffle(PALETTE).slice(0, 4);56    const target = colors[0]!;57    const targetCode = code(rng, rng.int(6, 8));5859    const cells = rng.shuffle([60      { x: 90, y: 70 },61      { x: 360, y: 60 },62      { x: 120, y: 180 },63      { x: 390, y: 200 },64      { x: 240, y: 270 },65      { x: 250, y: 130 },66    ]);6768    let texts = '';69    colors.forEach((c, i) => {70      const cell = cells[i]!;71      const isTarget = i === 0;72      const value = isTarget ? targetCode : code(rng, rng.int(6, 8));73      const rot = rng.int(-35, 35);74      const size = isTarget ? rng.int(20, 26) : rng.int(20, 30);75      const opacity = isTarget && rng.next() < 0.4 ? 0.55 : 1; // low-contrast twist76      texts += `<text x="${cell.x}" y="${cell.y}" transform="rotate(${rot} ${cell.x} ${cell.y})" font-family="monospace" font-size="${size}" font-weight="bold" fill="${c.fill}" opacity="${opacity}">${value}</text>`;77    });78    // extra black decoys79    for (let i = 4; i < 6; i++) {80      const cell = cells[i]!;81      texts += `<text x="${cell.x}" y="${cell.y}" transform="rotate(${rng.int(-20, 20)} ${cell.x} ${cell.y})" font-family="monospace" font-size="${rng.int(18, 24)}" fill="#111827">${code(rng, 7)}</text>`;82    }8384    const svg =85      `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${H}" viewBox="0 0 ${W} ${H}">` +86      `<rect width="${W}" height="${H}" fill="#f3f4f6"/>` +87      noise(rng, W, H, rng.int(14, 22)) +88      texts +89      `</svg>`;9091    return {92      templateId: this.id,93      domain: this.domain,94      prompt:95        `The image contains several printed codes in different colors, with noise. ` +96        `Transcribe EXACTLY the code printed in ${target.name.toUpperCase()}. ` +97        `It uses only digits and uppercase letters.\n\n${ANSWER_FORMAT_INSTRUCTIONS}`,98      answerKey: targetCode,99      grading: 'exact' as const,100      perturbSeed,101      svg,102    };103  },104};105106export const visionTableRead: ItemTemplate = {107  id: 'vision.ocr.table-read-v1',108  domain: 'vision_ocr',109  description:110    'Read a rendered mini-table and compute a small aggregate (sum/max of a column subset) — OCR plus grounded arithmetic.',111  paramSpace: 22 ** 4 * 90 ** 8 * 3,112  render(rng: Rng, perturbSeed: string) {113    const W = 520;114    const H = 300;115    const nRows = rng.int(5, 7);116    const rows = Array.from({ length: nRows }, () => ({117      id: code(rng, 4),118      qty: rng.int(11, 97),119      grade: rng.pick(['A', 'C', 'D'] as const),120    }));121    const targetGrade = rng.pick(['A', 'C', 'D'] as const);122    if (!rows.some((r) => r.grade === targetGrade)) rows[rng.int(0, nRows - 1)]!.grade = targetGrade;123    const mode = rng.pick(['sum', 'max'] as const);124    const matched = rows.filter((r) => r.grade === targetGrade).map((r) => r.qty);125    const answer = mode === 'sum' ? matched.reduce((a, b) => a + b, 0) : Math.max(...matched);126127    let body = '';128    rows.forEach((r, i) => {129      const y = 80 + i * 30;130      body +=131        `<text x="60" y="${y}" font-family="monospace" font-size="17" fill="#111827">${r.id}</text>` +132        `<text x="230" y="${y}" font-family="monospace" font-size="17" fill="#111827">${r.qty}</text>` +133        `<text x="380" y="${y}" font-family="monospace" font-size="17" fill="#111827">${r.grade}</text>`;134    });135136    const svg =137      `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${H}" viewBox="0 0 ${W} ${H}">` +138      `<rect width="${W}" height="${H}" fill="#ffffff"/>` +139      noise(rng, W, H, 8) +140      `<text x="60" y="45" font-family="monospace" font-size="16" font-weight="bold" fill="#374151">ID</text>` +141      `<text x="230" y="45" font-family="monospace" font-size="16" font-weight="bold" fill="#374151">QTY</text>` +142      `<text x="380" y="45" font-family="monospace" font-size="16" font-weight="bold" fill="#374151">GRADE</text>` +143      `<line x1="40" y1="55" x2="480" y2="55" stroke="#111827" stroke-width="2"/>` +144      body +145      `</svg>`;146147    return {148      templateId: this.id,149      domain: this.domain,150      prompt:151        `The image shows a table with columns ID, QTY, GRADE. ` +152        `Compute the ${mode === 'sum' ? 'SUM' : 'MAXIMUM'} of QTY over the rows whose GRADE is "${targetGrade}". ` +153        `Answer with the number only.\n\n${ANSWER_FORMAT_INSTRUCTIONS}`,154      answerKey: String(answer),155      grading: 'numeric' as const,156      perturbSeed,157      svg,158    };159  },160};161