۱. مرور کلی
تصور کنید که به صورت مجازی یا حضوری وارد یک فروشگاه اسباببازی میشوید، جایی که پیدا کردن هدیه مناسب بسیار آسان است. میتوانید آنچه را که به دنبالش هستید توصیف کنید، عکسی از یک اسباببازی آپلود کنید یا حتی اسباببازی خودتان را طراحی کنید و فروشگاه فوراً نیازهای شما را درک کرده و یک تجربه متناسب با آن را ارائه میدهد. این یک خیالپردازی آیندهنگرانه نیست؛ این یک واقعیت است که توسط هوش مصنوعی، فناوری ابری و چشماندازی برای تجارت الکترونیک شخصیسازیشده پشتیبانی میشود.
چالش: پیدا کردن محصول بینقصی که با تصورات شما مطابقت داشته باشد، میتواند دشوار باشد. عبارات جستجوی عمومی، کلمات کلیدی و جستجوهای مبهم اغلب جواب نمیدهند، مرور صفحات بیپایان میتواند خستهکننده باشد و عدم ارتباط بین آنچه تصور میکنید و آنچه موجود است میتواند منجر به ناامیدی شود.
راهکار: اپلیکیشن آزمایشی مستقیماً با این چالش مقابله میکند و با بهرهگیری از قدرت هوش مصنوعی، تجربهای واقعاً شخصیسازیشده و یکپارچه را با جستجوی زمینهای و تولید سفارشی محصول مطابق با زمینه جستجو ارائه میدهد.
آنچه خواهید ساخت
به عنوان بخشی از این آزمایشگاه، شما:
- یک نمونه AlloyDB ایجاد کنید و Toys Dataset را بارگذاری کنید
- فعال کردن افزونههای pgvector و مدل هوش مصنوعی مولد در AlloyDB
- ایجاد جاسازیها از توضیحات محصول و انجام جستجوی شباهت کسینوسی در لحظه برای متن جستجوی کاربر
- برای توصیف تصویر آپلود شده توسط کاربر برای جستجوی اسباببازیهای متنی، از Gemini 2.0 Flash استفاده کنید
- برای ایجاد یک اسباببازی سفارشی بر اساس علاقه کاربر، Imagen 3 را فراخوانی کنید
- برای جزئیات قیمت اسباببازی سفارشی ساخته شده، از ابزار پیشبینی قیمت ایجاد شده با استفاده از Gen AI Toolbox for Databases استفاده کنید.
- راهکار را در Cloud Run Functions بدون سرور مستقر کنید
الزامات
۲. معماری
جریان دادهها: بیایید نگاهی دقیقتر به نحوهی حرکت دادهها در سیستم خود بیندازیم:
- جستجوی متنی با RAG مبتنی بر هوش مصنوعی (بازیابی افزوده نسلی)
به این شکل به آن فکر کنید: به جای اینکه فقط به دنبال «ماشین قرمز» بگردد، سیستم موارد زیر را درک میکند:
«وسیله نقلیه کوچک مناسب برای یک پسر بچه ۳ ساله.»
AlloyDB به عنوان پایه: ما از AlloyDB، پایگاه داده کاملاً مدیریتشده و سازگار با PostgreSQL گوگل کلود، برای ذخیره دادههای اسباببازی خود، از جمله توضیحات، URLهای تصاویر و سایر ویژگیهای مرتبط، استفاده میکنیم.
pgvector برای جستجوی معنایی: pgvector، یک افزونه PostgreSQL، به ما امکان میدهد تا جاسازیهای برداری از توضیحات اسباببازی و همچنین جستجوهای کاربر را ذخیره کنیم. این امر جستجوی معنایی را امکانپذیر میکند، به این معنی که سیستم معنای پشت کلمات را میفهمد، نه فقط کلمات کلیدی دقیق.
شباهت کسینوسی برای سنجش ارتباط: ما از شباهت کسینوسی برای اندازهگیری شباهت معنایی بین بردار جستجوی کاربر و بردارهای توصیف اسباببازی استفاده میکنیم و مرتبطترین نتایج را نمایش میدهیم.
شاخص ScaNN برای سرعت و دقت: برای اطمینان از نتایج سریع و دقیق، به خصوص با افزایش موجودی اسباببازیهایمان، شاخص ScaNN (Scalable Nearest Neighbors) را ادغام میکنیم. این امر به طور قابل توجهی کارایی و فراخوانی جستجوی برداری ما را بهبود میبخشد.
- جستجو و درک مبتنی بر تصویر با Gemini 2.0 Flash
به جای تایپ متن، فرض کنید کاربر میخواهد عکسی از یک اسباببازی آشنا که میخواهد با آن جستجو کند را آپلود کند. کاربران میتوانند تصویری از اسباببازی مورد علاقه خود را آپلود کنند و با این کار ویژگیهای مرتبط را دریافت کنند. ما از مدل Gemini 2.0 Flash گوگل که با استفاده از LangChain4j فراخوانی میشود، برای تجزیه و تحلیل تصویر و استخراج زمینه مرتبط، مانند رنگ، جنس، نوع و گروه سنی مورد نظر اسباببازی، استفاده میکنیم.
- ساخت اسباببازی رویایی سفارشی با هوش مصنوعی مولد: Imagen 3
جادوی واقعی زمانی اتفاق میافتد که کاربران تصمیم میگیرند اسباببازی خودشان را بسازند. با استفاده از Imagen 3، ما به آنها اجازه میدهیم تا اسباببازی رویایی خود را با استفاده از پیامهای متنی ساده توصیف کنند. تصور کنید که بتوانید بگویید: "من یک اژدهای مخملی با بالهای بنفش و چهرهای دوستانه میخواهم" و ببینید که آن اژدها روی صفحه نمایش شما زنده میشود! سپس Imagen 3 تصویری از اسباببازی طراحیشده سفارشی ایجاد میکند و به کاربر تجسم روشنی از ساخته خود میدهد.
- پیشبینی قیمت با پشتیبانی نمایندگان و جعبه ابزار هوش مصنوعی عمومی برای پایگاههای داده
ما یک ویژگی پیشبینی قیمت پیادهسازی کردهایم که هزینه تولید اسباببازی سفارشی را تخمین میزند. این قابلیت توسط عاملی ارائه میشود که شامل یک ابزار محاسبه قیمت پیشرفته است.
جعبه ابزار Gen AI برای پایگاههای داده: این عامل با استفاده از ابزار جدید متنباز گوگل، Gen AI Toolbox for Databases، به طور یکپارچه با پایگاه داده ما ادغام شده است. این به عامل اجازه میدهد تا به دادههای بلادرنگ در مورد هزینههای مواد، فرآیندهای تولید و سایر عوامل مرتبط دسترسی داشته باشد تا یک تخمین قیمت دقیق ارائه دهد. اطلاعات بیشتر در مورد آن را اینجا بخوانید.
- Java Spring Boot، Gemini Code Assist و Cloud Run برای توسعه ساده و استقرار بدون سرور
کل برنامه با استفاده از Java Spring Boot، یک چارچوب قوی و مقیاسپذیر، ساخته شده است. ما در طول فرآیند توسعه، به ویژه برای توسعه front-end، از Gemini Code Assist بهره بردیم که به طور قابل توجهی چرخه توسعه را تسریع کرده و کیفیت کد را بهبود میبخشد. ما از Cloud Run برای استقرار کل برنامه و از Cloud Run Functions برای استقرار پایگاه داده و قابلیتهای agentic به عنوان نقاط پایانی مستقل استفاده کردیم.
۳. قبل از شروع
ایجاد یک پروژه
- در کنسول گوگل کلود ، در صفحه انتخاب پروژه، یک پروژه گوگل کلود را انتخاب یا ایجاد کنید.
- مطمئن شوید که صورتحساب برای پروژه ابری شما فعال است. یاد بگیرید که چگونه بررسی کنید که آیا صورتحساب در یک پروژه فعال است یا خیر .
- شما از Cloud Shell ، یک محیط خط فرمان که در Google Cloud اجرا میشود و bq از قبل روی آن بارگذاری شده است، استفاده خواهید کرد. روی Activate Cloud Shell در بالای کنسول Google Cloud کلیک کنید.

- پس از اتصال به Cloud Shell، با استفاده از دستور زیر بررسی میکنید که آیا از قبل احراز هویت شدهاید و پروژه روی شناسه پروژه شما تنظیم شده است یا خیر:
gcloud auth list
- دستور زیر را در Cloud Shell اجرا کنید تا تأیید شود که دستور gcloud از پروژه شما اطلاع دارد.
gcloud config list project
- اگر پروژه شما تنظیم نشده است، از دستور زیر برای تنظیم آن استفاده کنید:
gcloud config set project <YOUR_PROJECT_ID>
- با اجرای دستورات زیر به صورت یک به یک در ترمینال Cloud Shell خود، API های مورد نیاز را فعال کنید:
همچنین یک دستور واحد برای اجرای موارد زیر وجود دارد، اما اگر کاربر حساب آزمایشی هستید، ممکن است هنگام فعال کردن این موارد به صورت دستهای با مشکلات سهمیهبندی مواجه شوید. به همین دلیل است که دستورات در هر خط به صورت جداگانه آورده شدهاند.
gcloud services enable alloydb.googleapis.com
gcloud services enable compute.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable servicenetworking.googleapis.com
gcloud services enable run.googleapis.com
gcloud services enable cloudbuild.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
gcloud services enable aiplatform.googleapis.com
جایگزین دستور gcloud از طریق کنسول با جستجوی هر محصول یا استفاده از این لینک است.
اگر هر API از قلم افتاده باشد، میتوانید همیشه آن را در طول پیادهسازی فعال کنید.
برای دستورات و نحوهی استفاده از gcloud به مستندات مراجعه کنید.
۴. راهاندازی پایگاه داده
در این آزمایش، ما از AlloyDB به عنوان پایگاه داده برای نگهداری دادههای فروشگاه اسباببازی استفاده خواهیم کرد. این پایگاه داده از خوشهها برای نگهداری تمام منابع، مانند پایگاههای داده و گزارشها، استفاده میکند. هر خوشه یک نمونه اصلی دارد که یک نقطه دسترسی به دادهها را فراهم میکند. جداول، دادههای واقعی را نگهداری میکنند.
بیایید یک کلاستر، نمونه و جدول AlloyDB ایجاد کنیم که مجموعه دادههای تجارت الکترونیک در آن بارگذاری شود.
ایجاد یک کلاستر و نمونه
- در کنسول ابری، صفحه AlloyDB را پیمایش کنید. یک راه آسان برای یافتن اکثر صفحات در کنسول ابری، جستجوی آنها با استفاده از نوار جستجوی کنسول است.
- از آن صفحه، گزینه CREATE CLUSTER را انتخاب کنید:

- صفحهای مانند تصویر زیر خواهید دید. یک کلاستر و نمونه با مقادیر زیر ایجاد کنید (مطمئن شوید که مقادیر مطابقت دارند، در صورتی که کد برنامه را از مخزن کپی میکنید):
- شناسه خوشه : "
vector-cluster" - رمز عبور : "
alloydb" - سازگار با PostgreSQL 15
- منطقه : "
us-central1" - شبکه : "
default"

- وقتی شبکه پیشفرض را انتخاب میکنید، صفحهای مانند تصویر زیر مشاهده خواهید کرد.
تنظیم اتصال را انتخاب کنید. 
- از آنجا، « استفاده از یک محدوده IP اختصاص داده شده خودکار » را انتخاب کرده و ادامه دهید. پس از بررسی اطلاعات، «ایجاد اتصال» را انتخاب کنید.

- پس از راهاندازی شبکه، میتوانید به ایجاد خوشه خود ادامه دهید. برای تکمیل راهاندازی خوشه، مطابق شکل زیر، روی CREATE CLUSTER کلیک کنید:

حتماً شناسه نمونه را به تغییر دهید
vector-instance
اگر نمیتوانید آن را تغییر دهید، به یاد داشته باشید که شناسه نمونه را در تمام ارجاعات بعدی تغییر دهید .
توجه داشته باشید که ایجاد خوشه حدود ۱۰ دقیقه طول خواهد کشید. پس از موفقیتآمیز بودن، باید صفحهای را مشاهده کنید که نمای کلی خوشه ایجاد شده شما را نشان میدهد.
۵. دریافت دادهها
حالا وقت آن رسیده که یک جدول با دادههای مربوط به فروشگاه اضافه کنیم. به AlloyDB بروید، خوشه اصلی و سپس AlloyDB Studio را انتخاب کنید:

ممکن است لازم باشد منتظر بمانید تا نمونه شما به طور کامل ایجاد شود. پس از اتمام این کار، با استفاده از اعتبارنامههایی که هنگام ایجاد خوشه ایجاد کردهاید، وارد AlloyDB شوید. از دادههای زیر برای تأیید اعتبار در PostgreSQL استفاده کنید:
- نام کاربری: "
postgres" - پایگاه داده: "
postgres" - رمز عبور: "
alloydb"
پس از اینکه با موفقیت در AlloyDB Studio احراز هویت شدید، دستورات SQL در ویرایشگر وارد میشوند. میتوانید با استفاده از علامت + در سمت راست آخرین پنجره، چندین پنجره ویرایشگر اضافه کنید.

شما میتوانید دستورات AlloyDB را در پنجرههای ویرایشگر وارد کنید و در صورت لزوم از گزینههای Run، Format و Clear استفاده کنید.
فعال کردن افزونهها
برای ساخت این برنامه، از افزونههای pgvector و google_ml_integration استفاده خواهیم کرد. افزونه pgvector به شما امکان ذخیره و جستجوی جاسازیهای برداری را میدهد. افزونه google_ml_integration توابعی را ارائه میدهد که برای دسترسی به نقاط پایانی پیشبینی هوش مصنوعی Vertex برای دریافت پیشبینیها در SQL استفاده میکنید. این افزونهها را با اجرای DDL های زیر فعال کنید :
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
اگر میخواهید افزونههایی که در پایگاه داده شما فعال شدهاند را بررسی کنید، این دستور SQL را اجرا کنید:
select extname, extversion from pg_extension;
ایجاد یک جدول
با استفاده از دستور DDL زیر، یک جدول ایجاد کنید:
CREATE TABLE toys ( id VARCHAR(25), name VARCHAR(25), description VARCHAR(20000), quantity INT, price FLOAT, image_url VARCHAR(200), text_embeddings vector(768)) ;
پس از اجرای موفقیتآمیز دستور فوق، باید بتوانید جدول را در پایگاه داده مشاهده کنید.
دریافت داده
برای این آزمایش، ما دادههای آزمایشی حدود ۷۲ رکورد در این فایل SQL داریم. این فایل شامل فیلدهای id, name, description, quantity, price, image_url است. فیلدهای دیگر بعداً در این آزمایش پر خواهند شد.
فقط ۵ خط اول/عبارات درج را از آنجا کپی کنید و سپس آن خطوط را در یک برگه ویرایشگر خالی جایگذاری کنید و RUN را انتخاب کنید. اگر از حساب صورتحساب آزمایشی استفاده نمیکنید، احتمالاً میتوانید تمام عبارات درج را کپی کرده و اجرا کنید.
برای مشاهدهی محتوای جدول، بخش Explorer را باز کنید تا جدولی به نام apparels را ببینید. برای مشاهدهی گزینهی Query the table، علامت سهکلون (⋮) را انتخاب کنید. یک عبارت SELECT در یک تب جدید Editor باز خواهد شد.

اعطای مجوز
دستور زیر را اجرا کنید تا به کاربر postgres اجازه اجرای تابع embedding داده شود:
GRANT EXECUTE ON FUNCTION embedding TO postgres;
اعطای نقش کاربری Vertex AI به حساب سرویس AlloyDB
به ترمینال Cloud Shell بروید و دستور زیر را وارد کنید:
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"
۶. ایجاد جاسازیها برای متن
پردازش اعداد برای کامپیوترها بسیار آسانتر از پردازش متن است. یک سیستم جاسازی، متن را به مجموعهای از اعداد اعشاری تبدیل میکند که باید متن را نمایش دهند، صرف نظر از اینکه متن چگونه نوشته شده باشد، از چه زبانی استفاده شود و غیره.
توصیف یک مکان ساحلی را در نظر بگیرید. ممکن است به صورت «روی آب»، «کنار ساحل»، «از اتاقت تا اقیانوس قدم بزن»، «در دریا»، «در ساحل» و غیره نامیده شود. همه این اصطلاحات متفاوت به نظر میرسند، اما معنای معنایی آنها یا در اصطلاحات یادگیری ماشین، جاسازیهای آنها باید بسیار نزدیک به یکدیگر باشد.
اکنون که دادهها و زمینه آماده هستند، SQL را اجرا میکنیم تا جاسازیهای توضیحات محصول را به جدول در فیلد embedding اضافه کنیم. مدلهای جاسازی متنوعی وجود دارد که میتوانید از آنها استفاده کنید. ما text-embedding-005 از Vertex AI استفاده میکنیم. حتماً در طول پروژه از همان مدل جاسازی استفاده کنید!
توجه: اگر از یک پروژه Google Cloud موجود که مدتی پیش ایجاد شده است استفاده میکنید، ممکن است لازم باشد به استفاده از نسخههای قدیمیتر مدل جاسازی متن مانند textembedding-gecko ادامه دهید.
به برگه AlloyDB Studio برگردید و DML زیر را تایپ کنید:
UPDATE toys set text_embeddings = embedding( 'text-embedding-005', description);
دوباره به جدول toys نگاه کنید تا برخی از جاسازیها را ببینید. حتماً دستور SELECT را دوباره اجرا کنید تا تغییرات را ببینید.
SELECT id, name, description, price, quantity, image_url, text_embeddings FROM toys;
این باید بردار جاسازیها را که شبیه آرایهای از اعداد اعشاری است، برای توضیحات اسباببازی، همانطور که در زیر نشان داده شده است، برگرداند:

توجه: پروژههای جدید Google Cloud که تحت سطح رایگان ایجاد شدهاند، ممکن است در مورد تعداد درخواستهای جاسازی مجاز در هر ثانیه برای مدلهای جاسازی، با مشکلات سهمیهبندی مواجه شوند. پیشنهاد میکنیم هنگام ایجاد جاسازی، از یک پرسوجوی فیلتر برای شناسه استفاده کنید و سپس به صورت انتخابی ۱ تا ۵ رکورد و به همین ترتیب را انتخاب کنید.
۷. جستجوی برداری انجام دهید
اکنون که جدول، دادهها و جاسازیها آماده هستند، بیایید جستجوی برداری بلادرنگ را برای متن جستجوی کاربر انجام دهیم.
فرض کنید کاربر میپرسد:
« I want a white plush teddy bear toy with a floral pattern .»
با اجرای کوئری زیر میتوانید موارد منطبق با این مورد را پیدا کنید:
select * from toys
ORDER BY text_embeddings <=> CAST(embedding('text-embedding-005', 'I want a white plush teddy bear toy with a floral pattern') as vector(768))
LIMIT 2;
بیایید این پرس و جو را با جزئیات بررسی کنیم:
در این پرس و جو،
- متن جستجوی کاربر این است: «
I want a white plush teddy bear toy with a floral pattern.» - ما آن را در متد
embedding()با استفاده از مدلtext-embedding-005به embedding تبدیل میکنیم. این مرحله باید پس از مرحله قبل، که در آن تابع embedding را روی همه موارد موجود در جدول اعمال کردیم، آشنا به نظر برسد. - «
<=>» نشان دهنده استفاده از روش فاصله COSINE SIMILARITY است. میتوانید تمام معیارهای شباهت موجود را در مستندات pgvector بیابید. - ما در حال تبدیل نتیجه روش جاسازی به نوع بردار هستیم تا آن را با بردارهای ذخیره شده در پایگاه داده سازگار کنیم.
- محدودیت ۵ نشان میدهد که میخواهیم ۵ همسایه نزدیک برای متن جستجو استخراج کنیم.
نتیجه به این شکل است:

همانطور که در نتایج خود مشاهده میکنید، نتایج جستجو بسیار نزدیک به متن جستجو هستند. سعی کنید متن را تغییر دهید تا ببینید نتایج چگونه تغییر میکنند.
نکته مهم:
حال فرض کنید میخواهیم عملکرد (زمان پرسوجو)، کارایی و میزان فراخوانی این نتیجه جستجوی برداری را با استفاده از شاخص ScaNN افزایش دهیم. لطفاً مراحل موجود در این وبلاگ را مطالعه کنید تا تفاوت نتیجه را با و بدون شاخص مقایسه کنید.
مرحله اختیاری: بهبود کارایی و فراخوانی با شاخص ScaNN
اگر تعداد رکوردهای شما کمتر از ۱۰۰ است، این مرحله را نادیده بگیرید.
فقط برای راحتی، مراحل ایجاد فهرست را اینجا فهرست میکنم:
- از آنجایی که ما از قبل کلاستر، نمونه، زمینه و جاسازیها را ایجاد کردهایم، فقط باید افزونه ScaNN را با استفاده از دستور زیر نصب کنیم:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- در مرحله بعد، شاخص (ScaNN) را ایجاد خواهیم کرد:
CREATE INDEX toysearch_index ON toys
USING scann (text_embeddings cosine)
WITH (num_leaves=9);
در DDL بالا، apparel_index نام اندیس است.
«اسباببازیها» میز من است
"scann" متد اندیس است
«جاسازی» ستونی در جدول است که میخواهم آن را ایندکس کنم.
«کسینوس» روش فاصلهای است که میخواهم با اندیس استفاده کنم.
«۸» تعداد پارتیشنهایی است که باید به این شاخص اعمال شوند. میتوانید آن را روی هر مقداری بین ۱ تا ۱۰۴۸۵۷۶ تنظیم کنید. برای اطلاعات بیشتر در مورد نحوه تعیین این مقدار، به بخش تنظیم شاخص ScaNN مراجعه کنید.
من از جذر تعداد نقاط داده، همانطور که در مخزن ScaNN توصیه شده است، استفاده کردم (هنگام پارتیشنبندی، num_leaves باید تقریباً برابر با جذر تعداد نقاط داده باشد.)
- بررسی کنید که آیا ایندکس با استفاده از پرس و جو ایجاد شده است یا خیر:
SELECT * FROM pg_stat_ann_indexes;
- جستجوی برداری را با استفاده از همان پرسوجویی که بدون اندیس استفاده کردیم، انجام دهید:
select * from toys
ORDER BY text_embeddings <=> CAST(embedding('text-embedding-005', 'I want a white plush teddy bear toy with a floral pattern') as vector(768))
LIMIT 5;
کوئری بالا همان کوئریای است که در تمرین مرحله ۸ استفاده کردیم. با این حال، اکنون فیلد را اندیسگذاری کردهایم.
- با یک کوئری جستجوی ساده با و بدون اندیس (با حذف اندیس) تست کنید:
این مورد استفاده فقط ۷۲ رکورد دارد، بنابراین ایندکس واقعاً اعمال نمیشود. برای آزمایشی که در یک مورد استفاده دیگر انجام شده است، نتایج به شرح زیر است:
همان جستجوی برداری روی دادههای جاسازیشدهی INDEXED منجر به نتایج جستجوی باکیفیت و کارایی میشود. کارایی با استفاده از ایندکس بسیار بهبود یافته است (از نظر زمان اجرا: ۱۰.۳۷ میلیثانیه بدون ScaNN و ۰.۸۷ میلیثانیه با ScaNN). برای اطلاعات بیشتر در مورد این موضوع، لطفاً به این وبلاگ مراجعه کنید.
۸. اعتبارسنجی را با LLM مطابقت دهید
قبل از ادامه و ایجاد سرویسی برای بازگرداندن بهترین تطابقها به یک برنامه، بیایید از یک مدل هوش مصنوعی مولد برای اعتبارسنجی استفاده کنیم که آیا این پاسخهای بالقوه واقعاً مرتبط و برای اشتراکگذاری با کاربر ایمن هستند یا خیر.
اطمینان از راهاندازی نمونه برای Gemini
ابتدا بررسی کنید که آیا ادغام Google ML برای کلاستر و نمونه شما از قبل فعال شده است یا خیر. در AlloyDB Studio، دستور زیر را اجرا کنید:
show google_ml_integration.enable_model_support;
اگر مقدار به صورت "روشن" نشان داده شده است، میتوانید از دو مرحله بعدی صرف نظر کنید و مستقیماً به تنظیمات ادغام AlloyDB و Vertex AI Model بروید.
- به نمونه اصلی کلاستر AlloyDB خود بروید و روی ویرایش نمونه اصلی کلیک کنید.

- به بخش پرچمها در گزینههای پیکربندی پیشرفته بروید و مطمئن شوید که
google_ml_integration.enable_model_support flagمطابق شکل زیر روی «on» تنظیم شده باشد:

اگر روی "روشن" تنظیم نشده است، آن را روی "روشن" تنظیم کنید و سپس روی دکمهی UPDATE INSTANCE کلیک کنید. این مرحله چند دقیقه طول خواهد کشید.
ادغام مدل AlloyDB و Vertex AI
اکنون میتوانید به AlloyDB Studio متصل شوید و دستور DML زیر را برای تنظیم دسترسی مدل Gemini از AlloyDB، با استفاده از شناسه پروژه خود که در آن مشخص شده است، اجرا کنید. ممکن است قبل از اجرای دستور، یک خطای نحوی به شما هشدار داده شود، اما باید به خوبی اجرا شود.
ابتدا، اتصال مدل Gemini 1.5 را مطابق شکل زیر ایجاد میکنیم. به یاد داشته باشید که $PROJECT_ID در دستور زیر با شناسه پروژه Google Cloud خود جایگزین کنید.
CALL
google_ml.create_model( model_id => 'gemini-1.5',
model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-1.5-pro:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
میتوانید مدلهای پیکربندیشده برای دسترسی را از طریق دستور زیر در AlloyDB Studio بررسی کنید:
select model_id,model_type from google_ml.model_info_view;
در نهایت، باید به کاربران پایگاه داده اجازه اجرای تابع ml_predict_row را بدهیم تا پیشبینیها از طریق مدلهای هوش مصنوعی Google Vertex اجرا شوند. دستور زیر را اجرا کنید:
GRANT EXECUTE ON FUNCTION ml_predict_row to postgres;
توجه: اگر از یک پروژه Google Cloud موجود و یک کلاستر/نمونه AlloyDB که مدتی پیش ایجاد شده است استفاده میکنید، ممکن است لازم باشد ارجاعات قدیمی به مدل gemini-1.5 را حذف کرده و دوباره با دستور CALL بالا ایجاد کنید و دستور grant execute on function ml_predict_row را دوباره اجرا کنید تا در صورت بروز مشکل در فراخوانیهای بعدی gemini-1.5، بتوانید آن را اجرا کنید.
ارزیابی پاسخها
اگرچه در بخش بعدی از یک پرسوجوی بزرگ استفاده خواهیم کرد تا از منطقی بودن پاسخهای پرسوجو اطمینان حاصل کنیم، اما درک پرسوجو میتواند دشوار باشد. اکنون به بخشهای مختلف نگاه میکنیم و خواهیم دید که چگونه در عرض چند دقیقه کنار هم قرار میگیرند.
- ابتدا یک درخواست به پایگاه داده ارسال میکنیم تا 10 مورد از نزدیکترین موارد به جستجوی کاربر را دریافت کنیم.
- برای تعیین میزان اعتبار پاسخها، از یک پرسوجوی بیرونی استفاده خواهیم کرد که در آن نحوه ارزیابی پاسخها را توضیح میدهیم. این پرسوجو از فیلد
recommended_textکه متن جستجو وcontent(که فیلد توضیحات اسباببازی است) جدول داخلی را به عنوان بخشی از پرسوجو استفاده میکند. - با استفاده از آن، «خوبی» پاسخهای دریافتی را بررسی خواهیم کرد.
- تابع
predict_rowنتیجه خود را در قالب JSON برمیگرداند. کد "-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'"برای استخراج متن واقعی از آن JSON استفاده میشود. برای مشاهده JSON واقعی که برگردانده میشود، میتوانید این کد را حذف کنید. - در نهایت، برای دریافت پاسخ LLM، آن را با استفاده از
REGEXP_REPLACE(gemini_validation,'[^a-zA-Z,: ]','','g')استخراج میکنیم.
SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
REGEXP_REPLACE(gemini_validation, '[^a-zA-Z,: ]', '', 'g') AS gemini_validation
FROM (SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
CAST(ARRAY_AGG(LLM_RESPONSE) AS TEXT) AS gemini_validation
FROM (SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
json_array_elements(google_ml.predict_row(model_id => 'gemini-1.5',
request_body => CONCAT('{ "contents": [ { "role": "user", "parts": [ { "text": "User wants to buy a toy and this is the description of the toy they wish to buy: ', recommended_text, '. Check if the following product items from the inventory are close enough to really, contextually match the user description. Here are the items: ', content, '. Return a ONE-LINE response with 3 values: 1) MATCH: if the 2 contexts are reasonably matching in terms of any of the color or color family specified in the list, approximate style match with any of the styles mentioned in the user search text: This should be a simple YES or NO. Choose NO only if it is completely irrelevant to users search criteria. 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear one-line easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match. " } ] } ] }')::JSON)) -> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text' :: TEXT AS LLM_RESPONSE
FROM (SELECT id,
name,
description AS content,
quantity,
price,
image_url,
'Pink panther standing' AS recommended_text
FROM toys
ORDER BY text_embeddings <=> embedding('text-embedding-005',
'Pink panther standing')::VECTOR
LIMIT 1) AS xyz) AS X
GROUP BY id,
name,
content,
quantity,
price,
image_url,
recommended_text) AS final_matches
-- WHERE REGEXP_REPLACE(gemini_validation, '[^a-zA-Z,: ]', '', 'g') LIKE '%MATCH%:%YES%';
اگرچه این هنوز ممکن است دلهرهآور به نظر برسد، امیدوارم بتوانید کمی بیشتر از آن سر در بیاورید. نتایج نشان میدهند که آیا تطابقی وجود دارد یا خیر، درصد تطابق چقدر است و توضیحی در مورد رتبهبندی ارائه میدهند.
توجه داشته باشید که مدل Gemini به طور پیشفرض streaming را فعال کرده است، بنابراین پاسخ واقعی در چندین خط پخش میشود:

۹. جستجوی اسباببازی را بدون سرور ابری انجام دهید
آمادهاید که این برنامه را به وب ببرید؟ مراحل زیر را دنبال کنید تا این موتور دانش را بدون سرور و با استفاده از توابع ابری اجرا کنید:
- برای ایجاد یک تابع Cloud Run جدید، به Cloud Run Functions در کنسول Google Cloud بروید یا از لینک https://console.cloud.google.com/functions/add استفاده کنید.
- محیط را به عنوان " تابع اجرای ابری " انتخاب کنید. نام تابع را " get-toys-alloydb " و منطقه را " us-central1 " انتخاب کنید. Authentication را روی " Allow unauthenticated invocations " تنظیم کنید و روی NEXT کلیک کنید. Java 17 را به عنوان زمان اجرا و Inline Editor را برای کد منبع انتخاب کنید.
- به طور پیشفرض، نقطه ورود (Entry Point) را روی "
gcfv2.HelloHttpFunction" تنظیم میکند. کد جاینگهدار (placeholder) درHelloHttpFunction.javaوpom.xmlاز تابع Cloud Run خود را به ترتیب با کد HelloHttpFunction.java و pom.xml جایگزین کنید. - به یاد داشته باشید که محل <<YOUR_PROJECT>> و اعتبارنامههای اتصال AlloyDB را با مقادیر خود در فایل جاوا تغییر دهید. اعتبارنامههای AlloyDB همانهایی هستند که در ابتدای این آزمایشگاه کد استفاده کردهایم. اگر از مقادیر متفاوتی استفاده کردهاید، لطفاً همانها را در فایل جاوا تغییر دهید.
- روی استقرار کلیک کنید.
پس از استقرار، برای اینکه تابع ابری بتواند به نمونه پایگاه داده AlloyDB ما دسترسی پیدا کند، رابط VPC را ایجاد خواهیم کرد.
مرحله مهم:
پس از آماده شدن برای استقرار، باید بتوانید توابع را در کنسول توابع Google Cloud Run مشاهده کنید. تابع تازه ایجاد شده ( get-toys-alloydb ) را جستجو کنید، روی آن کلیک کنید، سپس روی ویرایش کلیک کنید و موارد زیر را تغییر دهید:
- به تنظیمات زمان اجرا، ساخت، اتصالات و امنیت بروید
- افزایش زمان انتظار به ۱۸۰ ثانیه
- به برگه اتصالات بروید:

- در تنظیمات Ingress، مطمئن شوید که گزینه «Allow all traffic» انتخاب شده است.
- در تنظیمات Egress، روی منوی کشویی Network کلیک کنید و گزینه "Add New VPC Connector" را انتخاب کنید و دستورالعملهای نمایش داده شده در کادر محاورهای را دنبال کنید:

- یک نام برای رابط VPC انتخاب کنید و مطمئن شوید که منطقه آن با منطقه شما یکسان است. مقدار Network را به صورت پیشفرض رها کنید و Subnet را روی Custom IP Range با محدوده IP 10.8.0.0 یا چیزی مشابه آن که در دسترس است، تنظیم کنید.
- SHOW SCALINING SETTINGS را باز کنید و مطمئن شوید که پیکربندی دقیقاً روی موارد زیر تنظیم شده است:

- روی CREATE کلیک کنید و این کانکتور اکنون باید در تنظیمات خروجی فهرست شده باشد.
- کانکتور تازه ایجاد شده را انتخاب کنید
- انتخاب کنید که تمام ترافیک از طریق این کانکتور VPC هدایت شود.
- روی NEXT و سپس DEPLOY کلیک کنید.
۱۰. عملکرد Cloud Run را آزمایش کنید
پس از استقرار تابع ابری بهروزرسانیشده، باید نقطه پایانی ایجاد شده را مشاهده کنید. آن را کپی کرده و در دستور زیر جایگزین کنید:
روش دیگر، میتوانید تابع Cloud Run را به صورت زیر آزمایش کنید:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST <<YOUR_ENDPOINT>> \
-H 'Content-Type: application/json' \
-d '{"search":"I want a standing pink panther toy"}' \
| jq .
و نتیجه:

همین! انجام جستجوی بردار شباهت با استفاده از مدل Embeddings روی دادههای AlloyDB به همین سادگی است.
۱۱. ساخت کلاینت برنامه وب!
در این بخش، ما یک برنامه وب خواهیم ساخت تا کاربر بتواند با آن تعامل داشته باشد و اسباببازیهای منطبق را بر اساس متن، تصویر پیدا کند و حتی بر اساس نیازهای خود یک اسباببازی جدید ایجاد کند. از آنجایی که برنامه از قبل ساخته شده است، میتوانید مراحل زیر را برای کپی کردن آن به IDE خود و راهاندازی برنامه دنبال کنید.
- از آنجایی که ما از Gemini 2.0 Flash برای توصیف تصویری که کاربر ممکن است برای یافتن اسباببازیهای منطبق آپلود کند استفاده میکنیم، باید کلید API این برنامه را دریافت کنیم. برای انجام این کار، به https://aistudio.google.com/apikey بروید و کلید API پروژه فعال Google Cloud خود را که این برنامه را در آن پیادهسازی میکنید، دریافت کنید و کلید را در جایی ذخیره کنید:

- به ترمینال Cloud Shell بروید
- مخزن را با دستور زیر کلون کنید:
git clone https://github.com/AbiramiSukumaran/toysearch
cd toysearch
- پس از کلون کردن مخزن، باید بتوانید از ویرایشگر Cloud Shell خود به پروژه دسترسی پیدا کنید.
- شما باید پوشههای "get-toys-alloydb" و "toolbox-toys" را از پروژه کلون شده حذف کنید، زیرا این دو، کدهای Cloud Run Functions هستند که در صورت نیاز میتوانید از مخزن به آنها مراجعه کنید.
- به پوشه وب GenerateToy.java بروید و خط زیر را پیدا کنید و آن را حذف کنید زیرا allow adult ممکن است به مجوز ویژهای نیاز داشته باشد که ممکن است برای برخی از حسابهای پرداخت آزمایشی در دسترس نباشد:
paramsMap.put("personGeneration", "allow_adult");
- قبل از ساخت و استقرار برنامه، مطمئن شوید که تمام متغیرهای محیطی لازم تنظیم شدهاند. به ترمینال Cloud Shell بروید و موارد زیر را اجرا کنید:
PROJECT_ID=$(gcloud config get-value project)
export PROJECT_ID=$PROJECT_ID
export GOOGLE_API_KEY=<YOUR API KEY that you saved>
- برنامه را به صورت محلی بسازید و اجرا کنید:
مطمئن شوید که در دایرکتوری پروژه هستید، دستورات زیر را اجرا کنید:
mvn package
mvn spring-boot:run
- استقرار در Cloud Run
gcloud run deploy --source .
۱۲. درک جزئیات هوش مصنوعی مولد
نیازی به اقدام خاصی نیست. فقط جهت اطلاع شما:
حالا که برنامه را برای استقرار آماده کردهاید، لحظهای وقت بگذارید تا بفهمید که چگونه جستجو (متن و تصویر) و تولید را انجام دادیم.
- جستجوی برداری مبتنی بر متن کاربر:
این مورد قبلاً در توابع Cloud Run که در بخش «برنامه جستجوی برداری تحت وب» پیادهسازی کردیم، مورد توجه قرار گرفته است.
- جستجوی برداری مبتنی بر آپلود تصویر:
به جای تایپ متن، فرض کنید کاربر میخواهد عکسی از یک اسباببازی آشنا که میخواهد با آن جستجو کند را آپلود کند. کاربران میتوانند تصویری از اسباببازی مورد علاقه خود را آپلود کنند و با این کار ویژگیهای مرتبط را دریافت کنند.
ما از مدل Gemini 2.0 Flash گوگل که با استفاده از LangChain4j فراخوانی میشود، برای تجزیه و تحلیل تصویر و استخراج زمینههای مرتبط، مانند رنگ، جنس، نوع و گروه سنی مورد نظر اسباببازی، استفاده میکنیم.
تنها در ۵ مرحله، ما ورودی دادههای چندوجهی کاربر را با استفاده از یک چارچوب متنباز، به تطبیق نتایج با فراخوانی مدل زبانی بزرگ بردیم. بیاموزید که چگونه:
package cloudcode.helloworld.web;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import java.util.Base64;
import java.util.Optional;
public class GeminiCall {
public String imageToBase64String(byte[] imageBytes) {
String base64Img = Base64.getEncoder().encodeToString(imageBytes);
return base64Img;
}
public String callGemini(String base64ImgWithPrefix) throws Exception {
String searchText = "";
// 1. Remove the prefix
String base64Img = base64ImgWithPrefix.replace("data:image/jpeg;base64,", "");
// 2. Decode base64 to bytes
byte[] imageBytes = Base64.getDecoder().decode(base64Img);
String image = imageToBase64String(imageBytes);
// 3. Get API key from environment variable
String apiKey = Optional.ofNullable(System.getenv("GOOGLE_API_KEY"))
.orElseThrow(() -> new IllegalArgumentException("GOOGLE_API_KEY environment variable not set"));
// 4. Invoke Gemini 2.0
ChatLanguageModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(apiKey)
.modelName("gemini-2.0-flash-001")
.build();
Response<AiMessage> response = gemini.generate(
UserMessage.from(
ImageContent.from(image, "image/jpeg"),
TextContent.from(
"The picture has a toy in it. Describe the toy in the image in one line. Do not add any prefix or title to your description. Just describe that toy that you see in the image in one line, do not describe the surroundings and other objects around the toy in the image. If you do not see any toy in the image, send response stating that no toy is found in the input image.")));
// 5. Get the text from the response and send it back to the controller
searchText = response.content().text().trim();
System.out.println("searchText inside Geminicall: " + searchText);
return searchText;
}
}
- درک کنید که چگونه از Imagen 3 برای ساخت یک اسباببازی سفارشی بر اساس درخواست کاربر با Generative AI استفاده کردیم.
سپس Imagen 3 تصویری از اسباببازی طراحیشدهی سفارشی تولید میکند و به کاربر تجسم روشنی از ساختهی خود میدهد. ما این کار را تنها در ۵ مرحله انجام دادیم:
// Generate an image using a text prompt using an Imagen model
public String generateImage(String projectId, String location, String prompt)
throws ApiException, IOException {
final String endpoint = String.format("%s-aiplatform.googleapis.com:443", location);
PredictionServiceSettings predictionServiceSettings =
PredictionServiceSettings.newBuilder().setEndpoint(endpoint).build();
// 1. Set up the context and prompt
String context = "Generate a photo-realistic image of a toy described in the following input text from the user. Make sure you adhere to all the little details and requirements mentioned in the prompt. Ensure that the user is only describing a toy. If it is anything unrelated to a toy, politely decline the request stating that the request is inappropriate for the current context. ";
prompt = context + prompt;
// 2. Initialize a client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
try (PredictionServiceClient predictionServiceClient =
PredictionServiceClient.create(predictionServiceSettings)) {
// 3. Invoke Imagen 3
final EndpointName endpointName =
EndpointName.ofProjectLocationPublisherModelName(
projectId, location, "google", "imagen-3.0-generate-001"); //"imagegeneration@006"; imagen-3.0-generate-001
Map<String, Object> instancesMap = new HashMap<>();
instancesMap.put("prompt", prompt);
Value instances = mapToValue(instancesMap);
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("sampleCount", 1);
paramsMap.put("aspectRatio", "1:1");
paramsMap.put("safetyFilterLevel", "block_few");
paramsMap.put("personGeneration", "allow_adult");
paramsMap.put("guidanceScale", 21);
paramsMap.put("imagenControlScale", 0.95); //Setting imagenControlScale
Value parameters = mapToValue(paramsMap);
// 4. Get prediction response image
PredictResponse predictResponse =
predictionServiceClient.predict(
endpointName, Collections.singletonList(instances), parameters);
// 5. Return the Base64 Encoded String to the controller
for (Value prediction : predictResponse.getPredictionsList()) {
Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
if (fieldsMap.containsKey("bytesBase64Encoded")) {
bytesBase64EncodedOuput = fieldsMap.get("bytesBase64Encoded").getStringValue();
}
}
return bytesBase64EncodedOuput.toString();
}
}
پیشبینی قیمت
در بخش قبلی بالا، ما در مورد چگونگی تولید تصویر اسباببازی توسط Imagen که کاربر مایل به طراحی آن است، بحث کردیم. برای اینکه کاربر بتواند آن را خریداری کند، برنامه باید قیمتی برای آن تعیین کند و ما از یک منطق شهودی برای تعریف قیمت برای اسباببازی سفارشی ساخته شده استفاده کردهایم. منطق این است که از میانگین قیمت ۵ اسباببازی برتر (از نظر توضیحات) که بیشترین تطابق را با اسباببازی طراحی شده توسط کاربر دارند، استفاده کنیم.
پیشبینی قیمت برای اسباببازی تولید شده بخش مهمی از این برنامه است و ما از یک رویکرد عاملمحور برای تولید آن استفاده کردهایم. معرفی جعبه ابزار Gen AI برای پایگاههای داده.
۱۳. جعبه ابزار Gen AI برای پایگاههای داده
جعبه ابزار Gen AI برای پایگاههای داده، یک سرور متنباز از گوگل است که ساخت ابزارهای Gen AI را برای تعامل با پایگاههای داده آسانتر میکند. این جعبه ابزار به شما این امکان را میدهد که با مدیریت پیچیدگیهایی مانند ادغام اتصال، احراز هویت و موارد دیگر، ابزارها را آسانتر، سریعتر و ایمنتر توسعه دهید. این جعبه ابزار به شما کمک میکند تا ابزارهای Gen AI بسازید که به عاملهای شما اجازه میدهد به دادههای موجود در پایگاه داده دسترسی داشته باشند.
در اینجا مراحلی که باید دنبال کنید تا بتوانید این ابزار را برای آمادهسازی و عاملدار کردن برنامه خود تنظیم کنید، آورده شده است: لینک به Toolbox Codelab
اکنون برنامه شما میتواند از این نقطه پایانی Cloud Run Function مستقر شده برای پر کردن قیمت به همراه نتیجه Imagen تولید شده برای تصویر اسباببازی سفارشی ساخته شده استفاده کند.
۱۴. برنامه وب خود را آزمایش کنید
اکنون که تمام اجزای برنامه شما ساخته و مستقر شدهاند، آماده ارائه در فضای ابری است. برنامه خود را برای همه سناریوها آزمایش کنید. در اینجا یک لینک ویدیویی برای آنچه ممکن است انتظار داشته باشید، آورده شده است:
https://www.youtube.com/shorts/ZMqUAWsghYQ
این همان چیزی است که صفحه فرود به نظر میرسد:

۱۵. تمیز کردن
برای جلوگیری از تحمیل هزینه به حساب Google Cloud خود برای منابع استفاده شده در این پست، این مراحل را دنبال کنید:
- در کنسول گوگل کلود، به صفحه مدیریت منابع بروید.
- در لیست پروژهها، پروژهای را که میخواهید حذف کنید انتخاب کنید و سپس روی «حذف» کلیک کنید.
- در کادر محاورهای، شناسه پروژه را تایپ کنید و سپس برای حذف پروژه، روی خاموش کردن کلیک کنید.
۱۶. تبریک
تبریک! شما با موفقیت یک جستجوی متنی و تولید Toystore را با استفاده از AlloyDB، pgvector، Imagen و Gemini 2.0 انجام دادهاید و در عین حال از کتابخانههای متنباز برای ایجاد یکپارچهسازیهای قوی استفاده کردهاید. با ترکیب قابلیتهای AlloyDB ، Vertex AI و Vector Search ، ما جهش بزرگی در قابل دسترس، کارآمد و واقعاً معنادار کردن جستجوهای متنی و برداری برداشتهایم.