【要約】LLMタイムアウト問題をpolling非同期ジョブで解決した話 [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者がLLMを用いた記事リライト機能を実装した際、応答に数分を要する問題に直面した。長時間のリクエストは、複数のレイヤーでタイムアウトを引き起こした。具体的には以下の問題が発生した。
- ・多層的なタイムアウト: CLI、Proxy、ブラウザの各層で通信が切断される。
- ・UXの乖離: サーバー側で処理が成功しても、UI上は失敗と表示される。
- ・コストの増大: ユーザーの再試行により、API料金が二重に発生する。
// Approach
開発者は、同期的なHTTPリクエストを避け、非同期ジョブとポーリングを組み合わせた設計を採用した。通信の複雑性を抑えつつ、確実に状態を伝えるための手法を選択した。
- ・非同期ジョブ化: リクエスト受付時に即座に202を返し、ジョブIDを返却する。
- ・ポーリングの採用: SSEではなく、実装が単純でProxyに強いGETリクエストによる確認を行う。
- ・状態復旧設計: /active エンドポイントにより、リロード後も実行中のジョブを再取得可能にする。
- ・軽量キュー実装: in-memoryのMapと配列を用い、並行実行数を1に制限して制御する。
// Result
この設計により、開発者はUXの向上と実装コストの抑制を同時に実現した。長時間処理がユーザー体験を阻害しない環境を構築できた。
- ・UXの改善: ユーザーは処理完了を待たずに他の操作が可能になった。
- ・堅牢性の向上: ブラウザのリロード後も、ジョブの状態を正確に復元できる。
- ・低コストな開発: わずか数百行のコードで、高度な非同期処理を実現した。
Senior Engineer Insight
> SSEの複雑性を避け、ポーリングを選択した判断は極めて合理的だ。インフラの制約を考慮した実戦的な設計と言える。ただし、in-memory管理はサーバー再起動でジョブが消失する。また、ポーリングによるリクエスト増も無視できない。小規模運用では十分だが、スケール時にはRedis等の外部キューへの移行が必須となる。技術的負債を認識した上での「あえての単純化」として高く評価できる。