チュートリアル: Azure OpenAI テキスト補完のヒントを Visual Studio Code の関数に追加する

この記事では、Visual Studio Code を使用して、前のクイックスタート記事で作成した関数アプリに HTTP エンドポイントを追加する方法について説明します。 この新しい HTTP エンドポイントは、トリガーされると Azure OpenAI テキスト補完入力バインドを使用してデータ モデルからテキスト補完のヒントを取得します。

このチュートリアルでは、次のタスクを行う方法を学習します。

  • Azure OpenAI でリソースを作成する。
  • OpenAI リソースでモデルをデプロイする。
  • モデル リソースにアクセス許可を設定する。
  • OpenAI に接続するように関数アプリを有効にする。
  • OpenAI バインドを HTTP によってトリガーされる関数に追加する。

1.前提条件を確認する

  • Azure サブスクリプション内の Azure OpenAI へのアクセス権を取得します。 まだアクセス権を得ていない場合は、このフォームに記入してアクセス権を要求してください。

2.Azure OpenAI リソースを作成する

以下の手順では、Azure portal で Azure OpenAI データ モデルを作成する方法を示します。

  1. Azure portal で Azure サブスクリプションにサインインします。

  2. [リソースの作成] を選択し、[Azure OpenAI] を検索します。 サービスを見つけたら、[作成] を選択します。

  3. [Azure OpenAI の作成] ページで、[基本] タブのフィールドに次の情報を入力します。

    フィールド 説明
    サブスクリプション Azure OpenAI を使用するためにオンボード済みのサブスクリプション。
    リソース グループ 前の記事で関数アプリのために作成したリソース グループ。 このリソース グループの名前を見つけるには、Azure リソース ブラウザー内で関数アプリを右クリックし、プロパティを選択して、返された JSON リソース ファイル内で resourceGroup 設定を検索します。
    リージョン できる限り、関数アプリと同じ場所にします。
    名前 Azure OpenAI Service リソースのわかりやすい名前 (mySampleOpenAI など)。
    価格レベル リソースの価格レベル。 現時点では、Azure OpenAI Service では Standard レベルのみ使用できます。 価格の詳細については、Azure OpenAI の価格ページを参照してください

    Azure portal で新しい Azure OpenAI リソースを構成する方法を示すスクリーンショット。

  4. [次へ] を 2 回選択して [ネットワーク] タブと [タグ] タブの両方の既定値を受け入れます。 作成するサービスには、インターネットを含め、ネットワークの制限事項はありません。

  5. 最後に [次へ] を選択して、プロセスの最後のステージである [確認と送信] に移動します。

  6. 構成設定を確認し、[作成]を選択します。

    Azure portal は、新しいリソースが使用可能になったときに通知を表示します。 通知内の [リソースに移動] を選択するか、新しい Azure OpenAI リソースを名前で検索します。

  7. 新しいリソースの Azure OpenAI リソース ページで、[要点]>[エンドポイント] の下にある [エンドポイントを表示するにはここをクリック] を選択します。 エンドポイントの URL とキーをコピーします。 後で必要になるため、これらの値を保存します。

Azure OpenAI でモデルに接続するための資格情報を取得できたら、アプリケーション設定でこれらのアクセス資格情報を設定する必要があります。

3.モデルをデプロイする

これでモデルをデプロイできるようになりました。 Azure OpenAI Studio で使用可能ないくつかのモデルから 1 つを選択できます。

モデルをデプロイするには、次の手順に従います。

  1. Azure OpenAI Studio にサインインします。

  2. 使用するサブスクリプションと作成した Azure OpenAI リソースを選択し、[リソースの使用] を選択します。

  3. [管理][デプロイ] を選択します。

  4. [新しいデプロイを作成する] を選択し、次のフィールドを構成します。

    フィールド 説明
    デプロイ名 名前は慎重に選択します。 デプロイ名は、クライアント ライブラリと REST API を使用してモデルを呼び出すためにコード内で使用されるため、後で使用できるように保存しておきます。
    モデルの選択 モデルの可用性はリージョンごとに異なります。 リージョンごとに利用可能なモデルの一覧については、「モデルの概要テーブルとリージョンの可用性」を参照してください。

    重要

    API を使用してモデルにアクセスする場合、API 呼び出しで、基になるモデル名ではなくデプロイ名を参照する必要があります。これは、OpenAI と Azure OpenAI の重要な違いの 1 つです。 OpenAI では、モデル名のみが必要です。 Azure OpenAI では、モデル パラメーターを使用する場合でも常にデプロイ名が必要です。 Microsoft のドキュメントに掲載されている例では、多くの場合、どのモデルが特定の API エンドポイントで機能するかを示すために、デプロイ名がモデル名と同一として表わされています。 結局のところ、実際のユース ケースに最適な任意の名前付け規則に従ってデプロイ名を付けることができます。

  5. 残りの設定の既定値をそのまま使用し、[作成] を選択します。

    デプロイの表に、新しく作成されたモデルに対応する新しいエントリが表示されます。

これで、Azure OpenAI ベースのテキスト補完を関数アプリに追加するために必要なものがすべて準備できました。

4. アプリケーション設定を更新する

  1. Visual Studio Code で、前の記事を完了したときに作成したローカル コード プロジェクトを開きます。

  2. プロジェクトのルート フォルダー内の local.settings.json ファイルで、AzureWebJobsStorage 設定を UseDevelopmentStorage=true に更新します。 local.settings.jsonAzureWebJobsStorage 設定が UseDevelopmentStorage=true ではなく既存の Azure Storage アカウントの接続文字列に設定されている場合は、この手順をスキップできます。

  3. local.settings.json ファイルで、次の設定値を追加します。

    • AZURE_OPENAI_ENDPOINT: バインド拡張機能によって要求されます。 先ほど作成した Azure OpenAI リソースのエンドポイントにこの値を設定します。
    • AZURE_OPENAI_KEY: バインド拡張機能によって要求されます。 この値を Azure OpenAI リソースのキーに設定します。
    • CHAT_MODEL_DEPLOYMENT_NAME: 入力バインドの定義に使用されます。 この値には、モデル デプロイのために選択した名前を設定します。
  4. ファイルを保存します。 Azure にデプロイするときに、これらの設定も関数アプリに追加する必要があります。

5.バインディング拡張機能を登録する

Azure OpenAI の出力バインドを使用しているため、このプロジェクトを実行する前に対応するバインド拡張機能をインストールしておく必要があります。

HTTP トリガーとタイマー トリガーを除き、バインドは拡張機能パッケージとして実装されます。 Azure OpenAI 拡張機能パッケージをプロジェクトに追加するには、[ターミナル] ウィンドウで次の dotnet add package コマンドを実行します。

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.OpenAI --prerelease

5.拡張機能バンドルを更新する

プレビューの Azure OpenAI バインドにアクセスするには、この拡張機能を含む拡張機能バンドルのプレビュー バージョンを使用する必要があります。

現在の host.json ファイルの extensionBundle 設定を次の JSON に置き換えます。

 "extensionBundle": {
   "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
   "version": "[4.*, 5.0.0)"
 }

これで、Azure OpenAI の出力バインドをプロジェクトで使用できるようになりました。

6.モデルからテキスト補完を返す

追加するコードによって、既存のプロジェクトに whois HTTP 関数エンドポイントが作成されます。 この関数により、GET 要求の URL name パラメーターに渡されたデータを使用して、補完プロンプトが動的に作成されます。 この動的プロンプトは、テキスト補完入力バインドにバインドされ、プロンプトに基づいた応答をモデルから返します。 モデルからの補完は HTTP 応答で返されます。

  1. 既存の HttpExample クラス ファイルに、次の using ステートメントを追加します。

    using Microsoft.Azure.Functions.Worker.Extensions.OpenAI.TextCompletion;
    
  2. 同じファイルに、whois という名前の新しい HTTP トリガー エンドポイントを定義する次のコードを追加します。

    [Function(nameof(WhoIs))]
    public IActionResult WhoIs([HttpTrigger(AuthorizationLevel.Function, Route = "whois/{name}")] HttpRequest req,
    [TextCompletionInput("Who is {name}?", Model = "%CHAT_MODEL_DEPLOYMENT_NAME%")] TextCompletionResponse response)
    {
        if(!String.IsNullOrEmpty(response.Content))
        {
            return new OkObjectResult(response.Content);
        }
        else
        {
            return new NotFoundObjectResult("Something went wrong.");
        }
    }
    
  1. pom.xml プロジェクト ファイルを更新して、この参照を properties コレクションに追加します。

    <azure-functions-java-library-openai>0.3.0-preview</azure-functions-java-library-openai>
    
  2. 同じファイル内で、この依存関係を dependencies コレクションに追加します。

    <dependency>
        <groupId>com.microsoft.azure.functions</groupId>
        <artifactId>azure-functions-java-library-openai</artifactId>
        <version>${azure-functions-java-library-openai}</version>
    </dependency>
    
  3. 既存の Function.java プロジェクト ファイルに、次の import ステートメントを追加します。

    import com.microsoft.azure.functions.openai.annotation.textcompletion.TextCompletion;
    import com.microsoft.azure.functions.openai.annotation.textcompletion.TextCompletionResponse;
    
  4. 同じファイルに、whois という名前の新しい HTTP トリガー エンドポイントを定義する次のコードを追加します。

    @FunctionName("WhoIs")
    public HttpResponseMessage whoIs(
        @HttpTrigger(
            name = "req", 
            methods = {HttpMethod.GET},
            authLevel = AuthorizationLevel.ANONYMOUS, 
            route = "whois/{name}") 
            HttpRequestMessage<Optional<String>> request,
        @BindingName("name") String name,
        @TextCompletion(prompt = "Who is {name}?", model = "%CHAT_MODEL_DEPLOYMENT_NAME%", name = "response") TextCompletionResponse response,
        final ExecutionContext context) {
        return request.createResponseBuilder(HttpStatus.OK)
            .header("Content-Type", "application/json")
            .body(response.getContent())
            .build();
    }
    
  1. Visual Studio Code で F1 キーを押し、コマンド パレットで「Azure Functions: Create Function...」と入力し、[HTTP トリガー] を選択し、関数名 (whois) を入力して Enter キーを押します。

  2. 新しい whois.js コード ファイルで、ファイルの内容を次のコードに置き換えます。

    const { app, input } = require("@azure/functions");
    
    // This OpenAI completion input requires a {name} binding value.
    const openAICompletionInput = input.generic({
        prompt: 'Who is {name}?',
        maxTokens: '100',
        type: 'textCompletion',
        model: '%CHAT_MODEL_DEPLOYMENT_NAME%'
    })
    
    app.http('whois', {
        methods: ['GET'],
        route: 'whois/{name}',
        authLevel: 'function',
        extraInputs: [openAICompletionInput],
        handler: async (_request, context) => {
            var response = context.extraInputs.get(openAICompletionInput)
            return { body: response.content.trim() }
        }
    });
    
  1. Visual Studio Code で F1 キーを押し、コマンド パレットで「Azure Functions: Create Function...」と入力し、[HTTP トリガー] を選択し、関数名 (whois) を入力して Enter キーを押します。

  2. 新しい whois.ts コード ファイルで、ファイルの内容を次のコードに置き換えます。

    import { app, input } from "@azure/functions";
    
    // This OpenAI completion input requires a {name} binding value.
    const openAICompletionInput = input.generic({
        prompt: 'Who is {name}?',
        maxTokens: '100',
        type: 'textCompletion',
        model: '%CHAT_MODEL_DEPLOYMENT_NAME%'
    })
    
    app.http('whois', {
        methods: ['GET'],
        route: 'whois/{name}',
        authLevel: 'function',
        extraInputs: [openAICompletionInput],
        handler: async (_request, context) => {
            var response: any = context.extraInputs.get(openAICompletionInput)
            return { body: response.content.trim() }
        }
    });
    
  1. 既存の function_app.py プロジェクト ファイルに、次の import ステートメントを追加します。

    import json
    
  2. 同じファイルに、whois という名前の新しい HTTP トリガー エンドポイントを定義する次のコードを追加します。

    @app.route(route="whois/{name}", methods=["GET"])
    @app.text_completion_input(arg_name="response", prompt="Who is {name}?", max_tokens="100", model = "%CHAT_MODEL_DEPLOYMENT_NAME%")
    def whois(req: func.HttpRequest, response: str) -> func.HttpResponse:
        response_json = json.loads(response)
        return func.HttpResponse(response_json["content"], status_code=200)
    
    
    @app.route(route="genericcompletion", methods=["POST"])
    @app.text_completion_input(arg_name="response", prompt="{Prompt}", model = "%CHAT_MODEL_DEPLOYMENT_NAME%")
    def genericcompletion(req: func.HttpRequest, response: str) -> func.HttpResponse:
        response_json = json.loads(response)
        return func.HttpResponse(response_json["content"], status_code=200)
    
  1. Visual Studio Code で F1 キーを押し、コマンド パレットに「Azure Functions: Create Function...」と入力し、[HTTP トリガー] を選択し、関数名 (whois) を入力し、[匿名] を選択して Enter キーを押します。

  2. 新しい whois/function.json コード ファイルを開き、その内容を次のコードに置き換えます。これにより、TextCompletionResponse 入力バインドの定義が追加されます。

    {
      "bindings": [
        {
          "authLevel": "function",
          "type": "httpTrigger",
          "direction": "in",
          "name": "Request",
          "route": "whois/{name}",
          "methods": [
            "get"
          ]
        },
        {
          "type": "http",
          "direction": "out",
          "name": "Response"
        },
        {
          "type": "textCompletion",
          "direction": "in",
          "name": "TextCompletionResponse",
          "prompt": "Who is {name}?",
          "maxTokens": "100",
          "model": "%CHAT_MODEL_DEPLOYMENT_NAME%"
        }
      ]
    }
    
  3. whois/run.ps1 コード ファイルの内容を次のコードに置き換えます。このコードは、入力バインド応答を返します。

    using namespace System.Net
    
    param($Request, $TriggerMetadata, $TextCompletionResponse)
    
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
            StatusCode = [HttpStatusCode]::OK
            Body       = $TextCompletionResponse.Content
        })
    

7.関数の実行

  1. Visual Studio Code で F1 キーを押し、コマンド パレットで「Azurite: Start」と入力し、Enter キーを押して Azurite Storage エミュレーターを起動します。

  2. F5 キーを押して関数アプリ プロジェクトと Core Tools をデバッグ モードで起動します。

  3. Core Tools を実行している状態で、whois エンドポイント関数に次の URL のように名前を含むパスで GET 要求を送信します。

    http://localhost:7071/api/whois/<NAME>

    <NAME> 文字列を、"Who is {name}?" プロンプトに渡したい値に置き換えます。 <NAME> は、Abraham%20Lincoln のような URL エンコードされた著名人の名前である必要があります。

    表示される応答は、Azure OpenAI モデルからのテキスト補完応答です。

  4. 応答が返されたら、Ctrl + C キーを押して Core Tools を停止します。

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

Azure では、"リソース" とは、関数アプリ、関数、ストレージ アカウントなどのことを指します。 これらは "リソース グループ" に分類されており、グループを削除することでグループ内のすべてのものを削除できます。

これらのクイックスタートを完了するためにリソースを作成しました。 アカウントの状態サービスの価格に応じて、これらのリソースの使用に対して課金される可能性があります。 リソースの必要がなくなった場合にそれらを削除する方法を、次に示します。

  1. Visual Studio Code で、F1 キーを押してコマンド パレットを開きます。 コマンド パレットで、Azure: Open in portal を検索して選択します。

  2. 関数アプリを選択し、Enter キーを押します。 その関数アプリのページが Azure portal で開きます。

  3. [概要] タブで、 [リソース グループ] の横にある名前付きリンクを選択します。

    関数アプリのページから削除するリソース グループを選択するスクリーンショット。

  4. [リソース グループ] ページで、含まれているリソースの一覧を確認し、削除するものであることを確認します。

  5. [リソース グループの削除] を選択し、指示に従います。

    削除には数分かかることがあります。 実行されると、通知が数秒間表示されます。 ページの上部にあるベルのアイコンを選択して、通知を表示することもできます。