แอปการค้นหาร้านขายของเล่นที่มีฐานข้อมูลระบบคลาวด์ รันไทม์แบบไม่ใช้เซิร์ฟเวอร์ และการผสานรวมโอเพนซอร์ส

1. ภาพรวม

ลองนึกภาพการเดินเข้าไปในร้านขายของเล่นแบบเสมือนจริงหรือแบบเข้าร่วมด้วยตนเอง ซึ่งคุณจะพบของขวัญที่ถูกใจได้อย่างง่ายดาย คุณสามารถอธิบายสิ่งที่กำลังมองหา อัปโหลดรูปภาพของเล่น หรือแม้แต่สร้างสรรค์ผลงานของคุณเองได้ แล้วร้านค้าจะเข้าใจความต้องการของคุณทันทีและมอบประสบการณ์ที่ปรับให้เหมาะกับคุณ นี่ไม่ใช่จินตนาการในอนาคต แต่เป็นความจริงที่ขับเคลื่อนด้วย AI, เทคโนโลยีระบบคลาวด์ และวิสัยทัศน์สำหรับอีคอมเมิร์ซที่ปรับเปลี่ยนในแบบของคุณ

ความท้าทาย: การค้นหาผลิตภัณฑ์ที่สมบูรณ์แบบซึ่งตรงกับจินตนาการของคุณอาจเป็นเรื่องยาก คำค้นหาทั่วไป คีย์เวิร์ด และการค้นหาแบบคร่าวๆ มักไม่เพียงพอ การเรียกดูหน้าเว็บที่ไม่มีที่สิ้นสุดอาจน่าเบื่อ และความแตกต่างระหว่างสิ่งที่คุณจินตนาการกับสิ่งที่พร้อมใช้งานอาจทำให้เกิดความหงุดหงิด

โซลูชัน: แอปพลิเคชันเดโมรับมือกับความท้าทายนี้โดยตรง โดยใช้ประโยชน์จากพลังของ AI เพื่อมอบประสบการณ์การใช้งานที่ปรับเปลี่ยนในแบบของคุณได้อย่างแท้จริงและราบรื่นด้วยการค้นหาตามบริบทและการสร้างผลิตภัณฑ์ที่กำหนดเองซึ่งตรงกับบริบทการค้นหา

สิ่งที่คุณจะสร้าง

ในแล็บนี้ คุณจะได้ทำสิ่งต่อไปนี้

  1. สร้างอินสแตนซ์ AlloyDB และโหลดชุดข้อมูลของเล่น
  2. เปิดใช้ส่วนขยาย pgvector และโมเดล Generative AI ใน AlloyDB
  3. สร้างการฝังจากคำอธิบายผลิตภัณฑ์และทำการค้นหาความคล้ายคลึงกันของโคไซน์แบบเรียลไทม์สำหรับข้อความค้นหาของผู้ใช้
  4. เรียกใช้ Gemini 2.0 Flash เพื่ออธิบายรูปภาพที่ผู้ใช้อัปโหลดสำหรับการค้นหาของเล่นตามบริบท
  5. เรียกใช้ Imagen 3 เพื่อสร้างของเล่นที่กำหนดเองตามความสนใจของผู้ใช้
  6. เรียกใช้เครื่องมือคาดการณ์ราคาที่สร้างขึ้นโดยใช้ Gen AI Toolbox สำหรับฐานข้อมูลเพื่อดูรายละเอียดราคาของของเล่นที่สร้างขึ้นเอง
  7. ติดตั้งใช้งานโซลูชันในฟังก์ชัน Cloud Run แบบ Serverless

ข้อกำหนด

  • เบราว์เซอร์ เช่น Chrome หรือ Firefox
  • โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน

2. สถาปัตยกรรม

การไหลเวียนของข้อมูล: มาดูรายละเอียดวิธีที่ข้อมูลไหลเวียนผ่านระบบของเรากัน

  1. การค้นหาตามบริบทด้วย RAG (Retrieval Augmented Generation) ที่ทำงานด้วยระบบ AI

ลองนึกภาพว่าแทนที่จะค้นหาแค่ "รถสีแดง" ระบบจะเข้าใจสิ่งต่อไปนี้

"รถขนาดเล็กที่เหมาะสำหรับเด็กชายอายุ 3 ขวบ"

AlloyDB เป็นรากฐาน: เราใช้ AlloyDB ซึ่งเป็นฐานข้อมูลที่เข้ากันได้กับ PostgreSQL ที่มีการจัดการครบวงจรของ Google Cloud เพื่อจัดเก็บข้อมูลของเล่น ซึ่งรวมถึงคำอธิบาย, URL ของรูปภาพ และแอตทริบิวต์อื่นๆ ที่เกี่ยวข้อง

pgvector สำหรับการค้นหาเชิงความหมาย: pgvector ซึ่งเป็นส่วนขยายของ PostgreSQL ช่วยให้เราจัดเก็บการฝังเวกเตอร์ของทั้งคำอธิบายของเล่นและข้อความค้นหาของผู้ใช้ได้ ซึ่งจะช่วยให้ระบบค้นหาตามความหมายได้ นั่นหมายความว่าระบบจะเข้าใจความหมายเบื้องหลังคำต่างๆ ไม่ใช่แค่คีย์เวิร์ดที่ตรงกันเท่านั้น

ความคล้ายคลึงแบบโคไซน์เพื่อความเกี่ยวข้อง: เราใช้ความคล้ายคลึงแบบโคไซน์เพื่อวัดความคล้ายคลึงเชิงความหมายระหว่างเวกเตอร์การค้นหาของผู้ใช้กับเวกเตอร์คำอธิบายของของเล่น เพื่อแสดงผลลัพธ์ที่เกี่ยวข้องมากที่สุด

ดัชนี ScaNN เพื่อความเร็วและความแม่นยำ: เราผสานรวมดัชนี ScaNN (Scalable Nearest Neighbors) เพื่อให้มั่นใจว่าผลลัพธ์จะรวดเร็วและแม่นยำ โดยเฉพาะอย่างยิ่งเมื่อสินค้าคงคลังของเล่นเพิ่มขึ้น ซึ่งจะช่วยปรับปรุงประสิทธิภาพและการเรียกคืนของการค้นหาเวกเตอร์ได้อย่างมาก

  1. การค้นหาและการทำความเข้าใจโดยอิงตามรูปภาพด้วย Gemini 2.0 Flash

สมมติว่าผู้ใช้ต้องการอัปโหลดรูปภาพของเล่นที่คุ้นเคยซึ่งต้องการใช้ค้นหาแทนการพิมพ์บริบทเป็นข้อความ ผู้ใช้สามารถอัปโหลดรูปภาพของเล่นที่ชอบและรับฟีเจอร์ที่เกี่ยวข้องได้ เราใช้ประโยชน์จากโมเดล Gemini 2.0 Flash ของ Google ซึ่งเรียกใช้โดยใช้ LangChain4j เพื่อวิเคราะห์รูปภาพและดึงบริบทที่เกี่ยวข้อง เช่น สี วัสดุ ประเภท และกลุ่มอายุที่ตั้งใจไว้ของของเล่น

  1. สร้างของเล่นในฝันที่ปรับแต่งด้วย Generative AI: Imagen 3

แต่ความมหัศจรรย์ที่แท้จริงจะเกิดขึ้นเมื่อผู้ใช้ตัดสินใจสร้างของเล่นของตัวเอง การใช้ Imagen 3 ช่วยให้ผู้ใช้สามารถอธิบายของเล่นในฝันได้โดยใช้พรอมต์ข้อความง่ายๆ ลองนึกภาพว่าคุณสามารถพูดว่า "ฉันอยากได้ตุ๊กตามังกรที่มีปีกสีม่วงและใบหน้าที่เป็นมิตร" แล้วเห็นมังกรตัวนั้นปรากฏขึ้นบนหน้าจอ จากนั้น Imagen 3 จะสร้างรูปภาพของของเล่นที่ออกแบบเอง ทำให้ผู้ใช้เห็นภาพผลงานของตนเองได้อย่างชัดเจน

  1. การคาดการณ์ราคาที่ทำงานด้วย Agent และ MCP Toolbox สำหรับฐานข้อมูล

เราได้ติดตั้งใช้งานฟีเจอร์การคาดการณ์ราคาซึ่งจะประมาณค่าใช้จ่ายในการผลิตของเล่นที่ออกแบบเอง ซึ่งขับเคลื่อนโดยเอเจนต์ที่มีเครื่องมือคำนวณราคาที่ซับซ้อน

MCP Toolbox สำหรับฐานข้อมูล: Agent นี้ผสานรวมกับฐานข้อมูลของเราได้อย่างราบรื่นโดยใช้เครื่องมือโอเพนซอร์สใหม่ของ Google ที่ชื่อว่า MCP Toolbox สำหรับฐานข้อมูล ซึ่งจะช่วยให้ตัวแทนเข้าถึงข้อมูลแบบเรียลไทม์เกี่ยวกับต้นทุนวัสดุ กระบวนการผลิต และปัจจัยอื่นๆ ที่เกี่ยวข้องเพื่อประมาณราคาได้อย่างถูกต้อง อ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ที่นี่

  1. Java Spring Boot, Gemini Code Assist และ Cloud Run เพื่อการพัฒนาที่คล่องตัวและการทำให้ใช้งานได้แบบไร้เซิร์ฟเวอร์

แอปพลิเคชันทั้งหมดสร้างขึ้นโดยใช้ Java Spring Boot ซึ่งเป็นเฟรมเวิร์กที่แข็งแกร่งและปรับขนาดได้ เราใช้ประโยชน์จาก Gemini Code Assist ตลอดกระบวนการพัฒนา โดยเฉพาะอย่างยิ่งสำหรับการพัฒนาส่วนหน้า ซึ่งช่วยเร่งวงจรการพัฒนาและปรับปรุงคุณภาพของโค้ดได้อย่างมาก เราใช้ Cloud Run เพื่อติดตั้งใช้งานแอปพลิเคชันทั้งหมด และใช้ฟังก์ชัน Cloud Run เพื่อติดตั้งใช้งานฟังก์ชันการทำงานของฐานข้อมูลและเอเจนต์เป็นปลายทางอิสระ

3. ก่อนเริ่มต้น

สร้างโปรเจ็กต์

  1. ในคอนโซล Google Cloud ให้เลือกหรือสร้างโปรเจ็กต์ Google Cloud ในหน้าตัวเลือกโปรเจ็กต์
  2. ตรวจสอบว่าได้เปิดใช้การเรียกเก็บเงินสำหรับโปรเจ็กต์ที่อยู่ในระบบคลาวด์แล้ว ดูวิธีตรวจสอบว่าได้เปิดใช้การเรียกเก็บเงินในโปรเจ็กต์แล้วหรือไม่
  3. คุณจะใช้ Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานใน Google Cloud และโหลด bq ไว้ล่วงหน้า คลิกเปิดใช้งาน Cloud Shell ที่ด้านบนของคอนโซล Google Cloud

รูปภาพปุ่มเปิดใช้งาน Cloud Shell

  1. เมื่อเชื่อมต่อกับ Cloud Shell แล้ว ให้ตรวจสอบว่าคุณได้รับการตรวจสอบสิทธิ์แล้วและตั้งค่าโปรเจ็กต์เป็นรหัสโปรเจ็กต์โดยใช้คำสั่งต่อไปนี้
gcloud auth list
  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคำสั่ง gcloud รู้จักโปรเจ็กต์ของคุณ
gcloud config list project
  1. หากไม่ได้ตั้งค่าโปรเจ็กต์ ให้ใช้คำสั่งต่อไปนี้เพื่อตั้งค่า
gcloud config set project <YOUR_PROJECT_ID>
  1. เปิดใช้ API ที่จำเป็นโดยการเรียกใช้คำสั่งต่อไปนี้ทีละรายการในเทอร์มินัล Cloud Shell

นอกจากนี้ ยังมีคำสั่งเดียวที่ใช้เรียกใช้คำสั่งด้านล่างได้ แต่หากคุณเป็นผู้ใช้บัญชีช่วงทดลองใช้ คุณอาจพบปัญหาเกี่ยวกับโควต้าเมื่อพยายามเปิดใช้ฟีเจอร์เหล่านี้พร้อมกันหลายรายการ ด้วยเหตุนี้จึงต้องระบุคำสั่งทีละรายการในแต่ละบรรทัด

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 ในเอกสารประกอบ

4. การตั้งค่าฐานข้อมูล

ในแล็บนี้ เราจะใช้ AlloyDB เป็นฐานข้อมูลเพื่อจัดเก็บข้อมูลของร้านขายของเล่น โดยจะใช้คลัสเตอร์เพื่อจัดเก็บทรัพยากรทั้งหมด เช่น ฐานข้อมูลและบันทึก แต่ละคลัสเตอร์มีอินสแตนซ์หลักที่ให้จุดเข้าใช้งานข้อมูล ตารางจะเก็บข้อมูลจริง

มาสร้างคลัสเตอร์ อินสแตนซ์ และตาราง AlloyDB ที่จะโหลดชุดข้อมูลอีคอมเมิร์ซกัน

สร้างคลัสเตอร์และอินสแตนซ์

  1. ไปที่หน้า AlloyDB ใน Cloud Console วิธีง่ายๆ ในการค้นหาหน้าส่วนใหญ่ใน Cloud Console คือการค้นหาโดยใช้แถบค้นหาของคอนโซล
  2. เลือกสร้างคลัสเตอร์จากหน้านั้น

f76ff480c8c889aa.png

  1. คุณจะเห็นหน้าจอคล้ายกับหน้าจอด้านล่าง สร้างคลัสเตอร์และอินสแตนซ์ด้วยค่าต่อไปนี้ (ตรวจสอบว่าค่าตรงกันในกรณีที่คุณโคลนโค้ดของแอปพลิเคชันจากที่เก็บ)
  • รหัสคลัสเตอร์: "vector-cluster"
  • password: "alloydb"
  • เข้ากันได้กับ PostgreSQL 15
  • ภูมิภาค: "us-central1"
  • เครือข่าย: "default"

538dba58908162fb.png

  1. เมื่อเลือกเครือข่ายเริ่มต้น คุณจะเห็นหน้าจอคล้ายกับหน้าจอด้านล่าง

เลือกตั้งค่าการเชื่อมต่อ
7939bbb6802a91bf.png

  1. จากนั้นเลือก "ใช้ช่วง IP ที่มีการจัดสรรโดยอัตโนมัติ" แล้วคลิก "ต่อไป" หลังจากตรวจสอบข้อมูลแล้ว ให้เลือกสร้างการเชื่อมต่อ 768ff5210e79676f.png
  2. เมื่อตั้งค่าเครือข่ายแล้ว คุณจะสร้างคลัสเตอร์ต่อไปได้ คลิกสร้างคลัสเตอร์เพื่อตั้งค่าคลัสเตอร์ให้เสร็จสมบูรณ์ตามที่แสดงด้านล่าง

e06623e55195e16e.png

อย่าลืมเปลี่ยนรหัสอินสแตนซ์เป็น

vector-instance

หากเปลี่ยนไม่ได้ โปรดอย่าลืมเปลี่ยนรหัสอินสแตนซ์ในการอ้างอิงที่กำลังจะมาถึงทั้งหมด

โปรดทราบว่าการสร้างคลัสเตอร์จะใช้เวลาประมาณ 10 นาที เมื่อดำเนินการสำเร็จแล้ว คุณควรเห็นหน้าจอที่แสดงภาพรวมของคลัสเตอร์ที่เพิ่งสร้าง

5. การนำเข้าข้อมูล

ตอนนี้ได้เวลาเพิ่มตารางที่มีข้อมูลเกี่ยวกับร้านค้าแล้ว ไปที่ AlloyDB เลือกคลัสเตอร์หลัก แล้วเลือก AlloyDB Studio โดยทำดังนี้

847e35f1bf8a8bd8.png

คุณอาจต้องรอให้อินสแตนซ์สร้างเสร็จ เมื่อพร้อมแล้ว ให้ลงชื่อเข้าใช้ AlloyDB โดยใช้ข้อมูลเข้าสู่ระบบที่คุณสร้างขึ้นเมื่อสร้างคลัสเตอร์ ใช้ข้อมูลต่อไปนี้เพื่อตรวจสอบสิทธิ์ใน PostgreSQL

  • ชื่อผู้ใช้ : "postgres"
  • ฐานข้อมูล : "postgres"
  • รหัสผ่าน : "alloydb"

เมื่อตรวจสอบสิทธิ์เข้าสู่ AlloyDB Studio สำเร็จแล้ว ให้ป้อนคำสั่ง SQL ในเอดิเตอร์ คุณเพิ่มหน้าต่างเอดิเตอร์หลายหน้าต่างได้โดยใช้เครื่องหมายบวกทางด้านขวาของหน้าต่างสุดท้าย

91a86d9469d499c4.png

คุณจะป้อนคำสั่งสำหรับ AlloyDB ในหน้าต่างเอดิเตอร์ โดยใช้ตัวเลือกเรียกใช้ จัดรูปแบบ และล้างตามที่จำเป็น

เปิดใช้ส่วนขยาย

ในการสร้างแอปนี้ เราจะใช้ส่วนขยาย pgvector และ google_ml_integration ส่วนขยาย pgvector ช่วยให้คุณจัดเก็บและค้นหาการฝังเวกเตอร์ได้ ส่วนขยาย google_ml_integration มีฟังก์ชันที่คุณใช้เพื่อเข้าถึงปลายทางการคาดการณ์ของ Vertex AI เพื่อรับการคาดการณ์ใน 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)) ;

เมื่อดำเนินการคำสั่งข้างต้นสำเร็จ คุณควรจะดูตารางในฐานข้อมูลได้

ส่งผ่านข้อมูล

สำหรับแล็บนี้ เรามีข้อมูลทดสอบประมาณ 72 รายการในไฟล์ SQL นี้ โดยไฟล์ดังกล่าวจะมีช่อง id, name, description, quantity, price, image_url ส่วนช่องอื่นๆ จะกรอกในภายหลังในห้องทดลอง

คัดลอกเฉพาะ 5 บรรทัดแรก/คำสั่งแทรกจากที่นั่น จากนั้นวางบรรทัดเหล่านั้นในแท็บเอดิเตอร์ว่าง แล้วเลือกเรียกใช้ หากไม่ได้ใช้บัญชีสำหรับการเรียกเก็บเงินแบบทดลองใช้ คุณอาจคัดลอกคำสั่ง INSERT ทั้งหมดและเรียกใช้ได้

หากต้องการดูเนื้อหาของตาราง ให้ขยายส่วน Explorer จนกว่าจะเห็นตารางชื่อ apparels เลือกปุ่มสามจุด (⋮) เพื่อดูตัวเลือกในการค้นหาตาราง คำสั่ง SELECT จะเปิดขึ้นในแท็บเครื่องมือแก้ไขใหม่

cfaa52b717f9aaed.png

ให้สิทธิ์

เรียกใช้คำสั่งด้านล่างเพื่อมอบสิทธิ์ในการเรียกใช้ฟังก์ชัน embedding ให้กับผู้ใช้ postgres

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"

6. สร้างการฝังสำหรับบริบท

คอมพิวเตอร์ประมวลผลตัวเลขได้ง่ายกว่าประมวลผลข้อความมาก ระบบการฝังจะแปลงข้อความเป็นชุดของตัวเลขทศนิยมที่ควรแสดงข้อความ ไม่ว่าข้อความนั้นจะเขียนอย่างไร ใช้ภาษาใด ฯลฯ

ลองอธิบายสถานที่ริมทะเล อาจเรียกว่า "ริมน้ำ" "ติดชายหาด" "เดินจากห้องไปมหาสมุทร" "sur la mer" "на берегу океана" ฯลฯ คำเหล่านี้มีลักษณะแตกต่างกัน แต่ความหมายเชิงความหมายหรือในคำศัพท์ของแมชชีนเลิร์นนิง การฝังควรจะใกล้เคียงกันมาก

เมื่อข้อมูลและบริบทพร้อมแล้ว เราจะเรียกใช้ 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;

ซึ่งควรแสดงเวกเตอร์การฝังที่มีลักษณะเป็นอาร์เรย์ของจำนวนทศนิยมสำหรับคำอธิบายของเล่นดังที่แสดงด้านล่าง

7d32f7cd7204e1f3.png

หมายเหตุ: โปรเจ็กต์ Google Cloud ที่สร้างใหม่ภายใต้รุ่นฟรีอาจประสบปัญหาโควต้าเมื่อพูดถึงจำนวนคำขอ Embedding ที่อนุญาตต่อวินาทีไปยังโมเดล Embedding เราขอแนะนำให้คุณใช้การค้นหาตัวกรองสำหรับรหัส จากนั้นเลือก 1-5 ระเบียนและอื่นๆ ในขณะที่สร้างการฝัง

7. ทำการค้นหาเวกเตอร์

ตอนนี้ตาราง ข้อมูล และการฝังพร้อมแล้ว เรามาทำการค้นหาเวกเตอร์แบบเรียลไทม์สำหรับข้อความค้นหาของผู้ใช้กัน

สมมติว่าผู้ใช้ถามว่า

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

มาดูรายละเอียดของคำค้นหานี้กัน

ในคำค้นหานี้

  1. ข้อความค้นหาของผู้ใช้คือ "I want a white plush teddy bear toy with a floral pattern."
  2. เราจะแปลงเป็น Embedding ในembedding()โดยใช้โมเดล text-embedding-005 ขั้นตอนนี้ควรจะคุ้นเคยหลังจากขั้นตอนสุดท้าย ซึ่งเราได้ใช้ฟังก์ชันการฝังกับรายการทั้งหมดในตาราง
  3. "<=>" แสดงถึงการใช้วิธีการวัดระยะทางความคล้ายกันของโคไซน์ คุณดูการวัดความคล้ายกันทั้งหมดที่มีได้ในเอกสารประกอบของ pgvector
  4. เราจะแปลงผลลัพธ์ของวิธีการฝังเป็นประเภทเวกเตอร์เพื่อให้เข้ากันได้กับเวกเตอร์ที่จัดเก็บไว้ในฐานข้อมูล
  5. LIMIT 5 หมายความว่าเราต้องการดึงเพื่อนบ้านที่ใกล้ที่สุด 5 รายการสำหรับข้อความค้นหา

ผลลัพธ์จะมีลักษณะดังนี้

fa7f0fc3a4c68804.png

ดังที่คุณเห็นในผลลัพธ์ การจับคู่นั้นค่อนข้างใกล้เคียงกับข้อความค้นหา ลองเปลี่ยนข้อความเพื่อดูว่าผลลัพธ์เปลี่ยนแปลงไปอย่างไร

หมายเหตุสำคัญ:

สมมติว่าเราต้องการเพิ่มประสิทธิภาพ (เวลาในการค้นหา) ประสิทธิภาพ และการเรียกคืนผลการค้นหาเวกเตอร์นี้โดยใช้ดัชนี ScaNN โปรดอ่านขั้นตอนในบล็อกนี้เพื่อเปรียบเทียบความแตกต่างของผลลัพธ์ที่มีและไม่มีดัชนี

ขั้นตอนที่ไม่บังคับ: ปรับปรุงประสิทธิภาพและการเรียกคืนด้วยดัชนี ScaNN

ข้ามขั้นตอนนี้หากจำนวนระเบียนน้อยกว่า 100

เราจะแสดงขั้นตอนการสร้างดัชนีที่นี่เพื่อความสะดวก

  1. เนื่องจากเราได้สร้างคลัสเตอร์ อินสแตนซ์ บริบท และการฝังไว้แล้ว เราจึงเพียงแค่ต้องติดตั้งส่วนขยาย ScaNN โดยใช้คำสั่งต่อไปนี้
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
  1. จากนั้นเราจะสร้างดัชนี (ScaNN)
CREATE INDEX toysearch_index ON toys
USING scann (text_embeddings cosine)
WITH (num_leaves=9);

ใน DDL ด้านบน apparel_index คือชื่อของดัชนี

"ของเล่น" คือตารางของฉัน

"scann" คือวิธีการจัดทำดัชนี

"การฝัง" คือคอลัมน์ในตารางที่ฉันต้องการจัดทำดัชนี

"โคไซน์" คือวิธีการวัดระยะทางที่ฉันต้องการใช้กับดัชนี

"8" คือจำนวนพาร์ติชันที่จะใช้กับดัชนีนี้ ตั้งค่าเป็นค่าใดก็ได้ระหว่าง 1 ถึง 1048576 ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีตัดสินใจเลือกค่านี้ได้ที่ปรับดัชนี ScaNN

ฉันใช้รากที่สองของจำนวนจุดข้อมูลตามที่แนะนำใน ScaNN repo (เมื่อทำการแบ่งพาร์ติชัน num_leaves ควรเป็นรากที่สองของจำนวนจุดข้อมูลโดยประมาณ)

  1. ตรวจสอบว่ามีการสร้างดัชนีโดยใช้การค้นหาต่อไปนี้หรือไม่
SELECT * FROM pg_stat_ann_indexes;
  1. ทำการค้นหาเวกเตอร์โดยใช้คำค้นหาเดียวกันกับที่เราใช้โดยไม่มีดัชนี
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;

คำค้นหาข้างต้นเป็นคำค้นหาเดียวกันกับที่เราใช้ในห้องทดลองในขั้นตอนที่ 8 แต่ตอนนี้เราได้จัดทำดัชนีฟิลด์แล้ว

  1. ทดสอบด้วยคำค้นหาอย่างง่ายโดยมีและไม่มีดัชนี (โดยการวางดัชนี):

กรณีการใช้งานนี้มีเพียง 72 รายการ ดัชนีจึงไม่มีผลจริงๆ สำหรับการทดสอบที่ดำเนินการในกรณีการใช้งานอื่น ผลลัพธ์มีดังนี้

การค้นหาเวกเตอร์เดียวกันในข้อมูลการฝังที่จัดทำดัชนีจะส่งผลให้ได้ผลการค้นหาที่มีคุณภาพและมีประสิทธิภาพ ดัชนีช่วยปรับปรุงประสิทธิภาพได้อย่างมาก (ในแง่ของเวลาในการดำเนินการ: 10.37 มิลลิวินาทีหากไม่มี ScaNN และ 0.87 มิลลิวินาทีหากมี ScaNN) ดูข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้ได้ในบล็อกนี้

8. การตรวจสอบความถูกต้องของการจับคู่ด้วย LLM

ก่อนที่จะดำเนินการต่อและสร้างบริการเพื่อแสดงผลลัพธ์ที่ตรงกันมากที่สุดให้กับแอปพลิเคชัน เรามาใช้โมเดล Generative AI เพื่อตรวจสอบว่าคำตอบที่อาจเกิดขึ้นเหล่านี้เกี่ยวข้องจริงและปลอดภัยที่จะแชร์กับผู้ใช้หรือไม่

ตรวจสอบว่าตั้งค่าอินสแตนซ์สำหรับ Gemini แล้ว

ก่อนอื่น ให้ตรวจสอบว่าได้เปิดใช้การผสานรวม ML ของ Google สำหรับคลัสเตอร์และอินสแตนซ์แล้วหรือยัง ใน AlloyDB Studio ให้ป้อนคำสั่งต่อไปนี้

show google_ml_integration.enable_model_support;

หากค่าแสดงเป็น "เปิด" คุณสามารถข้าม 2 ขั้นตอนถัดไปและไปที่การตั้งค่าการผสานรวมโมเดล AlloyDB และ Vertex AI โดยตรง

  1. ไปที่อินสแตนซ์หลักของคลัสเตอร์ AlloyDB แล้วคลิกแก้ไขอินสแตนซ์หลัก

cb76b934ba3735bd.png

  1. ไปที่ส่วนฟีเจอร์ทดลองในตัวเลือกการกำหนดค่าขั้นสูง และตรวจสอบว่าตั้งค่า google_ml_integration.enable_model_support flag เป็น "on" ตามที่แสดงด้านล่าง

6a59351fcd2a9d35.png

หากไม่ได้ตั้งค่าเป็น "เปิด" ให้ตั้งค่าเป็น "เปิด" แล้วคลิกปุ่มอัปเดตอินสแตนซ์ ขั้นตอนนี้จะใช้เวลาสักครู่

การผสานรวมโมเดล 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 AI เรียกใช้คำสั่งต่อไปนี้

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 ในอนาคต

การประเมินคำตอบ

แม้ว่าเราจะใช้การค้นหาขนาดใหญ่ 1 รายการในส่วนถัดไปเพื่อให้มั่นใจว่าคำตอบจากการค้นหานั้นสมเหตุสมผล แต่การค้นหาอาจเข้าใจยาก ตอนนี้เราจะมาดูชิ้นส่วนต่างๆ และดูว่าชิ้นส่วนเหล่านั้นรวมกันเป็นอะไรในอีกไม่กี่นาที

  1. ก่อนอื่นเราจะส่งคำขอไปยังฐานข้อมูลเพื่อรับรายการที่ตรงกับคำค้นหาของผู้ใช้มากที่สุด 10 รายการ
  2. เราจะใช้การค้นหาภายนอกเพื่ออธิบายวิธีประเมินคำตอบเพื่อพิจารณาว่าคำตอบนั้นถูกต้องเพียงใด โดยจะใช้ฟิลด์ recommended_text ซึ่งเป็นข้อความค้นหา และ content (ซึ่งเป็นฟิลด์คำอธิบายของเล่น) ของตารางด้านในเป็นส่วนหนึ่งของคำค้นหา
  3. จากนั้นเราจะใช้ข้อมูลดังกล่าวเพื่อตรวจสอบ "ความดี" ของคำตอบที่แสดง
  4. predict_row จะแสดงผลลัพธ์ในรูปแบบ JSON โค้ด "-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'" ใช้เพื่อดึงข้อความจริงจาก JSON นั้น หากต้องการดู JSON จริงที่ส่งคืน คุณสามารถนำโค้ดนี้ออกได้
  5. สุดท้ายนี้ หากต้องการรับคำตอบจาก 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 จะเปิดการสตรีมไว้โดยค่าเริ่มต้น ดังนั้นคำตอบจริงจะกระจายอยู่หลายบรรทัด

c2b006aeb3f3a2fc.png

9. ย้ายการค้นหาของเล่นไปยังเซิร์ฟเวอร์ในระบบคลาวด์แบบไร้เซิร์ฟเวอร์

พร้อมที่จะนำแอปนี้ไปใช้บนเว็บแล้วใช่ไหม ทำตามขั้นตอนด้านล่างเพื่อทำให้ Knowledge Engine เป็นแบบไร้เซิร์ฟเวอร์ด้วยฟังก์ชัน Cloud Run

  1. ไปที่ฟังก์ชัน Cloud Run ในคอนโซล Google Cloud เพื่อสร้างฟังก์ชัน Cloud Run ใหม่ หรือใช้ลิงก์ https://console.cloud.google.com/functions/add
  2. เลือกสภาพแวดล้อมเป็น "ฟังก์ชัน Cloud Run" ระบุชื่อฟังก์ชัน "get-toys-alloydb" และเลือกภูมิภาคเป็น "us-central1" ตั้งค่าการตรวจสอบสิทธิ์เป็น "อนุญาตการเรียกใช้ที่ไม่ผ่านการตรวจสอบสิทธิ์" แล้วคลิกถัดไป เลือก Java 17 เป็นรันไทม์และ Inline Editor สำหรับซอร์สโค้ด
  3. โดยค่าเริ่มต้น ระบบจะตั้งค่าจุดแรกเข้าเป็น "gcfv2.HelloHttpFunction" แทนที่โค้ดตัวยึดตำแหน่งใน HelloHttpFunction.java และ pom.xml ของฟังก์ชัน Cloud Run ด้วยโค้ดจาก HelloHttpFunction.java และ pom.xml ตามลำดับ
  4. อย่าลืมเปลี่ยนตัวยึดตำแหน่ง <<YOUR_PROJECT>> และข้อมูลเข้าสู่ระบบการเชื่อมต่อ AlloyDB ด้วยค่าของคุณในไฟล์ Java ข้อมูลเข้าสู่ระบบ AlloyDB คือข้อมูลที่เราใช้ตอนเริ่ม Codelab นี้ หากคุณใช้ค่าอื่น โปรดแก้ไขค่าดังกล่าวในไฟล์ Java
  5. คลิกทำให้ใช้งานได้

เมื่อติดตั้งใช้งานแล้ว เราจะสร้างเครื่องมือเชื่อมต่อ VPC เพื่ออนุญาตให้ Cloud Function เข้าถึงอินสแตนซ์ฐานข้อมูล AlloyDB

ขั้นตอนสำคัญ:

เมื่อพร้อมที่จะทําการติดตั้งใช้งานแล้ว คุณควรจะเห็นฟังก์ชันในคอนโซลฟังก์ชัน Cloud Run ของ Google ค้นหาฟังก์ชันที่สร้างขึ้นใหม่ (get-toys-alloydb) คลิกฟังก์ชันนั้น แล้วคลิกแก้ไขและเปลี่ยนข้อมูลต่อไปนี้

  1. ไปที่รันไทม์ การสร้าง การเชื่อมต่อ และการตั้งค่าความปลอดภัย
  2. เพิ่มการหมดเวลาเป็น 180 วินาที
  3. ไปที่แท็บการเชื่อมต่อ

4e83ec8a339cda08.png

  1. ตรวจสอบว่าได้เลือก "อนุญาตการรับส่งข้อมูลทั้งหมด" ในการตั้งค่าขาเข้า
  2. ในส่วนการตั้งค่าขาออก ให้คลิกเมนูแบบเลื่อนลงของเครือข่าย แล้วเลือกตัวเลือก "เพิ่มตัวเชื่อมต่อ VPC ใหม่" จากนั้นทำตามวิธีการที่เห็นในกล่องโต้ตอบที่ปรากฏขึ้น

8126ec78c343f199.png

  1. ระบุชื่อเครื่องมือเชื่อมต่อ VPC และตรวจสอบว่าภูมิภาคตรงกับอินสแตนซ์ ปล่อยให้ค่าเครือข่ายเป็นค่าเริ่มต้น และตั้งค่าเครือข่ายย่อยเป็นช่วง IP ที่กำหนดเองโดยมีช่วง IP เป็น 10.8.0.0 หรือค่าที่คล้ายกันที่ใช้ได้
  2. ขยาย "แสดงการตั้งค่าการปรับขนาด" และตรวจสอบว่าคุณได้ตั้งค่าการกำหนดค่าเป็นดังนี้

7baf980463a86a5c.png

  1. คลิกสร้าง แล้วเครื่องมือเชื่อมต่อนี้ควรแสดงในการตั้งค่าขาออกในตอนนี้
  2. เลือกตัวเชื่อมต่อที่สร้างขึ้นใหม่
  3. เลือกให้กำหนดเส้นทางการรับส่งข้อมูลทั้งหมดผ่านเครื่องมือเชื่อมต่อ VPC นี้
  4. คลิกถัดไป แล้วคลิกติดตั้งใช้งาน

10. ทดสอบฟังก์ชัน Cloud Run

เมื่อติดตั้งใช้งาน Cloud Function ที่อัปเดตแล้ว คุณจะเห็นปลายทางที่สร้างขึ้น คัดลอกและแทนที่ในคำสั่งต่อไปนี้

หรือคุณจะทดสอบฟังก์ชัน 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 .

ผลลัพธ์ที่ได้มีดังนี้

23861e9091565a64.png

เท่านี้ก็เรียบร้อย การค้นหาเวกเตอร์ความคล้ายคลึงโดยใช้โมเดลการฝังในข้อมูล AlloyDB นั้นง่ายดายเพียงเท่านี้

11. การสร้างไคลเอ็นต์เว็บแอปพลิเคชัน

ในส่วนนี้ เราจะสร้างเว็บแอปพลิเคชันเพื่อให้ผู้ใช้โต้ตอบและค้นหาของเล่นที่ตรงกันตามข้อความ รูปภาพ และแม้กระทั่งสร้างของเล่นใหม่ตามความต้องการ เนื่องจากสร้างแอปพลิเคชันไว้แล้ว คุณจึงทำตามขั้นตอนด้านล่างเพื่อคัดลอกไปยัง IDE และทำให้แอปทำงานได้

  1. เนื่องจากเราใช้ Gemini 2.0 Flash เพื่ออธิบายรูปภาพที่ผู้ใช้อาจอัปโหลดเพื่อค้นหาของเล่นที่ตรงกัน เราจึงต้องรับคีย์ API สำหรับแอปพลิเคชันนี้ โดยไปที่ https://aistudio.google.com/apikey แล้วรับคีย์ API สำหรับโปรเจ็กต์ Google Cloud ที่ใช้งานอยู่ซึ่งคุณกำลังใช้แอปพลิเคชันนี้ และบันทึกคีย์ไว้ที่ใดที่หนึ่ง

ae2db169e6a94e4a.png

  1. ไปยังเทอร์มินัล Cloud Shell
  2. โคลนที่เก็บด้วยคำสั่งต่อไปนี้
git clone https://github.com/AbiramiSukumaran/toysearch

cd toysearch
  1. เมื่อโคลนที่เก็บแล้ว คุณควรจะเข้าถึงโปรเจ็กต์จาก Cloud Shell Editor ได้
  2. คุณต้องลบโฟลเดอร์ "get-toys-alloydb" และ "toolbox-toys" ออกจากโปรเจ็กต์ที่โคลนมาเนื่องจากทั้ง 2 โฟลเดอร์นี้เป็นโค้ดฟังก์ชัน Cloud Run ซึ่งอ้างอิงได้จากที่เก็บเมื่อต้องการ
  3. ไปที่ GenerateToy.java ในโฟลเดอร์เว็บ แล้วค้นหาบรรทัดต่อไปนี้และนำออก เนื่องจากอนุญาตสำหรับผู้ใหญ่ต้องใช้สิทธิ์พิเศษซึ่งอาจไม่พร้อมใช้งานสำหรับบัญชีสำหรับการเรียกเก็บเงินแบบทดลองใช้บางบัญชี

paramsMap.put("personGeneration", "allow_adult");

  1. ตรวจสอบว่าได้ตั้งค่าตัวแปรสภาพแวดล้อมที่จำเป็นทั้งหมดแล้วก่อนที่จะสร้างและติดตั้งใช้งานแอป ไปที่เทอร์มินัล Cloud Shell แล้วเรียกใช้คำสั่งต่อไปนี้
PROJECT_ID=$(gcloud config get-value project)

export PROJECT_ID=$PROJECT_ID

export GOOGLE_API_KEY=<YOUR API KEY that you saved>
  1. สร้างและเรียกใช้แอปในเครื่อง

ตรวจสอบว่าคุณอยู่ในไดเรกทอรีโปรเจ็กต์ แล้วเรียกใช้คำสั่งต่อไปนี้

mvn package

mvn spring-boot:run 
  1. ติดตั้งใช้งานใน Cloud Run
gcloud run deploy --source .

12. ทำความเข้าใจรายละเอียดของ Generative AI

คุณไม่ต้องดำเนินการใดๆ เพื่อความเข้าใจของคุณ

ตอนนี้คุณมีแอปพลิเคชันที่จะนําไปใช้งานแล้ว โปรดสละเวลาทำความเข้าใจวิธีที่เราทําการค้นหา (ข้อความและรูปภาพ) และการสร้าง

  1. การค้นหาเวกเตอร์ตามข้อความของผู้ใช้:

เราได้กล่าวถึงเรื่องนี้แล้วในฟังก์ชัน Cloud Run ที่เราติดตั้งใช้งานในส่วน "สร้างเว็บแอปพลิเคชันการค้นหาเวกเตอร์"

  1. การอัปโหลดรูปภาพตามการค้นหาเวกเตอร์

สมมติว่าผู้ใช้ต้องการอัปโหลดรูปภาพของเล่นที่คุ้นเคยซึ่งต้องการใช้ค้นหาแทนการพิมพ์บริบทเป็นข้อความ ผู้ใช้สามารถอัปโหลดรูปภาพของเล่นที่ชอบและรับฟีเจอร์ที่เกี่ยวข้องได้

เราใช้ประโยชน์จากโมเดล Gemini 2.0 Flash ของ Google ซึ่งเรียกใช้โดยใช้ LangChain4j เพื่อวิเคราะห์รูปภาพและดึงบริบทที่เกี่ยวข้อง เช่น สี วัสดุ ประเภท และกลุ่มอายุที่ตั้งใจไว้ของของเล่น

เราใช้เวลาเพียง 5 ขั้นตอนในการนำข้อมูลมัลติโมดัลของผู้ใช้ไปจับคู่กับผลลัพธ์ด้วยการเรียกใช้โมเดลภาษาขนาดใหญ่โดยใช้เฟรมเวิร์กโอเพนซอร์ส เรียนรู้วิธีการดังนี้

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;
  }
}
  1. ดูวิธีที่เราใช้ Imagen 3 สร้างของเล่นที่ปรับแต่งตามคำขอของผู้ใช้ด้วย Generative AI

จากนั้น Imagen 3 จะสร้างรูปภาพของของเล่นที่ออกแบบเอง ทำให้ผู้ใช้เห็นภาพผลงานของตนเองได้อย่างชัดเจน เราทำได้โดยใช้ขั้นตอนง่ายๆ เพียง 5 ขั้นตอน ดังนี้

// 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 สร้างรูปภาพของเล่นที่ผู้ใช้ต้องการออกแบบด้วยตนเอง แอปพลิเคชันต้องตั้งราคาของของเล่นดังกล่าวเพื่อให้ผู้ใช้ซื้อได้ และเราได้ใช้ตรรกะที่ใช้งานง่ายเพื่อกำหนดราคาของเล่นที่สั่งทำแบบกำหนดเอง ตรรกะคือการใช้ราคาเฉลี่ยของของเล่น 5 อันดับแรกที่ตรงกันมากที่สุด (ในแง่ของคำอธิบาย) กับของเล่นที่ผู้ใช้ออกแบบ

การคาดการณ์ราคาของของเล่นที่สร้างขึ้นเป็นส่วนสำคัญของแอปพลิเคชันนี้ และเราได้ใช้วิธีการแบบเอเจนต์เพื่อสร้างการคาดการณ์นี้ ขอแนะนำ Gen AI Toolbox สำหรับฐานข้อมูล

13. กล่องเครื่องมือ Gen AI สำหรับฐานข้อมูล

กล่องเครื่องมือ Gen AI สำหรับฐานข้อมูลคือเซิร์ฟเวอร์โอเพนซอร์สจาก Google ที่ช่วยให้สร้างเครื่องมือ Gen AI สำหรับโต้ตอบกับฐานข้อมูลได้ง่ายขึ้น ซึ่งช่วยให้คุณพัฒนาเครื่องมือได้ง่ายขึ้น เร็วขึ้น และปลอดภัยยิ่งขึ้นด้วยการจัดการความซับซ้อนต่างๆ เช่น การจัดกลุ่มการเชื่อมต่อ การตรวจสอบสิทธิ์ และอื่นๆ ซึ่งจะช่วยคุณสร้างเครื่องมือ Gen AI ที่ช่วยให้ Agent เข้าถึงข้อมูลในฐานข้อมูลได้

ขั้นตอนที่คุณต้องทำตามเพื่อตั้งค่านี้ให้พร้อมใช้งานเครื่องมือและทำให้แอปพลิเคชันของเราเป็นแบบเอเจนต์มีดังนี้ ลิงก์ไปยัง Codelab ของกล่องเครื่องมือ

ตอนนี้แอปพลิเคชันของคุณสามารถใช้ปลายทางฟังก์ชัน Cloud Run ที่ทําให้ใช้งานได้นี้เพื่อป้อนราคาพร้อมกับผลลัพธ์ที่ Imagen สร้างขึ้นสําหรับรูปภาพของเล่นที่สั่งทําแบบกําหนดเองได้แล้ว

14. ทดสอบเว็บแอปพลิเคชัน

ตอนนี้คอมโพเนนต์ทั้งหมดของแอปพลิเคชันได้รับการสร้างและติดตั้งใช้งานแล้ว จึงพร้อมให้บริการในระบบคลาวด์ ทดสอบแอปพลิเคชันของคุณสำหรับทุกสถานการณ์ ลิงก์วิดีโอเกี่ยวกับสิ่งที่คุณอาจคาดหวังมีดังนี้

https://www.youtube.com/shorts/ZMqUAWsghYQ

หน้า Landing Page จะมีลักษณะดังนี้

241db19e7176e93e.png

15. ล้างข้อมูล

โปรดทำตามขั้นตอนต่อไปนี้เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud สำหรับทรัพยากรที่ใช้ในโพสต์นี้

  1. ในคอนโซล Google Cloud ให้ไปที่หน้าจัดการทรัพยากร
  2. ในรายการโปรเจ็กต์ ให้เลือกโปรเจ็กต์ที่ต้องการลบ แล้วคลิกลบ
  3. ในกล่องโต้ตอบ ให้พิมพ์รหัสโปรเจ็กต์ แล้วคลิกปิดเพื่อลบโปรเจ็กต์

16. ขอแสดงความยินดี

ยินดีด้วย คุณได้ทำการค้นหาและสร้างตามบริบทของร้านขายของเล่นโดยใช้ AlloyDB, pgvector, Imagen และ Gemini 2.0 เรียบร้อยแล้ว พร้อมทั้งใช้ประโยชน์จากไลบรารีโอเพนซอร์สเพื่อสร้างการผสานรวมที่แข็งแกร่ง การผสานความสามารถของ AlloyDB, Vertex AI และ Vector Search ทำให้เราก้าวกระโดดไปข้างหน้าในการทำให้การค้นหาตามบริบทและการค้นหาแบบเวกเตอร์เข้าถึงได้ มีประสิทธิภาพ และขับเคลื่อนด้วยความหมายอย่างแท้จริง