次の方法で共有


Azure OpenAI を使用したマルチモーダル ビジョン チャット アプリの概要

この記事では、Azure OpenAI マルチモーダル モデルを使用して、チャット アプリでユーザー メッセージとアップロードされた画像に対する応答を生成する方法について説明します。 このチャット アプリサンプルには、Azure OpenAI リソースをプロビジョニングし、Azure Developer CLI を使用してアプリを Azure Container Apps にデプロイするために必要なすべてのインフラストラクチャと構成も含まれています。

この記事の手順に従うことで、次の操作を行います:

  • 認証にマネージド ID を使用する Azure Container チャット アプリをデプロイします。
  • チャット ストリームの一部として使用する画像をアップロードします。
  • OpenAI ライブラリを使用して、Azure OpenAI マルチモーダル 大規模言語モデル (LLM) とチャットします。

この記事の手順の完了後は、カスタム コードを使用して、新しいプロジェクト用の変更を開始できます。

Note

この記事では、記事内の例とガイダンスの土台として、1 つ以上の AI アプリ テンプレートを使用しています。 AI アプリ テンプレートは、適切にメンテナンスされ、デプロイが容易なリファレンス実装を提供します。これは、高品質な AI アプリの作成を開始するために役立ちます。

アーキテクチャの概要

チャット アプリの単純なアーキテクチャを次の図に示します。 クライアントからバックエンド アプリへのアーキテクチャを示す図。

チャット アプリは Azure Container App として実行されています。 アプリは、API キーではなく、Microsoft Entra ID を介してマネージド ID を使用して Azure OpenAI で認証します。 チャット アプリは、Azure OpenAI を使用してユーザー メッセージへの応答を生成します。

アプリケーション アーキテクチャは、次のサービスとコンポーネントに依存しています。

コスト

このサンプルで可能な限り価格を低く保つために、ほとんどのリソースでは Basic 価格レベルまたは従量課金価格レベルが使用されます。 目的の使用法に基づいて、必要に応じてレベルを変更します。 料金の発生を停止するには、記事が完了したらリソースを削除します。

サンプル リポジトリでコストの詳細を参照してください。

前提条件

開発コンテナー環境は、この記事を完了するために必要なすべての依存関係と共に使用できます。 開発コンテナーは、(ブラウザーで) GitHub Codespaces で実行することも、Visual Studio Code を使用してローカルで実行することもできます。

この記事を使用するには、次の前提条件を満たす必要があります。

開発環境を開く

この記事を完了するために必要なすべての依存関係を含む、構成済みの開発環境をデプロイするには、次の手順に従います。

GitHub Codespaces は、 Visual Studio Code for the Web をユーザー インターフェイスとして使用して、GitHub によって管理される開発コンテナーを実行します。 最も簡単な開発環境では、GitHub Codespaces を使用して、この記事を完了するために正しい開発者ツールと依存関係がプレインストールされるようにします。

重要

すべての GitHub アカウントでは、2 つのコア インスタンスで毎月最大 60 時間無料で Codespaces を使用できます。 詳細については、「 GitHub Codespaces に月単位で含まれるストレージとコア時間」を参照してください。

Azure-Samples/openai-chat-vision-quickstart GitHub リポジトリの main ブランチに新しい GitHub Codespace を作成するには、次の手順に従います。

  1. 次のボタンを右クリックし、 [新しいウィンドウでリンクを開く]を選択します。 このアクションを使用すると、開発環境とドキュメントを確認できます。

    GitHub codespaces で開く

  2. コードスペースの作成 ページで、新しいコード空間確認して選択します。

  3. Codespace が起動するまで待ちます。 この起動プロセスには数分かかることがあります。

  4. 画面の下部にあるターミナルで、Azure Developer CLI を使用して Azure にサインインします。

    azd auth login
    
  5. ターミナルからコードをコピーし、ブラウザーに貼り付けます。 手順に従って、Azure アカウントで認証します。

この記事の残りのタスクは、この開発コンテナーのコンテキストで行われます。

デプロイして実行する

サンプル リポジトリには、チャット アプリの Azure デプロイのすべてのコードと構成ファイルが含まれています。 次の手順では、サンプル チャット アプリの Azure デプロイ プロセスについて説明します。

チャット アプリを Azure にデプロイする

重要

このセクションで作成された Azure リソースでは、すぐにコストが発生します。 これらのリソースは、コマンドが完全に実行される前に中断した場合でも、コストが発生する可能性があります。

  1. Azure リソースのプロビジョニングとソース コードのデプロイに対して、次の Azure Developer CLI コマンドを実行します。

    azd up
    
  2. プロンプトに応答するには、次の表を使用します。

    Prompt 回答
    環境名 常に短くし、小文字を使用します。 自分の名前またはエイリアスを追加します。 たとえば、chat-vision のようにします。 リソース グループ名の一部として使用されます。
    サブスクリプション リソースの作成先となるサブスクリプションを選択します。
    場所 (ホスティング用) リストから、自分に近い場所を選択します。
    Azure OpenAI モデルの場所 リストから、自分に近い場所を選択します。 最初の場所と同じ場所を使用できる場合は、その場所を選択します。
  3. アプリがデプロイされるまで待ちます。 通常、デプロイの完了には 5 分から 10 分かかります。

チャット アプリを使用して大規模言語モデルに質問する

  1. アプリケーションのデプロイが正常に完了すると、ターミナルに URL が表示されます。

  2. Deploying service web とラベルの付いたその URL を選択して、ブラウザーでチャット アプリケーションを開きます。

    ブラウザーのチャット アプリのスクリーンショット。チャット内のアップロードされた画像に関する質問と、質問を入力するための応答とチャット テキスト ボックスが表示されています。

  3. ブラウザーで[ファイルの選択]をクリックしイメージ選択して、画像をアップロードします。

  4. アップロードされた画像に関する質問をします (例: "What is the image about?")。

  5. 回答は Azure OpenAI に由来し、結果が表示されます。

サンプル コードの探索

OpenAI と Azure OpenAI Service は common Python クライアント ライブラリに依存していますが Azure OpenAI エンドポイントを使用する場合は小さなコード変更が必要です。 このサンプルでは、Azure OpenAI マルチモーダル モデルを使用して、ユーザー メッセージとアップロードされた画像に対する応答を生成します。

フロントエンドでアップロードされたイメージを Base64 エンコードする

アップロードされたイメージは、メッセージの一部としてデータ URI として直接使用できるように、Base64 でエンコードする必要があります。

このサンプルでは、src/quartapp/templates/index.html ファイルのscriptタグにある次のフロントエンド コード スニペットがその機能を処理します。 toBase64矢印関数はFileReaderreadAsDataURLメソッドを使用して、アップロードされたイメージ ファイルを base64 でエンコードされた文字列として非同期的に読み取ります。

    const toBase64 = file => new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
    });

toBase64関数は、フォームの submit イベントのリスナーによって呼び出されます。 submit イベントが発生すると、リスナーはイメージ ファイルをチェックし、存在する場合は、toBase64関数を使用してイメージをエンコードする Base64 によって処理されます。 その後、新しい画像データ URL fileDataがメッセージに追加されます。

    form.addEventListener("submit", async function(e) {
        e.preventDefault();

        const file = document.getElementById("file").files[0];
        const fileData = file ? await toBase64(file) : null;

        const message = messageInput.value;

        const userTemplateClone = userTemplate.content.cloneNode(true);
        userTemplateClone.querySelector(".message-content").innerText = message;
        if (file) {
            const img = document.createElement("img");
            img.src = fileData;
            userTemplateClone.querySelector(".message-file").appendChild(img);
        }
        targetContainer.appendChild(userTemplateClone);

バックエンドでのイメージの処理

src\quartapp\chat.py ファイルでは、キーレス認証を構成した後、イメージ処理のバックエンド コードが開始されます。

Note

Azure OpenAI への認証と承認にキーレス接続を使用する方法の詳細については、Azure OpenAI セキュリティ構成要素の概要 Microsoft Learn の記事を参照してください。

チャット ハンドラー関数

chat_handler()関数は、chat/stream エンドポイントからの受信要求 JSON データを待機し、それを処理します。 その後、メッセージは JSON データから抽出されます。 最後に、base64 でエンコードされたイメージが JSON データから取得されます。

@bp.post("/chat/stream")
async def chat_handler():
    request_json = await request.get_json()
    request_messages = request_json["messages"]
    # get the base64 encoded image from the request
    image = request_json["context"]["file"]

OpenAI クライアントとモデルを使用した応答ストリーム

chat_handler関数内のresponse_streamは、ルート内のチャット完了呼び出しを処理します。 次のコード スニペットは、ユーザー コンテンツ メッセージを前処理することから始まります。 イメージが存在する場合は、イメージ URL がユーザー コンテンツに追加され、

    @stream_with_context
    async def response_stream():
        # This sends all messages, so API request may exceed token limits
        all_messages = [
            {"role": "system", "content": "You are a helpful assistant."},
        ] + request_messages[0:-1]
        all_messages = request_messages[0:-1]
        if image:
            user_content = []
            user_content.append({"text": request_messages[-1]["content"], "type": "text"})
            user_content.append({"image_url": {"url": image, "detail": "auto"}, "type": "image_url"})
            all_messages.append({"role": "user", "content": user_content})
        else:
            all_messages.append(request_messages[-1])

Note

イメージ detail パラメーターと関連する設定の詳細については、「GpT-4 Turbo with Vision を使用する」の「画像処理の Detail パラメーターの設定:低、高、自動 」セクションを参照してください。

次に、 bp.openai_client.chat.completions Azure OpenAI API 呼び出しを介してチャットの完了を取得し、応答をストリーミングします。

        chat_coroutine = bp.openai_client.chat.completions.create(
            # Azure OpenAI takes the deployment name as the model name
            model=os.environ["OPENAI_MODEL"],
            messages=all_messages,
            stream=True,
            temperature=request_json.get("temperature", 0.5),
        )

最後に、応答はクライアントにストリーミングされ、例外に対するエラー処理が行われます。

        try:
            async for event in await chat_coroutine:
                event_dict = event.model_dump()
                if event_dict["choices"]:
                    yield json.dumps(event_dict["choices"][0], ensure_ascii=False) + "\n"
        except Exception as e:
            current_app.logger.error(e)
            yield json.dumps({"error": str(e)}, ensure_ascii=False) + "\n"

    return Response(response_stream())

探索するその他のサンプル リソース

チャット アプリのサンプルに加えて、リポジトリには、さらに学習するために探索する他のリソースがあります。 notebooks ディレクトリにある次のノートブックを確認します。

ノートブック 説明
chat_pdf_images.ipynb このノートブックでは、PDF ページを画像に変換し、推論のためにビジョン モデルに送信する方法を示します。
chat_vision.ipynb このノートブックは、アプリで使用されるビジョン モデルを手動で実験するために提供されます。

リソースをクリーンアップする

Azure リソースをクリーンアップする

この記事で作成した Azure リソースは、Azure サブスクリプションに課金されます。 今後これらのリソースが必要になるとは思わない場合は、削除して、より多くの料金が発生しないようにします。

次の Azure Developer CLI コマンドを実行して、Azure リソースを削除し、ソース コードを削除します:

azd down --purge

GitHub Codespaces をクリーンアップする

GitHub Codespaces 環境を削除すると、アカウントに対して取得するコアごとの無料時間エンタイトルメントの量を最大化できることが保証されます。

重要

GitHub アカウントのエンタイトルメントの詳細については、「 GitHub Codespaces に月単位で含まれるストレージとコア時間」を参照してください。

  1. GitHub Codespaces ダッシュボード (https://github.com/codespaces) にサインインします。

  2. Azure-Samples//openai-chat-vision-quickstart GitHub リポジトリをソースとして現在実行中の Codespaces を見つけます。

  3. codespace のコンテキスト メニューを開き、[削除] を選択します。

ヘルプを取得

リポジトリの Issues に問題をログに記録します。

次のステップ