← back to Ken
Ken: retry/backoff in geminiAnalyze for shared-Ollama 'server busy' contention (stays all-local, best-effort)
d83c6eeb36773adbd4a2031b49d9e0bffdeb7601 · 2026-07-14 12:34:27 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit d83c6eeb36773adbd4a2031b49d9e0bffdeb7601
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 14 12:34:27 2026 -0700
Ken: retry/backoff in geminiAnalyze for shared-Ollama 'server busy' contention (stays all-local, best-effort)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
kalshi-dash/server.js | 69 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 44 insertions(+), 25 deletions(-)
diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index 1105f63..82fe64b 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -142,32 +142,51 @@ const KEN_LOCAL_MODEL = process.env.KEN_LOCAL_MODEL || 'hermes3:8b';
const GEMINI_MODEL = KEN_LOCAL_MODEL; // kept name so the dashboard's model label still resolves
async function geminiAnalyze(prompt, maxTokens = 1024) {
- try {
- const controller = new AbortController();
- const timeout = setTimeout(() => controller.abort(), 45000);
- const res = await fetch(`${OLLAMA_URL}/api/generate`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- signal: controller.signal,
- body: JSON.stringify({
- model: KEN_LOCAL_MODEL,
- prompt,
- stream: false,
- format: 'json', // constrain output to valid JSON (callers JSON.parse the result)
- options: { temperature: 0.3, num_predict: maxTokens },
- }),
- });
- clearTimeout(timeout);
- if (!res.ok) return null;
- const data = await res.json();
- let text = data?.response || null;
- // thinking-style models (qwen etc.) may wrap output in <think>…</think>; strip it
- if (text) text = text.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
- return text || null;
- } catch (e) {
- console.log(`[Ken/Local] Error: ${e.message}`);
- return null;
+ // The Mac's Ollama is shared with other pipelines (vision enrichment etc.), so under
+ // load it can 200-OK with an empty response + {error:"server busy … maximum pending
+ // requests exceeded"}. Retry those transients with backoff so Ken's AI layer rides
+ // through contention instead of silently switching off. Still all-LOCAL ($0).
+ const MAX_TRIES = 3;
+ for (let attempt = 1; attempt <= MAX_TRIES; attempt++) {
+ try {
+ const controller = new AbortController();
+ const timeout = setTimeout(() => controller.abort(), 45000);
+ const res = await fetch(`${OLLAMA_URL}/api/generate`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ signal: controller.signal,
+ body: JSON.stringify({
+ model: KEN_LOCAL_MODEL,
+ prompt,
+ stream: false,
+ format: 'json', // constrain output to valid JSON (callers JSON.parse the result)
+ options: { temperature: 0.3, num_predict: maxTokens },
+ }),
+ });
+ clearTimeout(timeout);
+ if (!res.ok) return null;
+ const data = await res.json();
+ // Ollama-busy transient: retry with backoff before giving up.
+ if (data?.error && /busy|pending requests|overloaded/i.test(data.error)) {
+ if (attempt < MAX_TRIES) {
+ console.log(`[Ken/Local] Ollama busy (try ${attempt}/${MAX_TRIES}) — backing off`);
+ await new Promise(r => setTimeout(r, 1500 * attempt));
+ continue;
+ }
+ console.log(`[Ken/Local] Ollama still busy after ${MAX_TRIES} tries — skipping AI enhance this cycle`);
+ return null;
+ }
+ let text = data?.response || null;
+ // thinking-style models (qwen etc.) may wrap output in <think>…</think>; strip it
+ if (text) text = text.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
+ return text || null;
+ } catch (e) {
+ console.log(`[Ken/Local] Error (try ${attempt}/${MAX_TRIES}): ${e.message}`);
+ if (attempt < MAX_TRIES) { await new Promise(r => setTimeout(r, 1500 * attempt)); continue; }
+ return null;
+ }
}
+ return null;
}
// AI-Enhanced Signal Scoring — local Ollama analyzes top signals for smarter predictions
← 16c240e Ken: fix Weather page 400 — server now handles 'get_data' ac
·
back to Ken
·
Ken: scoped set-confidence.sh — fix endpoint to /api/trading c49a8e1 →