From 30876b34235b73a98f3614b86a0f3e60a48b9343 Mon Sep 17 00:00:00 2001 From: Philip Date: Tue, 4 Aug 2026 13:53:56 -0500 Subject: [PATCH] Extraction retry: 3 attempts with backoff Empty-content responses from the pool got through the single retry once two companies ran concurrently; 3 attempts with 3s/6s backoff. Co-Authored-By: Claude Fable 5 --- engine/protocol.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/protocol.py b/engine/protocol.py index 1634e60..1e7bcf5 100644 --- a/engine/protocol.py +++ b/engine/protocol.py @@ -5,6 +5,7 @@ trusting the worker to format correctly mid-run, the engine converts each raw report with one schema-enforced pool call (qwen3.5:9b scored 100% validity under `format` enforcement — benchmarks/RESULTS.md). """ +import asyncio import json from typing import Any @@ -58,7 +59,7 @@ DECOMPOSE_FORMAT: dict[str, Any] = { async def _chat_structured(system: str, user: str, fmt: dict) -> dict: async with httpx.AsyncClient(timeout=180) as client: - for attempt in (1, 2): # pool occasionally returns empty content; one retry + for attempt in (1, 2, 3): # pool returns empty content under load; retry with backoff r = await client.post( f"{settings.ollama_pool_url}/api/chat", json={ @@ -76,8 +77,9 @@ async def _chat_structured(system: str, user: str, fmt: dict) -> dict: try: return json.loads(r.json()["message"]["content"]) except json.JSONDecodeError: - if attempt == 2: + if attempt == 3: raise + await asyncio.sleep(3 * attempt) raise RuntimeError("unreachable")