Kurz: Vytvoření chatovacího robota se službou Azure App Service a Azure OpenAI (Spring Boot)

V tomto kurzu vytvoříte inteligentní aplikaci AI integrací Azure OpenAI s aplikací Java Spring Boot a jejím nasazením do Služby Azure App Service. Vytvoříte kontroler Spring Boot, který odešle dotaz do Azure OpenAI a odešle odpověď do prohlížeče.

Návod

I když tento kurz používá Spring Boot, základní koncepty vytváření chatovací aplikace pomocí Azure OpenAI platí pro libovolnou webovou aplikaci v Javě. Pokud ve službě App Service používáte jinou možnost hostování, jako je Tomcat nebo JBoss EAP, můžete přizpůsobit vzory ověřování a využití sady Azure SDK, které vidíte tady, podle preferované architektury.

Snímek obrazovky s chatovacím robotem spuštěným ve službě Azure App Service

V tomto návodu se naučíte, jak:

  • Vytvořte prostředek Azure OpenAI a nasaďte jazykový model.
  • Vytvořte aplikaci Spring Boot, která se připojuje k Azure OpenAI.
  • Pomocí injektáže závislostí nakonfigurujte klienta Azure OpenAI.
  • Nasaďte aplikaci do služby Azure App Service.
  • Implementujte zabezpečené ověřování bez hesla jak ve vývojovém prostředí, tak v Azure.

Požadavky

1. Vytvoření prostředku Azure OpenAI

V této části pomocí Azure CLI v GitHub Codespaces vytvoříte prostředek Azure OpenAI.

  1. Přihlaste se k GitHub Codespaces pomocí svého účtu GitHub.

  2. Výběrem možnosti Použít tuto šablonu na dlaždici Prázdné vytvoříte nový prázdný prostor kódu.

  3. V terminálu Codespace nainstalujte Azure CLI.

    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
    
  4. Přihlaste se ke svému účtu Azure.

    az login
    

    Proveďte ověření podle pokynů v terminálu.

  5. Nastavte proměnné prostředí zadáním názvů pro vaši skupinu prostředků a službu Azure OpenAI a nastavením příslušné oblasti Azure jako umístění.

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

    Důležité

    Umístění je svázané s regionální dostupností zvoleného modelu. Dostupnost typu modelu a nasazení se liší mezi oblastmi Azure a fakturačními úrovněmi. Tento kurz používá gpt-4o-mini, který je v několika oblastech dostupný jako součást standardního typu nasazení.

    Než vyberete umístění, projděte si tabulku dostupnosti souhrnu modelu a oblasti a ověřte podporu modelu ve vaší upřednostňované oblasti.

  6. Vytvořte skupinu prostředků a prostředek Azure OpenAI s vlastní doménou a pak přidejte gpt-4o-mini model:

    # 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 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
    

Teď, když máte prostředek Azure OpenAI, můžete vytvořit webovou aplikaci, která s ním bude pracovat.

2. Vytvoření a nastavení webové aplikace Spring Boot

  1. V terminálu Codespace naklonujte ukázku Spring Boot REST do pracovního prostoru a poprvé spusťte.

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

    V GitHub Codespaces byste měli vidět oznámení, že aplikace je dostupná na konkrétním portu. Výběrem možnosti Otevřít v prohlížeči spusťte aplikaci na nové kartě prohlížeče. Když se zobrazí chybová stránka s bílým popiskem, aplikace Spring Boot funguje.

  2. Zpátky v terminálu Codespace zastavte aplikaci pomocí Ctrl+C.

  3. Otevřete pom.xml a přidejte následující závislosti:

    <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. Do stejného adresáře jako Application.java (src/main/java/com/example/restservice) přidejte soubor Java s názvem ChatController.java a zkopírujte do něj následující obsah:

    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";
        }
    }
    

    Návod

    Aby se minimalizovaly soubory v tomto kurzu, kód kombinuje Spring @Configuration a @Controller třídy v jednom souboru. V produkčním prostředí byste normálně oddělily konfiguraci a obchodní logiku pro zajištění udržovatelnosti.

  5. V části src/main/resources vytvořte adresář šablon a přidejte chat.html s následujícím obsahem pro rozhraní chatu:

    <!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. V terminálu získejte koncový bod OpenAI.

    az cognitiveservices account show \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.endpoint \
      --output tsv
    
  7. Spusťte aplikaci znovu tak, že přidáte AZURE_OPENAI_ENDPOINT její hodnotu z výstupu rozhraní příkazového řádku:

    AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> mvn spring-boot:run
    
  8. Výběrem možnosti Otevřít v prohlížeči spusťte aplikaci na nové kartě prohlížeče.

  9. Do textového pole zadejte zprávu a vyberte Odeslat a dejte aplikaci několik sekund, aby na zprávu odpověděla z Azure OpenAI.

Aplikace používá defaultAzureCredential, který k ověřování tokenů automaticky používá přihlášeného uživatele Azure CLI. Později v tomto kurzu nasadíte webovou aplikaci do služby Azure App Service a nakonfigurujete ji tak, aby se bezpečně připojila k prostředku Azure OpenAI pomocí spravované identity. Ve vašem kódu může stejná DefaultAzureCredential detekovat spravovanou identitu a použít ji k ověřování. Není potřeba žádný další kód.

3. Nasazení do služby Azure App Service a konfigurace připojení OpenAI

Teď, když vaše aplikace funguje místně, ji nasadím do služby Azure App Service a nastavíme připojení služby k Azure OpenAI pomocí spravované identity.

  1. Vytvořte plán Linux App Service ve stejné skupině zdrojů jako váš OpenAI zdroj a poté vytvořte webovou aplikaci pro Java 21.

    az appservice plan create \
      --resource-group $RESOURCE_GROUP \
      --location $LOCATION \
      --name $APPSERVICE_NAME \
      --sku P0v3 \
      --is-linux
    az webapp create \
      --resource-group $RESOURCE_GROUP \
      --name $APPSERVICE_NAME \
      --plan $APPSERVICE_NAME \
      --runtime "JAVA:21-java21"
    
  2. Sestavte balíček nasazení s Mavenem.

    mvn clean package
    
  3. Nasaďte JAR aplikace Spring Boot.

    az webapp deploy \
      --resource-group $RESOURCE_GROUP \
      --name $APPSERVICE_NAME \
      --src-path target/rest-service-0.0.1-SNAPSHOT.jar \
      --type jar
    

    Nasazení může trvat několik minut.

  4. Po nasazení aplikace vytvořte připojení služby mezi vaší webovou aplikací a prostředkem Azure OpenAI pomocí spravované identity:

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

    Tento příkaz vytvoří propojení mezi vaší webovou aplikací a prostředkem Azure OpenAI:

    • Generování spravované identity přiřazené systémem pro webovou aplikaci
    • Přidání role Přispěvatele pro OpenAI ve službách Cognitive Services ke spravované identitě pro prostředek Azure OpenAI.
    • Přidání nastavení aplikace AZURE_OPENAI_ENDPOINT do vaší webové aplikace.
  5. Otevřete nasazenou webovou aplikaci v prohlížeči.

    az webapp browse --resource-group $RESOURCE_GROUP --name $APPSERVICE_NAME
    
  6. Do textového pole napište zprávu a vyberte Odeslat a dejte aplikaci několik sekund, abyste mohli odpovědět se zprávou z Azure OpenAI.

    Snímek obrazovky s chatovacím robotem spuštěným ve službě Azure App Service

Vaše aplikace je teď nasazená a připojená k Azure OpenAI se spravovanou identitou. Všimněte si, že přistupuje k AZURE_OPENAI_ENDPOINT nastavení aplikace prostřednictvím injekce @Configuration.

Nejčastější dotazy

Proč ukázka používá @Configuration a Spring beans pro klienta OpenAI?

Použití Spring beanu pro OpenAIAsyncClient zajišťuje, že:

  • Všechny vlastnosti konfigurace (jako koncový bod) jsou načteny a vloženy frameworkem Spring.
  • Přihlašovací údaje a klient se vytvoří po úplné inicializaci kontextu aplikace.
  • Injektáž závislostí se používá, což je standardní a nej robustnější vzor v aplikacích Spring.

Asynchronní klient je robustnější, zejména při použití DefaultAzureCredential s ověřováním Azure CLI. Synchronní OpenAIClient může v některých místních scénářích vývoje narazit na problémy s získáním tokenů. Použití asynchronního klienta se těmto problémům vyhne a je doporučeným přístupem.


Co když se chci připojit k OpenAI místo Azure OpenAI?

Pokud se chcete místo toho připojit k OpenAI, použijte následující kód:

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

Další informace najdete v tématu Ověřování rozhraní API OpenAI.

Při práci s tajnými kódy připojení ve službě App Service byste měli místo ukládání tajných kódů přímo do základu kódu použít odkazy služby Key Vault . Tím zajistíte, že citlivé informace zůstanou zabezpečené a budou spravovány centrálně.


Můžu se místo toho připojit k Azure OpenAI pomocí klíče rozhraní API?

Ano, k Azure OpenAI se můžete připojit pomocí klíče rozhraní API místo spravované identity. Tento přístup podporuje sady SDK Azure OpenAI a sémantické jádro.

Při práci s tajnými kódy připojení ve službě App Service byste měli místo ukládání tajných kódů přímo do základu kódu použít odkazy služby Key Vault . Tím zajistíte, že citlivé informace zůstanou zabezpečené a budou spravovány centrálně.


Jak v tomto kurzu funguje DefaultAzureCredential?

Zjednodušuje DefaultAzureCredential ověřování tím, že automaticky vybere nejlepší dostupnou metodu ověřování:

  • Během místního vývoje: Po spuštění az loginpoužije vaše místní přihlašovací údaje Azure CLI.
  • Při nasazení do služby Azure App Service používá spravovanou identitu aplikace k zabezpečenému ověřování bez hesla.

Tento přístup umožňuje bezpečně a bezproblémově spouštět kód v místním i cloudovém prostředí beze změny.

Další kroky