この記事はPython Advent Calendar 2025 の24日目の記事です。
はじめに
あるDjangoプロジェクトにAIエージェント機能を導入することになり、langChainを用いたReActエージェントを実装した。開発環境では問題なく動作していたのだが、本番環境(Render)にデプロイしたところtimeoutエラーが出てしまった...
WSGIとASGI
まず、djangoプロジェクトに存在するwsgi.pyとかasgi.pyの役割を見ていく。
| wsgi | asgi | |
|---|---|---|
| 名前 | Web Server Gateway Interface | Asynchronous Server Gateway Interface |
| それは何 | Pythonにおいて、WebサーバとWebアプリケーションが通信するための、標準化されたインタフェース定義 | WSGIの精神的な後継仕様であり、asyncioを介して非同期で動作するように設計されたインターフェース定義 |
| できること | 同期処理(同期的なHTTP req/res) | 非同期処理(http, websocket, SSE..) 長時間接続 |
| 動作環境例 | gunicorn | uvicorn |
なるほど。つまり、WSGIでは1リクエスト1プロセス前提であり、WebSocketやSEEなどの継続接続に対応していないということだ。
では、WSGIなんて使わずに同期・非同期どちらも扱えるASGIを使った方がいいのでは..?
ASGIは万能?
0から開発するのであれば、ASGI選定はほぼ最適解といえるだろう。しかし、WSGI対応で開発されたプロジェクトのASGIへのリプレイスコストや開発メンバの学習コストを考えたとき、それは最適解とならないかもしれない。
実際、自身のチームでは開発経験の浅いメンバがいたこともあり、WSGIを選定していた。
AIチャットの導入
先述した通り、私たちのプロジェクトはWSGI想定で開発されており、Renderでもgunicornで運用していた。そこに、ReActエージェントを用いたAIチャットの導入が企画された。実装の詳細は省くが、langChain + OpenAIで開発し、開発環境では安定した動作を見せていた。
しかし、デプロイのときになってエラーが我らを襲った。gunicornのtimeoutエラーである。エラーログを辿るとOpenAIなどの重いモジュールをimportするときにtimeoutしているらしかった。
ASGI分離
前項のエラーに対して、lazy importやtimeoutの延長などの対策を行ったが解消されず、最終的にAIチャット機能だけASGIに逃がす選択をした。ASGIは非同期処理ができるだけでなく、長時間接続が可能であることからtimeoutエラーを解消できると考えたからである。
この改修によって、プロジェクトはWSGI+ASGIの形態となりエラーは解消された。
また、Renderにおいてgunicornとuvicornを併用して実現できた。
副作用
timeoutエラー解消のためにASGI分離をしたことで、それまでWSGI故に諦めていたAIチャットのStreamingレスポンス処理が視野に入ってきた。SSEプロトコルを使ってAIエージェントからの回答をトークン単位でリアルタイムでフロントエンドに表示することで、回答待ちの体感時間が大幅に改善した。
まとめ
どちらかを採用するということではなく、状況に合わせて柔軟に選定することで安定性と革新を同時に満たすことができるとわかる、よい経験だった。Python以外でのインターフェースも見てみたいと思う。