フォーム読み込み中
ソフトバンクアドベントカレンダー18日目の記事を担当する森です。
普段はRAG向けのデータ作成ツール、TASUKIツールの開発を行なっています。
TASUKIツールには、お客様のデータ作成を支援するための機能がいくつかあります。その中の1つに、アップロードされたファイルを自動的にRAG向けのデータに変換する「自動構造化機能」があります。
TASUKIツールには毎日大量のファイルがアップロードされ、それらは「自動構造化機能」で処理されています。この機能では一部の処理にLLM APIを活用していますが、サービスとして提供するにあたって大量のデータを処理する際にいくつかの課題に直面しました。
LLMは非常に便利な機能を提供してくれますが、パフォーマンスの観点で、サービス導入における課題が多いと感じています。TASUKIツールでは、LLM APIを使う処理にAmazon SQSとLambdaを利用することで、パフォーマンスをとユーザビリティを両立させています。
今回の記事では、大量のデータをLLM APIを利用して効率的に処理するためのアーキテクチャや工夫について紹介します。
LLM APIを利用する上で以下の2点の課題がありました。
それぞれの課題について、説明していきます。
1つ目の課題はスループットの安定性です。
LLM APIは共有リソースを利用することが多いため、利用者が多い時間帯はスループットが安定しないことが多いです。
例えばAzure Open AI APIの場合「Standard」タイプでデプロイした場合、指定したリージョンのLLM APIを常に利用するので、リクエスト数に応じてスループットが変動しやすくなります。
参考) Azure OpenAI Service のデプロイの種類について - Azure AI services | Microsoft Learn
「グローバル標準」や「グローバルバッチ」などのデプロイタイプではスループットの最適化が行われますが、指定したリージョンと別のリージョンで処理が実行される可能性があります。そのため「データを国外リージョンに送信できない」のような厳密な要件がある場合、これらのタイプを利用できません。
また、TASUKIツールの自動構造化処理では、1つの処理でLLM APIを複数回呼び出しています。そのため、リクエスト数の増加によるスループットの低下発生しやすく、大量のリクエストが行われた場合「時間がかかりすぎる」「処理が失敗しやすくなる」という課題が発生していました。
さらに、LLM APIのレスポンスが遅くなると、Webアプリケーションに負担がかかり、スレッドやCPUの使用量が増加することがあります。その結果、他の処理にも悪影響を及ぼす可能性があります。
このように、LLM APIを利用する機能だけでなく他の機能にも影響が出て、ユーザビリティが低下する可能性を抱えていました。
2つ目の課題はLLM APIのリクエスト上限です。
2024年12月18日現在、例えば「o1-mini」では1分間に許可されるリクエスト回数が50回、トークン数が500,000トークンに設定されています。
参考) Azure OpenAI Service のクォータと制限 - Azure AI services | Microsoft Learn
大量のデータを処理する場合、単に処理数を増やすと、このリクエスト上限を超えてしまします。その場合、一定期間のリクエストが全て404になってしまいます。
私たちのサービスの場合、お客様の利用状況によっては一度に最大で1000回以上のリクエストを実行されることが想定されていました。
そのため、そのような場合でもリクエスト上限に到達しないように調整する必要がありました。
TASUKIツールでは上記の課題を対応するために、Amazon SQSとLambdaを利用したマイクロサービスアーキテクチャを採用しています。
本アーキテクチャのポイントは以下の3点です
※本記事ではLambdaやAmazon SQSについての説明は省きます。Amason SQSについては、本番環境でAmazon SQSを利用したマイクロサービス構築のプラクティス 記事を御覧ください。
SQS + Lambdaを利用したマイクロサービスアーキテクチャを採用することで、処理の非同期と並列化を実現しています。
シーケンスとしては以下の通りです。
1つの処理を1つのタスクとして定義しています。ユーザからリクエストがあった数だけ、WebサーバはSQSにタスクを追加します。
LambdaはSQSから1つのタスクを取得し、1つのタスクを完了させることを責務とします。
メリットは以下の2点です。
SQS + Lambdaの構成をとることで、Webサーバのパフォーマンスの安定化と、処理全体の速度の向上を実現できています。
1つ目の工夫で並列化可能にしましたが、並列数を増加すると次はLLM APIのリクエスト上限にあたります。
正確には以下の上限があります
※厳密にはもう少しありますが、今回は影響が大きい上記2つに絞っています。
Lambdaには「予約済みの同時実行数」というパラメータがあり、これを利用して同時実行数を制御することができます。
参考) 関数に対する予約済み同時実行数の設定 - AWS Lambda
Lambdaの並列数の見積を、以下の計算式で算出しています。
これにより「Rate Limitを考慮しない並列数(分)」を算出できます。そして以下の式で「1分間の実行回数」を見積もります。
1分間の実行回数 = 1並列の場合の処理回数 × Rate Limitを考慮しない並列数(分)
この値がLLM APIのRate Limitより小さい場合はそのまま「Rate Limitを考慮しない並列数(分)」を並列数と設定します。
Rate Limitより大きい場合、Rate Limit以下になるように並列数を調整します。
こちらで計算した「Rate Limitを考慮しない並列数(分) 」または「Rate Limitを考慮した並列数(分)」のどちらからを、Lambdaの「予約済みの同時実行数」に設定します。
これによりLLM APIへの実行回数を調整し、リクエスト上限への到達を抑止することができます。
※LLM APIはスループットが安定しないため、さらに安全率で80%を掛けるなど調整することを推奨します
2の工夫でリクエスト数の調整をしても、外部APIを使う以上、処理は必ず失敗します。そこで、LambdaとSQSの機能を利用したリトライ機能を実現しています。
失敗が発生した時のリトライ処理は、以下の流れになります。
また、リトライ回数の上限をSQSの「最大受信回数」で設定できます。「最大受信回数」を超えたリトライに失敗したタスクは、Dead Letter Queue(DLQ)に送信されます。
これにより、無限リトライを簡単に防ぐことができます。
参考) 本番環境でAmazon SQSを利用したマイクロサービス構築のプラクティス
Amazon SQSとLambdaの構成を利用することで、簡単にリトライ処理を実現することができます。
アーキテクチャ上の工夫はしましたが、それでもLLM APIの利用状況によっては処理が失敗することはあります。
その場合の最後の手段として、サービス側での再実行処理を組み込んでいます。ユーザが処理の失敗を検知し、自身でリトライできる機能です。
TASUKIツールでは処理の厳密さや高い処理速度は求められていないため、失敗した場合はユーザからサービス側でリトライしてもらうようにすることで、不安定さをカバーしています。
この記事では、LLM APIを使って大量のデータを処理する際のプラクティスについて記載しました。
LLMは非常に便利な機能を提供してくれますが、パフォーマンスの観点で、サービス導入における課題が多いと感じています。
TASUKIツールでは、LLM APIを使う処理にAmazon SQSとLambdaを利用することで、パフォーマンスをとユーザビリティを両立させています。
私たちの提供するTASUKIツールでは、本記事の内容を取り入れたRAG用データの自動構造化機能を提供しています。
TASUKIツールでは、この他にもRAG向けデータ作成に特化した複数の機能やLLM向けデータ作成のさまざまなサービスを提供しております。
TASUKIチームの技術やRAGの精度向上にご興味がある方は、以下のURLからぜひご相談ください。
データ構造化代行サービスで検索拡張生成(RAG)の検索精度を向上。膨大かつ多様な社内ドキュメントも、RAGへの高い知見をもったチームがデータ構造化を支援します。
条件に該当するページがございません