مشاركة عبر


البرنامج التعليمي: إنشاء روبوت دردشة باستخدام Azure App Service وAzure OpenAI (Spring Boot)

في هذا البرنامج التعليمي، ستقوم بإنشاء تطبيق ذكي الذكاء الاصطناعي من خلال دمج Azure OpenAI مع تطبيق Java Spring Boot ونشره في Azure App Service. ستقوم بإنشاء وحدة تحكم Spring Boot ترسل استعلاما إلى Azure OpenAI وترسل الاستجابة إلى المتصفح.

تلميح

بينما يستخدم هذا البرنامج التعليمي Spring Boot، تنطبق المفاهيم الأساسية لبناء تطبيق دردشة باستخدام Azure OpenAI على أي تطبيق ويب Java. إذا كنت تستخدم خيار استضافة مختلف على App Service، مثل Tomcat أو JBoss EAP، يمكنك تكييف أنماط المصادقة واستخدام Azure SDK الموضح هنا مع إطار العمل المفضل لديك.

لقطة شاشة تعرض روبوت دردشة يعمل في Azure App Service.

في هذا البرنامج التعليمي، تتعلم كيفية:

  • إنشاء مورد Azure OpenAI ونشر نموذج لغة.
  • إنشاء تطبيق Spring Boot يتصل ب Azure OpenAI.
  • استخدم إدخال التبعية لتكوين عميل Azure OpenAI.
  • نشر التطبيق إلى Azure App Service.
  • تنفيذ المصادقة الآمنة بدون كلمة مرور في كل من بيئة التطوير وفي Azure.

المتطلبات الأساسية

1. إنشاء مورد Azure OpenAI

في هذا القسم، ستستخدم GitHub Codespaces لإنشاء مورد Azure OpenAI باستخدام Azure CLI.

  1. انتقل إلى GitHub Codespaces وسجل الدخول باستخدام حساب GitHub الخاص بك.

  2. ابحث عن القالب Blank by GitHub وحدد Use this template لإنشاء Codespace فارغة جديدة.

  3. في محطة Codespace الطرفية، قم بتثبيت Azure CLI:

    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
    
  4. سجل الدخول إلى حساب Azure الخاص بك:

    az login
    

    اتبع الإرشادات الموجودة في المحطة الطرفية للمصادقة.

  5. تعيين متغيرات البيئة لاسم مجموعة الموارد واسم خدمة Azure OpenAI والموقع:

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

    هام

    تعد المنطقة بالغة الأهمية لأنها مرتبطة بالتوافر الإقليمي للنموذج المختار. يختلف توفر النموذج وتوافر نوع التوزيع من منطقة إلى أخرى. يستخدم gpt-4o-miniهذا البرنامج التعليمي ، والذي يتوفر في eastus2 ضمن نوع التوزيع القياسي. إذا قمت بالنشر في منطقة مختلفة، فقد لا يكون هذا النموذج متوفرا أو قد يتطلب مستوى مختلفا. قبل تغيير المناطق، راجع جدول ملخص النموذج وتوافر المنطقة للتحقق من دعم النموذج في منطقتك المفضلة.

  6. إنشاء مجموعة موارد ومورد Azure OpenAI مع مجال مخصص، ثم إضافة نموذج 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
    

الآن بعد أن أصبح لديك مورد Azure OpenAI، ستقوم بإنشاء تطبيق ويب للتفاعل معه.

2. إنشاء وإعداد تطبيق ويب Spring Boot

  1. في محطة Codespace الطرفية، انسخ عينة Spring Boot REST إلى مساحة العمل وحاول تشغيلها في المرة الأولى.

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

    يجب أن تشاهد إعلاما في GitHub Codespaces يشير إلى أن التطبيق متاح في منفذ معين. حدد فتح في المستعرض لتشغيل التطبيق في علامة تبويب مستعرض جديدة. عندما ترى صفحة خطأ التسمية البيضاء، يعمل تطبيق Spring Boot.

  2. مرة أخرى في محطة Codespace الطرفية، أوقف التطبيق باستخدام Ctrl+C.

  3. افتح pom.xml وأضف التبعيات التالية:

    <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 (src/main/java/com/example/restservice) أضف ملف Java يسمى ChatController.java وانسخ المحتوى التالي فيه:

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

    تلميح

    لتقليل الملفات في هذا البرنامج التعليمي، تجمع التعليمات البرمجية بين Spring @Configuration والفئات @Controller في ملف واحد. في الإنتاج، يمكنك عادة فصل التكوين ومنطق العمل لقابلية الصيانة.

  5. ضمن src/main/resources، أنشئ دليل قوالب ، وأضف chat.html بالمحتوى التالي لواجهة الدردشة:

    <!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. في المحطة الطرفية، قم باسترداد نقطة نهاية OpenAI:

    az cognitiveservices account show \
      --name $OPENAI_SERVICE_NAME \
      --resource-group $RESOURCE_GROUP \
      --query properties.endpoint \
      --output tsv
    
  7. قم بتشغيل التطبيق مرة أخرى عن طريق إضافة AZURE_OPENAI_ENDPOINT بقيمته من إخراج CLI:

    AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> mvn spring-boot:run
    
  8. حدد فتح في المستعرض لتشغيل التطبيق في علامة تبويب مستعرض جديدة.

  9. اكتب رسالة في مربع النص واختر إرسال، وأعط التطبيق بضع ثوان للرد بالرسالة من Azure OpenAI.

يستخدم التطبيق DefaultAzureCredential، والذي يستخدم تلقائيا مستخدم Azure CLI الذي قام بتسجيل الدخول لمصادقة الرمز المميز. لاحقا في هذا البرنامج التعليمي، ستقوم بنشر تطبيق الويب الخاص بك إلى Azure App Service وتكوينه للاتصال بأمان بمورد Azure OpenAI باستخدام الهوية المدارة. نفس الشيء DefaultAzureCredential في التعليمات البرمجية الخاصة بك يمكن الكشف عن الهوية المدارة واستخدامها للمصادقة. لا توجد حاجة إلى تعليمة برمجية إضافية.

3. النشر إلى Azure App Service وتكوين اتصال OpenAI

الآن بعد أن يعمل تطبيقك محليا، دعنا ننشره في Azure App Service ونعد اتصال خدمة إلى Azure OpenAI باستخدام الهوية المدارة.

  1. إنشاء حزمة توزيع باستخدام Maven.

    mvn clean package
    
  2. أولا، انشر تطبيقك في Azure App Service باستخدام أمر az webapp upAzure CLI . ينشئ هذا الأمر تطبيق ويب جديدا وينشر التعليمات البرمجية الخاصة بك إليه:

    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
    

    قد يستغرق هذا الأمر بضع دقائق لإكماله. يقوم بإنشاء تطبيق ويب جديد في نفس مجموعة الموارد مثل مورد OpenAI الخاص بك.

  3. بعد نشر التطبيق، أنشئ اتصال خدمة بين تطبيق الويب الخاص بك ومورد Azure OpenAI باستخدام الهوية المدارة:

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

    ينشئ هذا الأمر اتصالا بين تطبيق الويب الخاص بك ومورد Azure OpenAI من خلال:

    • إنشاء هوية مدارة معينة من قبل النظام لتطبيق الويب.
    • إضافة دور مساهم OpenAI للخدمات المعرفية إلى الهوية المدارة لمورد Azure OpenAI.
    • AZURE_OPENAI_ENDPOINT إضافة إعداد التطبيق إلى تطبيق الويب الخاص بك.
  4. افتح تطبيق الويب المنشور في المستعرض.

    az webapp browse
    
  5. اكتب رسالة في مربع النص وحدد "إرسال، وامنح التطبيق بضع ثوان للرد بالرسالة من Azure OpenAI.

    لقطة شاشة تعرض روبوت دردشة يعمل في Azure App Service.

يتم الآن نشر تطبيقك وتوصيمه ب Azure OpenAI بهوية مدارة. لاحظ أنه يتم الوصول إلى AZURE_OPENAI_ENDPOINT إعداد التطبيق من خلال حقن @Configuration .

الأسئلة الشائعة

لماذا تستخدم @Configuration العينة وحبوب الربيع لعميل OpenAI؟

يضمن استخدام زنبرك بون ل OpenAIAsyncClient ما يلي:

  • يتم تحميل جميع خصائص التكوين (مثل نقطة النهاية) وحقنها بواسطة Spring.
  • يتم إنشاء بيانات الاعتماد والعميل بعد تهيئة سياق التطبيق بالكامل.
  • يتم استخدام إدخال التبعية، وهو النمط القياسي والأكثر قوة في تطبيقات Spring.

العميل غير المتزامن أكثر قوة، خاصة عند استخدام DefaultAzureCredential مع مصادقة Azure CLI. يمكن أن يواجه المتزامن OpenAIClient مشكلات في الحصول على الرمز المميز في بعض سيناريوهات التطوير المحلية. يؤدي استخدام العميل غير المتزامن إلى تجنب هذه المشكلات وهو النهج الموصى به.


ماذا لو أردت الاتصال ب OpenAI بدلا من Azure OpenAI؟

للاتصال ب OpenAI بدلا من ذلك، استخدم التعليمات البرمجية التالية:

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

لمزيد من المعلومات، راجع مصادقة OpenAI API.

عند العمل مع أسرار الاتصال في App Service، يجب عليك استخدام مراجع Key Vault بدلا من تخزين الأسرار مباشرة في قاعدة التعليمات البرمجية الخاصة بك. وهذا يضمن بقاء المعلومات الحساسة آمنة وتدار مركزيا.


هل يمكنني الاتصال ب Azure OpenAI باستخدام مفتاح API بدلا من ذلك؟

نعم، يمكنك الاتصال ب Azure OpenAI باستخدام مفتاح API بدلا من الهوية المدارة. يتم دعم هذا الأسلوب من قبل Azure OpenAI SDKs وKernel الدلالي.

عند العمل مع أسرار الاتصال في App Service، يجب عليك استخدام مراجع Key Vault بدلا من تخزين الأسرار مباشرة في قاعدة التعليمات البرمجية الخاصة بك. وهذا يضمن بقاء المعلومات الحساسة آمنة وتدار مركزيا.


كيف يعمل DefaultAzureCredential في هذا البرنامج التعليمي؟

يبسط DefaultAzureCredential المصادقة عن طريق تحديد أفضل طريقة مصادقة متوفرة تلقائيا:

  • أثناء التطوير المحلي: بعد تشغيل az login، فإنه يستخدم بيانات اعتماد Azure CLI المحلية.
  • عند نشره في Azure App Service: يستخدم هوية التطبيق المدارة للمصادقة الآمنة بدون كلمة مرور.

يتيح هذا الأسلوب تشغيل التعليمات البرمجية الخاصة بك بشكل آمن وسلس في كل من البيئات المحلية والسحابية دون تعديل.

الخطوات التالية