From 301f24c6e4786e4422a7fa6687400e02627cd7a0 Mon Sep 17 00:00:00 2001 From: Chaim Date: Tue, 28 Apr 2026 16:38:53 +0000 Subject: [PATCH] =?UTF-8?q?fix(kb-classifier):=20bump=20default=20timeout?= =?UTF-8?q?=2090s=20=E2=86=92=20240s=20for=20long=20Hebrew=20caselaw?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Labor-law caselaw uploads (4 DOCX, 2026-04-28) timed out at exactly 90s, landing in awaiting_review with empty ai_suggestions. A live retry of the same payload through ai-gateway returned valid metadata in 91.8s — one second over the cap. PDF caselaw can be larger (20K-char cap vs DOCX 6K) and ai-gateway's serialized OAuth session lengthens the tail under batch load, so 180s would not be enough headroom either. 240s keeps the call fail-soft (user can still fill metadata manually) but covers realistic Hebrew legal documents. Override via KB_CLASSIFIER_TIMEOUT_S. --- api/services/kb/classifier.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/api/services/kb/classifier.py b/api/services/kb/classifier.py index 4cfb49a..654fd24 100644 --- a/api/services/kb/classifier.py +++ b/api/services/kb/classifier.py @@ -42,10 +42,13 @@ logger = logging.getLogger("shira.kb.classifier") # it's no worse than 1. _CONCURRENCY = int(os.environ.get("KB_CLASSIFIER_CONCURRENCY", "2")) # Empirically the ai-gateway → Claude tool-call round-trip with a ~3KB -# Hebrew system prompt + 5KB user content runs 18-25s. With 20 files -# queued through the gateway one-at-a-time, the tail can hit ~80s. -# Padded to 90s so we don't fail-soft on serialized queue waits. -_TIMEOUT_S = float(os.environ.get("KB_CLASSIFIER_TIMEOUT_S", "90")) +# Hebrew system prompt + 5KB user content runs 18-25s. Long Hebrew +# caselaw PDFs (full 20K-char first-3-pages cap) push the tail to +# ~92s on DOCX and noticeably more on dense PDFs; ai-gateway also +# serializes through one OAuth session, lengthening the tail in a +# batch. 240s buys headroom without making the user wait forever +# when something is genuinely stuck. +_TIMEOUT_S = float(os.environ.get("KB_CLASSIFIER_TIMEOUT_S", "240")) _MAX_INPUT_CHARS = 20_000 # ~3 pages of Hebrew legal text _semaphore = asyncio.Semaphore(_CONCURRENCY)