Python での素の HTTP リトライ(requests)
python · raw httpどんなときに使うか
requests や httpx で POST /v1/systemone を直接呼び、リトライロジックを自前のコードに見えておきたい方向け。408・429・5xx 系(529 を含む)を再試行し、Retry-After を尊重し、検証・認証エラーは決して再試行しません。
# jev_retry.py — raw-HTTP retry for POST /v1/systemone.
# Documented statuses: 401 · 422 · 429 · 529 (docs.typesafe.ai/api.md).
# The retry mechanics below are general engineering practice — the official
# docs publish no numeric limits, so none are assumed here.
import os
import random
import time
import requests
URL = "https://api.typesafe.ai/v1/systemone"
# Mirrors the official SDK's default retryable set ({408, 429, all 5xx});
# 529 is listed explicitly — it is TypeSafe's documented overload status.
RETRYABLE = {408, 429, 500, 502, 503, 504, 529}
def evaluate(state: str, questions: dict, max_attempts: int = 4) -> dict:
delay = 0.5 # first backoff; doubles per attempt, capped at 5 s (SDK shape)
resp = None
for _ in range(max_attempts):
resp = requests.post(
URL,
headers={
"Authorization": f"Bearer {os.environ['TYPESAFE_API_KEY']}",
"Content-Type": "application/json",
},
json={"model": "jev-latest", "state": state, "questions": questions},
timeout=5.0,
)
if resp.status_code < 400:
return resp.json()
if resp.status_code not in RETRYABLE:
# 400/401/403/404/422: identical bytes in, identical error out.
resp.raise_for_status()
# Honor the server's requested wait when it sends one:
# Retry-After (seconds). The official SDK also parses retry-after-ms.
wait = resp.headers.get("Retry-After")
sleep_s = (
float(wait) if wait else min(delay, 5.0) * random.uniform(0.75, 1.0)
)
time.sleep(sleep_s)
delay *= 2
resp.raise_for_status() # budget spent on a retryable status
raise RuntimeError("retry budget spent")再試行集合は公式 SDK のデフォルト({408, 429, 全 5xx})に合わせ、可読性のため 529 を明示しています。5 秒の上限はドキュメント済みの backoff_max に対応します。