見出し画像

OCR実行環境のインフラ構成

はじめに

こんにちは、株式会社ZISEDAIの程です。
今年もどうぞよろしくお願い致します。

先日、弊社SaaSのTASUKI TECH LAND内に機能実装したOCR機能について、触りの部分を紹介させていただきました。

本日はそこからもう少しDeep Diveしてみて、OCR機能のバックエンド側インフラ構成周りについてご紹介していきたいと思います。

インフラ構成

TASUKI TECH LANDのバックエンドシステムは、パブリッククラウドサービスのAWS上にインフラ環境を構築しています。今回構築したインフラ環境もAzure の ChatGPT用 API 以外は、基本的にAWSでインフラ構築しています。ざっくりその構成図を以下に掲載します。

インフラ構成図

上記インフラ構成の検討時、いくつか懸念事項がありました。

  • ChatGPT用APIのレスポンス速度の遅さ(20 ~ 30秒程度かかる)

  • ChatGPT用APIのレートリミットが結構すぐしきい値を上回りそう

  • それによるサービス安定性の悪化・全体的なユーザー体験悪化

  • 今後のリクエスト増に耐えられるか

それを踏まえて、以下のようなポイントを意識しました。

  1. 非同期実行
    リクエストが詰まってサーバーの負荷が上がりすぎないよう、クライアント側のリクエストに対して非同期なジョブ処理内で、ChatGPTのAPIを叩かせたい。

  2. ジョブ管理
    ChatGPTとのAPI処理が失敗することを前提に、失敗時は裏側でジョブの再実行が回る状態にしたい。また、流量制御 (同時実行数制御) を利かせる事ができる状態が理想。

  3. 双方向通信
    実行時間中、ユーザーが待機しなくてもよいよう、サーバー側からクライアントへジョブの完了を通信する方式にしたい。

  4. スケーラビリティ・インフラ伸縮性
    リクエストの増加に応じてインフラ環境もスケールさせたい。

また、運用面の視点でも下記のようなポイントを意識しました。

  1. スキーマ駆動
    ちょうど同時期に、社内の他のREST APIサービスで、OpenAPI形式で定義したREST APIのAPI仕様書の更新漏れが原因でバグが多発していたため、今回開発するAPIは、API仕様をクライアントとサーバー間でなるべく認識を合わせなくてもコードを見ればわかるような状態にしたい。

  2. コスト最適化
    従量課金型のコンピューティングサービスかつ、極力メンテナンス工数も少ないサーバーレス環境にしたい。

以上のポイントを考えた結果、スケーラブルでコスト最適なサーバーレス、かつ非同期ジョブの実行・管理もインフラ側である程度制御を利かせられる形というところでDynamoDB + AWS Lambda を中心とし、スキーマ駆動というところでGraphQLを使える AWS Appsync を活用することとしました。

構築時の想定外

このインフラ構成を構築している際に、想定外だったことがありました。せっかくなので共有しようと思います。
構築当初のことですが、AppSyncに対してジョブ実行リクエストを送信すると、どうも無限に同じLambdaが繰り返し実行されていることに気づきました。
今回、Lambda上で実行させている非同期Jobが実行終了したタイミングで、Appsyncへ実行状態の更新(mutation)をするという処理があったのですが、実はそのmutationがさらにLambdaを起動するトリガーとなってしまい、Lambdaが無限に実行されてしまうという無限ループが発生していたようでした。
図にすると下記のようなイメージです。

無限ループイメージ図

解決策として、Lambdaを発火させるためのDynamoDBイベントをINSERT に限定することで、UPDATE時(=mutation時)は発火させないようにしました。

むすびに

すでに一部ユーザー様にOCR機能を使っていただいている段階ですが、今のところ大きな想定外もなく安定した状態が続いています。

インフラ構成に関わる今後の課題として、OCR以外のユースケースでChatGPT APIを使いたいケースが増えたときに、現状の構成だとユースケースの拡張がやや面倒という課題があります。今後のChatGPTの活用ユースケース拡大を見据えて、機能拡張しやすいような設計を模索していこうと思います。