chore(giellie): add MiniMax vision/tool-call probe
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
662610ca28
commit
0eb9653359
1 changed files with 85 additions and 0 deletions
85
scripts/smoke/giellie-vision-probe.ts
Normal file
85
scripts/smoke/giellie-vision-probe.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* Probe: does the configured MiniMax endpoint accept (a) image blocks and
|
||||||
|
* (b) tool calls, and what content-block types come back?
|
||||||
|
*
|
||||||
|
* Read-only against PB (reads ai_settings); makes two small LLM calls.
|
||||||
|
*
|
||||||
|
* Run with: npx tsx scripts/smoke/giellie-vision-probe.ts
|
||||||
|
* Requires AI enabled + key set at /settings/ai.
|
||||||
|
*/
|
||||||
|
import "./_env"; // MUST be first
|
||||||
|
import Anthropic from "@anthropic-ai/sdk";
|
||||||
|
import { createCanvas } from "@napi-rs/canvas";
|
||||||
|
import { getActiveAiConfig } from "../../src/lib/server/ai-settings-service";
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const cfg = await getActiveAiConfig();
|
||||||
|
const client = new Anthropic({
|
||||||
|
apiKey: cfg.apiKey,
|
||||||
|
...(cfg.baseUrl ? { baseURL: cfg.baseUrl } : {}),
|
||||||
|
});
|
||||||
|
console.log(`[probe] model=${cfg.modelId} baseUrl=${cfg.baseUrl || "(default)"}`);
|
||||||
|
|
||||||
|
// (a) Vision: render "PRICE 4471" to a PNG and ask for the number.
|
||||||
|
const canvas = createCanvas(400, 120);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillStyle = "#fff";
|
||||||
|
ctx.fillRect(0, 0, 400, 120);
|
||||||
|
ctx.fillStyle = "#000";
|
||||||
|
ctx.font = "48px sans-serif";
|
||||||
|
ctx.fillText("PRICE 4471", 20, 75);
|
||||||
|
const png = canvas.toBuffer("image/png").toString("base64");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await client.messages.create({
|
||||||
|
model: cfg.modelId,
|
||||||
|
max_tokens: 1024,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: [
|
||||||
|
{ type: "image", source: { type: "base64", media_type: "image/png", data: png } },
|
||||||
|
{ type: "text", text: "What number is written in the image? Reply with just the number." },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const text = res.content.map((b) => (b.type === "text" ? b.text : "")).join("");
|
||||||
|
const types = res.content.map((b) => b.type).join(",");
|
||||||
|
console.log(`[probe] VISION block types=[${types}] answer=${JSON.stringify(text.trim())}`);
|
||||||
|
console.log(text.includes("4471") ? "[probe] VISION: PASS" : "[probe] VISION: FAIL (answer wrong)");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("[probe] VISION: FAIL (request rejected):", e instanceof Error ? e.message : e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (b) Tool calling.
|
||||||
|
try {
|
||||||
|
const res = await client.messages.create({
|
||||||
|
model: cfg.modelId,
|
||||||
|
max_tokens: 1024,
|
||||||
|
tools: [
|
||||||
|
{
|
||||||
|
name: "orders__get",
|
||||||
|
description: "Get an order by order number.",
|
||||||
|
input_schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: { order_number: { type: "string" } },
|
||||||
|
required: ["order_number"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
messages: [{ role: "user", content: "What is the status of order 12345? Use the tool." }],
|
||||||
|
});
|
||||||
|
const types = res.content.map((b) => b.type).join(",");
|
||||||
|
const tu = res.content.find((b) => b.type === "tool_use");
|
||||||
|
console.log(`[probe] TOOLS block types=[${types}] stop_reason=${res.stop_reason}`);
|
||||||
|
console.log(tu ? `[probe] TOOLS: PASS input=${JSON.stringify((tu as { input: unknown }).input)}` : "[probe] TOOLS: FAIL (no tool_use)");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("[probe] TOOLS: FAIL (request rejected):", e instanceof Error ? e.message : e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue