classifier: Add fallback model for transient LLM failures

The 26b model occasionally hangs or fails outright on the local Ollama
box, which used to drop every such update into 'manual' for no good
reason. Retry the same prompt with a smaller model before giving up,
and surface both errors when even the fallback fails.

OLLAMA_FALLBACK_MODEL is new config, see .env.sample.
This commit is contained in:
Jeena 2026-10-06 22:10:07 +09:00
parent 2df588b957
commit 86268107fa
2 changed files with 19 additions and 2 deletions

View file

@ -29,9 +29,11 @@ class Classifier:
self,
base_url: str = "",
model: str = "",
fallback_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")
self.fallback_model = fallback_model or os.getenv("OLLAMA_FALLBACK_MODEL", "gemma4:12b")
def classify(
self,
@ -54,9 +56,23 @@ class Classifier:
context = context_file.read_text(encoding="utf-8").strip() if context_file.is_file() else None
messages = self._build_messages(service_dir.name, examples, release_notes, current, latest, context)
try:
return self._classify_with_model(self.model, messages, timeout)
except Exception as primary_exc:
if not self.fallback_model or self.fallback_model == self.model:
return {"action": "manual", "reason": f"Classification error: {primary_exc}"}
try:
return self._classify_with_model(self.fallback_model, messages, timeout)
except Exception as fallback_exc:
return {
"action": "manual",
"reason": f"Classification error: {primary_exc}; fallback ({self.fallback_model}) also failed: {fallback_exc}",
}
def _classify_with_model(self, model: str, messages: List[Dict[str, str]], timeout: float) -> Dict[str, str]:
try:
payload = json.dumps({
"model": self.model,
"model": model,
"messages": messages,
"stream": False,
"options": {"temperature": 0},
@ -79,7 +95,7 @@ class Classifier:
raise ValueError(f"Unexpected action value: {action!r}")
return {"action": action, "reason": result.get("reason", "")}
except Exception as exc:
return {"action": "manual", "reason": f"Classification error: {exc}"}
raise RuntimeError(f"model {model}: {exc}") from exc
def _build_messages(
self,