fix(reranker): handle TEI 429/non-list responses + raise concurrency
Problem
When the TEI reranker on the GPU node is overloaded, it returns HTTP 429 with a JSON error OBJECT:
{"error": "Model is overloaded", "error_type": "Overloaded"}
The old reranker code called .json() (which succeeds on valid JSON), then iterated the result directly. Iterating a dict yields its string keys, so downstream r["index"] raised a confusing TypeError: string indices must be integers that completely hid the real upstream 429.
Reproduction
With k=20 (RETRIEVER_ARANGO_K=20, the prod-tested default), the reranker batches 20 chunks per chat request. TEI's default --max-concurrent-requests 8 saturates under this load -> 429. With k=4 the load stayed under the limit, so the bug appeared k-bound (masking the real cause).
Proven via instrumentation: TEI http=429 ct=application/json resp_type=dict resp_repr={"error":"Model is overloaded","error_type":"Overloaded"}
Fix (3 commits)
1. Code — genieai_tei_reranker.py: validate TEI response contract before consuming it.
- HTTP != 200 -> raise RuntimeError naming status + body
- non-list body -> raise RuntimeError naming type (contract violation)
- list length != ndocs -> warn (score alignment risk)
A 429 now surfaces as a clear RuntimeError: TEI reranker call failed: HTTP 429 ... Response: {'error': 'Model is overloaded', ...} instead of a cryptic TypeError deep in a listcomp.
2. Config (compose): raise 128 (was 8). Single source of truth aligned with prod-tested value.
3. Config (ansible): tei_reranking_max_concurrent_requests: "128" in itu_rtx_gpu_api/vars.yml.
Tests
test_reranker.py:
-
create_mock_aiohttp_sessionnow takesstatus=200 -
test_tei_429_overloaded_raises_with_status_and_body— pins HTTP 429 -> RuntimeError naming status -
test_tei_200_non_list_response_raises— pins 200 + non-list -> RuntimeError naming type
Guard logic validated standalone (all 3 cases: 429-dict, 200-non-list, valid-list pass).
Validation
Deployed on el-salvador-contextual. Before fix: chatqna HTTP 500 (cryptic TypeError) for k=20. After fix: clear HTTP 429 error surfaced, then TEI concurrency raise -> HTTP 200. Full 32-query eval ran clean (n_missed=0), retrieval_recall 0.54 -> 0.72 (+34%).
Ruff: clean.