From 7e15e63dae327f9fa34d573eea8635d44b798414 Mon Sep 17 00:00:00 2001 From: Jeena Date: Mon, 14 Sep 2026 05:37:37 +0000 Subject: [PATCH] classifier: Point at gemma4:26b and retry transient fetches Every classification returned "HTTP Error 404" because the configured model gemma4:26b-64k no longer exists on the Ollama host: the tag was retired upstream and the local weights were deleted, so all pending updates fell back to manual review. Switch to the current gemma4:26b tag (25.2B, 262k context) and make it explicit in .env so the classifier no longer depends on the code default matching reality. PieFed intermittently returned an empty body, which surfaced as a current version error in the digest. Retry version fetches with a short backoff so one bad response no longer triggers an alert. Leave-one-out validation for the new model: immich 6/7 (the miss is the conditional-breaking example where the model follows the written rule that thresholds below the running version do not apply), freshrss 6/6, uptime-kuma 4/4. --- .env.sample | 2 +- test_classifier.py | 2 +- update_monitor/checker.py | 30 ++++++++++++++++++++++++++++-- update_monitor/classifier.py | 2 +- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/.env.sample b/.env.sample index a1d212d..d4d11d0 100644 --- a/.env.sample +++ b/.env.sample @@ -22,4 +22,4 @@ UPTIME_KUMA_PASSWORD=your-password # Ollama for AI-driven auto-update classification OLLAMA_BASE_URL=http://192.168.1.20:11434 -OLLAMA_MODEL=gemma4:26b-64k +OLLAMA_MODEL=gemma4:26b diff --git a/test_classifier.py b/test_classifier.py index 4a9d0aa..93cc9ce 100644 --- a/test_classifier.py +++ b/test_classifier.py @@ -17,7 +17,7 @@ from urllib.request import Request, urlopen import re as _re OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://192.168.1.20:11434") -OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "gemma4:26b-64k") +OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "gemma4:26b") SERVICE_NAME = sys.argv[1] if len(sys.argv) > 1 else "immich" EXAMPLES_DIR = Path(__file__).parent / "services" / SERVICE_NAME / "review-examples" diff --git a/update_monitor/checker.py b/update_monitor/checker.py index 99ddf94..dd51e5c 100644 --- a/update_monitor/checker.py +++ b/update_monitor/checker.py @@ -1,4 +1,5 @@ import json +import time from typing import Any, Dict, List, Optional, Tuple from .comparator import compare_versions @@ -7,6 +8,29 @@ from .fetcher import authenticate_service, build_headers, fetch_response, fetch_ from .models import ServiceConfig +def fetch_version_with_retries( + url: str, + timeout: float, + user_agent: str, + extra_headers: Optional[Dict[str, str]] = None, + attempts: int = 3, +) -> tuple[str, Dict[str, str]]: + """Fetch a version endpoint with retries for transient failures + (empty bodies, timeouts).""" + last_exc: Optional[Exception] = None + for attempt in range(attempts): + try: + body, headers = fetch_response(url, timeout, user_agent, extra_headers) + if body.strip(): + return body, headers + last_exc = ValueError("empty response body") + except Exception as exc: + last_exc = exc + if attempt < attempts - 1: + time.sleep(2 * (attempt + 1)) + raise last_exc if last_exc else RuntimeError("fetch failed") + + def check_service(service: ServiceConfig, timeout: float, user_agent: str) -> Dict[str, Any]: result: Dict[str, Any] = { "name": service.name, @@ -25,7 +49,9 @@ def check_service(service: ServiceConfig, timeout: float, user_agent: str) -> Di login_cookie = authenticate_service(service, timeout, user_agent) if login_cookie: headers.setdefault("Cookie", login_cookie) - body, response_headers = fetch_response(service.current_version_url, timeout, user_agent, headers) + body, response_headers = fetch_version_with_retries( + service.current_version_url, timeout, user_agent, headers + ) result["current"] = extract_version(body, service.current_version_extract, response_headers) except Exception as exc: result["current_error"] = str(exc) @@ -38,7 +64,7 @@ def check_service(service: ServiceConfig, timeout: float, user_agent: str) -> Di if service.upstream_latest_version_url and service.upstream_latest_extract: headers = build_headers(service.upstream_latest_headers) try: - body, response_headers = fetch_response( + body, response_headers = fetch_version_with_retries( service.upstream_latest_version_url, timeout, user_agent, headers ) result["latest"] = extract_version(body, service.upstream_latest_extract, response_headers) diff --git a/update_monitor/classifier.py b/update_monitor/classifier.py index 03c9d4a..a27d797 100644 --- a/update_monitor/classifier.py +++ b/update_monitor/classifier.py @@ -31,7 +31,7 @@ class Classifier: model: str = "", ) -> None: self.base_url = base_url or os.getenv("OLLAMA_BASE_URL", "http://192.168.1.20:11434") - self.model = model or os.getenv("OLLAMA_MODEL", "gemma4:26b-64k") + self.model = model or os.getenv("OLLAMA_MODEL", "gemma4:26b") def classify( self,