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 を使用してユーザー メッセージへの応答を生成します。
アプリケーション アーキテクチャは、次のサービスとコンポーネントに依存しています。
- Azure OpenAI は、ユーザーのクエリを送信する AI プロバイダーを表します。
- Azure Container Apps は、アプリケーションがホストされるコンテナー環境です。
- マネージド ID は、クラス最高のセキュリティを確保するのに役立ち、開発者がシークレットを安全に管理する必要がなくなります。
- Azure OpenAI、Azure Container Apps、Azure Container Registry、Azure Log Analytics、ロールベースのアクセス制御 (RBAC) ロールなど、Azure リソースをプロビジョニングするための Bicep ファイル 。
- Microsoft AI チャット プロトコルは、AI ソリューションと言語全体で標準化された API コントラクトを提供します。 チャット アプリは、Microsoft AI チャット プロトコルに準拠しています。
openai
パッケージを使用して、アップロードされたイメージ ファイルを含むユーザー メッセージへの応答を生成する Python Quart。- ReadableStreamを介してJSON Linesを使用してバックエンドからの応答をストリーミングする基本的な HTML/JavaScript フロントエンド。
コスト
このサンプルで可能な限り価格を低く保つために、ほとんどのリソースでは Basic 価格レベルまたは従量課金価格レベルが使用されます。 目的の使用法に基づいて、必要に応じてレベルを変更します。 料金の発生を停止するには、記事が完了したらリソースを削除します。
サンプル リポジトリでコストの詳細を参照してください。
前提条件
開発コンテナー環境は、この記事を完了するために必要なすべての依存関係と共に使用できます。 開発コンテナーは、(ブラウザーで) GitHub Codespaces で実行することも、Visual Studio Code を使用してローカルで実行することもできます。
この記事を使用するには、次の前提条件を満たす必要があります。
Azure サブスクリプション - 無料アカウントを作成します
Azure アカウントのアクセス許可 - Azure アカウントには、User Access Administrator Owner などの
Microsoft.Authorization/roleAssignments/write
アクセス許可が必要です。GitHub アカウント
開発環境を開く
この記事を完了するために必要なすべての依存関係を含む、構成済みの開発環境をデプロイするには、次の手順に従います。
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 を作成するには、次の手順に従います。
次のボタンを右クリックし、 [新しいウィンドウでリンクを開く]を選択します。 このアクションを使用すると、開発環境とドキュメントを確認できます。
コードスペースの作成 ページで、新しいコード空間確認して選択します。
Codespace が起動するまで待ちます。 この起動プロセスには数分かかることがあります。
画面の下部にあるターミナルで、Azure Developer CLI を使用して Azure にサインインします。
azd auth login
ターミナルからコードをコピーし、ブラウザーに貼り付けます。 手順に従って、Azure アカウントで認証します。
この記事の残りのタスクは、この開発コンテナーのコンテキストで行われます。
デプロイして実行する
サンプル リポジトリには、チャット アプリの Azure デプロイのすべてのコードと構成ファイルが含まれています。 次の手順では、サンプル チャット アプリの Azure デプロイ プロセスについて説明します。
チャット アプリを Azure にデプロイする
重要
このセクションで作成された Azure リソースでは、すぐにコストが発生します。 これらのリソースは、コマンドが完全に実行される前に中断した場合でも、コストが発生する可能性があります。
Azure リソースのプロビジョニングとソース コードのデプロイに対して、次の Azure Developer CLI コマンドを実行します。
azd up
プロンプトに応答するには、次の表を使用します。
Prompt 回答 環境名 常に短くし、小文字を使用します。 自分の名前またはエイリアスを追加します。 たとえば、 chat-vision
のようにします。 リソース グループ名の一部として使用されます。サブスクリプション リソースの作成先となるサブスクリプションを選択します。 場所 (ホスティング用) リストから、自分に近い場所を選択します。 Azure OpenAI モデルの場所 リストから、自分に近い場所を選択します。 最初の場所と同じ場所を使用できる場合は、その場所を選択します。 アプリがデプロイされるまで待ちます。 通常、デプロイの完了には 5 分から 10 分かかります。
チャット アプリを使用して大規模言語モデルに質問する
アプリケーションのデプロイが正常に完了すると、ターミナルに URL が表示されます。
Deploying service web
とラベルの付いたその URL を選択して、ブラウザーでチャット アプリケーションを開きます。ブラウザーで[ファイルの選択]をクリックしイメージ選択して、画像をアップロードします。
アップロードされた画像に関する質問をします (例: "What is the image about?")。
回答は Azure OpenAI に由来し、結果が表示されます。
サンプル コードの探索
OpenAI と Azure OpenAI Service は common Python クライアント ライブラリに依存していますが Azure OpenAI エンドポイントを使用する場合は小さなコード変更が必要です。 このサンプルでは、Azure OpenAI マルチモーダル モデルを使用して、ユーザー メッセージとアップロードされた画像に対する応答を生成します。
フロントエンドでアップロードされたイメージを Base64 エンコードする
アップロードされたイメージは、メッセージの一部としてデータ URI として直接使用できるように、Base64 でエンコードする必要があります。
このサンプルでは、src/quartapp/templates/index.html
ファイルのscript
タグにある次のフロントエンド コード スニペットがその機能を処理します。 toBase64
矢印関数はFileReader
のreadAsDataURL
メソッドを使用して、アップロードされたイメージ ファイルを 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 に月単位で含まれるストレージとコア時間」を参照してください。
GitHub Codespaces ダッシュボード (https://github.com/codespaces) にサインインします。
Azure-Samples//openai-chat-vision-quickstart
GitHub リポジトリをソースとして現在実行中の Codespaces を見つけます。codespace のコンテキスト メニューを開き、[削除] を選択します。
ヘルプを取得
リポジトリの Issues に問題をログに記録します。