/** * llmindex.io — vision OCR templates: generated SVG scenes, hostile but unambiguous * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * License: Proprietary — © Simon-Pierre Boucher, all rights reserved * * Multimodal reading under load: the target string is embedded in a generated * scene among decoy strings, noise strokes, rotation and low-contrast patches. * The character set excludes visually ambiguous glyphs (0/O, 1/l/I, 5/S, 8/B, * 2/Z) so a perfect reader can always answer with certainty — difficulty comes * from clutter and selection, never from unfair glyph ambiguity. * The worker rasterizes `svg` to PNG; the prompt text never contains the code. */ import { ANSWER_FORMAT_INSTRUCTIONS } from '../answer'; import type { Rng } from '../rng'; import type { ItemTemplate } from '../types'; /** Unambiguous charset (no 0/O/Q, 1/I/l, 2/Z, 5/S, 8/B, 6/G). */ const GLYPHS = 'ACDEFHJKMNPRTUVWXY3479'; function code(rng: Rng, len: number): string { let out = ''; for (let i = 0; i < len; i++) out += GLYPHS[rng.int(0, GLYPHS.length - 1)]; return out; } const PALETTE = [ { name: 'red', fill: '#d92626' }, { name: 'blue', fill: '#2563eb' }, { name: 'green', fill: '#16a34a' }, { name: 'orange', fill: '#ea8a1a' }, { name: 'purple', fill: '#9333ea' }, ] as const; function noise(rng: Rng, w: number, h: number, n: number): string { let out = ''; for (let i = 0; i < n; i++) { out += ``; } return out; } export const visionCodeHunt: ItemTemplate = { id: 'vision.ocr.code-hunt-v1', domain: 'vision_ocr', description: 'Transcribe the one code printed in a named color among rotated decoy codes, noise strokes and a low-contrast patch; unambiguous glyph set.', paramSpace: 22 ** 8 * 5 * 4 ** 6, render(rng: Rng, perturbSeed: string) { const W = 560; const H = 320; const colors = rng.shuffle(PALETTE).slice(0, 4); const target = colors[0]!; const targetCode = code(rng, rng.int(6, 8)); const cells = rng.shuffle([ { x: 90, y: 70 }, { x: 360, y: 60 }, { x: 120, y: 180 }, { x: 390, y: 200 }, { x: 240, y: 270 }, { x: 250, y: 130 }, ]); let texts = ''; colors.forEach((c, i) => { const cell = cells[i]!; const isTarget = i === 0; const value = isTarget ? targetCode : code(rng, rng.int(6, 8)); const rot = rng.int(-35, 35); const size = isTarget ? rng.int(20, 26) : rng.int(20, 30); const opacity = isTarget && rng.next() < 0.4 ? 0.55 : 1; // low-contrast twist texts += `${value}`; }); // extra black decoys for (let i = 4; i < 6; i++) { const cell = cells[i]!; texts += `${code(rng, 7)}`; } const svg = `` + `` + noise(rng, W, H, rng.int(14, 22)) + texts + ``; return { templateId: this.id, domain: this.domain, prompt: `The image contains several printed codes in different colors, with noise. ` + `Transcribe EXACTLY the code printed in ${target.name.toUpperCase()}. ` + `It uses only digits and uppercase letters.\n\n${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: targetCode, grading: 'exact' as const, perturbSeed, svg, }; }, }; export const visionTableRead: ItemTemplate = { id: 'vision.ocr.table-read-v1', domain: 'vision_ocr', description: 'Read a rendered mini-table and compute a small aggregate (sum/max of a column subset) — OCR plus grounded arithmetic.', paramSpace: 22 ** 4 * 90 ** 8 * 3, render(rng: Rng, perturbSeed: string) { const W = 520; const H = 300; const nRows = rng.int(5, 7); const rows = Array.from({ length: nRows }, () => ({ id: code(rng, 4), qty: rng.int(11, 97), grade: rng.pick(['A', 'C', 'D'] as const), })); const targetGrade = rng.pick(['A', 'C', 'D'] as const); if (!rows.some((r) => r.grade === targetGrade)) rows[rng.int(0, nRows - 1)]!.grade = targetGrade; const mode = rng.pick(['sum', 'max'] as const); const matched = rows.filter((r) => r.grade === targetGrade).map((r) => r.qty); const answer = mode === 'sum' ? matched.reduce((a, b) => a + b, 0) : Math.max(...matched); let body = ''; rows.forEach((r, i) => { const y = 80 + i * 30; body += `${r.id}` + `${r.qty}` + `${r.grade}`; }); const svg = `` + `` + noise(rng, W, H, 8) + `ID` + `QTY` + `GRADE` + `` + body + ``; return { templateId: this.id, domain: this.domain, prompt: `The image shows a table with columns ID, QTY, GRADE. ` + `Compute the ${mode === 'sum' ? 'SUM' : 'MAXIMUM'} of QTY over the rows whose GRADE is "${targetGrade}". ` + `Answer with the number only.\n\n${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: String(answer), grading: 'numeric' as const, perturbSeed, svg, }; }, };