次の方法で共有


チュートリアル: Microsoft セマンティック カーネルまたは Foundry エージェント サービス (Spring Boot) を使用して Azure App Service でエージェント Web アプリを構築する

このチュートリアルでは、既存のデータ ドリブン Spring Boot WebFlux CRUD アプリケーションにエージェント機能を追加する方法について説明します。 これは、Microsoft セマンティック カーネルと Foundry エージェント サービスを使用して行われます。

Web アプリケーションにショッピング、ホテル予約、データ管理などの便利な機能が既にある場合は、プラグイン (LangGraph の場合) または OpenAPI エンドポイント (Foundry Agent Service の場合) でそれらの機能をラップすることで、Web アプリケーションにエージェント機能を追加するのは比較的簡単です。 このチュートリアルでは、簡単な to-do リスト アプリから始めます。 最終的には、App Service アプリでエージェントを使用してタスクを作成、更新、管理できるようになります。

セマンティック カーネルと Foundry Agent Service の両方を使用すると、AI 駆動型機能を使用してエージェント Web アプリケーションを構築できます。 次の表に、いくつかの考慮事項とトレードオフを示します。

考慮事項 セマンティック カーネル ファウンドリー エージェント サービス
Performance 高速 (ローカルで実行) 低速 (マネージド、リモート サービス)
発達 完全なコード、最大制御 低いコード、迅速な統合
Testing コードでの手動/単体テスト クイック テスト用の組み込みプレイグラウンド
スケーラビリティ アプリで管理 Azure マネージド、自動スケーリング
セキュリティ ガードレール カスタム実装が必要 組み込みのコンテンツの安全性とモデレーション
アイデンティティ カスタム実装が必要 組み込みのエージェント ID と認証
Enterprise カスタム統合が必要 組み込みの Microsoft 365/Teams 展開と Microsoft 365 統合ツール呼び出し。

このチュートリアルでは、以下の内容を学習します。

  • セマンティック カーネルのプラグインに既存のアプリ機能を変換します。
  • セマンティック カーネル エージェントにプラグインを追加し、Web アプリで使用します。
  • 既存のアプリ機能を Foundry Agent Service の OpenAPI エンドポイントに変換します。
  • Web アプリで Foundry エージェントを呼び出します。
  • マネージド ID 接続に必要なアクセス許可を割り当てます。

Prerequisites

Codespaces を使用してサンプルを開く

開始する最も簡単な方法は、GitHub Codespaces を使用することです。GitHub Codespaces を使用すると、必要なすべてのツールがプレインストールされた完全な開発環境が提供されます。

GitHub Codespaces で開きます。

  1. https://github.com/Azure-Samples/app-service-agentic-semantic-kernel-javaにある GitHub リポジトリに移動します。

  2. [ コード ] ボタンを選択し、[ Codespaces ] タブを選択し、[ メインでコードスペースを作成] を選択します。

  3. Codespace が初期化されるまでしばらく待ちます。 準備ができたら、ブラウザーに完全に構成された開発環境が表示されます。

  4. アプリケーションをローカルで実行します。

    mvn spring-boot:run
    
  5. ポート 8080 で実行されているアプリケーションが表示されたら、[ブラウザーで開く] を選択し、いくつかのタスクを追加します。

エージェント コードを確認する

セマンティック カーネル エージェントは、ユーザーが新しいブラウザー セッションで最初のプロンプトを入力すると、 src/main/java/com/example/crudtaskswithagent/controller/AgentController.java で初期化されます。

初期化コードは、 SemanticKernelAgentService コンストラクター ( src/main/java/com/example/crudtaskswithagent/service/SemanticKernelAgentService.java 内) にあります。 初期化コードでは、次の処理が行われます。

  • チャット補完用のカーネルを作成します。
  • CRUD アプリケーションの機能をカプセル化するカーネル プラグインを追加します ( src/main/java/com/example/crudtaskswithagent/plugin/TaskCrudPlugin.java)。 プラグインの興味深い部分は、カーネルがプラグインをインテリジェントに呼び出すのに役立つメソッド宣言とDefineKernelFunctiondescriptionパラメーターのreturnType注釈です。
  • チャット完了エージェントを作成し、AI モデルが関数 (FunctionChoiceBehavior.auto(true)) を自動的に呼び出すように構成します。
  • チャット履歴を自動的に管理するエージェント スレッドを作成します。
        // Create OpenAI client
        OpenAIAsyncClient openAIClient = new OpenAIClientBuilder()
                .endpoint(endpoint)
                .credential(new DefaultAzureCredentialBuilder().build())
                .buildAsyncClient();
        
        // Create chat completion service
        OpenAIChatCompletion chatCompletion = OpenAIChatCompletion.builder()
                .withOpenAIAsyncClient(openAIClient)
                .withModelId(deployment)
                .build();
        
        // Create kernel plugin from the task plugin
        KernelPlugin kernelPlugin = KernelPluginFactory.createFromObject(taskCrudPlugin, "TaskPlugin");
        
        // Create kernel with TaskCrudPlugin and chat completion service
        Kernel kernel = Kernel.builder()
                .withAIService(OpenAIChatCompletion.class, chatCompletion)
                .withPlugin(kernelPlugin)
                .build();
        
        // Use automatic function calling
        InvocationContext invocationContext = InvocationContext.builder()
            .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true))
            .build();

        // Create ChatCompletionAgent
        configuredAgent = ChatCompletionAgent.builder()
                .withKernel(kernel)
                .withName("TaskAgent")
                .withInvocationContext(invocationContext)
                .withInstructions(
                    "You are an agent that manages tasks using CRUD operations. " +
                    "Use the TaskCrudPlugin functions to create, read, update, and delete tasks. " +
                    "Always call the appropriate plugin function for any task management request. " +
                    "Don't try to handle any requests that are not related to task management."
                )
                .build();
        
    } catch (Exception e) {
        logger.error("Error initializing SemanticKernelAgentService: {}", e.getMessage(), e);
    }
}

this.agent = configuredAgent;

// Initialize thread for this instance
this.thread = ChatHistoryAgentThread.builder().build();

プロンプトが受信されるたびに、サーバー コードは ChatCompletionAgent.invokeAsync() を使用して、ユーザー プロンプトとエージェント スレッドを使用してエージェントを呼び出します。 エージェント スレッドはチャット履歴を追跡します。

// Use the agent to process the message with automatic function calling
return agent.invokeAsync(userMessageContent, thread)
        .<String>map(responses -> {
            
            if (responses != null && !responses.isEmpty()) {
                // Process all responses and concatenate them
                StringBuilder combinedResult = new StringBuilder();
                
                for (int i = 0; i < responses.size(); i++) {
                    var response = responses.get(i);
                    
                    // Update thread with the last response thread (as per Microsoft docs)
                    if (i == responses.size() - 1) {
                        var responseThread = response.getThread();
                        if (responseThread instanceof ChatHistoryAgentThread) {
                            this.thread = (ChatHistoryAgentThread) responseThread;
                        }
                    }
                    
                    // Get response content
                    ChatMessageContent<?> content = response.getMessage();
                    String responseContent = content != null ? content.getContent() : "";
                    
                    if (!responseContent.isEmpty()) {
                        if (combinedResult.length() > 0) {
                            combinedResult.append("\n\n"); // Separate multiple responses
                        }
                        combinedResult.append(responseContent);
                    }
                }
                
                String result = combinedResult.toString();
                if (result.isEmpty()) {
                    result = "No content returned from agent.";
                }
                return result;
            } else {
                return "I'm sorry, I couldn't process your request. Please try again.";
            }
        })
        .onErrorResume(throwable -> {
            logger.error("Error in processMessage: {}", throwable.getMessage(), throwable);
            return Mono.just("Error processing message: " + throwable.getMessage());
        });

サンプル アプリケーションをデプロイする

サンプル リポジトリには、マネージド ID を使用して App Service アプリを作成し、サンプル アプリケーションをデプロイする Azure Developer CLI (AZD) テンプレートが含まれています。

  1. ターミナルで、Azure Developer CLI を使用して Azure にログインします。

    azd auth login
    

    手順に従って認証プロセスを完了します。

  2. AZD テンプレートを使用して Azure App Service アプリをデプロイします。

    azd up
    
  3. メッセージが表示されたら、次の回答を入力します。

    Question Answer
    新しい環境名を入力します。 一意の名前を入力します。
    使用する Azure サブスクリプションを選択します。 サブスクリプションを選択します。
    使用するリソース グループを選択します。 [Create a new resource group]\(新しいリソース グループの作成\) を選択します。
    リソース グループを作成する場所を選択します。 [スウェーデン中部] を選択します。
    新しいリソース グループの名前を入力します。 Enter キーを押します
  4. AZD の出力で、アプリの URL を見つけ、ブラウザーでそこに移動します。 URL は、AZD の出力では次のようになります。

     Deploying services (azd deploy)
    
       (✓) Done: Deploying service web
       - Endpoint: <URL>
     
  5. 自動生成された OpenAPI スキーマを https://....azurewebsites.net/api/schema パスで開きます。 このスキーマは後で必要になります。

    これで、システム割り当てマネージド ID を持つ App Service アプリが作成されました。

Microsoft Foundry リソースを作成して構成する

  1. Foundry ポータルで、上部の [New Foundry] ラジオ ボタンがアクティブに設定されていることを確認し、プロジェクトを作成します。

  2. 任意のモデルをデプロイします ( Microsoft Foundry クイック スタート: リソースの作成を参照)。

  3. モデルプレイグラウンドの上部から、モデル名をコピーします。

  4. Azure OpenAI エンドポイントを取得する最も簡単な方法は、まだクラシック ポータルから行う方法です。 New Foundry のラジオ ボタンと Azure OpenAI を順に選択し、後で使用するために Azure OpenAI エンドポイント の URL をコピーします。

    Foundry ポータルで OpenAI エンドポイントと Foundry プロジェクト エンドポイントをコピーする方法を示すスクリーンショット。

必要なアクセス許可を割り当てる

  1. 新しい Foundry ポータルの上部メニューから [ 操作] を選択し、[ 管理者] を選択します。Foundry プロジェクトの行には、2 つのリンクが表示されます。 [名前] 列の 1 つは Foundry プロジェクト リソースで、[親リソース] 列のリソースは Foundry リソースです。

    Foundry リソースまたは Foundry プロジェクト リソースにすばやく移動する方法を示すスクリーンショット。

  2. 親リソースで Foundry リソース を選択し、 Azure portal で [このリソースの管理] を選択します。 Azure portal から、デプロイされた Web アプリにリソースのロールベースのアクセス権を割り当てることができます。

  3. App Service アプリのマネージド ID に次のロールを追加します。

    ターゲット リソース 必要なロール 次の場合に必要です
    鋳造所 Cognitive Services OpenAI ユーザー Microsoft Agent Framework のチャット完了サービス。

    手順については、「Azure portal を使用して Azure ロールを割り当てる」を参照してください。

サンプル アプリケーションで接続変数を構成する

  1. src/main/resources/application.properties を開きます。 Foundry ポータルから前にコピーした値を使用して、次の変数を構成します。

    Variable Description
    azure.openai.endpoint Azure OpenAI エンドポイント (クラシック Foundry ポータルからコピー)。
    azure.openai.deployment デプロイのモデル名(新しい Foundry ポータルのモデルプレイグラウンドからコピー)。

    Note

    チュートリアルをシンプルにするために、App Service のアプリ設定で上書きするのではなく 、.env でこれらの変数を使用します。

    Note

    チュートリアルをシンプルにするために、これらの変数は、App Service のアプリ設定で上書きするのではなく 、src/main/resources/application.properties で使用します。

  2. Azure CLI を使用して Azure にサインインします。

    az login
    

    これにより、サンプル コード内の Azure ID クライアント ライブラリは、ログインしているユーザーの認証トークンを受け取ることができます。 前にこのユーザーに必要なロールを追加したことを思い出してください。

  3. アプリケーションをローカルで実行します。

    mvn spring-boot:run
    
  4. ポート 8080 で実行されているアプリケーションが表示されたら、[ブラウザーで開く] を選択します。

  5. チャット インターフェイスを試してみてください。 応答が返された場合、アプリケーションは Microsoft Foundry リソースに正常に接続されています。

  6. GitHub コードスペースに戻り、アプリの変更をデプロイします。

    azd up
    
  7. デプロイされたアプリケーションにもう一度移動し、チャット エージェントをテストします。

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

アプリケーションの使用が完了したら、App Service リソースを削除して、追加のコストが発生しないようにすることができます。

azd down --purge

AZD テンプレートには Microsoft Foundry リソースが含まれていないため、必要に応じて手動で削除する必要があります。

その他のリソース