Руководство по созданию агентного веб-приложения в Службе приложений Azure с помощью семантического ядра Майкрософт или службы агента Foundry (Spring Boot)

В этом руководстве показано, как добавить агентическую возможность в существующее приложение Spring Boot WebFlux CRUD на основе данных. Это достигается с помощью Microsoft Semantic Kernel и службы агента Foundry Agent.

Если веб-приложение уже имеет полезные функции, такие как покупки, бронирование отелей или управление данными, это относительно просто добавить функции агента в веб-приложение, упаковав эти функции в подключаемый модуль (для LangGraph) или как конечную точку OpenAPI (для службы агента Foundry). В этом руководстве вы начнёте с простого приложения для списков to-do. К концу вы сможете создавать, обновлять и управлять задачами с агентом в приложении службы приложений.

Семантический ядро и служба агента Foundry позволяют создавать агентные веб-приложения с возможностями на основе ИИ. В следующей таблице показаны некоторые рекомендации и компромиссы.

Рассмотрение Семантическое ядро Служба агента Foundry
Performance Быстро (выполняется локально) Медленнее (управляемая, удаленная служба)
Развитие Полный код, максимальный контроль Низкий код, быстрая интеграция
Testing Тесты вручную и модульные тесты в коде Встроенная площадка для быстрого тестирования
Масштабируемость App-managed Под управлением Azure, с автоматическим масштабированием
Меры безопасности Требуется настраиваемая реализация Встроенная безопасность содержимого и модерация
Идентичность Требуется настраиваемая реализация Встроенный идентификатор агента и проверка подлинности
Предприятие Требуется настраиваемая интеграция Встроенное развертывание Microsoft 365/Teams и вызов интегрированных инструментов Microsoft 365.

В этом руководстве вы узнаете, как:

  • Преобразуйте существующую функциональность приложения в плагин для Семантического Ядра.
  • Добавьте подключаемый модуль в агент семантического ядра и используйте его в веб-приложении.
  • Преобразуйте существующую функциональность приложения в конечную точку OpenAPI для службы Foundry Agent.
  • Вызовите агента Foundry в веб-приложении.
  • Назначьте необходимые разрешения для подключения к системе с управляемыми удостоверениями.

Prerequisites

Открытие примера с помощью codespaces

Проще всего приступить к работе с помощью GitHub Codespaces, который предоставляет полную среду разработки со всеми необходимыми средствами, предварительно установленными.

Открыть в GitHub Codespaces.

  1. Перейдите в репозиторий GitHub по адресу https://github.com/Azure-Samples/app-service-agentic-semantic-kernel-java.

  2. Нажмите кнопку "Код" , перейдите на вкладку "Пространства кода" и выберите "Создать пространство кода" на главном.

  3. Подождите несколько минут, пока пространство кода инициализируется. Когда вы будете готовы, вы увидите полностью настроенную среду разработки в браузере.

  4. Запустите приложение локально:

    mvn spring-boot:run
    
  5. Когда вы увидите Ваше приложение, запущенное на порту 8080, доступно, выберите Открыть в браузере и добавьте несколько задач.

Проверка кода агента

Агент семантического ядра инициализирован в src/main/java/com/example/crudtaskswithagent/controller/AgentController.java, когда пользователь вводит первый запрос в новом сеансе браузера.

Код инициализации можно найти в конструкторе SemanticKernelAgentServicesrc/main/java/com/example/crudtaskswithagent/service/SemanticKernelAgentService.java). Код инициализации выполняет следующие действия:

  • Создает ядро с завершением чата.
  • Добавляет плагин ядра, который инкапсулирует функциональность приложения CRUD (в src/main/java/com/example/crudtaskswithagent/plugin/TaskCrudPlugin.java). Интересные части подключаемого модуля — это аннотации в объявлениях метода и параметры DefineKernelFunction и description, которые помогают ядру умно вызывать подключаемый модуль.
  • Создает агент завершения чата и настраивает его, чтобы модель ИИ автоматически вызывала функции (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());
        });

Развертывание примера приложения

Репозиторий с примером содержит шаблон для Azure Developer CLI (AZD), который создает приложение службы приложений Azure с управляемым удостоверением и развертывает образец приложения.

  1. В терминале войдите в Azure с помощью Интерфейса командной строки разработчика Azure:

    azd auth login
    

    Следуйте инструкциям, чтобы завершить процесс проверки подлинности.

  2. Разверните приложение Службы приложений Azure с помощью шаблона AZD:

    azd up
    
  3. При появлении запроса укажите следующие ответы:

    Question Answer
    Введите новое имя среды: Введите уникальное имя.
    Выберите подписку Azure для использования: Выберите подписку.
    Выберите группу ресурсов для использования: Выберите команду Создать группу ресурсов.
    Выберите расположение для создания группы ресурсов в: Выберите Швецию Центральную.
    Введите имя новой группы ресурсов: Нажмите Enter.
  4. В выводе AZD найдите URL вашего приложения и откройте его в браузере. URL-адрес выглядит следующим образом в выходных данных AZD:

     Deploying services (azd deploy)
    
       (✓) Done: Deploying service web
       - Endpoint: <URL>
     
  5. Откройте автоматически созданную схему OpenAPI по https://....azurewebsites.net/api/schema пути. Вам потребуется эта схема позже.

    Теперь у вас есть приложение службы приложений с управляемым удостоверением, назначаемое системой.

Создание и настройка ресурса Microsoft Foundry

  1. На портале Foundry убедитесь, что верхний переключатель New Foundry установлен как "Активный," и создайте проект.

  2. Разверните модель выбранного варианта (см. краткое руководство по Microsoft Foundry: создание ресурсов).

  3. В верхней части игровой площадки модели скопируйте имя модели.

  4. Самый простой способ получить конечную точку Azure OpenAI по-прежнему с классического портала. Нажмите переключатель New Foundry, затем переключатель Azure OpenAI, и скопируйте URL-адрес в в конечной точке Azure OpenAI на потом.

    Скриншот, на котором показано, как скопировать конечную точку OpenAI и конечную точку проекта Foundry в портале.

Назначьте необходимые разрешения

  1. В верхнем меню нового портала Foundry выберите "Работа", а затем выберите "Администратор". В строке проекта Foundry вы увидите две ссылки. Тот, что в столбце Name, — это ресурс проекта Foundry, а тот, что в столбце Parent resource, — ресурс Foundry.

    Снимок экрана, показывающий, как быстро перейти к ресурсу литейного завода или ресурсу проекта литейного завода.

  2. Выберите ресурс Foundry в родительском ресурсе и выберите "Управление этим ресурсом" на портале Azure. С портала Azure можно назначить роль-ориентированный доступ для управления развернутым веб-приложением и его ресурсами.

  3. Добавьте следующую роль для управляемой идентификации приложения службы приложений:

    Целевой ресурс Требуемая роль Требуется для
    Литейный завод Пользователь когнитивных сервисов OpenAI Служба завершения чата в Microsoft Agent Framework.

    Инструкции см. в разделе Назначение ролей Azure с помощью портала Azure.

Настройка переменных подключения в примере приложения

  1. Откройте src/main/resources/application.properties. Используя значения, скопированные ранее на портале Foundry, настройте следующие переменные:

    Variable Description
    azure.openai.endpoint Конечная точка Azure OpenAI (скопирована из классического портала Foundry).
    azure.openai.deployment Имя модели в развертывании (скопированное из тестовой среды модели на новом портале Foundry).

    Note

    Чтобы упростить руководство, вы будете использовать эти переменные в .env, вместо того чтобы перезаписывать их с настройками приложений в App Service.

    Note

    Для упрощения руководства, вы будете использовать эти переменные в src/main/resources/application.properties вместо их перезаписи с использованием параметров приложения в App Service.

  2. Войдите в Azure с помощью Azure CLI:

    az login
    

    Это позволяет клиентской библиотеке удостоверений Azure в примере кода получать маркер проверки подлинности для пользователя, вошедшего в систему. Помните, что вы добавили необходимую роль для этого пользователя ранее.

  3. Запустите приложение локально:

    mvn spring-boot:run
    
  4. Когда вы увидите ваше приложение, работающее на порту 8080, доступно, выберите "Открыть в браузере".

  5. Попробуйте использовать интерфейс чата. Если вы получите ответ, приложение успешно подключается к ресурсу Microsoft Foundry.

  6. Вернитесь в пространство кода GitHub, разверните изменения приложения.

    azd up
    
  7. Перейдите к развернутому приложению еще раз и протестируйте агенты чата.

Очистите ресурсы

После завершения работы с приложением можно удалить ресурсы службы приложений, чтобы избежать дополнительных затрат:

azd down --purge

Так как шаблон AZD не включает ресурсы Microsoft Foundry, их необходимо удалить вручную, если вы хотите.

Дополнительные ресурсы