← back to Corkwallcovering
cost-saver: local-first ollama enrichment (vocab-gated fallback)
0f095000ce4e8970774ab487fa8cc8fdaa0f4990 · 2026-07-03 09:12:53 -0700 · Steve
Files touched
M scripts/enrich-cork-ai.mjs
Diff
commit 0f095000ce4e8970774ab487fa8cc8fdaa0f4990
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Jul 3 09:12:53 2026 -0700
cost-saver: local-first ollama enrichment (vocab-gated fallback)
---
scripts/enrich-cork-ai.mjs | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/scripts/enrich-cork-ai.mjs b/scripts/enrich-cork-ai.mjs
index 7f4723d..cbc9a74 100644
--- a/scripts/enrich-cork-ai.mjs
+++ b/scripts/enrich-cork-ai.mjs
@@ -64,6 +64,23 @@ async function askGemini(key, img, need, title) {
`(title: "${title}"). Return STRICT JSON with exactly these keys: { ${asks.join(', ')} }. ` +
`Pick the single best-fitting value from each list — no other words, no explanation. ` +
`Most of these are cork / mica / natural-fiber textured wallcoverings.`;
+ // LOCAL-FIRST cost-saver (2026-07-03): free ollama qwen2.5vl before paid Gemini. ENRICH_GEMINI_ONLY=1 forces Gemini.
+ if (process.env.ENRICH_GEMINI_ONLY !== '1') {
+ try {
+ const lr = await fetch('http://127.0.0.1:11434/api/generate', {
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ model: process.env.OLLAMA_VISION_MODEL || 'qwen2.5vl:7b', prompt,
+ images: [img.data], format: 'json', stream: false, options: { temperature: 0 } }),
+ signal: AbortSignal.timeout(90000) });
+ if (lr.ok) { const lj = await lr.json();
+ let lout = {}; try { lout = JSON.parse((lj.response || '{}').replace(/^```json\s*|\s*```$/g, '').trim()); } catch (_) {}
+ const ladd = [];
+ if (wantStyle && STYLE_VOCAB.includes(lout.style)) ladd.push(lout.style);
+ if (wantPattern && PATTERN_VOCAB.includes(lout.pattern)) ladd.push(lout.pattern);
+ if (ladd.length) return ladd; // accept local only if it produced valid-vocab tags; else fall through to Gemini
+ }
+ } catch (_) { /* fall through to Gemini */ }
+ }
const body = {
contents: [{ parts: [ { text: prompt }, { inline_data: { mime_type: img.mime, data: img.data } } ] }],
generationConfig: { temperature: 0, responseMimeType: 'application/json' },
← 21b50ec chore: macstudio3 migration — reconcile from mac2 + repoint
·
back to Corkwallcovering
·
corner-nav: move login to its own hamburger in upper-left (p a1a004d →