AIの生成体験を向上させる Amazon SageMakerホスティングでのストリーミングサポートの導入

AI生成体験向上のためのAmazon SageMakerホスティングでのストリーミングサポート導入

Amazon SageMakerリアルタイム推論を通じてレスポンスストリーミングの利用が可能になりました。これにより、SageMakerリアルタイム推論を使用してジェネレーティブAIアプリケーション(チャットボット、仮想アシスタント、音楽生成器など)の対話型エクスペリエンスを構築する際に、連続的に推論のレスポンスをクライアントにストリーミングできるようになりました。この新機能により、完全なレスポンスが生成されるのを待つのではなく、利用可能な場合にはすぐにレスポンスのストリーミングを開始できます。これにより、ジェネレーティブAIアプリケーションの最初のバイトまでの時間が短縮されます。

この記事では、対話型チャットの使用例に対して、新しいレスポンスストリーミング機能を使用してSageMakerリアルタイムエンドポイントを使用したストリーミングWebアプリケーションの構築方法を示します。サンプルのデモアプリケーションUIにはStreamlitを使用しています。

ソリューションの概要

SageMakerからストリーミングでレスポンスを受け取るには、新しいInvokeEndpointWithResponseStream APIを使用できます。これにより、顧客の満足度が向上し、最初のレスポンスバイトまでの時間が短縮されます。この顧客が認識するレイテンシーの低減は、特にジェネレーティブAIモデルを使用して構築されたアプリケーションにとって重要です。ここでは、完全なペイロードを待つよりも即座の処理が重要なため、ジェネレーティブAIモデルの応用において特に重要です。また、この機能により、連続性のある対話を可能にするスティッキーセッションが導入され、チャットボットなどのユースケースにもメリットがあり、より自然で効率的なユーザーエクスペリエンスを作成できます。

SageMakerリアルタイムエンドポイントにおけるレスポンスストリーミングの実装は、HTTP 1.1チャンクエンコーディングを通じて行われます。これは、複数のレスポンスを送信するためのメカニズムです。これは、バイナリコンテンツをサポートするHTTPの標準であり、ほとんどのクライアント/サーバーフレームワークでサポートされています。HTTPチャンクエンコーディングは、テキストや画像データのストリーミングの両方をサポートしており、SageMakerエンドポイントにホストされているモデルは、Falcon、Llama 2、Stable Diffusionモデルなど、テキストまたは画像としてストリームされた応答を送信することができます。セキュリティに関しては、入力および出力の両方がTLSを使用してAWS Sigv4 Authを使用して保護されています。Server-Sent Events(SSE)などの他のストリーミング技術も、同じHTTPチャンクエンコーディングメカニズムを使用して実装されています。新しいストリーミングAPIの利点を活用するには、モデルコンテナがストリーム化されたレスポンスをチャンクエンコードされたデータとして返すことを確認する必要があります。

以下の図は、SageMaker推論エンドポイントでのレスポンスストリーミングのハイレベルアーキテクチャを示しています。

ストリーミングレスポンスを受けることで恩恵を受けるユースケースの1つは、ジェネレーティブAIモデルを活用したチャットボットです。従来、ユーザーはクエリを送信し、完全なレスポンスが生成されるのを待ってから回答を受け取ります。これには貴重な秒数、またはそれ以上の時間がかかる場合があり、アプリケーションのパフォーマンスが低下する可能性があります。レスポンスストリーミングを使用すると、チャットボットは生成される部分的な推論結果を送信し始めることができます。つまり、ユーザーはAIがバックグラウンドで回答を洗練させ続ける間も、初期の回答をほぼ瞬時に見ることができます。これにより、ユーザーはリアルタイムに理解し、応答するAIとの会話フローをシームレスかつ魅力的に感じることができます。

この記事では、レスポンスストリーミングを使用してSageMakerエンドポイントを作成するための2つのコンテナオプションを紹介します。AWS Large Model Inference(LMI)コンテナとHugging Face Text Generation Inference(TGI)コンテナを使用します。次のセクションでは、LMIおよびTGIコンテナを使用してFalcon-7B-InstructモデルをSageMakerで展開およびテストするための詳細な実装手順を説明します。Falcon 7Bを例に挙げましたが、どのモデルでもこの新しいストリーミング機能を活用することができます。

前提条件

このソリューションの一部として作成されるリソースを管理するためのアクセス許可を持つAWS Identity and Access Management(IAM)ロールを持つAWSアカウントが必要です。詳細については、「AWSアカウントの作成」を参照してください。Amazon SageMaker Studioを初めて使用する場合は、まずSageMakerドメインを作成する必要があります。また、対応するSageMakerホスティングインスタンスのサービスクオータを増やす必要がある場合もあります。Falcon-7B-Instructモデルでは、ml.g5.2xlarge SageMakerホスティングインスタンスを使用します。Falcon-40B-Instructモデルのホスティングには、ml.g5.48xlarge SageMakerホスティングインスタンスを使用します。サービスクオータの増加は、サービスクオータUIからリクエストすることができます。詳細については、「サービスクオータの増加のリクエスト」を参照してください。

オプション1:LMIコンテナを使用してリアルタイムストリーミングエンドポイントを展開する

LMIコンテナは、低レイテンシー推論ユースケースのためにAWSインフラストラクチャ上で大規模な言語モデル(LLM)をホストするためのSageMakerでホストされるDeep Learning Containersの1つです。LMIコンテナは、ディープジャバライブラリ(DJL)サービングを使用しており、これはオープンソースの高レベルでエンジンに依存しないJavaフレームワークです。これらのコンテナでは、DeepSpeed、Accelerate、Transformers-neuronx、FasterTransformerなどの対応するオープンソースライブラリを使用して、モデルパラメータをモデル並列技術を使用して複数のGPUまたはアクセラレータのメモリを使用するために分割することができます。SageMakerで大規模なモデルを展開するためのLMIコンテナの利点の詳細については、「Amazon SageMakerでFasterTransformerを使用して高パフォーマンスで大規模なモデルを展開する」と「DJLServingとDeepSpeedモデルパラレル推論を使用してAmazon SageMakerで大規模なモデルを展開する」を参照してください。また、このGitHubリポジトリでも、LMIコンテナを使用してSageMakerでオープンソースのLLMをホストするさまざまな例を見つけることができます。

LMIコンテナには、推論モデルをセットアップするための以下のアーティファクトが必要です:

  • serving.properties(必須) – モデルサーバーの設定を定義します
  • model.py(オプション) – コアの推論ロジックを定義するPythonファイルです
  • requirements.txt(オプション) – 追加のpipホイールをインストールする必要があります

LMIコンテナは、入力データのカスタム前処理やモデルの予測結果のカスタム後処理がない場合に、モデルをホストするために使用できます。以下の設定を使用しています:

  • この例では、Falcon-7B-Instructモデルをホストしています。希望のホスティングオプションを持つserving.properties構成ファイルを作成し、tar.gzアーティファクトにパッケージ化する必要があります。DJL Servingで応答ストリーミングを有効にするには、serving.propertiesファイルのenable_streamingオプションを設定します。サポートされているパラメータの詳細については、Streaming Python configurationを参照してください。
  • この例では、DJL Servingのデフォルトハンドラーを使用して応答をストリーミングしますので、リクエストの送信と出力応答の解析のみに関心があります。カスタムハンドラーを持つmodel.pyファイルのentrypointコードを指定することで、入力と出力のハンドラーをカスタマイズすることもできます。カスタムハンドラーの詳細については、Custom model.py handlerを参照してください。
  • Falcon-7B-Instructモデルを単一のGPUインスタンス(ml.g5.2xlarge)でホストしているため、option.tensor_parallel_degreeを1に設定しています。複数のGPUで実行する場合は、ワーカーごとのGPUの数を設定します。
  • option.output_formatterを使用して出力のコンテンツタイプを制御しています。デフォルトの出力コンテンツタイプはapplication/jsonですので、アプリケーションで異なる出力が必要な場合は、この値を上書きできます。使用可能なオプションの詳細については、Configurations and settingsおよびAll DJL configuration optionsを参照してください。
%%writefile serving.properties
engine=MPI 
option.model_id=tiiuae/falcon-7b-instruct
option.trust_remote_code=true
option.tensor_parallel_degree=1
option.max_rolling_batch_size=32
option.rolling_batch=auto
option.output_formatter=jsonlines
option.paged_attention=false
option.enable_streaming=true

SageMakerモデルを作成するには、コンテナイメージのURIを取得します:

image_uri = image_uris.retrieve(
    framework="djl-deepspeed",
    region=sess.boto_session.region_name,
    version="0.23.0"
)

SageMaker Python SDKを使用してSageMakerモデルを作成し、deployメソッドを使用してSageMakerリアルタイムエンドポイントにデプロイします:

instance_type = "ml.g5.2xlarge"
endpoint_name = sagemaker.utils.name_from_base("lmi-model-falcon-7b")

model = Model(sagemaker_session=sess, 
                image_uri=image_uri, 
                model_data=code_artifact, 
                role=role)

model.deploy(
    initial_instance_count=1,
    instance_type=instance_type,
    endpoint_name=endpoint_name,
    container_startup_health_check_timeout=900
)

エンドポイントがサービス中の場合、InvokeEndpointWithResponseStream API呼び出しを使用してモデルを呼び出すことができます。このAPIは、モデルが完全なレスポンスペイロードの一部としてストリーム形式で応答することを可能にします。これにより、モデルはより大きなサイズの応答で応答できるようになり、応答の最初のバイトと最後のバイトの生成に大きな差があるモデルでは、最初のバイトから最後のバイトまでの時間を短縮できます。

LMIコンテナのx-amzn-sagemaker-content-typeで表示される応答コンテンツタイプは、モデルのプロパティ設定で指定されたapplication/jsonlineです。推論にサポートされている一般的なデータ形式の一部であるため、SageMaker Python SDKが提供するデフォルトのデシリアライザを使用してJSON行データをデシリアライズすることができます。推論要求から受け取った応答ストリームを解析するためのヘルパーLineIteratorクラスを作成します:

class LineIterator:
    """
    バイトストリーム入力を解析するためのヘルパークラス。

    モデルの出力は次の形式になります:
    ```
    b'{"outputs": [" a"]}\n'
    b'{"outputs": [" challenging"]}\n'
    b'{"outputs": [" problem"]}\n'
    ...
    ```

    通常、イベントストリームの各PayloadPartイベントには、完全なJSONを持つバイト配列が含まれますが、これは保証されていません。一部のJSONオブジェクトは、PayloadPartイベントをまたいで分割される場合があります。例えば:
    ```
    {'PayloadPart': {'Bytes': b'{"outputs": '}}
    {'PayloadPart': {'Bytes': b'[" problem"]}\n'}}
    ```

    このクラスは、'write'関数で書き込まれたバイトを連結し、'scan_lines'関数を使用してバッファ内の行('\n'文字で終わる)を返すメソッドを公開します。前回の読み取り位置を保持して、以前のバイトが再度公開されないようにします。
    """

    def __init__(self, stream):
        self.byte_iterator = iter(stream)
        self.buffer = io.BytesIO()
        self.read_pos = 0

    def __iter__(self):
        return self

    def __next__(self):
        while True:
            self.buffer.seek(self.read_pos)
            line = self.buffer.readline()
            if line and line[-1] == ord('\n'):
                self.read_pos += len(line)
                return line[:-1]
            try:
                chunk = next(self.byte_iterator)
            except StopIteration:
                if self.read_pos < self.buffer.getbuffer().nbytes:
                    continue
                raise
            if 'PayloadPart' not in chunk:
                print('Unknown event type:' + chunk)
                continue
            self.buffer.seek(0, io.SEEK_END)
            self.buffer.write(chunk['PayloadPart']['Bytes'])

前のコードのクラスを使用すると、レスポンスがストリームされるたびに、Pythonの辞書に再度シリアル化できるバイナリ文字列(例:b'{"outputs": [" a"]}\n')が返されます。次のコードを使用して、テキストの各ストリーム行を反復処理し、テキストのレスポンスを返すことができます:

body = {"inputs": "what is life", "parameters": {"max_new_tokens":400}}
resp = smr.invoke_endpoint_with_response_stream(EndpointName=endpoint_name, Body=json.dumps(body), ContentType="application/json")
event_stream = resp['Body']

for line in LineIterator(event_stream):
    resp = json.loads(line)
    print(resp.get("outputs")[0], end='')

次のスクリーンショットは、SageMakerノートブックを使用してLMIコンテナを介してモデルを呼び出した場合の表示例です。

オプション2:Hugging Face TGIコンテナを使用したチャットボットの実装

前のセクションでは、LMIコンテナを使用してFalcon-7B-Instructモデルを展開する方法を見ました。このセクションでは、SageMakerでHugging Face Text Generation Inference(TGI)コンテナを使用して同じことを行う方法を示します。TGIは、LLMを展開するためのオープンソースの特別なソリューションです。テンソル並列処理を活用した高速なマルチGPU推論、全体のスループットを向上させるためのダイナミックバッチ処理、BLOOM、T5、GPT-NeoX、StarCoder、LLaMaなどの人気のあるモデルアーキテクチャに対応するための最適化されたトランスフォーマーコードを組み込んでいます。

TGIディープラーニングコンテナは、Server-Sent Events(SSE)を使用したトークンストリーミングをサポートしています。トークンストリーミングを使用すると、サーバーは最初のprefillパスの直後から回答を開始でき、すべての生成が完了するのを待つ必要はありません。非常に長いクエリの場合、クライアントは作業が完了する数桁も前から何かが起こっているのを見ることができます。次の図は、TGIコンテナを使用してSageMakerエンドポイントでLLMをホストするためのエンドツーエンドのリクエスト/レスポンスワークフローの概要を示しています。

SageMakerエンドポイントにFalcon-7B-Instructモデルを展開するために、SageMaker Python SDKのHuggingFaceModelクラスを使用します。次のようにパラメータを設定して始めます:

hf_model_id = "tiiuae/falcon-7b-instruct" # モデルID(huggingface.co/modelsから)
number_of_gpus = 1 # 推論とテンソル並列処理に使用するGPUの数
health_check_timeout = 300 # モデルのダウンロードに5分間のタイムアウトを設定するため、ヘルスチェックのタイムアウトを増やす
instance_type = "ml.g5.2xlarge" # デプロイに使用するインスタンスタイプ

通常のHugging Faceモデルを展開する場合と比較して、まずコンテナのURIを取得し、HuggingFaceModelモデルクラスにimage_uriを指すように提供する必要があります。SageMakerで新しいHugging Face LLM DLCを取得するには、SageMaker SDKが提供するget_huggingface_llm_image_uriメソッドを使用できます。このメソッドを使用すると、指定したバックエンド、セッション、リージョン、バージョンに基づいて、指定したHugging Face LLM DLCのURIを取得できます。使用可能なバージョンの詳細については、HuggingFace Text Generation Inference Containersを参照してください。

llm_image = get_huggingface_llm_image_uri(
    "huggingface",
    version="0.9.3"
)

次に、HuggingFaceModelを作成し、deployメソッドを使用してSageMakerに展開します:

endpoint_name = sagemaker.utils.name_from_base("tgi-model-falcon-7b")
llm_model = HuggingFaceModel(
    role=role,
    image_uri=llm_image,
    env={
            'HF_MODEL_ID': hf_model_id,
            # 'HF_MODEL_QUANTIZE': "bitsandbytes", # クオンタイズする場合はコメントを有効にする
            'SM_NUM_GPUS': str(number_of_gpus),
            'MAX_INPUT_LENGTH': "1900",  # 入力テキストの最大長
            'MAX_TOTAL_TOKENS': "2048",  # 生成物の最大長(入力テキストを含む)
        }
)

llm = llm_model.deploy(
    initial_instance_count=1,
    instance_type=instance_type,
    container_startup_health_check_timeout=health_check_timeout,
    endpoint_name=endpoint_name,
)

エンドポイントを呼び出す際に、呼び出しリクエストペイロードの一部としてstream=trueを指定することで、LMIコンテナと比較して、レスポンスのストリーミングを有効にすることが主な違いです。以下のコードは、ストリーミングを使用してTGIコンテナを呼び出すために使用されるペイロードの例です。

body = {
    "inputs":"tell me one sentence",
    "parameters":{
        "max_new_tokens":400,
        "return_full_text": False
    },
    "stream": True
}

次に、次のコマンドを使用してエンドポイントを呼び出し、ストリームされたレスポンスを受け取ることができます。

from sagemaker.base_deserializers import StreamDeserializer

llm.deserializer=StreamDeserializer()
resp = smr.invoke_endpoint_with_response_stream(EndpointName=llm.endpoint_name, Body=json.dumps(body), ContentType='application/json')

TGIコンテナのx-amzn-sagemaker-content-typeで表示されるレスポンスのコンテンツタイプはtext/event-streamです。レスポンスをEventStreamクラスに逆シリアル化し、レスポンスボディをLMIコンテナセクションで使用されるLineIteratorクラスと同じように解析するために、StreamDeserializerを使用します。

TGIコンテナからのストリームレスポンスはバイナリ文字列(例:b`data:{"token": {"text": "sometext"}}`)を返しますが、これはJSONパッケージを使用して再度Pythonの辞書に逆シリアル化することができます。以下のコードを使用して、テキストのストリームラインごとに反復処理し、テキストレスポンスを返すことができます:

event_stream = resp['Body']
start_json = b'{'
for line in LineIterator(event_stream):
    if line != b'' and start_json in line:
        data = json.loads(line[line.find(start_json):].decode('utf-8'))
        if data['token']['text'] != stop_token:
            print(data['token']['text'],end='')

以下のスクリーンショットは、SageMakerノートブックを使用してTGIコンテナを介してモデルを呼び出した場合の表示例です。

SageMaker Studioでチャットボットアプリを実行する

このユースケースでは、SageMaker StudioでStreamlitを使用して動的なチャットボットを構築し、SageMakerリアルタイムエンドポイントでホストされているFalcon-7B-Instructモデルを呼び出してストリーミングレスポンスを提供します。まず、前のセクションでノートブックでストリーミングレスポンスが機能することをテストできます。次に、SageMaker Studio JupyterServerのターミナルでStreamlitアプリケーションを設定し、以下の手順を完了することで、ブラウザからチャットボットUIにアクセスできます:

  1. SageMaker Studioでシステムのターミナルを開きます。

  2. SageMaker Studioコンソールの上部メニューで、ファイル新規ターミナルを選択します。

  3. requirements.txtファイルに指定されている必要なPythonパッケージをインストールします:

    $ pip install -r requirements.txt
  4. アカウントにデプロイされたFalcon-7B-instructエンドポイント名で環境変数を設定します:

    $ export endpoint_name=<Falcon-7B-instructエンドポイント名>
  5. Streamlitアプリケーションをstreamlit_chatbot_LMI.pyファイルから起動します。このプロセスでは、以前に設定した環境変数に基づいてスクリプト内のエンドポイント名が自動的に更新されます:

    $ streamlit run streamlit_chatbot_LMI.py --server.port 6006
  6. Streamlit UIにアクセスするには、SageMaker StudioのURLを別のタブにコピーし、lab?proxy/[PORT NUMBER]/に置き換えます。サーバーポートを6006に指定したため、URLは次のようになります:

    https://<domain ID>.studio.<region>.sagemaker.aws/jupyter/default/proxy/6006/

前述のURLのドメインIDとリージョンを、アカウントとリージョンに置き換えてチャットボットのUIにアクセスしてください。開始するためのいくつかの提案されたプロンプトが、左のペインに表示されます。

以下のデモでは、応答ストリーミングがユーザーエクスペリエンスを革新する様子を示しています。これにより、インタラクションがスムーズでレスポンシブに感じられ、ユーザーの満足度とエンゲージメントが向上します。チャットボットの実装の詳細については、GitHubのリポジトリを参照してください。

クリーンアップ

モデルのテストが完了したら、コストを節約するために、エンドポイントを削除することを推奨します(必要なくなった場合):

# - エンドポイントの削除
sm_client.delete_endpoint(EndpointName=endpoint_name)

結論

この投稿では、生成型AIを使用したアプリケーションの概要、課題、およびSageMakerリアルタイム応答ストリーミングがこれらの課題に対処する方法について説明しました。GitHubで利用可能な例を使用して、SageMaker LMIおよびHuggingFace TGIコンテナの両方を使用して、Falcon-7B-Instructモデルをデプロイし、応答ストリーミングを使用するチャットボットアプリケーションを構築する方法を紹介しました。

LLMsとSageMakerを使用して、最先端のストリーミングアプリケーションを今すぐ構築しましょう!専門的なガイダンスを受けるためにお問い合わせください。大規模モデルストリーミングのポテンシャルを解き放ち、プロジェクトに活かしましょう。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

機械学習

「メタのCode Llamaコード生成モデルは、Amazon SageMaker JumpStartを介して利用可能になりました」

今日は、Metaが開発したCode Llama foundationモデルが、Amazon SageMaker JumpStartを通じて顧客に提供され、クリックひとつ...

機械学習

「50以上の最新の最先端人工知能(AI)ツール(2023年11月)」

AIツールは急速に開発が進んでおり、定期的に新しいツールが導入されています。以下にいくつかのAIツールを紹介します。これ...

コンピュータサイエンス

暗闇で作られた堅牢な光学構造の構築

ハーバード大学の研究チームは、メタサーフェスを利用して、「光学的特異点」と呼ばれる電磁場の暗い領域を生成・操作しました

データサイエンス

「SPHINXをご紹介します:トレーニングタスク、データドメイン、および視覚的なエンベッディングをミキシングした多目的なマルチモーダル大規模言語モデル(MLLM)」

マルチモーダル言語モデルでは、複雑なビジュアル指示に対処し、多様なタスクをシームレスに実行するための既存のモデルの限...

機械学習

「Rust言語を使う開発者が増えています」

「2022年のRustの状況に関する調査は、今月初めに公開され、これまでにないほど多くの開発者がこのプログラミング言語を使用...

AIニュース

15 AIによる音声編集ツール

音響エンジニアや音楽プロデューサーは、メロディやハーモニーの生成、音質の向上など、創造プロセスのさまざまな領域を強化...