Bagikan melalui


Tutorial: Membangun chatbot dengan Azure App Service dan Azure OpenAI (Spring Boot)

Dalam tutorial ini, Anda akan membangun aplikasi AI cerdas dengan mengintegrasikan Azure OpenAI dengan aplikasi Java Spring Boot dan menyebarkannya ke Azure App Service. Anda akan membuat pengontrol Spring Boot yang mengirim kueri ke Azure OpenAI dan mengirim respons ke browser.

Petunjuk / Saran

Meskipun tutorial ini menggunakan Spring Boot, konsep inti membangun aplikasi obrolan dengan Azure OpenAI berlaku untuk aplikasi web Java apa pun. Jika Anda menggunakan opsi hosting yang berbeda di App Service, seperti Tomcat atau JBoss EAP, Anda dapat menyesuaikan pola autentikasi dan penggunaan Azure SDK yang ditunjukkan di sini ke kerangka kerja pilihan Anda.

Cuplikan layar memperlihatkan chatbot yang berjalan di Azure App Service.

Dalam tutorial ini, Anda akan belajar cara:

  • Buat sumber daya Azure OpenAI dan sebarkan model bahasa.
  • Buat aplikasi Spring Boot yang terhubung ke Azure OpenAI.
  • Gunakan injeksi dependensi untuk mengonfigurasi klien Azure OpenAI.
  • Sebarkan aplikasi ke Azure App Service.
  • Terapkan autentikasi aman tanpa kata sandi baik di lingkungan pengembangan maupun di Azure.

Prasyarat

  • Akun Azure dengan langganan aktif
  • Akun GitHub untuk menggunakan GitHub Codespaces

1. Membuat sumber daya Azure OpenAI

Di bagian ini, Anda akan menggunakan GitHub Codespaces untuk membuat sumber daya Azure OpenAI dengan Azure CLI.

  1. Buka GitHub Codespaces dan masuk dengan akun GitHub Anda.

  2. Temukan templat Kosong oleh GitHub dan pilih Gunakan templat ini untuk membuat Codespace kosong baru.

  3. Di terminal Codespace, instal Azure CLI:

    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
    
  4. Masuk ke akun Azure Anda:

    az login
    

    Ikuti instruksi di terminal untuk mengautentikasi.

  5. Atur variabel lingkungan untuk nama grup sumber daya, nama layanan Azure OpenAI, dan lokasi Anda:

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

    Penting

    Wilayah ini sangat penting karena terkait dengan ketersediaan regional model yang dipilih. Ketersediaan model dan ketersediaan jenis penyebaran bervariasi dari wilayah ke wilayah. Tutorial ini menggunakan gpt-4o-mini, yang tersedia di eastus2 dengan jenis penyebaran Standar. Jika Anda menyebarkan ke wilayah lain, model ini mungkin tidak tersedia atau mungkin memerlukan tingkat yang berbeda. Sebelum mengubah wilayah, lihat Tabel ringkasan model dan ketersediaan wilayah untuk memverifikasi dukungan model di wilayah pilihan Anda.

  6. Buat grup sumber daya dan sumber daya Azure OpenAI dengan domain kustom, lalu tambahkan model 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
    

Sekarang setelah Anda memiliki sumber daya Azure OpenAI, Anda akan membuat aplikasi web untuk berinteraksi dengannya.

2. Membuat dan menyiapkan aplikasi web Spring Boot

  1. Di terminal Codespace Anda, kloning sampel Spring Boot REST ke ruang kerja dan coba jalankan pertama kali.

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

    Anda akan melihat pemberitahuan di GitHub Codespaces yang menunjukkan bahwa aplikasi tersedia di port tertentu. Pilih Buka di browser untuk meluncurkan aplikasi di tab browser baru. Saat Anda melihat halaman kesalahan label putih, aplikasi Spring Boot berfungsi.

  2. Kembali ke terminal Codespace, hentikan aplikasi dengan Ctrl+C.

  3. Buka pom.xml dan tambahkan dependensi berikut:

    <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. Dalam direktori yang sama dengan Application.java (src/main/java/com/example/restservice) tambahkan file Java yang disebut ChatController.java dan salin konten berikut ke dalamnya:

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

    Petunjuk / Saran

    Untuk meminimalkan file dalam tutorial ini, kode menggabungkan Spring @Configuration dan @Controller kelas dalam satu file. Dalam produksi, Anda biasanya akan memisahkan konfigurasi dan logika bisnis untuk keberlangsungan.

  5. Di bawah src/main/resources, buat direktori templat , dan tambahkan chat.html dengan konten berikut untuk antarmuka obrolan:

    <!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. Pada terminal, dapatkan titik akhir OpenAI Anda:

    az cognitiveservices account show \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.endpoint \
      --output tsv
    
  7. Jalankan aplikasi lagi dengan menambahkan AZURE_OPENAI_ENDPOINT dengan nilainya dari output CLI:

    AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> mvn spring-boot:run
    
  8. Pilih Buka di browser untuk meluncurkan aplikasi di tab browser baru.

  9. Ketik pesan di kotak teks dan pilih Kirim, dan beri aplikasi beberapa detik untuk membalas dengan pesan dari Azure OpenAI.

Aplikasi ini menggunakan DefaultAzureCredential, yang secara otomatis menggunakan pengguna masuk Azure CLI Anda untuk autentikasi token. Nanti dalam tutorial ini, Anda akan menyebarkan aplikasi web ke Azure App Service dan mengonfigurasinya untuk terhubung dengan aman ke sumber daya Azure OpenAI Anda menggunakan identitas terkelola. Hal yang sama DefaultAzureCredential dalam kode Anda dapat mendeteksi identitas terkelola dan menggunakannya untuk autentikasi. Tidak ada kode tambahan yang diperlukan.

3. Sebarkan ke Azure App Service dan konfigurasikan koneksi OpenAI

Sekarang setelah aplikasi Anda berfungsi secara lokal, mari kita sebarkan ke Azure App Service dan siapkan koneksi layanan ke Azure OpenAI menggunakan identitas terkelola.

  1. Buat paket penyebaran dengan Maven.

    mvn clean package
    
  2. Pertama, sebarkan aplikasi Anda ke Azure App Service menggunakan perintah az webapp upAzure CLI . Perintah ini membuat aplikasi web baru dan menyebarkan kode Anda ke dalamnya:

    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
    

    Perintah ini mungkin perlu waktu beberapa menit untuk diselesaikan. Ini membuat aplikasi web baru di grup sumber daya yang sama dengan sumber daya OpenAI Anda.

  3. Setelah aplikasi disebarkan, buat koneksi layanan antara aplikasi web Anda dan sumber daya Azure OpenAI menggunakan identitas terkelola:

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

    Perintah ini membuat koneksi antara aplikasi web Anda dan sumber daya Azure OpenAI dengan:

    • Menghasilkan identitas terkelola yang ditetapkan sistem untuk aplikasi web.
    • Menambahkan peran Kontributor Cognitive Services OpenAI ke identitas yang dikelola untuk sumber daya Azure OpenAI.
    • AZURE_OPENAI_ENDPOINT Menambahkan pengaturan aplikasi ke aplikasi web Anda.
  4. Buka aplikasi web yang disebarkan di browser.

    az webapp browse
    
  5. Ketik pesan di kotak teks dan pilih "Kirim, dan berikan aplikasi beberapa detik untuk membalas dengan pesan dari Azure OpenAI.

    Cuplikan layar memperlihatkan chatbot yang berjalan di Azure App Service.

Aplikasi Anda sekarang disebarkan dan terhubung ke Azure OpenAI dengan identitas terkelola. Perhatikan bahwa sedang mengakses pengaturan aplikasi AZURE_OPENAI_ENDPOINT melalui injeksi @Configuration.

Tanya jawab umum

Mengapa sampel menggunakan @Configuration dan Spring Beans untuk klien OpenAI?

Menggunakan kacang Spring untuk OpenAIAsyncClient memastikan bahwa:

  • Semua properti konfigurasi (seperti titik akhir) dimuat dan disuntikkan oleh Spring.
  • Kredensial dan klien dibuat setelah konteks aplikasi diinisialisasi sepenuhnya.
  • Injeksi dependensi digunakan, yang merupakan pola standar dan paling kuat dalam aplikasi Spring.

Klien asinkron lebih kuat, terutama saat menggunakan DefaultAzureCredential dengan autentikasi Azure CLI. Sinkron OpenAIClient dapat mengalami masalah dengan akuisisi token dalam beberapa skenario pengembangan lokal tertentu. Menggunakan klien asinkron menghindari masalah ini dan merupakan pendekatan yang direkomendasikan.


Bagaimana jika saya ingin tersambung ke OpenAI alih-alih Azure OpenAI?

Untuk menyambungkan ke OpenAI, gunakan kode berikut:

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

Untuk informasi selengkapnya, lihat Autentikasi OpenAI API.

Saat bekerja dengan rahasia koneksi di App Service, Anda harus menggunakan referensi Key Vault alih-alih menyimpan rahasia langsung di basis kode Anda. Ini memastikan bahwa informasi sensitif tetap aman dan dikelola secara terpusat.


Dapatkah saya tersambung ke Azure OpenAI dengan kunci API sebagai gantinya?

Ya, Anda dapat terhubung ke Azure OpenAI menggunakan kunci API alih-alih identitas terkelola. Pendekatan ini didukung oleh Azure OpenAI SDK dan Semantic Kernel.

Saat bekerja dengan rahasia koneksi di App Service, Anda harus menggunakan referensi Key Vault alih-alih menyimpan rahasia langsung di basis kode Anda. Ini memastikan bahwa informasi sensitif tetap aman dan dikelola secara terpusat.


Bagaimana cara kerja DefaultAzureCredential dalam tutorial ini?

DefaultAzureCredential menyederhanakan autentikasi dengan secara otomatis memilih metode autentikasi terbaik yang tersedia.

  • Selama pengembangan lokal: Setelah Anda menjalankan az login, ini menggunakan kredensial Azure CLI lokal Anda.
  • Saat disebarkan ke Azure App Service: Ini menggunakan identitas terkelola aplikasi untuk autentikasi tanpa kata sandi yang aman.

Pendekatan ini memungkinkan kode Anda berjalan dengan aman dan lancar di lingkungan lokal dan cloud tanpa modifikasi.

Langkah selanjutnya