Aracılığıyla paylaş


Öğretici: Azure App Service ve Azure OpenAI (Spring Boot) ile sohbet botu oluşturma

Bu öğreticide, Azure OpenAI'yi bir Java Spring Boot uygulamasıyla tümleştirip Azure App Service'e dağıtarak akıllı bir yapay zeka uygulaması oluşturacaksınız. Azure OpenAI'ye sorgu gönderen ve yanıtı tarayıcıya gönderen bir Spring Boot denetleyicisi oluşturacaksınız.

Tavsiye

Bu öğreticide Spring Boot kullanılırken, Azure OpenAI ile sohbet uygulaması oluşturmanın temel kavramları tüm Java web uygulamaları için geçerlidir. App Service'te Tomcat veya JBoss EAP gibi farklı bir barındırma seçeneği kullanıyorsanız, burada gösterilen kimlik doğrulama desenlerini ve Azure SDK kullanımını tercih ettiğiniz çerçeveye uyarlayabilirsiniz.

Azure App Service'te çalışan bir sohbet botu gösteren ekran görüntüsü.

Bu eğitimde şunları öğreniyorsunuz:

  • Bir Azure OpenAI kaynağı oluşturun ve bir dil modeli dağıtın.
  • Azure OpenAI'ye bağlanan bir Spring Boot uygulaması oluşturun.
  • Azure OpenAI istemcisini yapılandırmak için bağımlılık ekleme özelliğini kullanın.
  • Uygulamayı Azure App Service'e dağıtın.
  • Hem geliştirme ortamında hem de Azure'da parolasız güvenli kimlik doğrulaması uygulayın.

Önkoşullar

  • Etkin aboneliği olan bir Azure hesabı
  • GitHub Codespaces'i kullanmak için bir GitHub hesabı

1. Azure OpenAI kaynağı oluşturma

Bu bölümde GitHub Codespaces kullanarak Azure CLI ile bir Azure OpenAI kaynağı oluşturacaksınız.

  1. GitHub Codespaces'a gidin ve GitHub hesabınızla oturum açın.

  2. GitHub'a göre Boş şablonu bulun ve Yeni boş bir Codespace oluşturmak için Bu şablonu kullan'ı seçin.

  3. Codespace terminalinde Azure CLI'yı yükleyin:

    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
    
  4. Azure hesabınızda oturum açın:

    az login
    

    Kimlik doğrulaması yapmak için terminaldeki yönergeleri izleyin.

  5. Kaynak grubu adınız, Azure OpenAI hizmet adınız ve konumunuz için ortam değişkenlerini ayarlayın:

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

    Önemli

    Bölge, seçilen modelin bölgesel kullanılabilirliğine bağlı olduğundan kritik öneme sahiptir. Model kullanılabilirliği ve dağıtım türü kullanılabilirliği bölgeden bölgeye farklılık gösterir. Bu öğreticide, Standart dağıtım türü altında bulunan gpt-4o-mini içindeki eastus2 kullanılır. Farklı bir bölgeye dağıtım yaparsanız, bu model kullanılamayabilir veya farklı bir katman gerektirebilir. Bölgeleri değiştirmeden önce tercih ettiğiniz bölgede model desteğini doğrulamak için Model özet tablosuna ve bölge kullanılabilirliğine başvurun.

  6. Özel etki alanına sahip bir Azure OpenAI kaynağı ve bir kaynak grubu oluşturun, ardından bir gpt-4o-mini modeli ekleyin:

    # 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
    

Artık bir Azure OpenAI kaynağınız olduğuna göre, bu kaynakla etkileşim kurmak için bir web uygulaması oluşturacaksınız.

2. Spring Boot web uygulaması oluşturma ve ayarlama

  1. Codespace terminalinizde Spring Boot REST örneğini çalışma alanına kopyalayın ve ilk kez çalıştırmayı deneyin.

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

    GitHub Codespaces'ta uygulamanın belirli bir bağlantı noktasında kullanılabilir olduğunu belirten bir bildirim görmeniz gerekir. Uygulamayı yeni bir tarayıcı sekmesinde başlatmak için Tarayıcıda aç'ı seçin. Beyaz etiket hata sayfasını gördüğünüzde Spring Boot uygulaması çalışıyor olur.

  2. Codespace terminalinde Ctrl+C tuşlarını kullanarak uygulamayı durdurun.

  3. pom.xml açın ve aşağıdaki bağımlılıkları ekleyin:

    <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. Application.java ile aynı dizinde (src/main/java/com/example/restservice) ChatController.java adlı bir Java dosyası ekleyin ve içine aşağıdaki içeriği kopyalayın:

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

    Tavsiye

    Bu öğreticideki dosyaları en aza indirmek için, Spring @Configuration ve @Controller sınıfları kodda tek bir dosyada birleştirilmiştir. Üretimde, bakım için normalde yapılandırmayı ve iş mantığını ayırırsınız.

  5. src/main/resources altında bir şablon dizini oluşturun ve sohbet arabirimi için aşağıdaki içeriğe sahip bir chat.html ekleyin:

    <!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. Terminalde OpenAI uç noktanızı alın:

    az cognitiveservices account show \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.endpoint \
      --output tsv
    
  7. CLI çıktısındaki değeriyle AZURE_OPENAI_ENDPOINT ekleyerek uygulamayı yeniden çalıştırın.

    AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> mvn spring-boot:run
    
  8. Uygulamayı yeni bir tarayıcı sekmesinde başlatmak için Tarayıcıda aç'ı seçin.

  9. Metin kutusuna bir ileti yazın ve "Gönder'i seçin ve uygulamaya Azure OpenAI'den gelen iletiyi yanıtlaması için birkaç saniye verin.

Uygulama, belirteç kimlik doğrulaması için Azure CLI üzerinden oturum açmış kullanıcınızı otomatik olarak kullanan DefaultAzureCredential'ı kullanır. Bu öğreticinin ilerleyen bölümlerinde web uygulamanızı Azure App Service'e dağıtacak ve yönetilen kimliği kullanarak Azure OpenAI kaynağınıza güvenli bir şekilde bağlanacak şekilde yapılandıracaksınız. Kodunuzda aynı DefaultAzureCredential, yönetilen kimliği algılayabilir ve kimlik doğrulaması için kullanabilir. Ek kod gerekmez.

3. Azure App Service'e dağıtma ve OpenAI bağlantısını yapılandırma

Uygulamanız yerel olarak çalıştığına göre, şimdi bunu Azure App Service'e dağıtalım ve yönetilen kimlik kullanarak Azure OpenAI'ye bir hizmet bağlantısı ayarlayalım.

  1. Maven ile bir dağıtım paketi oluşturun.

    mvn clean package
    
  2. İlk olarak, Azure CLI komutunu az webapp upkullanarak uygulamanızı Azure App Service'e dağıtın. Bu komut yeni bir web uygulaması oluşturur ve kodunuzu buna dağıtır:

    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
    

    Bu komutun tamamlanması birkaç dakika sürebilir. OpenAI kaynağınızla aynı kaynak grubunda yeni bir web uygulaması oluşturur.

  3. Uygulama dağıtıldıktan sonra yönetilen kimliği kullanarak web uygulamanızla Azure OpenAI kaynağı arasında bir hizmet bağlantısı oluşturun:

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

    Bu komut, web uygulamanızla Azure OpenAI kaynağı arasında şu şekilde bir bağlantı oluşturur:

    • Web uygulaması için sistem tarafından atanan yönetilen kimlik oluşturma.
    • Azure OpenAI kaynağının yönetilen kimliğine Bilişsel Hizmetler OpenAI Katkıda Bulunanı rolünü ekleme.
    • AZURE_OPENAI_ENDPOINT Uygulama ayarını web uygulamanıza ekleme.
  4. Dağıtılan web uygulamasını tarayıcıda açın.

    az webapp browse
    
  5. Metin kutusuna bir ileti yazın ve "Gönder'i seçin ve uygulamaya Azure OpenAI'den gelen iletiyi yanıtlaması için birkaç saniye verin.

    Azure App Service'te çalışan bir sohbet botu gösteren ekran görüntüsü.

Uygulamanız artık yönetilen kimlikle Azure OpenAI'ye dağıtılır ve bağlanır. AZURE_OPENAI_ENDPOINT uygulama ayarına, @Configuration enjeksiyonu yoluyla eriştiğini unutmayın.

Sıkça sorulan sorular

Neden örnek, OpenAI istemcisi için @Configuration ve Spring beans kullanıyor?

Spring bean kullanımı, OpenAIAsyncClient'nin aşağıdakileri sağlamasını garanti eder:

  • Tüm yapılandırma özellikleri (uç nokta gibi) Spring tarafından yüklenir ve eklenir.
  • Kimlik bilgileri ve istemci, uygulama bağlamı tamamen başlatıldıktan sonra oluşturulur.
  • Spring uygulamalarında standart ve en sağlam desen olan bağımlılık ekleme kullanılır.

Zaman uyumsuz istemci, özellikle Azure CLI kimlik doğrulaması ile kullanıldığında DefaultAzureCredential daha güçlüdür. Zaman uyumlu OpenAIClient, bazı yerel geliştirme senaryolarında jeton edinme ile ilgili sorunlarla karşılaşabilir. Zaman uyumsuz istemcinin kullanılması bu sorunları önler ve önerilen yaklaşımdır.


Azure OpenAI yerine OpenAI'ye bağlanmak istersem ne olur?

Bunun yerine OpenAI'ye bağlanmak için aşağıdaki kodu kullanın:

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

Daha fazla bilgi için bkz. OpenAI API kimlik doğrulaması.

App Service'te bağlantı gizli dizileriyle çalışırken, gizli dizileri doğrudan kod tabanınızda depolamak yerine Key Vault başvurularını kullanmanız gerekir. Bu, hassas bilgilerin güvenli kalmasını ve merkezi olarak yönetilmesini sağlar.


Bunun yerine bir API anahtarıyla Azure OpenAI'ye bağlanabilir miyim?

Evet, yönetilen kimlik yerine bir API anahtarı kullanarak Azure OpenAI'ye bağlanabilirsiniz. Bu yaklaşım Azure OpenAI SDK'ları ve Anlam Çekirdeği tarafından desteklenir.

App Service'te bağlantı gizli dizileriyle çalışırken, gizli dizileri doğrudan kod tabanınızda depolamak yerine Key Vault başvurularını kullanmanız gerekir. Bu, hassas bilgilerin güvenli kalmasını ve merkezi olarak yönetilmesini sağlar.


DefaultAzureCredential bu öğreticide nasıl çalışır?

, DefaultAzureCredential en iyi kullanılabilir kimlik doğrulama yöntemini otomatik olarak seçerek kimlik doğrulamasını basitleştirir:

  • Yerel geliştirme sırasında: komutunu çalıştırdıktan az loginsonra yerel Azure CLI kimlik bilgilerinizi kullanır.
  • Azure App Service'e dağıtıldığında: Güvenli, parolasız kimlik doğrulaması için uygulamanın yönetilen kimliğini kullanır.

Bu yaklaşım, kodunuzun hem yerel hem de bulut ortamlarında değişiklik yapmadan güvenli ve sorunsuz bir şekilde çalışmasını sağlar.

Sonraki Adımlar