تقنيات المراقبة العملية لتطبيق الذكاء الاصطناعي التوليدي في Java

1. نظرة عامة

تتطلّب تطبيقات الذكاء الاصطناعي التوليدي إمكانية المراقبة مثل أي تطبيقات أخرى. هل هناك تقنيات مراقبة خاصة مطلوبة للذكاء الاصطناعي التوليدي؟

في هذا التمرين المعملي، ستنشئ تطبيقًا بسيطًا للذكاء الاصطناعي التوليدي. انشرها على Cloud Run. ويمكنك تزويده بإمكانات الرصد والتسجيل الأساسية باستخدام خدمات ومنتجات إمكانية تتبُّع البيانات في Google Cloud.

ما ستتعلمه

  • كتابة تطبيق يستخدم Vertex AI مع Cloud Shell Editor
  • تخزين الرمز البرمجي للتطبيق في GitHub
  • استخدِم gcloud CLI لنشر الرمز المصدر لتطبيقك على Cloud Run
  • إضافة إمكانات رصد وتسجيل البيانات إلى تطبيق الذكاء الاصطناعي التوليدي
  • استخدام المقاييس المستندة إلى السجلّات
  • تنفيذ التسجيل والرصد باستخدام حزمة تطوير البرامج (SDK) الخاصة بـ Open Telemetry
  • التعرّف على كيفية التعامل مع بيانات الذكاء الاصطناعي المسؤول

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

إذا لم يكن لديك حساب على Google، عليك إنشاء حساب جديد.

3- إعداد المشروع

  1. سجِّل الدخول إلى Google Cloud Console باستخدام حسابك على Google.
  2. أنشِئ مشروعًا جديدًا أو اختَر إعادة استخدام مشروع حالي. دوِّن رقم تعريف المشروع الذي أنشأته أو اخترته للتو.
  3. فعِّل الفوترة للمشروع.
    • يجب أن تكون تكلفة إكمال هذا الدرس التطبيقي أقل من 5 دولارات أمريكية.
    • يمكنك اتّباع الخطوات في نهاية هذا المختبر لحذف الموارد وتجنُّب المزيد من الرسوم.
    • يمكن للمستخدمين الجدد الاستفادة من فترة تجريبية مجانية بقيمة 300 دولار أمريكي.
  4. تأكَّد من تفعيل الفوترة في مشاريعي ضمن
      الفوترة في السحابة الإلكترونية
    • إذا كان مشروعك الجديد يعرض Billing is disabled في العمود Billing account:
      1. انقر على النقاط الثلاث في العمود Actions
      2. انقر على تغيير الفوترة.
      3. اختَر حساب الفوترة الذي تريد استخدامه
    • إذا كنت تحضر حدثًا مباشرًا، من المحتمل أن يكون اسم الحساب هو حساب فوترة تجريبي على Google Cloud Platform.

4. إعداد Cloud Shell Editor

  1. انتقِل إلى محرِّر Cloud Shell. إذا ظهرت لك الرسالة التالية التي تطلب منك منح Cloud Shell الإذن باستدعاء gcloud باستخدام بيانات الاعتماد الخاصة بك، انقر على منح الإذن للمتابعة.
    انقر لتفويض Cloud Shell
  2. فتح نافذة المحطة الطرفية
    1. انقر على قائمة الهامبرغر رمز قائمة الخطوط الثلاثة
    2. انقر على Terminal.
    3. انقر على نافذة Terminal جديدة
      فتح نافذة طرفية جديدة في "محرِّر Cloud Shell".
  3. في نافذة الوحدة الطرفية، اضبط رقم تعريف مشروعك:
    gcloud config set project [PROJECT_ID]
    
    استبدِل [PROJECT_ID] بمعرّف مشروعك. على سبيل المثال، إذا كان رقم تعريف مشروعك هو lab-example-project، سيكون الأمر كما يلي:
    gcloud config set project lab-project-id-example
    
    إذا ظهرت لك الرسالة التالية التي تفيد بأنّ gcloud يطلب بيانات الاعتماد الخاصة بك إلى GCPI API، انقر على تفويض للمتابعة.
    انقر لتفويض Cloud Shell
    عند التنفيذ بنجاح، من المفترض أن تظهر لك الرسالة التالية:
    Updated property [core/project].
    
    إذا ظهرت لك WARNING وطُلب منك Do you want to continue (Y/N)?، من المحتمل أنّك أدخلت رقم تعريف المشروع بشكل غير صحيح. اضغط على N، ثم على Enter، وحاوِل تنفيذ الأمر gcloud config set project مرة أخرى بعد العثور على رقم تعريف المشروع الصحيح.
  4. (اختياري) إذا كنت تواجه مشكلة في العثور على رقم تعريف المشروع، نفِّذ الأمر التالي للاطّلاع على أرقام تعريف جميع مشاريعك مرتّبة حسب وقت الإنشاء بترتيب تنازلي:
    gcloud projects list \
         --format='value(projectId,createTime)' \
         --sort-by=~createTime
    

5- تفعيل واجهات Google APIs

في الوحدة الطرفية، فعِّل واجهات Google APIs المطلوبة لهذا التمرين العملي:

gcloud services enable \
     run.googleapis.com \
     cloudbuild.googleapis.com \
     aiplatform.googleapis.com \
     logging.googleapis.com \
     monitoring.googleapis.com \
     cloudtrace.googleapis.com

سيستغرق إكمال هذا الأمر بعض الوقت. في النهاية، ستظهر رسالة نجاح مشابهة لما يلي:

Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.

إذا تلقّيت رسالة خطأ تبدأ بـ ERROR: (gcloud.services.enable) HttpError accessing وتتضمّن تفاصيل الخطأ كما هو موضّح أدناه، أعِد محاولة تنفيذ الأمر بعد تأخير لمدة دقيقة أو دقيقتَين.

"error": {
  "code": 429,
  "message": "Quota exceeded for quota metric 'Mutate requests' and limit 'Mutate requests per minute' of service 'serviceusage.googleapis.com' ...",
  "status": "RESOURCE_EXHAUSTED",
  ...
}

6. إنشاء تطبيق مستنِد إلى الذكاء الاصطناعي التوليدي

في هذه الخطوة، ستكتب رمزًا برمجيًا لتطبيق بسيط يستند إلى الطلبات ويستخدم نموذج Gemini لعرض 10 حقائق مسلّية عن حيوان من اختيارك. اتّبِع الخطوات التالية لإنشاء الرمز البرمجي للتطبيق.

  1. في الوحدة الطرفية، أنشِئ الدليل codelab-o11y:
    mkdir "${HOME}/codelab-o11y"
    
  2. غيِّر الدليل الحالي إلى codelab-o11y:
    cd "${HOME}/codelab-o11y"
    
  3. نزِّل رمز التشغيل لتطبيق Java باستخدام أداة بدء إطار عمل Spring:
    curl https://start.spring.io/starter.zip \
        -d dependencies=web \
        -d javaVersion=17 \
        -d type=maven-project \
        -d bootVersion=3.4.1 -o java-starter.zip
    
  4. أزِل الأرشيف عن رمز bootstrap في المجلد الحالي:
    unzip java-starter.zip
    
  5. وأزِل ملف الأرشيف من المجلد:
    rm java-starter.zip
    
  6. أنشئ ملف project.toml لتحديد إصدار Java Runtime الذي سيتم استخدامه عند نشر الرمز البرمجي على Cloud Run:
    cat > "${HOME}/codelab-o11y/project.toml" << EOF
    [[build.env]]
        name = "GOOGLE_RUNTIME_VERSION"
        value = "17"
    EOF
    
  7. أضِف العناصر الاعتمادية لحزمة تطوير البرامج (SDK) من Google Cloud إلى الملف pom.xml:
    1. أضِف حزمة Google Cloud Core:
      sed -i 's/<dependencies>/<dependencies>\
      \
              <dependency>\
                  <groupId>com.google.cloud<\/groupId>\
                  <artifactId>google-cloud-core<\/artifactId>\
                  <version>2.49.1<\/version>\
              <\/dependency>\
              /g' "${HOME}/codelab-o11y/pom.xml"
      
    2. أضِف حزمة Google Cloud Vertex AI:
      sed -i 's/<dependencies>/<dependencies>\
      \
              <dependency>\
                  <groupId>com.google.cloud<\/groupId>\
                  <artifactId>google-cloud-vertexai<\/artifactId>\
                  <version>1.16.0<\/version>\
              <\/dependency>\
              /g' "${HOME}/codelab-o11y/pom.xml"
      
  8. افتح الملف DemoApplication.java في "محرِّر Cloud Shell":
    cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/DemoApplication.java"
    
    من المفترض أن يظهر الآن رمز مصدر مُنشأ مسبقًا للملف DemoApplication.java في نافذة المحرّر أعلى نافذة الوحدة الطرفية. سيكون رمز المصدر للملف مشابهًا لما يلي:
    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
  9. استبدِل الرمز في أداة التعديل بالإصدار الموضّح أدناه. لاستبدال الرمز، احذف محتوى الملف ثم انسخ الرمز أدناه في أداة التعديل:
    package com.example.demo;
    
    import java.io.IOException;
    import java.util.Collections;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.google.cloud.ServiceOptions;
    import com.google.cloud.vertexai.VertexAI;
    import com.google.cloud.vertexai.api.GenerateContentResponse;
    import com.google.cloud.vertexai.generativeai.GenerativeModel;
    import com.google.cloud.vertexai.generativeai.ResponseHandler;
    
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            String port = System.getenv().getOrDefault("PORT", "8080");
            SpringApplication app = new SpringApplication(DemoApplication.class);
            app.setDefaultProperties(Collections.singletonMap("server.port", port));
            app.run(args);
        }
    }
    
    @RestController
    class HelloController {
        private final String projectId = ServiceOptions.getDefaultProjectId();
        private VertexAI vertexAI;
        private GenerativeModel model;
    
        @PostConstruct
        public void init() {
            vertexAI = new VertexAI(projectId, "us-central1");
            model = new GenerativeModel("gemini-1.5-flash", vertexAI);
        }
    
        @PreDestroy
        public void destroy() {
            vertexAI.close();
        }
    
        @GetMapping("/")
        public String getFacts(@RequestParam(defaultValue = "dog") String animal) throws IOException {
            String prompt = "Give me 10 fun facts about " + animal + ". Return this as html without backticks.";
            GenerateContentResponse response = model.generateContent(prompt);
            return ResponseHandler.getText(response);
        }
    }
    
    بعد بضع ثوانٍ، سيحفظ Cloud Shell Editor الرمز تلقائيًا.

نشر رمز تطبيق الذكاء الاصطناعي التوليدي على Cloud Run

  1. في نافذة الوحدة الطرفية، شغِّل الأمر لنشر الرمز المصدر للتطبيق على Cloud Run.
    gcloud run deploy codelab-o11y-service \
         --source="${HOME}/codelab-o11y/" \
         --region=us-central1 \
         --allow-unauthenticated
    
    إذا ظهرت لك الرسالة أدناه التي تُعلمك بأنّ الأمر سينشئ مستودعًا جديدًا. انقر على Enter.
    Deploying from source requires an Artifact Registry Docker repository to store built containers.
    A repository named [cloud-run-source-deploy] in region [us-central1] will be created.
    
    Do you want to continue (Y/n)?
    
    قد تستغرق عملية النشر بضع دقائق. بعد اكتمال عملية النشر، ستظهر لك نتيجة مشابهة لما يلي:
    Service [codelab-o11y-service] revision [codelab-o11y-service-00001-t2q] has been deployed and is serving 100 percent of traffic.
    Service URL: https://codelab-o11y-service-12345678901.us-central1.run.app
    
  2. انسخ عنوان URL لخدمة Cloud Run المعروض في علامة تبويب أو نافذة منفصلة في المتصفّح. بدلاً من ذلك، شغِّل الأمر التالي في الوحدة الطرفية لطباعة عنوان URL الخاص بالخدمة وانقر على عنوان URL المعروض مع الضغط على المفتاح Ctrl لفتح عنوان URL:
    gcloud run services list \
         --format='value(URL)' \
         --filter='SERVICE:"codelab-o11y-service"'
    
    عند فتح عنوان URL، قد يظهر الخطأ 500 أو الرسالة التالية:
    Sorry, this is just a placeholder...
    
    يعني ذلك أنّ الخدمات لم تنتهِ من عملية النشر. يُرجى الانتظار بضع لحظات وإعادة تحميل الصفحة. في النهاية، سيظهر لك نص يبدأ بـ معلومات طريفة عن الكلاب ويتضمّن 10 معلومات طريفة عن الكلاب.

جرِّب التفاعل مع التطبيق للحصول على معلومات مسلّية عن الحيوانات المختلفة. لإجراء ذلك، أضِف المَعلمة animal إلى عنوان URL، مثل ?animal=[ANIMAL] حيث [ANIMAL] هو اسم حيوان. على سبيل المثال، أضِف ?animal=cat للحصول على 10 حقائق طريفة عن القطط أو ?animal=sea turtle للحصول على 10 حقائق طريفة عن السلاحف البحرية.

7. تدقيق طلبات البيانات من Vertex API

توفّر عمليات تدقيق طلبات بيانات Google API إجابات عن أسئلة مثل "مَن طلب بيانات واجهة برمجة تطبيقات معيّنة وأين ومتى؟". تكون عملية التدقيق مهمة عند تحديد المشاكل في تطبيقك أو التحقيق في استهلاك الموارد أو إجراء تحليل الطب الشرعي للبرامج.

تتيح لك سجلات التدقيق تتبُّع الأنشطة الإدارية وأنشطة النظام، بالإضافة إلى تسجيل المكالمات إلى عمليات واجهة برمجة التطبيقات "قراءة البيانات" و "كتابة البيانات". للتدقيق في طلبات Vertex AI لإنشاء المحتوى، عليك تفعيل سجلّات التدقيق "قراءة البيانات" في وحدة تحكّم Cloud.

  1. انقر على الزر أدناه لفتح صفحة "سجلات التدقيق" في Cloud Console

  2. تأكَّد من اختيار المشروع الذي أنشأته لهذا المختبر في الصفحة. يظهر المشروع المحدّد في أعلى يمين الصفحة مباشرةً من قائمة الهامبرغر:
    القائمة المنسدلة الخاصة بالمشاريع في Google Cloud Console
    إذا لزم الأمر، اختَر المشروع الصحيح من مربّع التحرير والسرد.
  3. في جدول إعدادات سجلّات تدقيق الوصول إلى البيانات، ابحث عن خدمة Vertex AI API في عمود "الخدمة"، ثم اختَر الخدمة من خلال وضع علامة في مربّع الاختيار على يمين اسم الخدمة.
    اختَر Vertex AI API
  4. في لوحة المعلومات على اليسار، اختَر نوع التدقيق "قراءة البيانات".
    التحقّق من سجلّات قراءة البيانات
  5. انقر على حفظ.

لإنشاء سجلّات التدقيق، افتح عنوان URL للخدمة. أعِد تحميل الصفحة أثناء تغيير قيمة المَعلمة ?animal= للحصول على نتائج مختلفة.

استكشاف سجلّات التدقيق

  1. انقر على الزر أدناه لفتح صفحة "مستكشف السجلّات" في وحدة تحكّم Cloud:

  2. الصِق الفلتر التالي في جزء "طلب البحث".
    LOG_ID("cloudaudit.googleapis.com%2Fdata_access") AND
    protoPayload.serviceName="aiplatform.googleapis.com"
    
    جزء "طلب البحث" هو محرّر يقع بالقرب من أعلى صفحة "مستكشف السجلات":
    طلب البحث في سجلّات التدقيق
  3. انقر على Run query (تنفيذ طلب البحث).
  4. اختَر أحد إدخالات سجلّ التدقيق ووسِّع الحقول لفحص المعلومات التي تم تسجيلها في السجلّ.
    يمكنك الاطّلاع على تفاصيل حول طلب بيانات من واجهة برمجة التطبيقات Vertex، بما في ذلك الطريقة والنموذج اللذان تم استخدامهما. يمكنك أيضًا الاطّلاع على هوية الجهة التي أرسلت الطلب والأذونات التي سمحت بتنفيذه.

8. تسجيل التفاعلات مع الذكاء الاصطناعي التوليدي

لا يمكنك العثور على مَعلمات طلب البيانات من واجهة برمجة التطبيقات أو بيانات الاستجابة في سجلّات التدقيق. ومع ذلك، يمكن أن تكون هذه المعلومات مهمة لتحديد المشاكل وحلّها في التطبيق وتحليل سير العمل. في هذه الخطوة، سنملأ هذه الفجوة من خلال إضافة تسجيل التطبيق.

تستخدِم عملية التنفيذ Logback مع Spring Boot لطباعة سجلّات التطبيق إلى الناتج العادي. تتضمّن هذه الطريقة إمكانية Cloud Run في تسجيل المعلومات المطبوعة في الإخراج العادي ونقلها إلى Cloud Logging تلقائيًا. من أجل تسجيل المعلومات كبيانات منظَّمة، يجب تنسيق السجلات المطبوعة وفقًا لذلك. اتّبِع التعليمات التالية لإضافة إمكانات تسجيل البيانات المنظَّمة إلى التطبيق.

  1. ارجع إلى نافذة (أو علامة تبويب) Cloud Shell في متصفّحك.
  2. أنشئ ملفًا جديدًا LoggingEventGoogleCloudEncoder.java وافتحه في Clooud Shell Editor:
    cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/LoggingEventGoogleCloudEncoder.java"
    
  3. انسخ الرمز التالي وألصِقه لتنفيذ أداة ترميز Logback التي ترمّز السجلّ بتنسيق JSON محوَّل إلى سلسلة يتبع تنسيق السجلّ المنظَّم في Google Cloud:
    package com.example.demo;
    
    import static ch.qos.logback.core.CoreConstants.UTF_8_CHARSET;
    
    import java.time.Instant;
    import ch.qos.logback.core.encoder.EncoderBase;
    import ch.qos.logback.classic.Level;
    import ch.qos.logback.classic.spi.ILoggingEvent;
    import java.util.HashMap;
    
    import com.google.gson.Gson;
    
    public class LoggingEventGoogleCloudEncoder extends EncoderBase<ILoggingEvent>  {
        private static final byte[] EMPTY_BYTES = new byte[0];
        private final Gson gson = new Gson();
    
        @Override
        public byte[] headerBytes() {
            return EMPTY_BYTES;
        }
    
        @Override
        public byte[] encode(ILoggingEvent e) {
            var timestamp = Instant.ofEpochMilli(e.getTimeStamp());
            var fields = new HashMap<String, Object>() {
                {
                    put("timestamp", timestamp.toString());
                    put("severity", severityFor(e.getLevel()));
                    put("message", e.getMessage());
                }
            };
            var params = e.getKeyValuePairs();
            if (params != null && params.size() > 0) {
                params.forEach(kv -> fields.putIfAbsent(kv.key, kv.value));
            }
            var data = gson.toJson(fields) + "\n";
            return data.getBytes(UTF_8_CHARSET);
        }
    
        @Override
        public byte[] footerBytes() {
            return EMPTY_BYTES;
        }
    
        private static String severityFor(Level level) {
            switch (level.toInt()) {
                case Level.TRACE_INT:
                return "DEBUG";
                case Level.DEBUG_INT:
                return "DEBUG";
                case Level.INFO_INT:
                return "INFO";
                case Level.WARN_INT:
                return "WARNING";
                case Level.ERROR_INT:
                return "ERROR";
                default:
                return "DEFAULT";
            }
        }
    }
    
  4. أنشئ ملفًا جديدًا logback.xml وافتحه في Clooud Shell Editor:
    cloudshell edit "${HOME}/codelab-o11y/src/main/resources/logback.xml"
    
  5. انسخ XML التالي والصقه لضبط Logback لاستخدام برنامج الترميز مع أداة Logback التي تطبع السجلات إلى الإخراج العادي:
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration debug="true">
        <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="com.example.demo.LoggingEventGoogleCloudEncoder"/>
        </appender>
    
        <root level="info">
            <appender-ref ref="Console" />
        </root>
    </configuration>
    
  6. أعِد فتح الملف DemoApplication.java في "محرِّر Cloud Shell":
    cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/DemoApplication.java"
    
  7. استبدِل الرمز في أداة التعديل بالإصدار الموضّح أدناه لتسجيل طلبات واستجابات الذكاء الاصطناعي التوليدي. لاستبدال الرمز، احذف محتوى الملف ثم انسخ الرمز أدناه في أداة التعديل:
    package com.example.demo;
    
    import java.io.IOException;
    import java.util.Collections;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.google.cloud.ServiceOptions;
    import com.google.cloud.vertexai.VertexAI;
    import com.google.cloud.vertexai.api.GenerateContentResponse;
    import com.google.cloud.vertexai.generativeai.GenerativeModel;
    import com.google.cloud.vertexai.generativeai.ResponseHandler;
    
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            String port = System.getenv().getOrDefault("PORT", "8080");
            SpringApplication app = new SpringApplication(DemoApplication.class);
            app.setDefaultProperties(Collections.singletonMap("server.port", port));
            app.run(args);
        }
    }
    
    @RestController
    class HelloController {
        private final String projectId = ServiceOptions.getDefaultProjectId();
        private VertexAI vertexAI;
        private GenerativeModel model;
        private final Logger LOGGER = LoggerFactory.getLogger(HelloController.class);
    
        @PostConstruct
        public void init() {
            vertexAI = new VertexAI(projectId, "us-central1");
            model = new GenerativeModel("gemini-1.5-flash", vertexAI);
        }
    
        @PreDestroy
        public void destroy() {
            vertexAI.close();
        }
    
        @GetMapping("/")
        public String getFacts(@RequestParam(defaultValue = "dog") String animal) throws IOException {
            String prompt = "Give me 10 fun facts about " + animal + ". Return this as html without backticks.";
            GenerateContentResponse response = model.generateContent(prompt);
            LOGGER.atInfo()
                    .addKeyValue("animal", animal)
                    .addKeyValue("prompt", prompt)
                    .addKeyValue("response", response)
                    .log("Content is generated");
            return ResponseHandler.getText(response);
        }
    }
    

بعد بضع ثوانٍ، يحفظ Cloud Shell Editor التغييرات تلقائيًا.

نشر رمز تطبيق الذكاء الاصطناعي التوليدي على Cloud Run

  1. في نافذة الوحدة الطرفية، شغِّل الأمر لنشر الرمز المصدر للتطبيق على Cloud Run.
    gcloud run deploy codelab-o11y-service \
         --source="${HOME}/codelab-o11y/" \
         --region=us-central1 \
         --allow-unauthenticated
    
    إذا ظهرت لك الرسالة أدناه التي تُعلمك بأنّ الأمر سينشئ مستودعًا جديدًا. انقر على Enter.
    Deploying from source requires an Artifact Registry Docker repository to store built containers.
    A repository named [cloud-run-source-deploy] in region [us-central1] will be created.
    
    Do you want to continue (Y/n)?
    
    قد تستغرق عملية النشر بضع دقائق. بعد اكتمال عملية النشر، ستظهر لك نتيجة مشابهة لما يلي:
    Service [codelab-o11y-service] revision [codelab-o11y-service-00001-t2q] has been deployed and is serving 100 percent of traffic.
    Service URL: https://codelab-o11y-service-12345678901.us-central1.run.app
    
  2. انسخ عنوان URL لخدمة Cloud Run المعروض في علامة تبويب أو نافذة منفصلة في المتصفّح. بدلاً من ذلك، شغِّل الأمر التالي في الوحدة الطرفية لطباعة عنوان URL الخاص بالخدمة وانقر على عنوان URL المعروض مع الضغط على المفتاح Ctrl لفتح عنوان URL:
    gcloud run services list \
         --format='value(URL)' \
         --filter='SERVICE:"codelab-o11y-service"'
    
    عند فتح عنوان URL، قد يظهر الخطأ 500 أو الرسالة التالية:
    Sorry, this is just a placeholder...
    
    يعني ذلك أنّ الخدمات لم تنتهِ من عملية النشر. يُرجى الانتظار بضع لحظات وإعادة تحميل الصفحة. في النهاية، سيظهر لك نص يبدأ بـ معلومات طريفة عن الكلاب ويتضمّن 10 معلومات طريفة عن الكلاب.

لإنشاء سجلّات التطبيق، افتح عنوان URL للخدمة. أعِد تحميل الصفحة أثناء تغيير قيمة المَعلمة ?animal= للحصول على نتائج مختلفة.
للاطّلاع على سجلّات التطبيق، اتّبِع الخطوات التالية:

  1. انقر على الزر أدناه لفتح صفحة "مستكشف السجلّات" في Cloud Console:

  2. الصِق الفلتر التالي في لوحة "طلب البحث" (الخطوة 2 في واجهة "مستكشف السجلات"):
    LOG_ID("run.googleapis.com%2Fstdout") AND
    severity=DEBUG
    
  3. انقر على Run query (تنفيذ طلب البحث).

تعرض نتيجة طلب البحث السجلات التي تتضمّن الطلب وردّ Vertex AI، بما في ذلك تقييمات الأمان.

9- احتساب التفاعلات مع الذكاء الاصطناعي التوليدي

تكتب Cloud Run مقاييس مُدارة يمكن استخدامها لمراقبة الخدمات التي تم نشرها. توفّر مقاييس المراقبة التي يديرها المستخدم تحكّمًا أكبر في البيانات ووتيرة تعديل المقياس. لتنفيذ هذا المقياس، يجب كتابة رمز برمجي يجمع البيانات ويكتبها في Cloud Monitoring. راجِع الخطوة التالية (اختيارية) لمعرفة طريقة تنفيذها باستخدام حزمة تطوير البرامج (SDK) الخاصة بـ OpenTelemetry.

تعرض هذه الخطوة بديلاً لتنفيذ مقياس سلوك المستخدمين في الرمز، وهو المقاييس المستندة إلى السجلّ. تتيح لك المقاييس المستندة إلى السجلّات إنشاء مقاييس رصد من إدخالات السجلّ التي يكتبها تطبيقك في Cloud Logging. سنستخدم سجلّات التطبيق التي نفّذناها في الخطوة السابقة لتحديد مقياس مستند إلى السجلّ من نوع العداد. سيحصي المقياس عدد الطلبات الناجحة إلى Vertex API.

  1. انظر إلى نافذة مستكشف السجلات التي استخدمناها في الخطوة السابقة. ضمن "لوحة طلب البحث"، ابحث عن القائمة المنسدلة الإجراءات وانقر عليها لفتحها. اطّلِع على لقطة الشاشة أدناه للعثور على القائمة:
    شريط أدوات نتائج طلب البحث مع القائمة المنسدلة &quot;الإجراءات&quot;
  2. في القائمة التي تم فتحها، اختَر إنشاء مقياس لفتح لوحة إنشاء مقياس مستند إلى السجلّ.
  3. اتّبِع الخطوات التالية لضبط مقياس عدّاد جديد في لوحة إنشاء مقياس مستند إلى السجلّ:
    1. اضبط نوع المقياس: اختَر عداد.
    2. اضبط الحقول التالية في قسم التفاصيل:
      • اسم مقياس السجلّ: اضبط الاسم على model_interaction_count. تنطبق بعض القيود على التسمية. لمزيد من التفاصيل، يُرجى الاطّلاع على تحديد المشاكل وحلّها بشأن القيود على التسمية.
      • الوصف: أدخِل وصفًا للمقياس. على سبيل المثال، Number of log entries capturing successful call to model inference.
      • الوحدات: اترك هذا الحقل فارغًا أو أدخِل الرقم 1.
    3. اترك القيم في قسم اختيار الفلتر. يُرجى العِلم أنّ حقل إنشاء فلتر يتضمّن الفلتر نفسه الذي استخدمناه لعرض سجلّات التطبيق.
    4. (اختياري) أضِف تصنيفًا يساعد في احتساب عدد المكالمات لكل حيوان. ملاحظة: يمكن أن تؤدي هذه التصنيفات إلى زيادة عدد القيم الممكنة للمقياس بشكل كبير، ولا يُنصح باستخدامها في مرحلة الإنتاج:
      1. انقر على إضافة تصنيف.
      2. اضبط الحقول التالية في قسم التصنيفات:
        • اسم التصنيف: اضبط الاسم على animal.
        • الوصف: أدخِل وصفًا للتصنيف. مثلاً: Animal parameter
        • نوع التصنيف: اختَر STRING.
        • اسم الحقل: النوع jsonPayload.animal
        • التعبير العادي: اتركه فارغًا.
      3. 3. انقر على تم.
    5. انقر على إنشاء مقياس لإنشاء المقياس.

يمكنك أيضًا إنشاء مقياس مستند إلى السجلّ من صفحة المقاييس المستندة إلى السجلّ باستخدام الأمر gcloud logging metrics create CLI أو باستخدام google_logging_metric مورد Terraform.

لإنشاء بيانات المقاييس، افتح عنوان URL الخاص بالخدمة. أعِد تحميل الصفحة المفتوحة عدة مرات لإجراء طلبات متعددة إلى النموذج. كما في السابق، حاوِل استخدام حيوانات مختلفة في المَعلمة.

أدخِل طلب بحث PromQL للبحث عن بيانات المقياس المستند إلى السجلّ. لإدخال طلب بحث PromQL، اتّبِع الخطوات التالية:

  1. انقر على الزر أدناه لفتح صفحة "مستكشف المقاييس" في Cloud Console:

  2. في شريط أدوات جزء "أداة إنشاء طلبات البحث"، انقر على الزر الذي يحمل الاسم < > MQL أو < > PromQL. يمكنك الاطّلاع على الصورة أدناه لمعرفة مكان الزر.
    موقع زرّ طلب البحث بلغة الاستعلامات الخاصة بـ &quot;مقاييس Google&quot; في &quot;أداة استكشاف المقاييس&quot;
  3. تأكَّد من اختيار PromQL في مفتاح التبديل اللغة. يظهر مفتاح تبديل اللغة في شريط الأدوات نفسه الذي يتيح لك تنسيق طلب البحث.
  4. أدخِل طلب البحث في محرّر طلبات البحث:
    sum(rate(logging_googleapis_com:user_model_interaction_count{monitored_resource="cloud_run_revision"}[${__interval}]))
    
    لمزيد من المعلومات حول استخدام PromQL، يُرجى الاطّلاع على PromQL في Cloud Monitoring.
  5. انقر على تنفيذ طلب البحث. سيظهر لك رسم بياني خطي مشابه للقطة الشاشة هذه:
    عرض المقاييس التي تم الاستعلام عنها

    يُرجى العِلم أنّه عند تفعيل زر التبديل التشغيل التلقائي، لن يظهر الزر تنفيذ طلب البحث.

10. (اختياري) استخدام Open Telemetry للمراقبة والتتبُّع

كما ذكرنا في الخطوة السابقة، يمكن تنفيذ المقاييس باستخدام حزمة تطوير البرامج (SDK) الخاصة بمنصة OpenTelemetry (Otel). يُعدّ استخدام OTel في بنى الخدمات المتعددة من الممارسات الموصى بها. توضّح هذه الخطوة كيفية إضافة أدوات OTel إلى تطبيق Spring Boot. في هذه الخطوة، عليك إجراء ما يلي:

  • تجهيز تطبيق Spring Boot بإمكانات التتبُّع التلقائي
  • تنفيذ مقياس عدّاد لتتبُّع عدد طلبات النموذج الناجحة
  • ربط التتبُّع بسجلات التطبيق

البنية المقترَحة للخدمات على مستوى المنتج هي استخدام أداة تجميع OTel لجمع جميع بيانات المراقبة واستيعابها من خدمات متعددة. لا يستخدم الرمز البرمجي في هذه الخطوة أداة التجميع لتبسيط العملية. بدلاً من ذلك، تستخدم عمليات تصدير OTel التي تكتب البيانات مباشرةً إلى Google Cloud.

إعداد تطبيق Spring Boot باستخدام مكوّنات OTel والتتبُّع التلقائي

  1. ارجع إلى نافذة (أو علامة تبويب) Cloud Shell في متصفّحك.
  2. في نافذة الأوامر، عدِّل الملف application.permissions بإضافة مَعلمات إعداد إضافية:
    cat >> "${HOME}/codelab-o11y/src/main/resources/application.properties" << EOF
    otel.logs.exporter=none
    otel.traces.exporter=google_cloud_trace
    otel.metrics.exporter=google_cloud_monitoring
    otel.resource.attributes.service.name=codelab-o11y-service
    otel.traces.sampler=always_on
    EOF
    
    تحدّد هذه المَعلمات عملية تصدير بيانات إمكانية المراقبة إلى Cloud Trace وCloud Monitoring، وتفرض أخذ عيّنات من جميع عمليات التتبُّع.
  3. أضِف الاعتماديات المطلوبة في OpenTelemetry إلى ملف pom.xml:
    sed -i 's/<dependencies>/<dependencies>\
    \
            <dependency>\
                <groupId>io.opentelemetry.instrumentation<\/groupId>\
                <artifactId>opentelemetry-spring-boot-starter<\/artifactId>\
            <\/dependency>\
            <dependency>\
                <groupId>com.google.cloud.opentelemetry<\/groupId>\
                <artifactId>exporter-auto<\/artifactId>\
                <version>0.33.0-alpha<\/version>\
            <\/dependency>\
            <dependency>\
                <groupId>com.google.cloud.opentelemetry<\/groupId>\
                <artifactId>exporter-trace<\/artifactId>\
                <version>0.33.0<\/version>\
            <\/dependency>\
            <dependency>\
                <groupId>com.google.cloud.opentelemetry<\/groupId>\
                <artifactId>exporter-metrics<\/artifactId>\
                <version>0.33.0<\/version>\
            <\/dependency>\
    /g' "${HOME}/codelab-o11y/pom.xml"
    
  4. أضِف قائمة مواد OpenTelemetry إلى ملف pom.xml:
    sed -i 's/<\/properties>/<\/properties>\
        <dependencyManagement>\
            <dependencies>\
                <dependency>\
                    <groupId>io.opentelemetry.instrumentation<\/groupId>\
                    <artifactId>opentelemetry-instrumentation-bom<\/artifactId>\
                    <version>2.12.0<\/version>\
                    <type>pom<\/type>\
                    <scope>import<\/scope>\
                <\/dependency>\
            <\/dependencies>\
        <\/dependencyManagement>\
    /g' "${HOME}/codelab-o11y/pom.xml"
    
  5. أعِد فتح الملف DemoApplication.java في "محرِّر Cloud Shell":
    cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/DemoApplication.java"
    
  6. استبدِل الرمز الحالي بالرمز الذي يزيد من قيمة مقياس الأداء. لاستبدال الرمز، احذف محتوى الملف ثم انسخ الرمز أدناه في أداة التعديل:
    package com.example.demo;
    
    import io.opentelemetry.api.common.AttributeKey;
    import io.opentelemetry.api.common.Attributes;
    import io.opentelemetry.api.OpenTelemetry;
    import io.opentelemetry.api.metrics.LongCounter;
    
    import java.io.IOException;
    import java.util.Collections;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.google.cloud.ServiceOptions;
    import com.google.cloud.vertexai.VertexAI;
    import com.google.cloud.vertexai.api.GenerateContentResponse;
    import com.google.cloud.vertexai.generativeai.GenerativeModel;
    import com.google.cloud.vertexai.generativeai.ResponseHandler;
    
    
    @SpringBootApplication
    public class DemoApplication {
    
        public static void main(String[] args) {
            String port = System.getenv().getOrDefault("PORT", "8080");
            SpringApplication app = new SpringApplication(DemoApplication.class);
            app.setDefaultProperties(Collections.singletonMap("server.port", port));
            app.run(args);
        }
    }
    
    @RestController
    class HelloController {
        private final String projectId = ServiceOptions.getDefaultProjectId();
        private VertexAI vertexAI;
        private GenerativeModel model;
        private final Logger LOGGER = LoggerFactory.getLogger(HelloController.class);
        private static final String INSTRUMENTATION_NAME = "genai-o11y/java/workshop/example";
        private static final AttributeKey<String> ANIMAL = AttributeKey.stringKey("animal");
        private final LongCounter counter;
    
        public HelloController(OpenTelemetry openTelemetry) {
            this.counter = openTelemetry.getMeter(INSTRUMENTATION_NAME)
                    .counterBuilder("model_call_counter")
                    .setDescription("Number of successful model calls")
                    .build();
        }
    
        @PostConstruct
        public void init() {
            vertexAI = new VertexAI(projectId, "us-central1");
            model = new GenerativeModel("gemini-1.5-flash", vertexAI);
        }
    
        @PreDestroy
        public void destroy() {
            vertexAI.close();
        }
    
        @GetMapping("/")
        public String getFacts(@RequestParam(defaultValue = "dog") String animal) throws IOException {
            String prompt = "Give me 10 fun facts about " + animal + ". Return this as html without backticks.";
            GenerateContentResponse response = model.generateContent(prompt);
            LOGGER.atInfo()
                    .addKeyValue("animal", animal)
                    .addKeyValue("prompt", prompt)
                    .addKeyValue("response", response)
                    .log("Content is generated");
            counter.add(1, Attributes.of(ANIMAL, animal));
            return ResponseHandler.getText(response);
        }
    }
    
  7. أعِد فتح الملف LoggingEventGoogleCloudEncoder.java في "محرِّر Cloud Shell":
    cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/LoggingEventGoogleCloudEncoder.java"
    
  8. استبدِل الرمز الحالي بالإصدار الذي يضيف سمات التتبُّع إلى السجلات المكتوبة. تتيح إضافة السمات ربط السجلات بفترات التتبُّع الصحيحة. لاستبدال الرمز، احذف محتوى الملف ثم انسخ الرمز أدناه في أداة التعديل:
    package com.example.demo;
    
    import static ch.qos.logback.core.CoreConstants.UTF_8_CHARSET;
    
    import java.time.Instant;
    import java.util.HashMap;
    
    import ch.qos.logback.core.encoder.EncoderBase;
    import ch.qos.logback.classic.Level;
    import ch.qos.logback.classic.spi.ILoggingEvent;
    import com.google.cloud.ServiceOptions;
    import io.opentelemetry.api.trace.Span;
    import io.opentelemetry.api.trace.SpanContext;
    import io.opentelemetry.context.Context;
    
    import com.google.gson.Gson;
    
    
    public class LoggingEventGoogleCloudEncoder extends EncoderBase<ILoggingEvent>  {
        private static final byte[] EMPTY_BYTES = new byte[0];
        private final Gson gson;
        private final String projectId;
        private final String tracePrefix;
    
    
        public LoggingEventGoogleCloudEncoder() {
            this.gson = new Gson();
            this.projectId = lookUpProjectId();
            this.tracePrefix = "projects/" + (projectId == null ? "" : projectId) + "/traces/";
        }
    
        private static String lookUpProjectId() {
            return ServiceOptions.getDefaultProjectId();
        }
    
        @Override
        public byte[] headerBytes() {
            return EMPTY_BYTES;
        }
    
        @Override
        public byte[] encode(ILoggingEvent e) {
            var timestamp = Instant.ofEpochMilli(e.getTimeStamp());
            var fields = new HashMap<String, Object>() {
                {
                    put("timestamp", timestamp.toString());
                    put("severity", severityFor(e.getLevel()));
                    put("message", e.getMessage());
                    SpanContext context = Span.fromContext(Context.current()).getSpanContext();
                    if (context.isValid()) {
                        put("logging.googleapis.com/trace", tracePrefix + context.getTraceId());
                        put("logging.googleapis.com/spanId", context.getSpanId());
                        put("logging.googleapis.com/trace_sampled", Boolean.toString(context.isSampled()));
                    }
                }
            };
            var params = e.getKeyValuePairs();
            if (params != null && params.size() > 0) {
                params.forEach(kv -> fields.putIfAbsent(kv.key, kv.value));
            }
            var data = gson.toJson(fields) + "\n";
            return data.getBytes(UTF_8_CHARSET);
        }
    
        @Override
        public byte[] footerBytes() {
            return EMPTY_BYTES;
        }
    
        private static String severityFor(Level level) {
            switch (level.toInt()) {
                case Level.TRACE_INT:
                return "DEBUG";
                case Level.DEBUG_INT:
                return "DEBUG";
                case Level.INFO_INT:
                return "INFO";
                case Level.WARN_INT:
                return "WARNING";
                case Level.ERROR_INT:
                return "ERROR";
                default:
                return "DEFAULT";
            }
        }
    }
    

بعد بضع ثوانٍ، يحفظ Cloud Shell Editor التغييرات تلقائيًا.

نشر رمز تطبيق الذكاء الاصطناعي التوليدي على Cloud Run

  1. في نافذة الوحدة الطرفية، شغِّل الأمر لنشر الرمز المصدر للتطبيق على Cloud Run.
    gcloud run deploy codelab-o11y-service \
         --source="${HOME}/codelab-o11y/" \
         --region=us-central1 \
         --allow-unauthenticated
    
    إذا ظهرت لك الرسالة أدناه التي تُعلمك بأنّ الأمر سينشئ مستودعًا جديدًا. انقر على Enter.
    Deploying from source requires an Artifact Registry Docker repository to store built containers.
    A repository named [cloud-run-source-deploy] in region [us-central1] will be created.
    
    Do you want to continue (Y/n)?
    
    قد تستغرق عملية النشر بضع دقائق. بعد اكتمال عملية النشر، ستظهر لك نتيجة مشابهة لما يلي:
    Service [codelab-o11y-service] revision [codelab-o11y-service-00001-t2q] has been deployed and is serving 100 percent of traffic.
    Service URL: https://codelab-o11y-service-12345678901.us-central1.run.app
    
  2. انسخ عنوان URL لخدمة Cloud Run المعروض في علامة تبويب أو نافذة منفصلة في المتصفّح. بدلاً من ذلك، شغِّل الأمر التالي في الوحدة الطرفية لطباعة عنوان URL الخاص بالخدمة وانقر على عنوان URL المعروض مع الضغط على المفتاح Ctrl لفتح عنوان URL:
    gcloud run services list \
         --format='value(URL)' \
         --filter='SERVICE:"codelab-o11y-service"'
    
    عند فتح عنوان URL، قد يظهر الخطأ 500 أو الرسالة التالية:
    Sorry, this is just a placeholder...
    
    يعني ذلك أنّ الخدمات لم تنتهِ من عملية النشر. يُرجى الانتظار بضع لحظات وإعادة تحميل الصفحة. في النهاية، سيظهر لك نص يبدأ بـ معلومات طريفة عن الكلاب ويتضمّن 10 معلومات طريفة عن الكلاب.

لإنشاء بيانات القياس عن بُعد، افتح عنوان URL الخاص بالخدمة. أعِد تحميل الصفحة أثناء تغيير قيمة المَعلمة ?animal= للحصول على نتائج مختلفة.

استكشاف عمليات تتبُّع التطبيقات

  1. انقر على الزر أدناه لفتح صفحة "مستكشف عمليات التتبُّع" في Cloud Console:

  2. اختَر أحد عمليات التتبُّع الأحدث. من المفترض أن تظهر لك 5 أو 6 فترات زمنية كما هو موضّح في لقطة الشاشة أدناه.
    عرض مدى التطبيق في &quot;مستكشف سجلّات التتبُّع&quot;
  3. ابحث عن النطاق الذي يتتبّع طلب الحدث إلى معالج الأحداث (الطريقة fun_facts). سيكون هذا هو النطاق الأخير الذي يحمل الاسم /.
  4. في لوحة تفاصيل التتبُّع، اختَر السجلات والأحداث. ستظهر لك سجلّات التطبيق المرتبطة بهذا النطاق المحدّد. يتم رصد الارتباط باستخدام أرقام تعريف التتبُّع والمدّة في عملية التتبُّع وفي السجلّ. من المفترض أن يظهر لك سجلّ التطبيق الذي كتب الطلب واستجابة Vertex API.

استكشاف مقياس العداد

  1. انقر على الزر أدناه لفتح صفحة "مستكشف المقاييس" في Cloud Console:

  2. في شريط أدوات جزء "أداة إنشاء طلبات البحث"، انقر على الزر الذي يحمل الاسم < > MQL أو < > PromQL. يمكنك الاطّلاع على الصورة أدناه لمعرفة مكان الزر.
    موقع زرّ طلب البحث بلغة الاستعلامات الخاصة بـ &quot;مقاييس Google&quot; في &quot;أداة استكشاف المقاييس&quot;
  3. تأكَّد من اختيار PromQL في مفتاح التبديل اللغة. يظهر مفتاح تبديل اللغة في شريط الأدوات نفسه الذي يتيح لك تنسيق طلب البحث.
  4. أدخِل طلب البحث في محرّر طلبات البحث:
    sum(rate(workload_googleapis_com:model_call_counter{monitored_resource="generic_task"}[${__interval}]))
    
  5. انقر على تنفيذ طلب البحث.عندما يكون خيار التشغيل التلقائي مفعَّلاً، لا يظهر الزر تنفيذ طلب البحث.

11. (اختياري) إخفاء المعلومات الحسّاسة من السجلات

في الخطوة 10، سجّلنا معلومات حول تفاعل التطبيق مع نموذج Gemini. تضمّنت هذه المعلومات اسم الحيوان والطلب الفعلي وردّ النموذج. مع أنّ تخزين هذه المعلومات في السجلّ يجب أن يكون آمنًا، إلا أنّ ذلك لا ينطبق على العديد من السيناريوهات الأخرى. قد يتضمّن الطلب بعض المعلومات الشخصية أو الحساسة الأخرى التي لا يريد المستخدم تخزينها. لحلّ هذه المشكلة، يمكنك إخفاء البيانات الحساسة التي يتم تسجيلها في Cloud Logging. للحدّ من تعديلات الرمز، ننصحك بالحلّ التالي.

  1. إنشاء موضوع Pub/Sub لتخزين إدخالات السجل الواردة
  2. أنشئ مخزَن سجلّ يعيد توجيه السجلات التي تمّت إضافتها إلى موضوع PubSub.
  3. أنشئ سلسلة من الإجراءات في Dataflow تعدّل السجلات التي تمّت إعادة توجيهها إلى موضوع Pub/Sub باتّباع الخطوات التالية:
    1. قراءة إدخال في السجلّ من موضوع Pub/Sub
    2. فحص حمولة الإدخال بحثًا عن معلومات حساسة باستخدام DLP Inspection API
    3. إخفاء المعلومات الحساسة في الحمولة باستخدام إحدى طرق الإخفاء في "منع فقدان البيانات"
    4. كتابة إدخال السجلّ المشوّش في Cloud Logging
  4. نشر مسار المعالجة

12. (اختياري) إخلاء مساحة تخزين

لتجنُّب تحمُّل رسوم مقابل الموارد وواجهات برمجة التطبيقات المستخدَمة في درس تطبيقي حول الترميز، يُنصح بإزالة الموارد بعد الانتهاء من الدرس التطبيقي حول الترميز. أسهل طريقة لإيقاف الفوترة هي حذف المشروع الذي أنشأته من أجل جلسة التدريب العملي.

  1. لحذف المشروع، نفِّذ أمر حذف المشروع في الوحدة الطرفية:
    PROJECT_ID=$(gcloud config get-value project)
    gcloud projects delete ${PROJECT_ID} --quiet
    
    يؤدي حذف مشروعك على السحابة الإلكترونية إلى إيقاف الفوترة لجميع الموارد وواجهات برمجة التطبيقات المستخدَمة في هذا المشروع. من المفترض أن تظهر لك هذه الرسالة حيث يمثّل PROJECT_ID رقم تعريف مشروعك:
    Deleted [https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID].
    
    You can undo this operation for a limited period by running the command below.
        $ gcloud projects undelete PROJECT_ID
    
    See https://cloud.google.com/resource-manager/docs/creating-managing-projects for information on shutting down projects.
    
  2. (اختياري) إذا تلقّيت رسالة خطأ، راجِع الخطوة 5 للعثور على رقم تعريف المشروع الذي استخدمته أثناء الجلسة التدريبية. استبدِلها بالأمر في التعليمات الأولى. على سبيل المثال، إذا كان رقم تعريف مشروعك هو lab-example-project، سيكون الأمر كما يلي:
    gcloud projects delete lab-project-id-example --quiet
    

13. تهانينا

في هذا التمرين العملي، أنشأت تطبيقًا مستندًا إلى الذكاء الاصطناعي التوليدي يستخدم نموذج Gemini لتقديم التوقعات. وتم تزويد التطبيق بإمكانات أساسية للمراقبة والتسجيل. لقد نشرت التطبيق والتغييرات من رمز المصدر إلى Cloud Run. بعد ذلك، يمكنك استخدام منتجات Google Cloud Observability لتتبُّع أداء التطبيق، ما يضمن لك موثوقيته.

إذا كنت مهتمًا بالمشاركة في دراسة بحثية حول تجربة المستخدم (UX) لتحسين المنتجات التي عملت عليها اليوم، يمكنك التسجيل هنا.

في ما يلي بعض الخيارات لمواصلة التعلّم: