ست وصفات لتحقيق دقة تقارب% 100 في تحويل النص إلى SQL في AlloyDB - برنامج تعليمي

1. مقدمة

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية الحصول على أفضل النتائج باستخدام QueryData API. تتعرّف على كيفية إنشاء نتائج دقيقة وقابلة للتكرار عند تقديم طلبات باللغة الطبيعية إلى قاعدة البيانات. لمساعدتك في تحقيق ذلك، يرشدك الدليل إلى ستة أساليب في عدة فصول، ويستكشف جوانب مختلفة من تحويل اللغة الطبيعية إلى لغة SQL (NL2SQL) وتطبيقاتها العملية.

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

  • فهم أساسي لـ Google Cloud وGoogle Cloud Console
  • مهارات أساسية في استخدام واجهة سطر الأوامر وCloud Shell

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

  • كيفية نشر مجموعة AlloyDB ومثيل أساسي
  • كيفية تفعيل QueryData ووظائف الذكاء الاصطناعي و"طرق العرض الآمنة التي تتضمّن معلَمات"
  • كيفية إنشاء مجموعة سياقات QueryData
  • كيفية استخدام نماذج وسياقات مختلفة في واجهة برمجة التطبيقات QueryData
  • كيفية جعل نماذج QueryData أكثر مرونة باستخدام عوامل التصفية
  • كيفية حلّ مشكلة غموض البيانات باستخدام البحث عن القيم وفهرسة ثلاثية الأوجه
  • كيفية استخدام وظائف الذكاء الاصطناعي للبحث الدلالي باستخدام النماذج
  • كيفية استخدام طُرق العرض الآمنة التي تتضمّن مَعلمات مع QueryData API

المتطلبات

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

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

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

  1. سجِّل الدخول إلى Google Cloud Console. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.

استخدام حساب شخصي بدلاً من حساب تديره المؤسسة التعليمية أو حساب تابع للعمل.

  1. أنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. لإنشاء مشروع جديد في Google Cloud Console، انقر على الزر "اختيار مشروع" في العنوان، ما سيؤدي إلى فتح نافذة منبثقة.

295004821bab6a87.png

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

37d264871000675d.png

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

96d86d3d5655cdbe.png

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

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

إعداد حساب فوترة شخصي

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

لإعداد حساب فوترة شخصي، انتقِل إلى هنا لتفعيل الفوترة في Cloud Console.

ملاحظات:

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

بدء Cloud Shell

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

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

تفعيل Cloud Shell

يمكنك بدلاً من ذلك الضغط على G ثم S. سيؤدي هذا التسلسل إلى تفعيل Cloud Shell إذا كنت تستخدم Google Cloud Console أو هذا الرابط.

لن يستغرق توفير البيئة والاتصال بها سوى بضع لحظات. عند الانتهاء، من المفترض أن يظهر لك ما يلي:

لقطة شاشة لواجهة سطر الأوامر في Google Cloud Shell توضّح أنّه تم ربط البيئة

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

3- قبل البدء

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

لاستخدام AlloyDB وCompute Engine وخدمات الشبكات و"منصة الوكيل"، فعِّل واجهات برمجة التطبيقات الخاصة بها في مشروعك على السحابة الإلكترونية على Google Cloud.

داخل نافذة Cloud Shell، تأكَّد من إعداد رقم تعريف مشروعك:

gcloud config get-value project

من المفترض أن يعرض الأمر رقم تعريف مشروعك على Google Cloud.

اضبط متغيّر البيئة PROJECT_ID:

PROJECT_ID=$(gcloud config get-value project)

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

gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       geminidataanalytics.googleapis.com \
                       cloudaicompanion.googleapis.com \
                       aiplatform.googleapis.com \
                       dataplex.googleapis.com

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

student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$ 
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       geminidataanalytics.googleapis.com \
                       cloudaicompanion.googleapis.com \
                       aiplatform.googleapis.com \
                       dataplex.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

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

4. تفعيل AlloyDB

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

نشر AlloyDB باستخدام نص برمجي آلي

يستخدم هذا الأسلوب نصًا برمجيًا مبرمَجًا لنشر مجموعة AlloyDB وتوفير تفاصيل الإعداد اللازمة للبدء في استخدام الموارد التي تم نشرها.

في نافذة Cloud Shell، شغِّل الأمر لاستنساخ النص البرمجي للنشر من المستودع:

REPO_NAME="codelabs"
REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME"
SOURCE_DIR="alloydb-ai-nla"

git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL

cd $REPO_NAME
git sparse-checkout set $SOURCE_DIR
git checkout
cd $SOURCE_DIR

شغِّل نص النشر البرمجي:

./deploy_alloydb.sh

يستغرق تنفيذ النص البرمجي من خمس إلى سبع دقائق. تعرض النتيجة تفاصيل نشر مجموعتك. يُرجى العِلم أنّ كلمة المرور ستكون مختلفة، لذا احفظها لاستخدامها في المستقبل.

...
<redacted>
...
Creating primary instance: alloydb-aip-01-pr (8 vCPUs for TRIAL cluster)
Operation ID: operation-1765988049916-646282264938a-bddce198-9f248715
Creating instance...done.                                                                                                                                                                                                             
----------------------------------------
Deployment Process Completed
Cluster:  alloydb-aip-01 (TRIAL)
Instance: alloydb-aip-01-pr
Region:   us-central1
Initial Password: JBBoDTgixzYwYpkF (if new cluster)
----------------------------------------
 

يمكنك الاطّلاع على المجموعة والآلة الافتراضية الجديدتَين في صفحة مجموعات AlloyDB في Google Cloud Console.

4271eb55bcc9ec84.png

5- إعداد قاعدة البيانات

أنشئ قاعدة بيانات، وفعِّل عملية التكامل مع "منصة وكيل Gemini Enterprise"، وأنشئ عناصر قاعدة البيانات، وأضِف بيانات نموذجية.

منح الأذونات اللازمة إلى AlloyDB

امنح أدوار "إدارة الهوية وإمكانية الوصول" المطلوبة لوكيل خدمة AlloyDB:

افتح علامة تبويب جديدة في Cloud Shell من خلال النقر على "إضافة" (+).

abc505ac4d41f24e.png

في علامة التبويب الجديدة، نفِّذ ما يلي:

PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"

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

student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-11039]
student@cloudshell:~ (test-project-001-402417)$ gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"
Updated IAM policy for project [test-project-001-402417].
bindings:
- members:
  - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com
  role: roles/aiplatform.user
- members:
...
etag: BwYIEbe_Z3U=
version: 1
 

تفعيل Data Access API

فعِّل Data Access API على مجموعة AlloyDB.

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

PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
ADBCLUSTER=alloydb-aip-01
curl -X PATCH \
 -H "Authorization: Bearer $(gcloud auth print-access-token)" \
 -H "Content-Type: application/json" \
 https://alloydb.googleapis.com/v1alpha/projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER/instances/$ADBCLUSTER-pr?updateMask=dataApiAccess \
 -d '{
   "dataApiAccess": "ENABLED",
 }'

تعديل علامات قاعدة البيانات

قبل تفعيل العلامات على مستوى المثيل، انتظِر إلى أن تنتهي خطوة Data Access API. تأكَّد من أنّ حالة الجهاز الافتراضي تعرض علامة اختيار خضراء، كما هو موضّح في الصورة التالية.

6284731b8eff74c.jpeg

لاستخدام إضافات الذكاء الاصطناعي ومصادقة IAM للأدوات المستندة إلى الوكلاء، يجب تفعيل علامات قاعدة بيانات معيّنة على المثيل وإضافة نفسك كمستخدم لقاعدة البيانات. فعِّل العلامات التالية:

  • alloydb.iam_authentication
  • password.enforce_complexity
  • google_ml_integration.enable_ai_query_engine
  • parameterized_views

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

PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
ADBCLUSTER=alloydb-aip-01
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags password.enforce_complexity=on,alloydb.iam_authentication=on,google_ml_integration.enable_ai_query_engine=on,parameterized_views.enabled=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

أنشئ مستخدمًا في "إدارة الهوية وإمكانية الوصول" (IAM) لحسابك على AlloyDB:

REGION=us-central1
ADBCLUSTER=alloydb-aip-01
gcloud alloydb users create $(gcloud config get-value account) \
--cluster=$ADBCLUSTER \
--superuser=true \
--region=$REGION \
--type=IAM_BASED

أغلِق علامة التبويب من خلال تنفيذ أمر الخروج في الوحدة الطرفية:

exit

الربط بـ AlloyDB Studio

في الفصول التالية، يمكنك تنفيذ جميع أوامر SQL التي تتطلّب الاتصال بقاعدة بيانات في AlloyDB Studio.

لفتح AlloyDB Studio، اتّبِع الخطوات التالية:

  1. في Google Cloud Console، انتقِل إلى صفحة المجموعات في AlloyDB for PostgreSQL.
  2. اختَر مثيلك الأساسي لفتح واجهة الويب الخاصة به.

1d7298e7096e7313.png

  1. بعد ذلك، انقر على AlloyDB Studio في يمين الصفحة:

a33131c72ad29478.png

  1. اختَر قاعدة بيانات postgres، ثم اختَر "مصادقة إدارة الهوية وإمكانية الوصول"، وانقر على "مصادقة".

8ddfb250344ca749.jpeg

يؤدي هذا الإجراء إلى فتح واجهة AlloyDB Studio.

  1. انقر على علامة التبويب "طلب بدون عنوان" (Untitled Query) لفتح محرِّر SQL.

6696bc771fab9983.png

سيؤدي ذلك إلى فتح محرِّر يمكنك من خلاله تنفيذ أوامر SQL، كما هو موضّح في الصورة التالية:

ae34288e5bf237c7.png

إنشاء قاعدة بيانات

إنشاء قاعدة بيانات Quickstart

في محرّر AlloyDB Studio، نفِّذ الأمر التالي لإنشاء قاعدة البيانات:

CREATE DATABASE quickstart_db

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

Statement executed successfully

الاتصال بقاعدة بيانات quickstart_db

انقر على "تغيير قاعدة البيانات/المستخدم" في AlloyDB Studio.

6f5c98f5d0b3d550.png

اختَر quickstart_db من قائمة قواعد البيانات، ثم اختَر "مصادقة إدارة الهوية وإمكانية الوصول" (IAM Authentication) وأثبِت ملكية حسابك.

a1940c26c36ff840.jpeg

سيتم فتح اتصال جديد يمكنك من خلاله العمل مع عناصر من قاعدة بيانات quickstart_db.

تفعيل الإضافات

تحقَّق من جميع الإضافات المطلوبة للتأكّد من أنّها مفعَّلة في قاعدة البيانات وأنّ لديها الحد الأدنى الصحيح من الإصدارات.

تأكَّد من توفّر جميع الإضافات المطلوبة في قاعدة البيانات:

SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector', 'google_ml_integration', 'parameterized_views');

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

        extname        |   extversion   
-----------------------+----------------
 google_ml_integration | 1.5.9
 parameterized_views   | 1.0
 vector                | 0.8.2.google-1

إذا لم تعرض جميع الصفوف أعلاه، يعني ذلك أنّ بعض الإضافات غير مفعّلة.

قبل تفعيل الإضافات، يجب التأكّد من تفعيل جميع علامات قاعدة البيانات ،"google_ml_integration.enable_ai_query_engine" و "parameterized_views.enabled" على المثيل.

في AlloyDB Studio، أثناء الاتصال بقاعدة بيانات quickstart_db، نفِّذ ما يلي:

show google_ml_integration.enable_ai_query_engine;
show parameterized_views.enabled;

إذا كان أي من هذه الخيارات يظهر على أنّه "غير مفعّل"، حاوِل تكرار الخطوة "تعديل علامات قاعدة البيانات" والتحقّق من الحالة باستخدام أوامر "show..." مرة أخرى.

فعِّل الإضافات المطلوبة.

في AlloyDB Studio، أثناء الاتصال بقاعدة بيانات quickstart_db، نفِّذ ما يلي:

CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS parameterized_views;

تحقَّق من إصدارات الإضافات parameterized_views وgoogle_ml.

في AlloyDB Studio، أثناء الاتصال بقاعدة بيانات quickstart_db، نفِّذ ما يلي:

SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector', 'google_ml_integration', 'parameterized_views');

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

        extname        |   extversion   
-----------------------+----------------
 google_ml_integration | 1.5.9
 parameterized_views   | 1.0
 vector                | 0.8.2.google-1

إذا كان الإصدار أقدم من الإصدار المطلوب، حاوِل تحديث إضافة parameterized_views.

بالنسبة إلى parameterized_views، جرِّب ما يلي:

ALTER EXTENSION parameterized_views UPDATE;

يُرجى التحقّق من الإصدار مرة أخرى.

في AlloyDB Studio، أثناء الاتصال بقاعدة بيانات quickstart_db، نفِّذ ما يلي:

SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector', 'google_ml_integration', 'parameterized_views');

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

        extname        |   extversion   
-----------------------+----------------
 google_ml_integration | 1.5.9
 parameterized_views   | 1.0
 vector                | 0.8.2.google-1

6. عيّنات البيانات

الآن، عليك إنشاء عناصر في قاعدة البيانات وتحميل البيانات. ستستخدم مجموعة بيانات لشركة عقارية وهمية. وتتضمّن بيانات وهمية حول مبيعات العقارات والوكلاء. تم توفير البيانات في نص SQL البرمجي real_estate_data.sql في المستودع المستنسخ.

إنشاء حزمة Storage

استخدِم حزمة تطوير البرامج (SDK) من Google‏ (gcloud) لاستيراد البيانات من المستودع الذي تم استنساخه إلى قاعدة بيانات AlloyDB. عليك إنشاء حزمة Cloud Storage لهذا الغرض ومنح إذن الوصول إلى حساب خدمة AlloyDB. يمكنك بدلاً من ذلك محاولة تنفيذ ذلك باستخدام وحدة تحكّم الويب، كما هو موضّح في المستندات.

في وحدة Google Cloud Shell الطرفية، نفِّذ ما يلي:

PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
gcloud storage buckets create gs://$PROJECT_ID-import --project=$PROJECT_ID --location=$REGION
gcloud storage buckets add-iam-policy-binding gs://$PROJECT_ID-import --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" --role=roles/storage.objectViewer

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

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

انسخ ملف تفريغ قاعدة البيانات إلى حزمة Cloud Storage:

REPO_NAME="codelabs"
SOURCE_DIR="alloydb-ai-nla"
cd ~/$REPO_NAME/$SOURCE_DIR
gcloud storage cp ~/$REPO_NAME/$SOURCE_DIR/real_estate_data.sql  gs://$PROJECT_ID-import

استورِد مجموعة البيانات إلى quickstart_db:

PROJECT_ID=$(gcloud config get-value project)
CLUSTER_NAME=alloydb-aip-01
REGION=us-central1
IAM_USER=$(gcloud config get-value account)
gcloud alloydb clusters import $CLUSTER_NAME  --region=us-central1 --database=quickstart_db --gcs-uri=gs://$PROJECT_ID-import/real_estate_data.sql --project=$PROJECT_ID --sql --user=$IAM_USER

سيحمّل الأمر مجموعة البيانات النموذجية إلى قاعدة بيانات quickstart_db.

تحقَّق من عملية الاستيراد من خلال حساب السجلات في جدول real_estate.agents باستخدام AlloyDB Studio:

SELECT COUNT(*) FROM real_estate.agents;

7. إعداد مخطط علم الوجود

إعداد مجموعة السياقات في QueryData وتوفير البيانات الوصفية للمخطط وتشغيل وكيل ADK

إنشاء بيانات وصفية

تتألف بيانات التعريف من تعليقات SQL يتم تطبيقها على جداول وأعمدة قاعدة البيانات. توجّه هذه التعليقات محرك QueryData عند اختيار عناصر قاعدة البيانات.

إذا كنت قد استوردت مخطّط البيانات باستخدام تفريغ SQL المقدَّم، تكون جميع البيانات الوصفية قد تم إنشاؤها في المخطّط.

في ما يلي مثال على مقتطف من بيانات التعريف المطبَّقة على مخطط real_estate:

COMMENT ON TABLE real_estate.agents IS 'Stores profile, contact, brokerage affiliation, and active status for individual real estate agents.';

COMMENT ON COLUMN real_estate.agents.agent_id IS 'Primary key uniquely identifying each real estate agent in the database.';

...

إذا كنت تعمل على مجموعة البيانات الخاصة بك، يمكنك اتّباع الدليل الموثّق حول كيفية إضافة البيانات الوصفية إلى المخطط.

إنشاء سياق علم الوجود للمخطط

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

مجموعة سياق QueryData هي ملف JSON يتضمّن نماذج طلبات بحث وأوجه بحث وعمليات بحث عن القيم. يمكنك الاطّلاع على أمثلة مختلفة في المستندات.

تحميل مجموعة سياق QueryData في "وحدة تحكّم الويب"

لتحميل مجموعة سياق، افتح AlloyDB Studio وفي اللوحة اليمنى في أسفل الشاشة، سترى Context sets وثلاث نقاط.

d3578ceee65cd0dd.jpeg

انقروا على هذه النقاط الثلاث واختاروا Create context set.

في مربّع الحوار الذي فتح، أدخِل القيم التالية:

  • الاسم: sixrecipes
  • الوصف: Real Estate Query Data
  • تحميل ملف السياق: اتركه فارغًا

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

تحقَّق من رقم تعريف مجموعة السياق QueryData بالنقر مرة أخرى على النقاط الثلاث على يسار اسم مجموعة السياق واختَر Edit context set.

6739fb9f54d7f79d.jpeg

يظهر معرّف مجموعة السياقات في أعلى علامة التبويب المفتوحة على اليسار

746b38c52a70bb3c.jpeg

احفظ رقم التعريف هذا لاستخدامه في الخطوات اللاحقة.

بدء وكيل الذكاء الاصطناعي

للتفاعل مع الخلفية البرمجية QueryData من أجل إنشاء طلب بحث وتنفيذه، يمكنك استخدام واجهة AlloyDB Studio كما هو موضّح في المستندات. ولكن في هذا التمرين العملي، ستستخدم وكيل الذكاء الاصطناعي كأداة رئيسية للتواصل مع قاعدة البيانات. تمثّل برامج الذكاء الاصطناعي سيناريو أكثر واقعية لأحمال العمل المستقبلية، ويوفّر إطار عمل ADK من Google واجهة ويب رائعة يمكنك من خلالها الاطّلاع على جميع الخطوات والتفاعلات بين النماذج وواجهات برمجة التطبيقات والتطبيقات.

راجِع إعدادات مصدر الوكيل في Cloud Shell:

REPO_NAME="codelabs"
SOURCE_DIR="alloydb-ai-nla"
cd ~/$REPO_NAME/$SOURCE_DIR/data_agent
edit agent.py

في الملف، يمكنك الاطّلاع على المكان الذي نحدّد فيه قائمة الجداول في المخطط. سنعود إلى ذلك في إحدى خطواتنا المستقبلية.

# List of database tables included in QueryData API requests
TABLE_IDS = [
    "real_estate.municipalities",
    "real_estate.cities",
    "real_estate.agents",
    "real_estate.properties",
    "real_estate.schools",
    "real_estate.school_to_property",
    "real_estate.property_transactions",
    "real_estate.secure_offers",
]

وهناك إجراء call_querydata_api للعمل مع QueryData API بالإضافة إلى مجموعة أدوات للعمل مع مهارات QueryData API.

def call_querydata_api(
    prompt: str,
    target_project_id: str = project_id,
    target_location: str = location,
    target_cluster_id: str = cluster_name,
    target_instance_id: str = instance_name,
    target_database_id: str = database_name,
    target_context_set_id: str = context_set_id,
    target_table_ids: list[str] = TABLE_IDS,
) -> dict:
    """Calls the Gemini Data Analytics QueryData API to translate natural ...
<Redacted>
...

# ADK File-Based Skill

database_query_skill = load_skill_from_dir(
    pathlib.Path(__file__).parent / "skills" / "database-query-skill"
)

skill_toolset = SkillToolset(
    skills=[database_query_skill]
)

في ما يلي الوكيل الأساسي نفسه مع طلب وأدوات متاحة.

# Agent configuration

root_agent = Agent(
    model=MODEL_ID,
    name='root_agent',
    description='A helpful assistant for analyst requests.',
    instruction=f"""
    Answer user questions to the best of your knowledge using provided tools.
    Do not try to generate non-existent data but use the grounded data from the database.
    When you answer questions about database contents, real estate properties, or sales activity:
    1. Refer to database-query-skill for instructions on querying data using QueryData API.
    2. Use `call_querydata_api` to submit the natural language prompt to the QueryData API.
       CRITICAL: Call `call_querydata_api` EXACTLY ONCE per user request. Do NOT make retries, follow-up calls, or rephrased calls to `call_querydata_api`, even if the result contains zero rows or empty data.
    3. Immediately parse the JSON response from that first `call_querydata_api` call.
    4. Format your final response to the user containing:
       - The generated SQL query (formatted in a Markdown SQL code block).
       - The query results formatted as a Markdown table (constructed from `queryResult.columns` and `queryResult.rows`).
       - The natural language answer (`naturalLanguageAnswer`).
    """,
    tools=[call_querydata_api, skill_toolset],
)

راجِع ملف data_agent/SKILL.md للتعرّف على تعليمات النظام الخاصة بالوكيل:

REPO_NAME="codelabs"
SOURCE_DIR="alloydb-ai-nla"
cd ~/$REPO_NAME/$SOURCE_DIR/data_agent
edit SKILL.md

قبل بدء تشغيل الوكيل، عليك إعداد ملف .env يتضمّن مَعلمات لطلبات Agent API وQueryData API.

صدِّر معرّف مجموعة السياق إلى متغيّر بيئة:

export QUERYDATA_CONTEXTSET=<context set id from the Create Context Set chapter>

أنشئ ملف إعداد بيئة وقت التشغيل (.env) في دليل data_agent:

PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
REPO_NAME="codelabs"
SOURCE_DIR="alloydb-ai-nla"
cd ~/$REPO_NAME/$SOURCE_DIR/data_agent
echo "GOOGLE_GENAI_USE_ENTERPRISE=true" > .env
echo "GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project -q)" >> .env
echo "GOOGLE_CLOUD_LOCATION=global" >> .env
echo "QUERYDATA_CONTEXTSET=$QUERYDATA_CONTEXTSET" >> .env
echo "ALLOYDB_CLUSTER=alloydb-aip-01" >> .env
echo "ALLOYDB_INSTANCE=alloydb-aip-01-pr" >> .env
echo "ALLOYDB_DATABASE=quickstart_db" >> .env
echo "ALLOYDB_LOCATION=$REGION" >> .env

ثبِّت التبعيات وابدأ خدمة الويب الخاصة بالوكيل:

cd ~/$REPO_NAME/$SOURCE_DIR/
uv sync

ابدأ الوكيل:

uv run adk web --allow_origins 'regex:https://.*\.cloudshell\.dev'

من المفترض أن يظهر لك الناتج التالي مع نقطة النهاية http://127.0.0.1:8000 .

INFO:     Started server process [83608]
INFO:     Waiting for application startup.

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://127.0.0.1:8000.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

4aa60270e31efe37.jpeg

انقر على عنوان URL لخادم الويب الذي تم إنشاؤه (مثل http://127.0.0.1:8000) في Cloud Shell لتشغيل واجهة البرنامج الوكيل. إذا لم ينجح ذلك، انقر في Cloud Shell على "معاينة الويب" (Web Preview) -> "معاينة على المنفذ 8000" (Preview on port 8000) لفتح واجهة الوكيل.

تأكَّد من اختيار data_agent في القائمة المنسدلة في أعلى يمين الصفحة.

ad695db289666da3.jpeg

إنشاء طلبات البحث وتنفيذها

لننفّذ الاستعلام Q1

نفِّذ طلب اللغة الطبيعية هذا في واجهة محادثة الوكيل لتقييم أداء QueryData الأساسي بدون نماذج أو تصنيفات مخصّصة:

How many properties are currently for sale in San Diego?

ثم اضغط على زر السهم.

77773a81de6360a2.jpeg

سيبدأ سير عمل الوكيل عندما يختار المهارة المناسبة ويستخدمها مع الدالة لإرسال الطلب إلى نقطة نهاية واجهة برمجة التطبيقات واسترداد طلب البحث والنتائج التي تم إنشاؤها.

de9b3e4854b9a506.jpeg

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

605dcf936ba38cb8.jpeg

إرسال طلب بحث متابعة (Q2):

List agents who sold a property for over $1000000.

ستلاحظ أنّ الوكيل ينتقل مباشرةً إلى مهارة QueryData API لأنّه سبق له أن كتب في الذاكرة المهارات المتاحة ولا يحتاج إلى المرور بمرحلة الاستكشاف مرة أخرى.

يشبه استعلام SQL الذي تم إنشاؤه العبارة التالية:

SELECT DISTINCT "a"."agent_id", "a"."firstname", "a"."lastname", "a"."email", "a"."brokerage" 
FROM "real_estate"."agents" AS "a" 
INNER JOIN "real_estate"."property_transactions" AS "t" ON "a"."agent_id" = "t"."seller_agent_id" 
WHERE "t"."sale_price" > 1000000 AND "a"."agent_id" IS NOT NULL 
ORDER BY "a"."lastname" ASC NULLS LAST;

جرِّب طلب بحث آخر (السؤال 3):

What is the average price of a single-family home with a garage in San Diego?

تنشئ QueryData طلبات بحث عادية مع مجموعة سياق فارغة، ولكن غالبًا ما تتطلّب مهام العمل منطق عمل محدّدًا وسلوكًا حتميًا.

8. تحقيق دقة عالية وملاءمة للنشاط التجاري من خلال إدخال التفسير

يضمن إدخال التفسير في الطلبات أن تتطابق طلبات البحث التي يتم إنشاؤها مع منطق عمل محدّد.

ستجرّب هذا المثال مع عميل يطلب الحصول على منازل من طابق واحد في ديل مار. يتضمّن السؤال مقياسَين مهمَّين ويمثّل نمطًا متكرّرًا لعملية الاختيار.

جرِّب طلب اللغة الطبيعية التالي (السؤال الرابع) في الوكيل.

Single level Del Mar houses

تعرض الآلة طلب بحث عامًا، ولكنها قد تتضمّن بعض الشروط الإضافية، مثل is_single_family = TRUE:

SELECT p."property_id", p."address_street", p."price", p."bedrooms", p."bathrooms", p."listing_status", p."is_single_family", p."num_stories", c."city_name" 
FROM "real_estate"."properties" AS p 
JOIN "real_estate"."cities" AS c ON p."city_id" = c."city_id" 
WHERE c."city_name" ILIKE 'Del Mar' AND p."num_stories" = 1 AND p."is_single_family" = TRUE 
ORDER BY p."property_id" ASC NULLS LAST;

نحصل على صف واحد تم عرضه كنتيجة:

Natural Language Answer
The database contains one single-level, single-family house in Del Mar:

Address: 999 Main Ave (Postal Code: 90024)
Price: $3,800,000.00
Bedrooms: 4
Bathrooms: 3.5
Listing Status: Active
Features: Single-family home (1 story), has a garage, and no condo fees.

اختبار طلب آخر (السؤال 5):

Del Mar houses close to good schools

وهي ذكية بما يكفي لاستخدام العمودَين proximity_miles وschool_ranking لترتيب الخصائص، ولكنّها لا تقيِّم وزن وأهمية كل مقياس.

SELECT "p"."property_id", "p"."address_street", "p"."price", "p"."bedrooms", "p"."bathrooms", "s"."school_name", "s"."school_ranking", "sp"."proximity_miles" 
FROM "real_estate"."properties" AS "p" 
INNER JOIN "real_estate"."cities" AS "c" ON "p"."city_id" = "c"."city_id" 
INNER JOIN "real_estate"."school_to_property" AS "sp" ON "p"."property_id" = "sp"."property_id" 
INNER JOIN "real_estate"."schools" AS "s" ON "sp"."school_id" = "s"."school_id" 
WHERE "c"."city_name" = 'Del Mar' AND "sp"."proximity_miles" IS NOT NULL AND "s"."school_ranking" IS NOT NULL 
ORDER BY "sp"."proximity_miles" ASC NULLS LAST, "s"."school_ranking" ASC NULLS LAST;

تعميم مثال طلب البحث في نموذج

يتطلّب منطق النشاط التجاري ما يلي:

  • في نطاق ميلَين
  • ترتيب المؤسسة التعليمية 5 أو أقل
  • الترتيب المرجّح: %80 من ترتيب المؤسسة التعليمية +% 20 من القرب (النتيجة = 0.8 * ترتيب_المؤسسة_التعليمية + 0.2 * القرب_بالأميال)

في ما يلي صيغة الترتيب الموزون:

‬‭‬‭‬‭‬‭‬Score = 0.8 * school_ranking + 0.2 * proximity_miles

نزِّل ملف السياق sixrecipe_context1_1.json من Cloud Shell باستخدام واجهة سطر الأوامر في Cloud Shell:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context1_1.json

أو باستخدام عنصر القائمة Download من قائمة Cloud Shell:

c0d781806d966dcb.jpeg

حمِّل sixrecipe_context1_1.json إلى مجموعة سياق sixrecipe باستخدام AlloyDB Studio لتحديد هذه البنية العادية. انقر على النقاط الثلاث على يسار سياق sixrecipes واستخدِم "تعديل مجموعة السياقات" لتحميل الملف الجديد. سيؤدي ذلك إلى استبدال السياق القديم الفارغ بالسياق الجديد.

يحدّد النموذج قواعد نموذج SQL الصريحة لقواعد التقارب الجيد للمدرسة:

{
  "facets": [],
  "templates": [
    {
      "nl_query": "Riverside houses close to good schools.",
      "sql": "SELECT \"p\".\"address_street\", \"p\".\"address_postal_code\", \"s\".\"school_name\", \"stp\".\"proximity_miles\" FROM \"real_estate\".\"properties\" AS \"p\" JOIN \"real_estate\".\"cities\" AS \"c\" ON \"p\".\"city_id\" = \"c\".\"city_id\" JOIN \"real_estate\".\"school_to_property\" AS \"stp\" ON \"p\".\"property_id\" = \"stp\".\"property_id\" JOIN \"real_estate\".\"schools\" AS \"s\" ON \"stp\".\"school_id\" = \"s\".\"school_id\" WHERE \"c\".\"city_name\" = 'Riverside' AND \"s\".\"school_ranking\" <= 5 AND \"stp\".\"proximity_miles\" <= 2 ORDER BY 0.8 * \"s\".\"school_ranking\" + 0.2 * \"stp\".\"proximity_miles\"",
      "intent": "Houses in Riverside close to good schools (within 2 miles of schools with a rank of at least 5).",
      "manifest": "A given city houses close to good schools.",
      "parameterized": {
        "parameterized_intent": "Houses in $1 close to good schools (within 2 miles of schools with a rank of at least 5).",
        "parameterized_sql": "SELECT \"p\".\"address_street\", \"p\".\"address_postal_code\", \"s\".\"school_name\", \"stp\".\"proximity_miles\" FROM \"real_estate\".\"properties\" AS \"p\" JOIN \"real_estate\".\"cities\" AS \"c\" ON \"p\".\"city_id\" = \"c\".\"city_id\" JOIN \"real_estate\".\"school_to_property\" AS \"stp\" ON \"p\".\"property_id\" = \"stp\".\"property_id\" JOIN \"real_estate\".\"schools\" AS \"s\" ON \"stp\".\"school_id\" = \"s\".\"school_id\" WHERE \"c\".\"city_name\" = $1 AND \"s\".\"school_ranking\" <= 5 AND \"stp\".\"proximity_miles\" <= 2 ORDER BY 0.8 * \"s\".\"school_ranking\" + 0.2 * \"stp\".\"proximity_miles\""
      }
    }
  ]
}

أعِد إرسال الطلب:

Del Mar houses close to good schools

يتطابق طلب البحث الناتج الآن مع المنطق التجاري المحدّد في النموذج:

SELECT "p"."address_street", "p"."address_postal_code", "s"."school_name", "stp"."proximity_miles" 
FROM "real_estate"."properties" AS "p" 
JOIN "real_estate"."cities" AS "c" ON "p"."city_id" = "c"."city_id" 
JOIN "real_estate"."school_to_property" AS "stp" ON "p"."property_id" = "stp"."property_id" 
JOIN "real_estate"."schools" AS "s" ON "stp"."school_id" = "s"."school_id" 
WHERE "c"."city_name" = 'Del Mar' AND "s"."school_ranking" <= 5 AND "stp"."proximity_miles" <= 2 
ORDER BY 0.8 * "s"."school_ranking" + 0.2 * "stp"."proximity_miles"

بالإضافة إلى عبارة SQL التي تم إنشاؤها، يتم إنشاء الغرض التالي:

intentExplanation: "Houses in Del Mar close to good schools (within 2 miles of schools with a rank of at least 5)."

يمكنك الاطّلاع على النية في الجزء الأيمن من واجهة ADK على الويب كما هو موضّح هنا:

bfb9d6bc718f57cf.jpeg

تعرض النتائج فندقَين مرتّبَين حسب "النتيجة":

Query Results
address_street        address_postal_code        school_name        proximity_miles
200 Coast Blvd        92014        Del Mar Heights Elementary        0.50
100 Del Mar Heights Rd        92014        Del Mar Heights Elementary        1.00
Answer
Based on the data, here are the properties in Del Mar located within 2 miles of a top-rated school (ranking of 5 or better):

200 Coast Blvd (92014)

School: Del Mar Heights Elementary
Proximity: 0.50 miles
100 Del Mar Heights Rd (92014)

School: Del Mar Heights Elementary
Proximity: 1.00 miles

في الفصل التالي، ستوسّع نطاق النموذج.

إدخال التفسير من خلال التقاط أسئلة متعددة وتفسيرها

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

نزِّل ملف السياق المعدَّل:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context1_2.json

حمِّل ملف sixrecipe_context1_2.json المعدَّل إلى مجموعة السياقات.

في ملف مجموعة السياقات الجديد، سنستبدل ملف البيان من: "manifest": "A given city houses close to good schools." بملف البيان: "manifest": "A given city houses close to good schools, or are great for families with kids.". ويوسّع نطاق استخدام هذا النموذج ليشمل أكثر من حالة واحدة.

إرسال طلب البحث هذا (س6):

Houses in Waterloo great for families with kids.

يستخدم الوكيل بيان النموذج المعدَّل لتطبيق منطق طلب موحّد يعرض الطلب نفسه كما هو موضّح أعلاه، وذلك بهدف:

intentExplanation
:
"Houses in Waterloo close to good schools (within 2 miles of schools with a rank of at least 5)."

9. استخدام "النماذج المتعدّدة الأوجه" لتحقيق دقة عالية مع الحفاظ على المرونة

الأوجه هي شروط SQL نموذجية يتم دمجها ديناميكيًا مع النماذج للتعامل مع المؤهلات (مثل "مناسبة للعائلات المبتدئة" أو "تطل على البحر") بدون إنشاء نماذج منفصلة لكل تركيبة.

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

حدِّد وجهًا للخصائص التي تتضمّن السمات التالية:

  • منزل مناسب لعائلة واحدة
  • حالة بطاقة بيانات المتجر النشطة
  • ثلاث أو أربع غرف نوم وحمّامان على الأقل
  • الموقع الجغرافي في بلدية يقل فيها معدل الجريمة عن 500 جريمة لكل 100,000 مقيم

نزِّل ملف السياق المتعدّد الأوجه:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context2_1.json

حمِّل sixrecipe_context2_1.json إلى مجموعة سياق sixrecipes في AlloyDB Studio لضبط عوامل التصفية.

  "facets": [
    {
      "sql_snippet": "real_estate.properties.is_single_family = TRUE AND real_estate.properties.listing_status = 'Active' AND real_estate.properties.bedrooms BETWEEN 3 AND 4 AND real_estate.properties.bathrooms >= 2.0 AND 500 > (SELECT m.crime_rate_per_100k FROM real_estate.cities c JOIN real_estate.municipalities m ON c.municipality_id = m.municipality_id AND c.city_id = real_estate.properties.city_id)",
      "intent": "for a starter family (active single-family home listings with 3 to 4 bedrooms, 2+ bathrooms, and a crime rate under 500 per 100,000 residents)",
      "manifest": "for a starter family",
      "parameterized": {
        "parameterized_intent": "for a starter family (active single-family home listings with 3 to 4 bedrooms, 2+ bathrooms, and a crime rate under 500 per 100,000 residents)",
        "parameterized_sql_snippet": "real_estate.properties.is_single_family = TRUE AND real_estate.properties.listing_status = 'Active' AND real_estate.properties.bedrooms BETWEEN 3 AND 4 AND real_estate.properties.bathrooms >= 2.0 AND 500 > (SELECT m.crime_rate_per_100k FROM real_estate.cities c JOIN real_estate.municipalities m ON c.municipality_id = m.municipality_id AND c.city_id = real_estate.properties.city_id)"
      }
    }
  ]

نفِّذ طلب البحث هذا باللغة الطبيعية (Q7):

Del Mar houses close to good schools for a starter family.

يضيف المحرك شروط البحث المتعدّد الأوجه مباشرةً إلى طلب البحث الأساسي:

SELECT "p"."address_street", "p"."address_postal_code", "s"."school_name", "stp"."proximity_miles" 
FROM "real_estate"."properties" AS "p" 
JOIN "real_estate"."cities" AS "c" ON "p"."city_id" = "c"."city_id" 
JOIN "real_estate"."school_to_property" AS "stp" ON "p"."property_id" = "stp"."property_id" 
JOIN "real_estate"."schools" AS "s" ON "stp"."school_id" = "s"."school_id" 
WHERE "c"."city_name" = 'Del Mar' 
  AND "s"."school_ranking" <= 5 
  AND "stp"."proximity_miles" <= 2 
  AND "p"."is_single_family" = TRUE 
  AND "p"."listing_status" = 'Active' 
  AND "p"."bedrooms" BETWEEN 3 AND 4 
  AND "p"."bathrooms" >= 2.0 
  AND 500 > (
    SELECT m.crime_rate_per_100k 
    FROM real_estate.cities c 
    JOIN real_estate.municipalities m ON c.municipality_id = m.municipality_id 
    AND c.city_id = p.city_id
  ) 
ORDER BY 0.8 * "s"."school_ranking" + 0.2 * "stp"."proximity_miles"

في ما يلي النتائج:

Query Results
address_street        address_postal_code        school_name        proximity_miles
200 Coast Blvd        92014        Del Mar Heights Elementary        0.50
Natural Language Answer
Based on your criteria, there is an active listing for a single-family house in Del Mar that fits your needs:

Address: 200 Coast Blvd, Del Mar, 92014
Nearby School: Del Mar Heights Elementary (ranked within the top 5)
Proximity to School: 0.50 miles

إضافة المزيد من التصنيفات الفرعية

ماذا لو أردنا إضافة بُعد آخر استنادًا إلى النمط الجديد الناشئ، مثل عرض نافذة للعقار؟

أضِف مطابقة دلالية لإطلالة على المحيط داخل تعريف عامل تصفية.

    {
      "sql_snippet": "((real_estate.properties.description_embedding <=> google_ml.embedding('gemini-embedding-001', 'unobstructed, panoramic, ocean vista, vast Pacific, breathtaking, commanding view, deep blue horizon, massive, sweeping view')::vector) < 0.4)",
      "intent": "with ocean view",
      "manifest": "with ocean view",
      "parameterized": {
        "parameterized_intent": "with ocean view",
        "parameterized_sql_snippet": "((real_estate.properties.description_embedding <=> google_ml.embedding('gemini-embedding-001', 'unobstructed, panoramic, ocean vista, vast Pacific, breathtaking, commanding view, deep blue horizon, massive, sweeping view')::vector) < 0.4)"
      }

القيمة 0.4 في تعريف عامل التصفية أعلاه هي حدّ تم ضبطه تجريبيًا. نزِّل ملف السياق المتعدّد الأوجه:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context2_2.json

حمِّل sixrecipe_context2_2.json إلى مجموعة السياق ونفِّذ هذا الطلب (Q8):

Ocean view Del Mar homes near good schools.

يحتوي الإخراج على شروط عادية مدمجة مع مطابقة تشابه المتجهات من خلال google_ml.embedding:

SELECT "p"."address_street", "p"."address_postal_code", "s"."school_name", "stp"."proximity_miles" 
FROM "real_estate"."properties" AS "p" 
JOIN "real_estate"."cities" AS "c" ON "p"."city_id" = "c"."city_id" 
JOIN "real_estate"."school_to_property" AS "stp" ON "p"."property_id" = "stp"."property_id" 
JOIN "real_estate"."schools" AS "s" ON "stp"."school_id" = "s"."school_id" 
WHERE "c"."city_name" = 'Del Mar' AND "s"."school_ranking" <= 5 AND "stp"."proximity_miles" <= 2 
AND (((p.description_embedding <=> google_ml.embedding('gemini-embedding-001', 'unobstructed, panoramic, ocean vista, vast Pacific, breathtaking, commanding view, deep blue horizon, massive, sweeping view')::vector) <= 0.4)) 
ORDER BY 0.8 * "s"."school_ranking" + 0.2 * "stp"."proximity_miles";

ويعرض طلب البحث سمة واحدة:

Query Results
address_street        address_postal_code        school_name        proximity_miles
100 Del Mar Heights Rd        92014        Del Mar Heights Elementary        1.00
Answer
The ocean-view home in Del Mar near a top-ranked school is located at 100 Del Mar Heights Rd (92014).

It is situated just 1.00 mile away from Del Mar Heights Elementary, which is one of the area's highly-ranked schools (ranking of 5 or better).

تحقَّق من النتائج من خلال مراجعة وصف الموقع في AlloyDB Studio وتشغيل الاستعلام التالي:

select description from real_estate.properties where address_postal_code='92014' and description is not null;

سيظهر الوصف مع عبارة "مشهد بحري رائع".

Well-located 2-bedroom condo with excellent proximity to coastal shopping and dining. The balcony provides a magnificent marine spectacle against an azure backdrop. Under contract, high monthly HOA fee.

10. إزالة الغموض عن بياناتك الخاصة باستخدام عمليات البحث عن القيم

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

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

الغموض في طلب البحث

وقد يكون الأمر أكثر صعوبة في الحياة الواقعية بسبب الأخطاء الإملائية في الأسماء والمواقع الجغرافية المختلفة. نفِّذ الطلب التالي (س9) الذي يحتوي على خطأ إملائي وعبارة غامضة:

Westwod's sold properties in the last 1 month.

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

SELECT "p"."property_id", "p"."address_street", "p"."address_postal_code", "p"."price" AS "listing_price", "p"."bedrooms", "p"."bathrooms", "p"."listing_status", "pt"."sale_date", "pt"."sale_price", "c"."city_name" FROM "real_estate"."properties" AS "p" INNER JOIN "real_estate"."property_transactions" AS "pt" ON "p"."property_id" = "pt"."property_id" INNER JOIN "real_estate"."cities" AS "c" ON "p"."city_id" = "c"."city_id" WHERE ("c"."city_name" ILIKE '%Westwood%' OR "c"."city_name" ILIKE '%Westwod%') AND "pt"."sale_date" >= '2025-09-01'::date AND "pt"."sale_date" <= '2025-09-30'::date ORDER BY "pt"."sale_date" DESC NULLS LAST, "pt"."sale_price" DESC NULLS LAST

وقد صحّح الاسم وافترض أنّ السؤال كان حول موقع العقارات في محاولة لمطابقة العقارات في مدينة ويستوود.

فعِّل إضافة pg_trgm في AlloyDB Studio لإتاحة عمليات مقارنة السلاسل التقريبية:

CREATE EXTENSION IF NOT EXISTS pg_trgm;

بعد ذلك، يمكننا استخدام الإضافة لإضافة عمليات بحث عن القيم إلى مجموعة السياقات QueryData.

في ما يلي قائمة عمليات البحث عن القيم التي نريد استخدامها:

"value_searches": [
    {
      "conceptType": "Municipality name",
      "query": "/* Requires extension: pg_trgm */ WITH TrigramMetrics AS (SELECT T.municipality_name AS original_value, (T.municipality_name % $value::text) AS normalized_dist FROM real_estate.municipalities T WHERE T.municipality_name % $value::text) SELECT original_value AS value, 'real_estate.municipalities.municipality_name' AS columns, 'Name of the municipality' AS concept_type, normalized_dist AS distance, ''::text AS context FROM TrigramMetrics",
      "description": "Trigram match for municipality name"
    },
    {
      "conceptType": "City name",
      "query": "/* Requires extension: pg_trgm */ WITH TrigramMetrics AS (SELECT T.city_name AS original_value, (T.city_name % $value::text) AS normalized_dist FROM real_estate.cities T WHERE T.city_name % $value::text) SELECT original_value AS value, 'real_estate.cities.city_name' AS columns, 'Name of the city' AS concept_type, normalized_dist AS distance, ''::text AS context FROM TrigramMetrics",
      "description": "Trigram match for city name"
    },
    {
      "conceptType": "Brokerage name",
      "query": "/* Requires extension: pg_trgm */ WITH TrigramMetrics AS (SELECT T.brokerage AS original_value, (T.brokerage % $value::text) AS normalized_dist FROM real_estate.agents T WHERE T.brokerage % $value::text) SELECT original_value AS value, 'real_estate.agents.brokerage' AS columns, 'Name of the brokerage' AS concept_type, normalized_dist AS distance, ''::text AS context FROM TrigramMetrics",
      "description": "Trigram match for brokerage name"
    }
  ]

نزِّل ملف سياق البحث عن القيم:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context3_1.json

حمِّل ملف sixrecipe_context3_1.json إلى مجموعة سياقات sixrecipes في QueryData واحفظه.

أعِد تنفيذ الطلب (السؤال 9):

Westwod's sold properties in the last 1 month.

عرضت هذه السمة ردًا توضيحيًا لأنّها عثرت في البحث عن القيمة على 3 كيانات مختلفة تتضمّن قيمًا مشابهة:

The database requires some clarification to provide the exact information you need:

The search term 'Westwod' (Westwood) is ambiguous because it can refer to:

A municipality name (e.g., the municipality of Westwood)
A city name (e.g., the city of Westwood)
A brokerage name (e.g., properties sold by agents affiliated with the Westwood brokerage)
Could you please clarify which of these you are referring to?

يقدّم لنا التتبُّع فكرة عن سبب اختيار هذا المسار تحديدًا

88c52932dcbef8f9.jpeg

إليك النص الكامل:

"[NOT_ENOUGH_INFO] The search term 'Westwod' is ambiguous because it can refer to a municipality name, a city name, or a brokerage name. Could you please clarify if you are referring to properties sold within the municipality of Westwood, the city of Westwood, or properties sold by agents affiliated with the Westwood brokerage?"

إزالة الغموض من طلب البحث

تحسين طلب الإدخال (السؤال 10):

Westwood city location properties sold in September 2025.

والآن لدينا طلب البحث والنتائج:

Generated SQL
SELECT "p"."property_id", "p"."address_street", "p"."address_postal_code", "p"."price", "pt"."sale_date", "pt"."sale_price" 
FROM "real_estate"."properties" AS "p" 
INNER JOIN "real_estate"."cities" AS "c" ON "p"."city_id" = "c"."city_id" 
INNER JOIN "real_estate"."property_transactions" AS "pt" ON "p"."property_id" = "pt"."property_id" 
WHERE "c"."city_name" = 'Westwood' 
  AND "pt"."sale_date" >= '2025-09-01'::date 
  AND "pt"."sale_date" <= '2025-09-30'::date 
ORDER BY "pt"."sale_date" ASC NULLS LAST

Query Results
property_id        address_street        address_postal_code        price        sale_date        sale_price
32        999 Main St        99999        3800000.00        2025-09-12        1000000.00

11. البحث الدلالي ووظائف الذكاء الاصطناعي

تتيح وظائف AlloyDB AI إجراء فلترة دلالية على البيانات غير المنظَّمة. استخدِم دوال مثل ai.if وgoogle_ml.embedding مباشرةً في استعلامات SQL إلى جانب مشغّلات قاعدة البيانات العادية.

نموذج يتضمّن عوامل تشغيل ILIKE

في الخطوة الأولى، حمِّل ملف السياق الجديد باستخدام عوامل التشغيل ILIKE.

نزِّل ملف سياق نموذج ILIKE:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context4_1.json

حمِّل الملف sixrecipe_context4_1.json إلى مجموعة السياق لتقييم المطابقة العادية للأنماط ILIKE للمنازل "الجاهزة للسكن".

    {
      "nl_query": "Move-in ready houses",
      "sql": "SELECT \"p\".\"address_street\", \"p\".\"address_postal_code\" FROM \"real_estate\".\"properties\" AS \"p\" WHERE \"p\".listing_status = 'Active' AND \"p\".\"description\" IS NOT NULL AND (\"p\".description ILIKE '%turnkey%' OR \"p\".description ILIKE '%move-in%')",
      "intent": "Move-in ready houses",
      "manifest": "Move-in ready houses",
      "parameterized": {
        "parameterized_intent": "Move-in ready houses",
        "parameterized_sql": "SELECT \"p\".\"address_street\", \"p\".\"address_postal_code\" FROM \"real_estate\".\"properties\" AS \"p\" WHERE \"p\".listing_status = 'Active' AND \"p\".\"description\" IS NOT NULL AND (\"p\".description ILIKE '%turnkey%' OR \"p\".description ILIKE '%move-in%')"
      }
    }

إرسال طلب البحث هذا (Q11):

List move-in ready houses.

طلب البحث الناتج:

SELECT "p"."address_street", "p"."address_postal_code" 
FROM "real_estate"."properties" AS "p" 
WHERE "p".listing_status = 'Active' 
  AND "p"."description" IS NOT NULL 
  AND ("p".description ILIKE '%turnkey%' OR "p".description ILIKE '%move-in%')

تعرض هذه الدالة سجلاً واحدًا مطابقًا.

Query Results
address_street        address_postal_code
40 Main St, Unit 8        N2H 2G8

نموذج يتضمّن دالة AI.IF

نزِّل ملف سياق نموذج AI.IF:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context4_2.json

حمِّل الملف sixrecipe_context4_2.json إلى مجموعة السياق لتقييم دالة الفلترة الدلالية ai.if.

    {
      "nl_query": "List Move-in ready houses",
      "sql": "SELECT \"p\".\"address_street\", \"p\".\"address_postal_code\" FROM \"real_estate\".\"properties\" AS \"p\" WHERE \"p\".listing_status = 'Active' AND \"p\".\"description\" IS NOT NULL AND ai.if('Does this description represent a move-in ready house? Description: ' || \"p\".\"description\")",
      "intent": "List Move-in ready houses",
      "manifest": "List Move-in ready houses",
      "parameterized": {
        "parameterized_intent": "List Move-in ready houses",
        "parameterized_sql": "SELECT \"p\".\"address_street\", \"p\".\"address_postal_code\" FROM \"real_estate\".\"properties\" AS \"p\" WHERE \"p\".listing_status = 'Active' AND \"p\".\"description\" IS NOT NULL AND ai.if('Does this description represent a move-in ready house? Description: ' || \"p\".\"description\")"
      }
    }

كرِّر الطلب (السؤال 12):

List move-in ready houses.

استعلام SQL الذي تم إنشاؤه:

SELECT "p"."address_street", "p"."address_postal_code" 
FROM "real_estate"."properties" AS "p" 
WHERE "p".listing_status = 'Active' 
  AND "p"."description" IS NOT NULL 
  AND ai.if('Does this description represent a move-in ready house? Description: ' || "p"."description")

يمنحنا ذلك السمة نفسها في النتيجة:

Query Results
Address Street        Address Postal Code
40 Main St, Unit 8        N2H 2G8
Natural Language Answer
The move-in ready home currently available is located at:

Address: 40 Main St, Unit 8
Postal Code: N2H 2G8

نزِّل ملف سياق البحث المضمّن:

cloudshell download ~/codelabs/alloydb-ai-nla/sixrecipe_context4_3.json

حمِّل الملف sixrecipe_context4_3.json إلى مجموعة السياق لتقييم البحث المستند إلى المتجهات الدلالية باستخدام google_ml.embedding والبحث عن منازل مزوّدة بأجهزة مطبخ جديدة.

عدِّل مجموعة السياق باستخدام الملف sixrecipe_context4_3.json مع إضافة عامل تصفية باستخدام ميزة "البحث المتّجه" في AlloyDB.

    {
      "sql_snippet": "((real_estate.properties.description_embedding <=> google_ml.embedding('gemini-embedding-001', 'Upgraded kitchen appliances')::vector) < 0.4)",
      "intent": "with upgraded kitchen appliances",
      "manifest": "with upgraded kitchen appliances",
      "parameterized": {
        "parameterized_intent": "with upgraded kitchen appliances",
        "parameterized_sql_snippet": "((real_estate.properties.description_embedding <=> google_ml.embedding('gemini-embedding-001', 'Upgraded kitchen appliances')::vector) < 0.4)"
      }
    }

القيمة 0.4 في تعريف عامل التصفية أعلاه هي حدّ تم ضبطه تجريبيًا.

نفِّذ طلب البحث هذا (Q13):

List move-in ready houses with upgraded kitchen appliances.

استعلام SQL الذي تم إنشاؤه:

SELECT "p"."address_street", "p"."address_postal_code" FROM "real_estate"."properties" AS "p" WHERE "p"."listing_status" = 'Active' AND "p"."description" IS NOT NULL AND ai.if('Does this description represent a Move-in ready house? Description: ' || "p"."description") AND ((("p"."description_embedding" <=> google_ml.embedding('gemini-embedding-001', 'Upgraded kitchen appliances')::vector) < 0.4))

في ما يلي نتائج طلب البحث والاقتراح باللغة الطبيعية:

Query Results
Address        Postal Code
40 Main St, Unit 8        N2H 2G8
Natural Language Answer
The move-in ready house with upgraded kitchen appliances is located at:

Address: 40 Main St, Unit 8
Postal Code: N2H 2G8

12. الأمان والخصوصية

عندما تنشئ واجهة برمجة التطبيقات QueryData طلبات بحث، يكون هناك خطر على الخصوصية يتمثل في أنّ طلبات البحث التي تم إنشاؤها قد تكشف بيانات تخص مستخدمين آخرين. تفرض "طرق العرض الآمنة ذات المَعلمات" (PSV) حدود أمان على مستوى الصف أثناء إنشاء NL2SQL.

إنشاء "طريقة عرض آمنة" تتضمّن معلَمات

لدينا جدول real_estate.offers يتضمّن معلومات حول العروض المقدَّمة على جميع صفقاتنا العقارية. نريد أن يرى وكلاؤنا صفقاتهم فقط وليس صفقات وكلاء آخرين. ننشئ PSV مع إمكانية فلترة الصفوف استنادًا إلى agent_id.

أنشئ "عرضًا آمنًا مع تحديد المَعلمات" لجدول العروض في AlloyDB Studio:

CREATE VIEW real_estate.secure_offers
  WITH (security_barrier) AS
SELECT offer_id, property_id, buyer_agent_id,
    seller_agent_id, offer_amount, offer_date,
    offer_status, offer_expiration_date,
    contingencies
FROM real_estate.offers
WHERE buyer_agent_id = $@agent_id;

تحقَّق من تعريف عرض الأمان الذي يتضمّن معلَمة:

SELECT definition
FROM parameterized_views.all_parameterized_views
WHERE schemaname = 'real_estate' AND viewname = 'secure_offers';

ماذا عن جدول real_estate.offers؟

حصر الوصول إلى بيانات QueryData باستخدام طرق العرض الآمنة ذات المَعلمات في AlloyDB

في ملف agent.py، يتم تسجيل عرض الأمان المحدّد المَعلمات real_estate.secure_offers في TABLE_IDS بدلاً من real_estate.offers:

رمز المصدر agent.py:

 List of database tables included in QueryData API requests
TABLE_IDS = [
    "real_estate.municipalities",
    "real_estate.cities",
    "real_estate.agents",
    "real_estate.properties",
    "real_estate.schools",
    "real_estate.school_to_property",
    "real_estate.property_transactions",
    "real_estate.secure_offers",
]

ويتم تمرير سياق وقت تشغيل الجلسة لوكيل لديه agent_id=1:

            "parameterized_secure_view_parameters": {
                "parameters": {
                    "key": "agent_id",
                    "value": "1"
                }
            }
        },

نتيجةً لذلك، سيمرّر كل طلب بيانات من واجهة برمجة التطبيقات QueryData هذه المَعلمة، وعند تضمين العرض الآمن في الطلب، سيتم تطبيق الفلترة لعرض نتائج هذا الوكيل فقط.

نفِّذ طلب البحث هذا (Q14):

List the offer id and listing price in 2025 where the offer was within 5% of the final selling price.

استعلام SQL الذي تم إنشاؤه:

SELECT "o"."offer_id", "p"."price" AS "listing_price" 
FROM "real_estate"."secure_offers" AS "o" 
INNER JOIN "real_estate"."properties" AS "p" ON "o"."property_id" = "p"."property_id" 
INNER JOIN "real_estate"."property_transactions" AS "t" ON "o"."property_id" = "t"."property_id" 
WHERE "o"."offer_date" >= '2025-01-01' 
  AND "o"."offer_date" <= '2025-12-31' 
  AND "o"."offer_amount" IS NOT NULL 
  AND "t"."sale_price" IS NOT NULL 
  AND "p"."price" IS NOT NULL 
  AND ABS("o"."offer_amount" - "t"."sale_price") <= (0.05 * "t"."sale_price") 
ORDER BY "o"."offer_id" ASC NULLS LAST

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

Query Results
Offer ID        Listing Price
7        $750,000.00
8        $510,000.00
Natural Language Answer
Here are the offers from 2025 where the offer amount was within 5% of the final selling price:

Offer ID 7: Listing Price of $750,000.00
Offer ID 8: Listing Price of $510,000.00

إذا نفّذت الاستعلام التالي على جدول real_estate.offers الأساسي في AlloyDB Studio:

SELECT "o"."offer_id", "p"."price" AS "listing_price" 
FROM "real_estate"."offers" AS "o" 
INNER JOIN "real_estate"."properties" AS "p" ON "o"."property_id" = "p"."property_id" 
INNER JOIN "real_estate"."property_transactions" AS "t" ON "o"."property_id" = "t"."property_id" 
WHERE "o"."offer_date" >= '2025-01-01' 
  AND "o"."offer_date" <= '2025-12-31' 
  AND "o"."offer_amount" IS NOT NULL 
  AND "t"."sale_price" IS NOT NULL 
  AND "p"."price" IS NOT NULL 
  AND ABS("o"."offer_amount" - "t"."sale_price") <= (0.05 * "t"."sale_price") 
ORDER BY "o"."offer_id" ASC NULLS LAST

تعرض هذه الطريقة أكثر من سجلّين، وتُظهر بيانات جميع الموظفين.

بهذا نكون قد وصلنا إلى نهاية الدرس التطبيقي. لقد تعلّمت كيفية استخدام واجهة برمجة التطبيقات QueryData، ودوال الذكاء الاصطناعي، و"طرق العرض الآمنة ذات المَعلمات" في AlloyDB.

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

إتلاف مثيلات AlloyDB ومجموعة AlloyDB عند الانتهاء من الدرس التطبيقي

حذف مجموعة AlloyDB وجميع الآلات الافتراضية

يتم إيقاف المجموعة باستخدام الخيار force الذي يؤدي أيضًا إلى حذف جميع الآلات الافتراضية التابعة للمجموعة.

إذا تم قطع اتصال الجهاز الطرفي، أعِد الاتصال وحدِّد متغيرات المشروع والبيئة في Cloud Shell:

gcloud config set project <YOUR_PROJECT_ID>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)

احذف المجموعة:

gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force

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

student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
All of the cluster data will be lost when the cluster is deleted.

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

Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f
Deleting cluster...done.   

حذف النُسخ الاحتياطية من AlloyDB

احذف جميع النُسخ الاحتياطية من AlloyDB للمجموعة:

for i in $(gcloud alloydb backups list \
  --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" \
  --format="value(name)" \
  --sort-by=~createTime) ; do \
  gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done

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

student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f
Deleting backup...done.                                                                                                                                                                                                                                                            

حذف حزمة Cloud Storage

احذف حزمة الاستيراد في Cloud Storage لمنع فرض رسوم تخزين مستمرة:

gcloud storage rm -r gs://${PROJECT_ID}-import 

14. تهانينا

تهانينا على إكمال الدرس العملي.

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

  • كيفية نشر مجموعة AlloyDB ومثيل أساسي
  • كيفية تفعيل QueryData ووظائف الذكاء الاصطناعي و"طرق العرض الآمنة ذات المَعلمات" في AlloyDB
  • كيفية إنشاء مجموعة سياقات QueryData
  • كيفية استخدام نماذج وسياقات مختلفة في واجهة برمجة التطبيقات QueryData
  • كيفية جعل نماذج QueryData أكثر مرونة باستخدام عوامل التصفية
  • كيفية حلّ مشكلة غموض البيانات باستخدام البحث عن القيم وفهرسة ثلاثية الأوجه
  • كيفية استخدام وظائف الذكاء الاصطناعي للبحث الدلالي باستخدام النماذج
  • كيفية استخدام "طرق العرض الآمنة التي تتضمّن معلَمات" مع QueryData API

استطلاع

إخراج:

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

قراءة المحتوى فقط قراءة المحتوى وإكمال التمارين