From ed2195d87962c69ec5519834d29100c26ebbe762 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Fri, 22 May 2026 20:25:19 +0000 Subject: [PATCH] feat(meet-kevin): throttle inter-video LLM calls (30s) to stay under Anthropic RPM First production run hit Anthropic's per-account rate_limit_error (429) trying to burn through 16 backfill videos in seconds. The SDK's built-in retry can't recover because the rate limit window resets slower than the 3 retry attempts. Added meet_kevin_inter_video_sleep_seconds (default 30s) to PipelineDeps and main's _process_pending_videos loop. 16 backfill videos now take ~8 min (16 * 30s sleeps + ~30s per LLM call) instead of bursting into the rate limit. --- services/meet_kevin_watcher/config.py | 1 + services/meet_kevin_watcher/main.py | 6 +++++- services/meet_kevin_watcher/pipeline.py | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/services/meet_kevin_watcher/config.py b/services/meet_kevin_watcher/config.py index 99d55e9..b5e8d53 100644 --- a/services/meet_kevin_watcher/config.py +++ b/services/meet_kevin_watcher/config.py @@ -21,6 +21,7 @@ class MeetKevinWatcherConfig(BaseConfig): meet_kevin_llm_model: str = "claude-sonnet-4-5" meet_kevin_prompt_version: str = "v1" meet_kevin_daily_cost_cap_usd: float = 5.0 + meet_kevin_inter_video_sleep_seconds: int = 30 # API credentials anthropic_oauth_token: str = "" diff --git a/services/meet_kevin_watcher/main.py b/services/meet_kevin_watcher/main.py index 0e8f96a..79b167f 100644 --- a/services/meet_kevin_watcher/main.py +++ b/services/meet_kevin_watcher/main.py @@ -104,7 +104,10 @@ async def _process_pending_videos( ) videos = result.scalars().all() - for video in videos: + for i, video in enumerate(videos): + # Throttle between videos to avoid bursting into Anthropic's per-account RPM limit + if i > 0: + await asyncio.sleep(deps.inter_video_sleep_seconds) async with session_factory() as session: # Re-fetch inside its own session so we can commit per-video result = await session.execute( @@ -207,6 +210,7 @@ async def run() -> None: prompt_version=config.meet_kevin_prompt_version, daily_cost_cap_usd=Decimal(str(config.meet_kevin_daily_cost_cap_usd)), workdir=config.meet_kevin_workdir, + inter_video_sleep_seconds=config.meet_kevin_inter_video_sleep_seconds, ) # Graceful shutdown diff --git a/services/meet_kevin_watcher/pipeline.py b/services/meet_kevin_watcher/pipeline.py index 0f114ef..93fe6e1 100644 --- a/services/meet_kevin_watcher/pipeline.py +++ b/services/meet_kevin_watcher/pipeline.py @@ -66,6 +66,9 @@ class PipelineDeps: workdir: str """Filesystem directory for yt-dlp caption downloads.""" + inter_video_sleep_seconds: int = 30 + """Sleep between consecutive videos to stay under the LLM provider RPM limit.""" + # --------------------------------------------------------------------------- # Daily cost accounting