‫AlloyDB Omni وEmbeddingGemma مع Gemma 4 على Kubernetes

1. مقدمة

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية نشر AlloyDB Omni على Google Kubernetes Engine‏ (GKE) واستخدامه مع نماذج مفتوحة المصدر، مثل EmbeddingGemma وGemma 4، لإنشاء التضمينات والتوقّعات. يؤدي تشغيل كل من قاعدة البيانات والنماذج في المجموعة نفسها إلى تقليل وقت استجابة الشبكة وتجنُّب الاعتماد على خدمات تابعة لجهات خارجية. ويساعد أيضًا في تلبية متطلبات الامتثال والموقع الجغرافي للبيانات لأنّ بياناتك لا تغادر بيئتك أبدًا.

مخطّط بياني لبنية AlloyDB Omni وEmbeddingGemma على GKE

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

  • فهم أساسي لـ Google Cloud ووحدة تحكّم Google Cloud
  • معرفة أساسية بـ Kubernetes وGKE
  • الإلمام بواجهة سطر الأوامر وGoogle Cloud Shell

أهداف الدورة التعليمية

  • كيفية نشر AlloyDB Omni على مجموعة GKE
  • كيفية الربط بـ AlloyDB Omni
  • كيفية تحميل البيانات إلى AlloyDB Omni
  • كيفية نشر نماذج الذكاء الاصطناعي (التضمين والنموذج اللغوي الكبير) على GKE
  • كيفية تسجيل نماذج الذكاء الاصطناعي في AlloyDB Omni
  • كيفية إنشاء تضمينات للبحث الدلالي
  • كيفية تنفيذ طلبات البحث الدلالي في AlloyDB Omni
  • كيفية إنشاء فهارس المتّجهات واستخدامها في AlloyDB Omni

المتطلبات

  • حساب Google Cloud ومشروع على السحابة الإلكترونية
  • متصفّح ويب، مثل Chrome

2. الإعداد والمتطلبات

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

  1. سجِّل الدخول إلى Google Cloud Console. إذا لم يكن لديك حساب على Gmail أو Google Workspace، يمكنك إنشاء حساب. استخدام حساب شخصي بدلاً من حساب عمل أو حساب تديره مؤسسة تعليمية
  1. أنشِئ مشروعًا جديدًا أو اختَر مشروعًا حاليًا. في عنوان Google Cloud Console، انقر على اختيار مشروع، ثم انقر على مشروع جديد.

مربّع حوار "اختيار مشروع" في Google Cloud Console

في نافذة اختيار مشروع، انقر على مشروع جديد لفتح مربّع حوار إنشاء المشروع.

مربّع حوار إنشاء مشروع جديد

في مربّع الحوار، أدخِل اسم المشروع واختَر مؤسستك أو موقعك الجغرافي.

حقول إدخال تفاصيل المشروع

  • اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. لا تستخدم Google APIs اسم المشروع، ويمكنك تغييره في أي وقت.
  • رقم تعريف المشروع فريد في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكنك تغييره بعد ضبطه). تنشئ وحدة تحكّم Google Cloud تلقائيًا معرّفًا فريدًا، أو يمكنك تقديم معرّفك الخاص. في هذا الدرس التطبيقي حول الترميز، يمكنك الإشارة إلى رقم تعريف مشروعك باستخدام العنصر النائب .
  • رقم المشروع هو معرّف ثالث تستخدمه بعض واجهات برمجة التطبيقات. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات Resource Manager.

تفعيل الفوترة

إذا أعددت الفوترة باستخدام أرصدة Google Cloud، يمكنك تخطّي هذه الخطوة.

لإعداد حساب فوترة شخصي، فعِّل الفوترة في Google Cloud Console.

  • تبلغ تكلفة إكمال هذا التمرين العملي أقل من 5 دولار أمريكي من موارد Google Cloud.
  • اتّبِع خطوات التنظيف في نهاية هذا التمرين لحذف الموارد وتجنُّب فرض رسوم إضافية.
  • يمكن للمستخدمين الجدد الاستفادة من فترة تجريبية مجانية بقيمة 300 دولار أمريكي.

بدء Cloud Shell

في هذا الدرس التطبيقي حول الترميز، ستستخدم Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.

من وحدة تحكّم Google Cloud، انقر على رمز تفعيل Cloud Shell في شريط الأدوات في أعلى يسار الصفحة:

زر تفعيل Cloud Shell

بدلاً من ذلك، اضغط على G ثم S، أو افتح Google Cloud Shell مباشرةً.

عند الاتصال، يعرض Cloud Shell طلب Terminal:

لقطة شاشة لوحدة Google Cloud Shell الطرفية

يتضمّن Cloud Shell مساحة تخزين دائمة وأدوات للمطوّرين. يمكنك تنفيذ جميع الخطوات في هذا الدرس التطبيقي حول الترميز من متصفّحك.

3- تفعيل واجهات برمجة التطبيقات

لاستخدام Google Kubernetes Engine‏ (GKE) في عمليات نشر AlloyDB Omni والنماذج، فعِّل واجهتَي برمجة التطبيقات Compute Engine وGKE في مشروعك على Google Cloud.

في Cloud Shell، تأكَّد من ضبط رقم تعريف مشروعك:

PROJECT_ID=$(gcloud config get-value project)
echo $PROJECT_ID

إذا لم يتم تحديد رقم تعريف مشروعك، اضبطه:

export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

فعِّل واجهات برمجة التطبيقات المطلوبة:

gcloud services enable compute.googleapis.com
gcloud services enable container.googleapis.com

الناتج المتوقَّع:

student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=test-project-001-402417
student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable compute.googleapis.com
gcloud services enable container.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

يمكنك الاطّلاع على معلومات عن كل واجهة برمجة تطبيقات مفعَّلة في المستندات.

4. نشر AlloyDB Omni على GKE

لنشر AlloyDB Omni على GKE، عليك إعداد مجموعة Kubernetes باتّباع متطلبات مشغّل AlloyDB Omni.

إنشاء مجموعة GKE

انشر مجموعة GKE في وضع "الطيار الآلي" لتشغيل AlloyDB Omni والمشغّل وحاويات المراقبة. باستخدام Autopilot، نسهّل عملية النشر، إذ سيتم تلقائيًا تخصيص جميع الموارد لمشغّل AlloyDB Omni والمجموعة والمكوّنات الأخرى.

اختَر المنطقة التي تنشر فيها مواردك. اختَر منطقة قريبة جغرافيًا من موقعك الجغرافي:

export LOCATION=<your region>

اضبط متغيّرات البيئة لعملية النشر:

export PROJECT_ID=$(gcloud config get-value project)
export CLUSTER_NAME=alloydb-ai-gke

أنشئ مجموعة GKE Autopilot:

gcloud container clusters create-auto ${CLUSTER_NAME} \
  --project=${PROJECT_ID} \
  --region=${LOCATION}

الناتج المتوقّع في وحدة التحكّم:

student@cloudshell:~ (test-project-001-402417)$ export PROJECT_ID=$(gcloud config get project)
export CLUSTER_NAME=alloydb-ai-gke
Your active configuration is: [test-project-001-402417]
student@cloudshell:~ (test-project-001-402417)$ gcloud container clusters create-auto ${CLUSTER_NAME} \
>   --project=${PROJECT_ID} \
>   --region=${LOCATION}
Creating cluster alloydb-ai-gke in us-east4... Cluster is being health-checked.
..⠹
Creating cluster alloydb-ai-gke in us-east4... Cluster is being health-checked
(Kubernetes Control Plane is healthy)...done.
Created [https://container.googleapis.com/v1/projects/gleb-genai-002/zones/us-east4/clusters/alloydb-ai-gke].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-east4/alloydb-ai-gke?project=gleb-genai-002
kubeconfig entry generated for alloydb-ai-gke.
NAME            LOCATION  MASTER_VERSION      MASTER_IP      MACHINE_TYPE   NODE_VERSION        NUM_NODES  STATUS   STACK_TYPE
alloydb-ai-gke  us-east4  1.36.4-gke.1391002  34.145.214.51  ek-standard-8  1.36.4-gke.1391002  3          RUNNING  IPV4

إعداد المجموعة

ثبِّت المكوّنات المطلوبة، مثل cert-manager، وهو وحدة التحكّم في الشهادات في Kubernetes. لمعرفة التفاصيل، يُرجى الاطّلاع على مستندات تثبيت cert-manager.

يتضمّن Cloud Shell أداة سطر الأوامر kubectl وhelm في Kubernetes. احصل على بيانات اعتماد المجموعة باستخدام gcloud:

gcloud container clusters get-credentials ${CLUSTER_NAME} --region=${LOCATION}

ثبِّت cert-manager باستخدام helm:

helm install \
  cert-manager oci://quay.io/jetstack/charts/cert-manager \
  --version v1.21.2 \
  --namespace cert-manager \
  --create-namespace \
  --set featureGates="ServerSideApply=true" \
  --set global.leaderElection.namespace=cert-manager \
  --set "extraArgs={--certificate-request-minimum-backoff-duration=15s,--certificate-request-maximum-backoff-duration=5m}" \
  --set crds.enabled=true

الناتج المتوقّع في وحدة التحكّم (تم حجبه):

student@cloudshell:~$ elm install \
>   cert-manager oci://quay.io/jetstack/charts/cert-manager \
>   --version v1.21.2 \
>   --namespace cert-manager \
>   --create-namespace \
>  --set featureGates="ServerSideApply=true" \
>  --set global.leaderElection.namespace=cert-manager \
>  --set "extraArgs={--certificate-request-minimum-backoff-duration=15s,--certificate-request-maximum-backoff-duration=5m}" \
>   --set crds.enabled=true
Pulled: quay.io/jetstack/charts/cert-manager:v1.21.2
Digest: sha256:634dce9c13b56677a2c05e2ab76c312d0be2664022d5dd05815da67e1fd5f610
I1016 12:25:06.128464   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment cert-manager/cert-manager-cainjector: defaulted unspecified 'cpu' resource for containers [cert-manager-cainjector] (see http://g.co/gke/autopilot-defaults)."
I1016 12:25:06.129972   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment cert-manager/cert-manager: defaulted unspecified 'cpu' resource for containers [cert-manager-controller] (see http://g.co/gke/autopilot-defaults)."
I1016 12:25:06.134580   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment cert-manager/cert-manager-webhook: defaulted unspecified 'cpu' resource for containers [cert-manager-webhook] (see http://g.co/gke/autopilot-defaults)."
I1016 12:25:06.250590   30644 warnings.go:107] "Warning: AdmissionWebhookController: mutated namespaceselector of the webhooks to enforce GKE Autopilot policies."
I1016 12:25:09.758249   30644 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Job cert-manager/cert-manager-startupapicheck: defaulted unspecified 'cpu' resource for containers [cert-manager-startupapicheck] (see http://g.co/gke/autopilot-defaults)."
NAME: cert-manager
LAST DEPLOYED: Fri Oct 16 12:24:57 2026
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None
NOTES:
cert-manager v1.21.2 has been deployed successfully!

تثبيت عامل تشغيل AlloyDB Omni

ثبِّت عامل تشغيل AlloyDB Omni باستخدام Helm.

نزِّل مخطّط عامل تشغيل AlloyDB Omni وثبِّته:

helm install alloydbomni-operator oci://gcr.io/alloydb-omni/alloydbomni-operator \
--version 1.9.0 \
--create-namespace \
--namespace alloydb-omni-system \
$(helm install --help | grep -q -- '--rollback-on-failure' && echo '--rollback-on-failure' || echo '--atomic') \
--timeout 5m

الناتج المتوقّع في وحدة التحكّم (تم حجبه):

student@cloudshell:~$ helm install alloydbomni-operator oci://gcr.io/alloydb-omni/alloydbomni-operator \
> --version 1.9.0 \
> --create-namespace \
> --namespace alloydb-omni-system \
> $(helm install --help | grep -q -- '--rollback-on-failure' && echo '--rollback-on-failure' || echo '--atomic') \
> --timeout 5m

Pulled: gcr.io/alloydb-omni/alloydbomni-operator:1.9.0
Digest: sha256:4f6cc3f0c1fbe003ab7d0119afee516e5c67ec950cd2909b418e5a3f6f09d1f6
I1016 12:28:50.088533   30982 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment alloydb-omni-system/fleet-controller-manager: adjusted 'cpu' resource to meet requirements for containers [fleet-manager] (see http://g.co/gke/autopilot-defaults)."
I1016 12:28:50.092917   30982 warnings.go:107] "Warning: autopilot-default-resources-mutator:Autopilot updated Deployment alloydb-omni-system/local-controller-manager: adjusted 'cpu' resource to meet requirements for containers [local-manager] (see http://g.co/gke/autopilot-defaults)."
I1016 12:28:50.229717   30982 warnings.go:107] "Warning: AdmissionWebhookController: mutated namespaceselector of the webhooks to enforce GKE Autopilot policies."
I1016 12:28:50.238578   30982 warnings.go:107] "Warning: AdmissionWebhookController: mutated namespaceselector of the webhooks to enforce GKE Autopilot policies."
NAME: alloydbomni-operator
LAST DEPLOYED: Fri Oct 16 12:28:45 2026
NAMESPACE: alloydb-omni-system
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None

انشر مجموعة قواعد البيانات.

يضبط ملف البيان التالي مجموعة قواعد بيانات مع تفعيل googleMLExtension وجهاز موازنة حمل داخلي:

cat << 'EOF' > my-omni.yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-pw-my-omni
type: Opaque
data:
  my-omni: "VmVyeVN0cm9uZ1Bhc3N3b3Jk"
---
apiVersion: alloydbomni.dbadmin.goog/v1
kind: DBCluster
metadata:
  name: my-omni
spec:
  databaseVersion: "18.4.0"
  primarySpec:
    adminUser:
      passwordRef:
        name: db-pw-my-omni
    features:
      googleMLExtension:
        enabled: true
    resources:
      cpu: 1
      memory: 8Gi
      disks:
      - name: DataDisk
        size: 20Gi
    dbLoadBalancerOptions:
      annotations:
        networking.gke.io/load-balancer-type: "internal"
  allowExternalIncomingTraffic: true
EOF

قيمة كلمة المرور السرية هي تمثيل Base64 لـ VeryStrongPassword. في بيئات التشغيل الفعلي، استخدِم Google Secret Manager لإدارة كلمات المرور. لمعرفة التفاصيل، يُرجى الاطّلاع على مستندات Secret Manager.

يتم حفظ البيان باسم my-omni.yaml. في Cloud Shell، انقر على فتح المحرِّر في أعلى يسار نافذة المحطة الطرفية واقرأ الملف.

فتح &quot;المحرِّر&quot; في Cloud Shell

بعد قراءة بيان my-omni.yaml، انقر على فتح الوحدة الطرفية للعودة إلى موجّه الأوامر.

فتح Terminal في Cloud Shell

طبِّق ملف بيان my-omni.yaml:

kubectl apply -f my-omni.yaml

الناتج المتوقّع في وحدة التحكّم:

secret/db-pw-my-omni created
dbcluster.alloydbomni.dbadmin.goog/my-omni created

تحقَّق من حالة مجموعة my-omni:

kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default

أثناء عملية النشر، تنتقل مجموعة قواعد البيانات عبر مراحل الإعداد إلى أن تصل إلى الحالة DBClusterReady.

الناتج المتوقّع في وحدة التحكّم:

$ kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default
NAME      PRIMARYENDPOINT   PRIMARYPHASE   DBCLUSTERPHASE   HAREADYSTATUS   HAREADYREASON
my-omni   10.131.0.33        Ready          DBClusterReady

يمكنك اختياريًا مراقبة عملية نشر المجموعة باستخدام الأمر kubectl log:

kubectl logs -l alloydbomni.internal.dbadmin.goog/dbcluster=my-omni --all-containers -f

الربط بـ AlloyDB Omni

عندما تصبح المجموعة جاهزة، اتصِل بمجموعة قاعدة البيانات باستخدام عميل PostgreSQL (psql). كلمة المرور هي VeryStrongPassword كما هو محدّد في my-omni.yaml:

DB_CLUSTER_NAME=my-omni
DB_CLUSTER_NAMESPACE=default
DBPOD=`kubectl get pod --selector=alloydbomni.internal.dbadmin.goog/dbcluster=$DB_CLUSTER_NAME,alloydbomni.internal.dbadmin.goog/task-type=database -n $DB_CLUSTER_NAMESPACE -o jsonpath='{.items[0].metadata.name}'`
kubectl exec -ti $DBPOD -n $DB_CLUSTER_NAMESPACE -c database -- psql -h localhost -U postgres

مثال على الناتج في وحدة التحكّم:

DB_CLUSTER_NAME=my-omni
DB_CLUSTER_NAMESPACE=default
DBPOD=`kubectl get pod --selector=alloydbomni.internal.dbadmin.goog/dbcluster=$DB_CLUSTER_NAME,alloydbomni.internal.dbadmin.goog/task-type=database -n $DB_CLUSTER_NAMESPACE -o jsonpath='{.items[0].metadata.name}'`
kubectl exec -ti $DBPOD -n $DB_CLUSTER_NAMESPACE -c database -- psql -h localhost -U postgres
Password for user postgres:
psql (18.4)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off, ALPN: postgresql)
Type "help" for help.

postgres=#

اخرج من جلسة psql بكتابة \q والضغط على Enter:

postgres=# \q

5- نشر نموذج EmbeddingGemma على GKE

لاختبار دمج AlloyDB Omni AI مع النماذج المحلية، انشر نموذج تضمين في مجموعة GKE. يستخدم هذا البرنامج التعليمي نموذج EmbeddingGemma من Google.

الحصول على رمز Hugging Face

ينشر هذا الدليل التعليمي نموذج EmbeddingGemma من Hugging Face. للوصول إلى أوزان النموذج، أنشِئ رمز دخول Hugging Face:

  1. سجِّل الدخول إلى حسابك على Hugging Face أو أنشِئ حسابًا.
  2. انتقِل إلى ملفك الشخصي > رموز الدخول.
  3. انقر على إنشاء رمز مميّز جديد.
  4. أدخِل اسمًا للرمز المميّز واختَر دور القراءة.
  5. انقر على إنشاء رمز مميّز وانسخ قيمة الرمز المميّز الذي تم إنشاؤه.
  6. اقبل بنود النموذج في صفحة نموذج EmbeddingGemma إذا لم يسبق لك إجراء ذلك.

أنشِئ رمزًا سريًا في Kubernetes يحتوي على رمز Hugging Face المميّز في Cloud Shell (استبدِل العنصر النائب للرمز المميّز برمزك المميّز):

export HF_TOKEN=<YOUR_HUGGING_FACE_TOKEN>
kubectl create secret generic hf-secret \
  --from-literal=hf_api_token=$HF_TOKEN \
  --dry-run=client -o yaml | kubectl apply -f -

إعداد بيان النشر

لنشر النموذج، استخدِم حزمة حاوية Text Embeddings Inference (TEI) من Hugging Face. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات Hugging Face GKE TEI.

استنسِخ مستودع النشر من GitHub:

git clone https://github.com/huggingface/Google-Cloud-Containers

افحص بيان إعدادات وحدة المعالجة المركزية وعدِّله:

edit Google-Cloud-Containers/examples/gke/tei-deployment/cpu-config/deployment.yaml

بيان التحديث لنشر وحدة المعالجة المركزية:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tei-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tei-server
  template:
    metadata:
      labels:
        app: tei-server
        hf.co/model: Google--embeddinggemma-300m
        hf.co/task: text-embeddings
    spec:
      containers:
        - name: tei-container
          image: ghcr.io/huggingface/text-embeddings-inference:cpu-latest
          resources:
            requests:
              cpu: "6"
              memory: "24Gi"
            limits:
              cpu: "6"
              memory: "24Gi"
          env:
            - name: MODEL_ID
              value: google/embeddinggemma-300m
            - name: NUM_SHARD
              value: "1"
            - name: PORT
              value: "8080"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
          volumeMounts:
            - mountPath: /tmp
              name: tmp
      volumes:
        - name: tmp
          emptyDir: {}
      nodeSelector:
        cloud.google.com/machine-family: "c3"

احفظ التغييرات بالضغط على ctrl+s ثم ارجع إلى الوحدة الطرفية.

نشر النموذج

طبِّق ملف البيان لنشر خادم TEI:

kubectl apply -f Google-Cloud-Containers/examples/gke/tei-deployment/cpu-config

راقِب عملية النشر إلى أن تصبح في حالة جاهزة:

printf "Waiting for model to load..."; until kubectl logs -l app=tei-server --tail=50 2>/dev/null | grep -q "Ready"; do printf "."; sleep 3; done; printf '\n\033[1;32m========================================\n[SUCCESS] Model is loaded and ready!\nYou can now proceed to the next step.\n========================================\033[0m\n'

تحقَّق من خدمة tei-service Kubernetes:

kubectl get service tei-service

الناتج المتوقَّع:

student@cloudshell$ kubectl get service tei-service
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
tei-service   ClusterIP   34.118.233.48   <none>        8080/TCP   10m

تخدم الخدمة CLUSTER-IP الطلبات داخليًا على http://34.118.233.48:8080/embed.

اختبِر نقطة نهاية النموذج محليًا باستخدام kubectl port-forward:

kubectl port-forward service/tei-service 8080:8080

افتح علامة تبويب ثانية في Cloud Shell بالنقر على + في أعلى الوحدة الطرفية:

إضافة علامة تبويب Cloud Shell

في علامة التبويب الجديدة، اختبِر إنشاء التضمينات باستخدام curl:

curl http://localhost:8080/embed \
  -X POST \
  -d '{"inputs":"Test"}' \
  -H 'Content-Type: application/json'

الناتج المتوقّع (مصفوفة متّجهات):

curl http://localhost:8080/embed \
>     -X POST \
>     -d '{"inputs":"Test"}' \
>     -H 'Content-Type: application/json'
[[-0.018975832,0.0071419072,0.06347208,0.022992613,0.014205903
...
-0.03677433,0.01636146,0.06731572]]

أوقِف إعادة توجيه المنفذ في علامة التبويب الأولى من خلال الضغط على ctrl+c.

6. تسجيل نموذج التضمين في AlloyDB Omni

لاستخدام النموذج المنشور من AlloyDB Omni، أنشئ قاعدة بيانات وحدِّد دوال التحويل وسجِّل نقطة نهاية النموذج.

إنشاء جهاز افتراضي وقاعدة بيانات للعميل

أنشئ مثيل جهاز افتراضي في Compute Engine على شبكة VPC نفسها ليعمل كمضيف انتقال للعميل:

مخطّط بياني لبنية الشبكة يعرض الجهاز الافتراضي للعميل وAlloyDB Omni

في Cloud Shell، أنشئ الجهاز الافتراضي للعميل:

export ZONE=${LOCATION}-a
gcloud compute instances create instance-1 \
  --zone=$ZONE

استرِدّ عنوان IP لنقطة نهاية AlloyDB Omni:

echo "INSTANCE_IP=$(kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default -o jsonpath='{.status.primary.endpoint}')"

الناتج المتوقَّع:

INSTANCE_IP=10.128.0.33

قيمة INSTANCE_IP هي عنوان IP الخاص بجهاز موازنة الحمل الداخلي لمجموعة AlloyDB Omni. في هذا المثال، هو 10.131.0.33.

اتّصِل بمثيل الجهاز الافتراضي باستخدام بروتوكول النقل الآمن (SSH):

gcloud compute ssh instance-1 --zone=$ZONE

في جلسة SSH على instance-1، ثبِّت عميل PostgreSQL:

sudo apt-get update && sudo apt-get install --yes postgresql-client 

صدِّر عنوان IP الخاص بجهاز موازنة الحمل في AlloyDB Omni (استبدِله بعنوان IP الخاص بـ PRIMARYENDPOINT):

export INSTANCE_IP=10.131.0.33

اتصِل بـ AlloyDB Omni باستخدام psql (كلمة المرور هي VeryStrongPassword):

psql "host=$INSTANCE_IP user=postgres sslmode=require"

في جلسة psql، أنشئ قاعدة بيانات demo:

CREATE DATABASE demo;

انتقِل إلى قاعدة بيانات demo:

\c demo

إنشاء دوال التحويل

تتطلّب نقاط نهاية التضمين المخصّصة دوال تحويل الإدخال والإخراج لتكييف تنسيقات البيانات بين AlloyDB Omni وواجهة برمجة التطبيقات للنموذج.

أنشئ دالة تحويل الإدخال:

CREATE OR REPLACE FUNCTION tei_text_input_transform(model_id VARCHAR(100), input_text TEXT)
RETURNS JSON
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_input JSON;
BEGIN
  SELECT json_build_object('inputs', input_text, 'truncate', true)::JSON INTO transformed_input;
  RETURN transformed_input;
END;
$$;

الناتج المتوقَّع:

demo=# CREATE OR REPLACE FUNCTION tei_text_input_transform(model_id VARCHAR(100), input_text TEXT)
RETURNS JSON
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_input JSON;
BEGIN
  SELECT json_build_object('inputs', input_text, 'truncate', true)::JSON INTO transformed_input;
  RETURN transformed_input;
END;
$$;
CREATE FUNCTION
demo=#

أنشئ دالة تحويل المخرجات لتحليل استجابة مصفوفة المتجهات:

CREATE OR REPLACE FUNCTION tei_text_output_transform(model_id VARCHAR(100), response_json JSON)
RETURNS REAL[]
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_output REAL[];
BEGIN
  SELECT ARRAY(SELECT json_array_elements_text(response_json->0)) INTO transformed_output;
  RETURN transformed_output;
END;
$$;

الناتج المتوقَّع:

demo=# CREATE OR REPLACE FUNCTION tei_text_output_transform(model_id VARCHAR(100), response_json JSON)
RETURNS REAL[]
LANGUAGE plpgsql
AS $$
DECLARE
  transformed_output REAL[];
BEGIN
  SELECT ARRAY(SELECT json_array_elements_text(response_json->0)) INTO transformed_output;
  RETURN transformed_output;
END;
$$;
CREATE FUNCTION
demo=#

تسجيل النموذج

سجِّل النموذج في AlloyDB Omni باستخدام الإجراء google_ml.create_model. حدِّد http://tei-service:8080/embed على أنّه model_request_url لتوجيه الطلبات إلى خدمة مجموعة Kubernetes:

CALL
  google_ml.create_model(
    model_id => 'embeddinggemma',
    model_request_url => 'http://tei-service:8080/embed',
    model_provider => 'custom',
    model_type => 'text_embedding',
    model_in_transform_fn => 'tei_text_input_transform',
    model_out_transform_fn => 'tei_text_output_transform');

الناتج المتوقَّع:

demo=# CALL
  google_ml.create_model(
    model_id => 'embeddinggemma',
    model_request_url => 'http://tei-service:8080/embed',
    model_provider => 'custom',
    model_type => 'text_embedding',
    model_in_transform_fn => 'tei_text_input_transform',
    model_out_transform_fn => 'tei_text_output_transform');
CALL
demo=#

اختبِر النموذج المسجَّل باستخدام نموذج طلب بحث SQL:

SELECT google_ml.embedding('embeddinggemma', 'What is AlloyDB Omni?');

تعرض الدالة تمثيل صفيف الأعداد الحقيقية الذي تم إنشاؤه بواسطة نموذج EmbeddingGemma المحلي الذي يعمل على GKE.

اضغط على "q" للعودة إلى طلب جلسة "psql".

اخرج من جلسة psql:

\q

7. اختبار النموذج باستخدام عيّنات بيانات

تحميل عيّنات البيانات

يستخدم هذا البرنامج التعليمي مجموعة بيانات Cymbal للبيع بالتجزئة لتوضيح البحث عن التشابه في المتجهات. ستستخدم Google Cloud SDK وعميل PostgreSQL لاستيراد البيانات إلى AlloyDB Omni.

في جلسة SSH على instance-1، اتصِل بقاعدة البيانات التجريبية وفعِّل إضافة vector:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

في جلسة psql:

CREATE EXTENSION IF NOT EXISTS vector;

اخرج من جلسة psql:

\q

نزِّل المخطط وطبِّقه لإنشاء جداول في قاعدة بيانات demo:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=demo"

الناتج المتوقَّع:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=demo"
Password for user postgres:
SET
SET
SET
SET
SET
 set_config
------------

(1 row)

SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER SEQUENCE
ALTER TABLE
ALTER TABLE
ALTER TABLE
student@cloudshell:~$

تحقَّق من الجداول التي تم إنشاؤها:

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\dt+"

الناتج المتوقَّع:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\dt+"
Password for user postgres: 
                                           List of relations
 Schema |       Name       | Type  |  Owner   | Persistence | Access method |    Size    | Description 
--------+------------------+-------+----------+-------------+---------------+------------+-------------
 public | cymbal_embedding | table | postgres | permanent   | heap          | 8192 bytes | 
 public | cymbal_inventory | table | postgres | permanent   | heap          | 8192 bytes | 
 public | cymbal_products  | table | postgres | permanent   | heap          | 8192 bytes | 
 public | cymbal_stores    | table | postgres | permanent   | heap          | 8192 bytes | 
(4 rows)

حمِّل البيانات إلى جدول cymbal_products:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_products from stdin csv header"

الناتج المتوقَّع:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_products from stdin csv header"
COPY 941
student@cloudshell:~$ 

في ما يلي نموذج لبعض الصفوف من جدول cymbal_products.

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT uniq_id,left(product_name,30),left(product_description,50),sale_price FROM cymbal_products limit 3"

الناتج المتوقَّع:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT uniq_id,left(product_name,30),left(product_description,50),sale_price FROM cymbal_products limit 3"
Password for user postgres: 
             uniq_id              |              left              |                        left                        | sale_price 
----------------------------------+--------------------------------+----------------------------------------------------+------------
 a73d5f754f225ecb9fdc64232a57bc37 | Laundry Tub Strainer Cup       |   Laundry tub strainer cup Chrome For 1-.50, drain |      11.74
 41b8993891aa7d39352f092ace8f3a86 | LED Starry Star Night Light La |  LED Starry Star Night Light Laser Projector 3D Oc |      46.97
 ed4a5c1b02990a1bebec908d416fe801 | Surya Horizon HRZ-1060 Area Ru |  The 100% polypropylene construction of the Surya  |       77.4
(3 rows)
student@cloudshell:~$ 

حمِّل البيانات إلى جدول cymbal_inventory:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_inventory from stdin csv header"

الناتج المتوقَّع:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_inventory from stdin csv header"
Password for user postgres: 
COPY 263861
student@cloudshell:~$ 

في ما يلي نموذج لبعض الصفوف من جدول cymbal_inventory.

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT * FROM cymbal_inventory LIMIT 3"

إخراج:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT * FROM cymbal_inventory LIMIT 3"
Password for user postgres: 
 store_id |             uniq_id              | inventory 
----------+----------------------------------+-----------
     1583 | adc4964a6138d1148b1d98c557546695 |         5
     1490 | adc4964a6138d1148b1d98c557546695 |         4
     1492 | adc4964a6138d1148b1d98c557546695 |         3
(3 rows)
student@cloudshell:~$ 

حمِّل البيانات إلى جدول cymbal_stores:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_stores from stdin csv header"

الناتج المتوقّع في وحدة التحكّم:

student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_stores from stdin csv header"
Password for user postgres: 
COPY 4654
student@cloudshell:~$

في ما يلي نموذج لبعض الصفوف من جدول cymbal_stores.

psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT store_id, name, zip_code FROM cymbal_stores limit 3"

إخراج:

student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT store_id, name, zip_code FROM cymbal_stores limit 3"
Password for user postgres: 
 store_id |       name        | zip_code 
----------+-------------------+----------
     1990 | Mayaguez Store    |      680
     2267 | Ware Supercenter  |     1082
     4359 | Ponce Supercenter |      780
(3 rows)
student@cloudshell:~$ 

إنشاء التضمينات

اتصِل بقاعدة البيانات التجريبية باستخدام psql وأنشئ تضمينات للمنتجات الموضّحة في جدول cymbal_products استنادًا إلى أوصاف المنتجات.

الاتصال بقاعدة البيانات التجريبية:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

استخدِم العمود embedding من النوع vector لتخزين تضمينات النصوص التي تم إنشاؤها لأوصاف المنتجات.

تفعيل توقيت طلب البحث:

\timing

أنشِئ تضمينات لكل وصف منتج وخزِّنها في الجدول cymbal_embedding:

INSERT INTO cymbal_embedding (uniq_id, embedding)
SELECT uniq_id, google_ml.embedding('embeddinggemma', product_description)::vector
FROM cymbal_products;

الناتج المتوقَّع:

demo=# INSERT INTO cymbal_embedding(uniq_id,embedding)  SELECT uniq_id, google_ml.embedding('embeddinggemma',product_description)::vector FROM cymbal_products;
INSERT 0 941
Time: 497878.136 ms (08:17.878)
demo=#

تنفيذ طلبات البحث الدلالي

في جلسة psql، ابحث عن أهم خمسة منتجات تطابق السؤال "What kind of fruit trees grow well here?" باستخدام مسافة جيب التمام (<=>):

SELECT
    cp.product_name,
    left(cp.product_description, 80) AS description,
    cp.sale_price,
    cs.zip_code,
    (ce.embedding <=> google_ml.embedding('embeddinggemma', 'What kind of fruit trees grow well here?')::vector) AS distance
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;

الناتج المتوقَّع:

demo=# SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (ce.embedding <=> google_ml.embedding('embeddinggemma','What kind of fruit trees grow well here?')::vector) as distance
FROM
        cymbal_products cp
JOIN cymbal_embedding ce on ce.uniq_id=cp.uniq_id
JOIN cymbal_inventory ci on ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on cs.store_id=ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;
     product_name      |                                   description                                    | sale_price | zip_code |      distance
-----------------------+----------------------------------------------------------------------------------+------------+----------+--------------------
 Cherry Tree           | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.5210549378080666
 California Lilac      | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 | 0.5639421771781971
 Toyon                 | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 | 0.5670010914504852
 Rose Bush             | This is a beautiful rose bush that will produce fragrant roses. It is a perennia |      50.00 |    93230 | 0.5731542622882957
 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 | 0.5750934653011995
(5 rows)

Time: 83.610 ms
demo=#

تم تنفيذ طلب البحث في 83 ملي ثانية وعرض قائمة بالأشجار من جدول cymbal_products التي تطابق الطلب مع المخزون المتاح في المتجر بالرقم 1583.

إنشاء فهرس ANN

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

أعِد الاتصال بقاعدة البيانات التجريبية إذا انقطع الاتصال:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

فعِّل إضافة alloydb_scann:

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

أنشِئ فهرس ScaNN في العمود embedding:

CREATE INDEX cymbal_products_embeddings_scann ON cymbal_embedding
  USING scann (embedding cosine)
  WITH (num_leaves=10, max_num_levels = 1);

أعِد تشغيل طلب البحث الدلالي لمقارنة أداء التنفيذ:

SELECT
    cp.product_name,
    left(cp.product_description, 80) AS description,
    cp.sale_price,
    cs.zip_code,
    (ce.embedding <=> google_ml.embedding('embeddinggemma', 'What kind of fruit trees grow well here?')::vector) AS distance
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;

الناتج المتوقَّع:

demo=# SELECT
    cp.product_name,
    left(cp.product_description,80) as description,
    cp.sale_price,
    cs.zip_code,
    (ce.embedding <=> google_ml.embedding('embeddinggemma', 'What kind of fruit trees grow well here?')::vector) AS distance
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
    ci.inventory > 0
    AND cs.store_id = 1583
ORDER BY
    distance ASC
LIMIT 5;
     product_name      |                                   description                                    | sale_price | zip_code |      distance
-----------------------+----------------------------------------------------------------------------------+------------+----------+--------------------
 Cherry Tree           | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.5210549378080666
 California Lilac      | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 | 0.5639421771781971
 Toyon                 | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 | 0.5670010914504852
 Rose Bush             | This is a beautiful rose bush that will produce fragrant roses. It is a perennia |      50.00 |    93230 | 0.5731542622882957
 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 | 0.5750934653011995
(5 rows)

Time: 64.783 ms

تم تقليل وقت تنفيذ الاستعلام بشكل طفيف وسيكون الكسب أكثر وضوحًا مع مجموعات البيانات الأكبر. يجب أن تكون البيانات المعروضة مماثلة أو مشابهة جدًا لما حصلنا عليه بدون فهرس.

جرِّب طلبات بحث أخرى واقرأ المزيد عن تحسين فهرس المتّجهات في المستندات.

اخرج من جلسة psql:

\q

ارجع إلى Google Cloud Shell عن طريق قطع الاتصال بجلسة instance-1 ssh بالضغط على CTRL+D أو كتابة exit.

8. نشر Gemma باستخدام vLLM

إضافة مجموعة عُقد لـ Gemma

أولاً، تحقَّق من أنواع العُقد المتاحة في منطقتك:

gcloud compute accelerator-types list --filter="zone:${LOCATION}"

من المفترض أن تظهر لك قائمة بأنواع المسرّعات المتاحة، بما في ذلك مسرّع nvidia-l4.

أنشئ بيان نشر لنموذج Google Gemini 4 12B باستخدام vLLM:

cat << 'EOF' > gemma-12b-gpu-vllm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gemma-12b-gpu-vllm-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gemma-12b-gpu-vllm
  template:
    metadata:
      labels:
        app: gemma-12b-gpu-vllm
        ai.gke.io/model: gemma-4-12b-it
        ai.gke.io/inference-server: vllm
        examples.ai.gke.io/source: user-guide
    spec:
      containers:
      - name: inference-server
        image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:latest
        resources:
          requests:
            cpu: "4"
            memory: "16Gi"
            ephemeral-storage: "30Gi"
            nvidia.com/gpu: "1"
          limits:
            cpu: "8"
            memory: "24Gi"
            ephemeral-storage: "30Gi"
            nvidia.com/gpu: "1"
        command: ["python3", "-m", "vllm.entrypoints.api_server"]
        args:
          - --model=$(MODEL_ID)
          - --host=0.0.0.0
          - --port=8000
          - --tensor-parallel-size=1
          - --enable-log-requests
          - --enable-chunked-prefill
          - --enable-prefix-caching
          - --enable-auto-tool-choice
          - --generation-config=auto
          - --tool-call-parser=gemma4
          - --dtype=bfloat16
          - --max-num-seqs=16
          - --max-model-len=32768
          - --gpu-memory-utilization=0.95
          - --reasoning-parser=gemma4
          - --trust-remote-code
          - --quantization=fp8
        env:
        - name: LD_LIBRARY_PATH
          value: ${LD_LIBRARY_PATH}:/usr/local/nvidia/lib64
        - name: MODEL_ID
          value: google/gemma-4-12b-it
        - name: HF_TOKEN
          valueFrom:
            secretKeyRef:
              name: hf-secret
              key: hf_api_token
        volumeMounts:
        - mountPath: /dev/shm
          name: dshm
      volumes:
      - name: dshm
        emptyDir:
            medium: Memory
      nodeSelector:
        cloud.google.com/gke-accelerator: nvidia-l4
        cloud.google.com/gke-gpu-driver-version: latest
---
apiVersion: v1
kind: Service
metadata:
  name: gemma-12b-gpu-vllm-service
spec:
  selector:
    app: gemma-12b-gpu-vllm
  type: ClusterIP
  ports:
    - protocol: TCP
      port: 8000
      targetPort: 8000
EOF

طبِّق عملية نشر gemma-12b-gpu-vllm-deployment.yaml المحفوظة:

kubectl apply -f gemma-12b-gpu-vllm-deployment.yaml

الناتج المتوقَّع:

$ kubectl apply -f gemma-12b-gpu-vllm-deployment.yaml
deployment.apps/gemma-12b-gpu-vllm-deployment created
service/gemma-12b-gpu-vllm-service created

انتظِر حتى يكتمل النشر ويتم تحميل النموذج. قد يستغرق ذلك عدّة دقائق.

printf "Waiting for model to load..."; until kubectl logs -l app=gemma-12b-gpu-vllm --tail=50 2>/dev/null | grep -q "Application startup complete"; do printf "."; sleep 3; done; printf '\n\033[1;32m========================================\n[SUCCESS] Model is loaded and ready!\nYou can now proceed to the next step.\n========================================\033[0m\n'

الناتج المتوقَّع:

Waiting for model to load...
========================================
[SUCCESS] Model is loaded and ready!
You can now proceed to the next step.
========================================

اختبِر النموذج. فعِّل إعادة توجيه المنفذ للوصول إلى النموذج:

kubectl port-forward svc/gemma-12b-gpu-vllm-service 8090:8000

في نافذة أخرى من المحطة الطرفية، استخدِم curl لإرسال طلب إلى النموذج:

curl http://localhost:8090/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "system", "content": "You are a helpful assistant running on GKE."},
      {"role": "user", "content": "What is AlloyDB Omni."}
    ],
    "temperature": 0.7
  }' | jq -r '.choices[0].message.content'

الناتج المتوقَّع:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3957  100  3761  100   196     85      4  0:00:49  0:00:43  0:00:06   830
**AlloyDB Omni** is a fully managed, PostgreSQL-compatible database engine from Google Cloud that can be run **on-premises, in other clouds, or in your own data centers.**

To understand it simply: It allows you to run the high-performance, enterprise-grade capabilities of Google's **AlloyDB** (a cloud-native database) on your own infrastructure.

Here is a breakdown of what makes it significant:

### 1. The "Best of Both Worlds" Architecture
Normally, you have to choose between:
*   **Managed Cloud Databases:** Easy to scale and manage, but you are locked into the cloud provider's infrastructure.
*   **Self-Managed Databases:** You have full control over the hardware/location, but you are responsible for scaling, patching, and high availability.

**AlloyDB Omni** bridges this gap. It provides the advanced features of a cloud-native database (like intelligent indexing, high availability, and massive scalability) while allowing you to run it anywhere.

أوقِف إعادة توجيه المنفذ في الوحدة الطرفية الأولى (إذا كانت لا تزال قيد التشغيل) بالضغط على Ctrl+C.

9. تسجيل نموذج Gemma 4 في AlloyDB Omni

سجِّل نموذج Gemma 12B في AlloyDB Omni باستخدام الإجراء google_ml.create_model. حدِّد http://gemma-12b-gpu-vllm-service:8000/v1/chat/completions على أنّه model_request_url لتوجيه الطلبات إلى خدمة مجموعة Kubernetes:

استرِدّ عنوان IP لنقطة نهاية AlloyDB Omni:

echo "INSTANCE_IP=$(kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default -o jsonpath='{.status.primary.endpoint}')"

اتّصِل بمثيل الجهاز الافتراضي باستخدام بروتوكول النقل الآمن (SSH):

gcloud compute ssh instance-1 --zone=$ZONE

بعد الاتصال بالجهاز الافتراضي، عليك تصدير المتغيّر INSTANCE_IP من الخطوة السابقة (القيمة 10.128.0.33 هي مثال، لذا استبدِلها بعنوان IP الخاص بك):

export INSTANCE_IP=10.128.0.33

تصدير كلمة مرور AlloyDB:

export PGPASSWORD=VeryStrongPassword

الاتصال بقاعدة بيانات demo:

psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"

في جلسة psql، سجِّل النموذج:

CALL
  google_ml.create_model(
    model_id => 'gemma-12b-gpu',
    model_request_url => 'http://gemma-12b-gpu-vllm-service:8000/v1/chat/completions',
    model_provider => 'custom',
    model_type => 'llm');

اختبِر النموذج باستخدام نموذج طلب بحث SQL:

SELECT google_ml.predict_row(
  model_id => 'gemma-12b-gpu',
  request_body => json_build_object(
    'messages', json_build_array(
      json_build_object('role', 'user', 'content', 'What is AlloyDB Omni?'))))->'choices'->0->'message'->'content';

اضغط على q للخروج من نافذة النتائج والعودة إلى طلب psql

الجمع بين البحث بالمتّجهات والتوليد المعزّز بالاسترجاع (RAG) في النماذج اللغوية الكبيرة في AlloyDB Omni

استخدِم البحث بالمتّجهات مع طلب النموذج اللغوي الكبير لتوضيح "التوليد المعزّز بالاسترجاع" (RAG) باستخدام النموذج اللغوي الكبير.

نفِّذ طلب بحث SQL في plsql:

WITH trees AS (
SELECT
        cp.product_name,
        cp.product_description AS description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id AS product_id
FROM
    cymbal_products cp
JOIN cymbal_embedding ce ON ce.uniq_id = cp.uniq_id
JOIN cymbal_inventory ci ON ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON cs.store_id = ci.store_id
WHERE
        ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (ce.embedding <=> embedding('embeddinggemma',
        'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
        'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
        trees),
response AS (
SELECT
        google_ml.predict_row(
          model_id =>'gemma-12b-gpu',
          request_body => json_build_object(
            'messages', json_build_array(
              json_build_object('role', 'user', 'content',prompt_text)
            )))->'choices'->0->'message'->'content' AS resp
FROM
        prompt)
SELECT
REPLACE(resp::text, '\n', CHR(10))
FROM
        response;

الناتج المتوقَّع:

----------------------------------------------------------------------------------------------------------------------------------------------
 "Hello there! I'd be happy to help you find the perfect tree for your garden.                                                               +
                                                                                                                                             +
 Based on your location, we have a wonderful option that would grow beautifully in your area:                                                +
                                                                                                                                             +
 **Cherry Tree**                                                                                                                             +
 *   **Price:** $75.00                                                                                                                       +
 *   **Description:** This is a stunning deciduous tree that not only provides a beautiful landscape but also produces delicious cherries.   +
 *   **Supplemental Information:**                                                                                                           +
     *   **Growth:** It grows to about 15 feet tall.                                                                                         +
     *   **Appearance:** You can look forward to dark green leaves in the summer that transform into a vibrant red in the fall.              +
     *   **Benefits:** It's a great choice if you're looking for both fruit and extra shade or privacy in your yard.                         +
     *   **Care Tips:** It performs best in a cool, moist climate with sandy soil. Since you are in a suitable zone, it should thrive nicely!+
                                                                                                                                             +
 Would you like more details on how to plant this, or would you like to proceed with an order?"
(1 row)

يُكمّل الطلب الموجّه إلى النموذج اللغوي الكبير نتائج البحث عن المتّجهات.

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

الخروج من جلسة psql:

\q

اقطع الاتصال بجلسة SSH مع الجهاز الافتراضي:

exit

يُرجى العِلم أنّ AlloyDB Omni يتضمّن المزيد من الميزات والمختبرات.

10. تنظيف البيئة

لتجنُّب تحمُّل رسوم مستمرة على حسابك على Google Cloud، احذف الموارد التي تم إنشاؤها في هذا الدرس التطبيقي حول الترميز.

حذف مجموعة GKE

في Cloud Shell، احذف مجموعة GKE:

export PROJECT_ID=$(gcloud config get-value project)
export CLUSTER_NAME=alloydb-ai-gke
gcloud container clusters delete ${CLUSTER_NAME} \
  --project=${PROJECT_ID} \
  --region=${LOCATION}

الناتج المتوقَّع:

student@cloudshell:~$ gcloud container clusters delete ${CLUSTER_NAME} \
>   --project=${PROJECT_ID} \
>   --region=${LOCATION}
The following clusters will be deleted.
 - [alloydb-ai-gke] in [us-east4]

Do you want to continue (Y/n)?  Y

Deleting cluster alloydb-ai-gke...done.
Deleted

حذف الجهاز الافتراضي للعميل

في Cloud Shell، احذف مثيل Compute Engine:

export PROJECT_ID=$(gcloud config get-value project)
gcloud compute instances delete instance-1 \
  --project=${PROJECT_ID} \
  --zone=${ZONE}

الناتج المتوقَّع:

student@cloudshell:~$ export PROJECT_ID=$(gcloud config get project)
export ZONE=us-east4-a
gcloud compute instances delete instance-1 \
  --project=${PROJECT_ID} \
  --zone=${ZONE}
Your active configuration is: [cloudshell-5399]
The following instances will be deleted. Any attached disks configured to be auto-deleted will be deleted unless they are attached to any other instances or the `--keep-disks` flag is given and specifies them for keeping. Deleting a disk 
is irreversible and any data on the disk will be lost.
 - [instance-1] in [us-east4-a]

Do you want to continue (Y/n)?  Y

Deleted

إذا أنشأت مشروعًا جديدًا لهذا الدرس التطبيقي حول الترميز، يمكنك حذف المشروع بأكمله في Google Cloud Resource Manager.

11. تهانينا

تهانينا على إكمال الدرس التطبيقي حول الترميز.

المواضيع التي تناولتها

  • كيفية نشر AlloyDB Omni على مجموعة GKE
  • كيفية الربط بـ AlloyDB Omni
  • كيفية تحميل البيانات إلى AlloyDB Omni
  • كيفية نشر نماذج الذكاء الاصطناعي (التضمين والنموذج اللغوي الكبير) على GKE
  • كيفية تسجيل نماذج الذكاء الاصطناعي في AlloyDB Omni
  • كيفية إنشاء تضمينات للبحث الدلالي
  • كيفية تنفيذ طلبات البحث الدلالي في AlloyDB Omni
  • كيفية إنشاء فهارس المتّجهات واستخدامها في AlloyDB Omni

يمكنك الاطّلاع على مزيد من المعلومات حول العمل باستخدام الذكاء الاصطناعي في AlloyDB Omni في المستندات.

استطلاع

إخراج:

كيف ستستخدم هذا البرنامج التعليمي؟

قراءته فقط قراءته وإكمال التمارين