Compartilhar via


Tutorial: Criar um chatbot com o Serviço de Aplicativo do Azure e o Azure OpenAI (Spring Boot)

Neste tutorial, você criará um aplicativo de IA inteligente integrando o Azure OpenAI a um aplicativo Java Spring Boot e implantando-o no Serviço de Aplicativo do Azure. Você criará um controlador spring boot que envia uma consulta ao Azure OpenAI e envia a resposta para o navegador.

Dica

Embora este tutorial use o Spring Boot, os principais conceitos de criação de um aplicativo de chat com o Azure OpenAI se aplicam a qualquer aplicativo Web Java. Se você estiver usando uma opção de hospedagem diferente no Serviço de Aplicativo, como Tomcat ou JBoss EAP, poderá adaptar os padrões de autenticação e o uso do SDK do Azure mostrados aqui para sua estrutura preferida.

Captura de tela mostrando um chatbot em execução no Serviço de Aplicativo do Azure.

Neste tutorial, você aprenderá como:

  • Crie um recurso do Azure OpenAI e implante um modelo de linguagem.
  • Crie um aplicativo Spring Boot que se conecte ao Azure OpenAI.
  • Use a injeção de dependência para configurar o cliente do Azure OpenAI.
  • Implante o aplicativo no Serviço de Aplicativo do Azure.
  • Implemente a autenticação segura sem senha no ambiente de desenvolvimento e no Azure.

Pré-requisitos

1. Criar um recurso do Azure OpenAI

Nesta seção, você usará os Codespaces do GitHub para criar um recurso do Azure OpenAI com a CLI do Azure.

  1. Acesse os Codespaces do GitHub e entre com sua conta do GitHub.

  2. Localize o modelo em branco pelo GitHub e selecione Usar este modelo para criar um novo Codespace em branco.

  3. No terminal do Codespace, instale a CLI do Azure:

    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
    
  4. Entre na sua conta do Azure:

    az login
    

    Siga as instruções no terminal para autenticar.

  5. Defina variáveis de ambiente para o nome do grupo de recursos, o nome do serviço do Azure OpenAI e a localização:

    export RESOURCE_GROUP="<group-name>"
    export OPENAI_SERVICE_NAME="<azure-openai-name>"
    export APPSERVICE_NAME="<app-name>"
    export LOCATION="eastus2"
    

    Importante

    A região é crítica, pois está vinculada à disponibilidade regional do modelo escolhido. A disponibilidade do modelo e a disponibilidade do tipo de implantação variam de região para região. Este tutorial usa gpt-4o-mini, que está disponível em eastus2 no tipo de implantação Standard. Se você implantar em uma região diferente, esse modelo pode não estar disponível ou pode exigir uma camada diferente. Antes de alterar as regiões, consulte a tabela de resumo do modelo e a disponibilidade da região para verificar o suporte ao modelo em sua região preferida.

  6. Crie um grupo de recursos e um recurso do Azure OpenAI com um domínio personalizado e adicione um modelo gpt-4o-mini:

    # Resource group
    az group create --name $RESOURCE_GROUP --location $LOCATION
    # Azure OpenAI resource
    az cognitiveservices account create \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --location $LOCATION \
      --custom-domain $OPENAI_SERVICE_NAME \
      --kind OpenAI \
      --sku s0
    # gpt-4o-mini model
    az cognitiveservices account deployment create \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --deployment-name gpt-4o-mini \
      --model-name gpt-4o-mini \
      --model-version 2024-07-18 \
      --model-format OpenAI \
      --sku-name Standard \
      --sku-capacity 1
    # Cognitive Services OpenAI User role that lets the signed in Azure user to read models from Azure OpenAI
    az role assignment create \
      --assignee $(az ad signed-in-user show --query id -o tsv) \
      --role "Cognitive Services OpenAI User" \
      --scope /subscriptions/$(az account show --query id -o tsv)/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.CognitiveServices/accounts/$OPENAI_SERVICE_NAME
    

Agora que você tem um recurso do Azure OpenAI, criará um aplicativo Web para interagir com ele.

2. Criar e configurar um aplicativo web Spring Boot

  1. No terminal do Codespace, clone o exemplo REST do Spring Boot no workspace e tente executá-lo pela primeira vez.

    git clone https://github.com/rd-1-2022/rest-service .
    mvn spring-boot:run
    

    Você deve ver uma notificação nos Codespaces do GitHub indicando que o aplicativo está disponível em uma porta específica. Selecione Abrir no navegador para iniciar o aplicativo em uma nova guia do navegador. Quando você vê a página de erros do rótulo branco, o aplicativo Spring Boot está funcionando.

  2. De volta ao terminal do Codespace, interrompa o aplicativo com Ctrl+C.

  3. Abra pom.xml e adicione as seguintes dependências:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-ai-openai</artifactId>
        <version>1.0.0-beta.16</version>
    </dependency>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-core</artifactId>
        <version>1.55.3</version>
    </dependency>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-identity</artifactId>
        <version>1.16.0</version>
        <scope>compile</scope>
    </dependency>
    
  4. No mesmo diretório que Application.java (src/main/java/com/example/restservice) adicione um arquivo Java chamado ChatController.java e copie o seguinte conteúdo para ele:

    package com.example.restservice;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import com.azure.ai.openai.OpenAIAsyncClient;
    import com.azure.ai.openai.models.ChatChoice;
    import com.azure.ai.openai.models.ChatCompletionsOptions;
    import com.azure.ai.openai.models.ChatRequestMessage;
    import com.azure.ai.openai.models.ChatRequestUserMessage;
    import com.azure.ai.openai.models.ChatResponseMessage;
    import com.azure.core.credential.TokenCredential;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    
    @Configuration
    class AzureConfig {
        // Reads the endpoint from environment variable AZURE_OPENAI_ENDPOINT
        @Value("${azure.openai.endpoint}")
        private String openAiEndpoint;
    
        // Provides a credential for local dev and production
        @Bean
        public TokenCredential tokenCredential() {
            return new DefaultAzureCredentialBuilder().build();
        }
    
        // Configures the OpenAIAsyncClient bean
        @Bean
        public OpenAIAsyncClient openAIClient(TokenCredential tokenCredential) {
            return new com.azure.ai.openai.OpenAIClientBuilder()
                    .endpoint(openAiEndpoint)
                    .credential(tokenCredential)
                    .buildAsyncClient();
        }
    }
    
    @Controller
    public class ChatController {
        private final OpenAIAsyncClient openAIClient;
    
        // Inject the OpenAIAsyncClient bean
        public ChatController(OpenAIAsyncClient openAIClient) {
            this.openAIClient = openAIClient;
        }
    
        @RequestMapping(value = "/", method = RequestMethod.GET)
        public String chatFormOrWithMessage(Model model, @RequestParam(value = "userMessage", required = false) String userMessage) {
            String aiResponse = null;
            if (userMessage != null && !userMessage.isBlank()) {
    
                // Create a list of chat messages
                List<ChatRequestMessage> chatMessages = new ArrayList<>();
                chatMessages.add(new ChatRequestUserMessage(userMessage));
    
                // Send the chat completion request
                String deploymentName = "gpt-4o-mini";
                StringBuilder serverResponse = new StringBuilder();
                var chatCompletions = openAIClient.getChatCompletions(
                    deploymentName, 
                    new ChatCompletionsOptions(chatMessages)
                ).block();
                if (chatCompletions != null) {
                    for (ChatChoice choice : chatCompletions.getChoices()) {
                        ChatResponseMessage message = choice.getMessage();
                        serverResponse.append(message.getContent());
                    }
                }
                aiResponse = serverResponse.toString();
            }
            model.addAttribute("aiResponse", aiResponse);
            return "chat";
        }
    }
    

    Dica

    Para minimizar os arquivos neste tutorial, o código combina o Spring @Configuration e @Controller as classes em um arquivo. Em produção, você normalmente separaria a configuração e a lógica de negócios para facilitar a manutenção.

  5. Em src/main/resources, crie um diretório de modelos e adicione um chat.html com o seguinte conteúdo para a interface de chat:

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Azure OpenAI Chat</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
    <div class="container py-4">
        <h2 class="mb-4">Azure OpenAI Chat</h2>
        <form action="/" method="get" class="d-flex mb-3">
            <input name="userMessage" class="form-control me-2" type="text" placeholder="Type your message..." autocomplete="off" required />
            <button class="btn btn-primary" type="submit">Send</button>
        </form>
        <div class="mb-3">
            <div th:if="${aiResponse}" class="alert alert-info">AI: <span th:text="${aiResponse}"></span></div>
        </div>
    </div>
    </body>
    </html>
    
  6. No terminal, recupere o ponto de extremidade do OpenAI:

    az cognitiveservices account show \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.endpoint \
      --output tsv
    
  7. Execute o aplicativo novamente adicionando AZURE_OPENAI_ENDPOINT com seu valor da saída da CLI:

    AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> mvn spring-boot:run
    
  8. Selecione Abrir no navegador para iniciar o aplicativo em uma nova guia do navegador.

  9. Digite uma mensagem na caixa de texto e selecione Enviar e dê ao aplicativo alguns segundos para responder com a mensagem do Azure OpenAI.

O aplicativo usa DefaultAzureCredential, que usa automaticamente o usuário conectado da CLI do Azure para autenticação de token. Posteriormente neste tutorial, você implantará seu aplicativo Web no Serviço de Aplicativo do Azure e o configurará para se conectar com segurança ao recurso do Azure OpenAI usando a identidade gerenciada. O mesmo DefaultAzureCredential em seu código pode detectar a identidade gerenciada e usá-la para autenticação. Nenhum código extra é necessário.

3. Implantar no Serviço de Aplicativo do Azure e configurar a conexão OpenAI

Agora que seu aplicativo funciona localmente, vamos implantá-lo no Serviço de Aplicativo do Azure e configurar uma conexão de serviço com o Azure OpenAI usando a identidade gerenciada.

  1. Crie um pacote de implantação com o Maven.

    mvn clean package
    
  2. Primeiro, implante seu aplicativo no Serviço de Aplicativo do Azure usando o comando az webapp upda CLI do Azure. Esse comando cria um novo aplicativo Web e implanta seu código nele:

    az webapp up \
      --resource-group $RESOURCE_GROUP \
      --location $LOCATION \
      --name $APPSERVICE_NAME \
      --plan $APPSERVICE_NAME \
      --sku B1 \
      --runtime "JAVA:21" \
      --os-type Linux \
      --track-status false
    

    Esse comando pode levar alguns minutos para ser concluído. Ele cria um novo aplicativo Web no mesmo grupo de recursos que o recurso OpenAI.

  3. Depois que o aplicativo for implantado, crie uma conexão de serviço entre seu aplicativo Web e o recurso do Azure OpenAI usando a identidade gerenciada:

    az webapp connection create cognitiveservices \
      --resource-group $RESOURCE_GROUP \
      --name $APPSERVICE_NAME \
      --target-resource-group $RESOURCE_GROUP \
      --account $OPENAI_SERVICE_NAME \
      --system-identity
    

    Esse comando cria uma conexão entre seu aplicativo Web e o recurso do Azure OpenAI:

    • Gerando identidade gerenciada atribuída pelo sistema para o aplicativo Web.
    • Adicionando a função de Colaborador de OpenAI dos Serviços Cognitivos à identidade gerenciada para o recurso do Azure OpenAI.
    • Adicionando a configuração de aplicativo AZURE_OPENAI_ENDPOINT ao seu aplicativo web.
  4. Abra o aplicativo Web implantado no navegador.

    az webapp browse
    
  5. Digite uma mensagem na caixa de texto e selecione "Enviar e dê ao aplicativo alguns segundos para responder com a mensagem do Azure OpenAI.

    Captura de tela mostrando um chatbot em execução no Serviço de Aplicativo do Azure.

Seu aplicativo agora está implantado e conectado ao Azure OpenAI com identidade gerenciada. Observe que ele está acessando a configuração do aplicativo AZURE_OPENAI_ENDPOINT por meio da injeção de @Configuration.

Perguntas frequentes

Por que o exemplo usa @Configuration e o spring beans para o cliente OpenAI?

Usar um Spring bean para OpenAIAsyncClient garante que:

  • Todas as propriedades de configuração (como o ponto de extremidade) são carregadas e injetadas pelo Spring.
  • A credencial e o cliente são criados depois que o contexto do aplicativo é totalmente inicializado.
  • A injeção de dependência é usada, sendo o padrão mais robusto em aplicativos Spring.

O cliente assíncrono é mais robusto, especialmente ao usar DefaultAzureCredential com a autenticação da CLI do Azure. O OpenAIClient síncrono pode enfrentar problemas na obtenção de tokens em alguns cenários de desenvolvimento local. Usar o cliente assíncrono evita esses problemas e é a abordagem recomendada.


E se eu quiser me conectar ao OpenAI em vez do Azure OpenAI?

Para se conectar ao OpenAI, use o seguinte código:

OpenAIClient client = new OpenAIClientBuilder()
    .credential(new KeyCredential(<openai-api-key>))
    .buildClient();

Para obter mais informações, consulte a autenticação da API openai.

Ao trabalhar com segredos de conexão no Serviço de Aplicativo, você deve usar referências do Key Vault em vez de armazenar segredos diretamente em sua base de código. Isso garante que as informações confidenciais permaneçam seguras e sejam gerenciadas centralmente.


Posso me conectar ao OpenAI do Azure com uma chave de API?

Sim, você pode se conectar ao Azure OpenAI usando uma chave de API em vez de uma identidade gerenciada. Essa abordagem é compatível com os SDKs do Azure OpenAI e o Kernel Semântico.

Ao trabalhar com segredos de conexão no Serviço de Aplicativo, você deve usar referências do Key Vault em vez de armazenar segredos diretamente em sua base de código. Isso garante que as informações confidenciais permaneçam seguras e sejam gerenciadas centralmente.


Como o DefaultAzureCredential funciona neste tutorial?

O DefaultAzureCredential simplifica a autenticação selecionando automaticamente o melhor método de autenticação disponível.

  • Durante o desenvolvimento local: depois de executar az login, ele usa as credenciais da CLI local do Azure.
  • Quando implantado no Serviço de Aplicativo do Azure: ele usa a identidade gerenciada do aplicativo para autenticação segura e sem senha.

Essa abordagem permite que seu código seja executado de forma segura e direta em ambientes locais e de nuvem sem modificação.

Próximas etapas