หน้านี้แสดงวิธีใช้ Cloud Firestore เพื่อทำ K ให้อยู่ใกล้ที่สุด ค้นหาเวกเตอร์เพื่อนบ้าน (KNN) โดยใช้เทคนิคต่อไปนี้
- เก็บค่าเวกเตอร์
- สร้างและจัดการดัชนีเวกเตอร์ KNN
- สร้างการค้นหา K-Nabest-Neighbor (KNN) โดยใช้เวกเตอร์ที่รองรับ การวัดระยะทาง
การฝังเวกเตอร์ที่จัดเก็บ
คุณสามารถสร้างค่าเวกเตอร์ เช่น การฝังข้อความ จาก Cloud Firestore และจัดเก็บไว้ในเอกสาร Cloud Firestore ฉบับ
การดำเนินการเขียนที่มีการฝังเวกเตอร์
ตัวอย่างต่อไปนี้แสดงวิธีจัดเก็บการฝังเวกเตอร์ใน เอกสาร Cloud Firestore รายการ:
Python
Node.js
import { Firestore, FieldValue, } from "@google-cloud/firestore"; const db = new Firestore(); const coll = db.collection('coffee-beans'); await coll.add({ name: "Kahawa coffee beans", description: "Information about the Kahawa coffee beans.", embedding_field: FieldValue.vector([1.0 , 2.0, 3.0]) });
การฝังเวกเตอร์การประมวลผลด้วย Cloud Function
เพื่อคำนวณและจัดเก็บการฝังเวกเตอร์เมื่อมีการอัปเดตเอกสาร หรือ ที่สร้างขึ้น คุณก็สามารถตั้งค่า Cloud Function โดยทำดังนี้
Python
@functions_framework.cloud_event def store_embedding(cloud_event) -> None: """Triggers by a change to a Firestore document. """ firestore_payload = firestore.DocumentEventData() payload = firestore_payload._pb.ParseFromString(cloud_event.data) collection_id, doc_id = from_payload(payload) # Call a function to calculate the embedding embedding = calculate_embedding(payload) # Update the document doc = firestore_client.collection(collection_id).document(doc_id) doc.set({"embedding_field": embedding}, merge=True)
Node.js
/** * A vector embedding will be computed from the * value of the `content` field. The vector value * will be stored in the `embedding` field. The * field names `content` and `embedding` are arbitrary * field names chosen for this example. */ async function storeEmbedding(event: FirestoreEvent<any>): Promise<void> { // Get the previous value of the document's `content` field. const previousDocumentSnapshot = event.data.before as QueryDocumentSnapshot; const previousContent = previousDocumentSnapshot.get("content"); // Get the current value of the document's `content` field. const currentDocumentSnapshot = event.data.after as QueryDocumentSnapshot; const currentContent = currentDocumentSnapshot.get("content"); // Don't update the embedding if the content field did not change if (previousContent === currentContent) { return; } // Call a function to calculate the embedding for the value // of the `content` field. const embeddingVector = calculateEmbedding(currentContent); // Update the `embedding` field on the document. await currentDocumentSnapshot.ref.update({ embedding: embeddingVector, }); }
สร้างและจัดการดัชนีเวกเตอร์
ก่อนที่คุณจะสามารถค้นหาเพื่อนบ้านที่อยู่ใกล้ที่สุดด้วยการฝังเวกเตอร์ของคุณ คุณต้องสร้างดัชนีที่เกี่ยวข้อง ตัวอย่างต่อไปนี้แสดง วิธีสร้างและจัดการดัชนีเวกเตอร์
สร้างดัชนีเวกเตอร์
ก่อนสร้างดัชนีเวกเตอร์ ให้อัปเกรดเป็น Google Cloud CLI เวอร์ชันล่าสุด:
gcloud components update
หากต้องการสร้างดัชนีเวกเตอร์ ให้ใช้ gcloud firestore indexes composite create
ดังนี้
gcloud
gcloud firestore indexes composite create \ --collection-group=collection-group \ --query-scope=COLLECTION \ --field-config field-path=vector-field,vector-config='vector-configuration' \ --database=database-id
โดยมี
- collection-group คือรหัสของกลุ่มคอลเล็กชัน
- vector-field คือชื่อของฟิลด์ที่มีการฝังเวกเตอร์
- database-id คือรหัสของฐานข้อมูล
- vector-configuration ประกอบด้วยเวกเตอร์
dimension
และประเภทดัชนีdimension
เป็นจำนวนเต็มสูงสุด 2048 ประเภทดัชนีต้องเป็นflat
จัดรูปแบบการกำหนดค่าดัชนีดังนี้:{"dimension":"DIMENSION", "flat": "{}"}
ตัวอย่างต่อไปนี้สร้างดัชนีผสม รวมถึงดัชนีเวกเตอร์สำหรับฟิลด์ vector-field
และดัชนีจากน้อยไปมากสำหรับช่อง color
คุณสามารถใช้ดัชนีประเภทนี้เพื่อกรองล่วงหน้า
ข้อมูลก่อนการค้นหาใกล้เคียงที่สุดได้
gcloud
gcloud firestore indexes composite create \ --collection-group=collection-group \ --query-scope=COLLECTION \ --field-config=order=ASCENDING,field-path="color" \ --field-config field-path=vector-field,vector-config='{"dimension":"1024", "flat": "{}"}' \ --database=database-id
แสดงรายการดัชนีเวกเตอร์ทั้งหมด
gcloud
gcloud firestore indexes composite list --database=database-id
แทนที่ database-id ด้วยรหัสของฐานข้อมูล
ลบดัชนีเวกเตอร์
gcloud
gcloud firestore indexes composite delete index-id --database=database-id
โดยมี
- index-id คือรหัสของดัชนีที่จะลบ
ใช้
indexes composite list
เพื่อดึงข้อมูลรหัสดัชนี - database-id คือรหัสของฐานข้อมูล
อธิบายดัชนีเวกเตอร์
gcloud
gcloud firestore indexes composite describe index-id --database=database-id
โดยมี
- index-id คือรหัสของดัชนีที่จะอธิบาย ใช้หรือ
indexes composite list
เพื่อเรียกข้อมูลรหัสดัชนี - database-id คือรหัสของฐานข้อมูล
ค้นหาเพื่อนบ้านที่อยู่ใกล้ที่สุด
คุณสามารถใช้การค้นหาความคล้ายคลึงกันเพื่อค้นหาเพื่อนบ้านที่ใกล้ที่สุดของ การฝังเวกเตอร์ การค้นหาความคล้ายคลึงกันต้องใช้ดัชนีเวกเตอร์ หากไม่มีดัชนี Cloud Firestore จะแนะนำดัชนีที่จะสร้าง โดยใช้ gcloud CLI
ตัวอย่างต่อไปนี้จะค้นหาเพื่อนบ้านที่ใกล้เคียงที่สุด 10 คนของเวกเตอร์การค้นหา
Python
Node.js
import { Firestore, FieldValue, VectorQuery, VectorQuerySnapshot, } from "@google-cloud/firestore"; // Requires a single-field vector index const vectorQuery: VectorQuery = coll.findNearest({ vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN' }); const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
ระยะทางเวกเตอร์
การค้นหาเพื่อนบ้านที่ใกล้ที่สุดรองรับตัวเลือกต่อไปนี้สำหรับระยะทางเวกเตอร์
EUCLIDEAN
: วัดระยะห่าง EUCLIDEAN ระหว่างเวกเตอร์ ดูข้อมูลเพิ่มเติมได้ที่ ยุคลิดCOSINE
: เปรียบเทียบเวกเตอร์ตามมุมระหว่างเวกเตอร์ ซึ่งจะช่วยให้คุณ วัดความคล้ายคลึงกันที่ไม่ได้อิงตามขนาดเวกเตอร์ เราขอแนะนำให้ใช้DOT_PRODUCT
กับเวกเตอร์ที่ได้รับการปรับให้เป็นหน่วยมาตรฐานแทน COSINE ซึ่งมีความเทียบเท่าทางคณิตศาสตร์และดีกว่า ด้านประสิทธิภาพ หากต้องการดูข้อมูลเพิ่มเติม โปรดดู ความคล้ายคลึงกันของโคไซน์เพื่อเรียนรู้ และอีกมากมายDOT_PRODUCT
: คล้ายกับCOSINE
แต่ได้รับผลกระทบจากขนาดของ เวกเตอร์ ดูข้อมูลเพิ่มเติมได้ที่ ผลิตภัณฑ์ Dot
เลือกการวัดระยะทาง
ทั้งนี้ขึ้นอยู่กับว่าการฝังเวกเตอร์ทั้งหมดได้รับการทำให้เป็นมาตรฐานหรือไม่ คุณสามารถ กำหนดวิธีวัดระยะทางที่จะใช้ค้นหาการวัดระยะทาง A ที่ปรับให้เป็นมาตรฐาน การฝังเวกเตอร์มีขนาด (ความยาว) เท่ากับ 1.0
นอกจากนี้ หากคุณทราบว่าโมเดลของคุณใช้หน่วยวัดระยะทางใด ให้ใช้การวัดระยะทางนั้นเพื่อคำนวณระยะทางระหว่างเวกเตอร์ของคุณ การฝังวิดีโอ
ข้อมูลมาตรฐาน
ถ้าคุณมีชุดข้อมูลที่มีการฝังเวกเตอร์ทั้งหมดให้เป็นมาตรฐาน ทั้งสาม
การวัดระยะทางจะแสดงผลการค้นหาเชิงความหมายเดียวกัน โดยพื้นฐานแล้ว แม้ว่าแต่ละ
มาตรวัดระยะทางจะแสดงผลค่าที่แตกต่างกัน โดยค่าเหล่านั้นจะจัดเรียงในลักษณะเดียวกัน วันและเวลา
การฝังจะถูกทำให้เป็นมาตรฐาน โดย DOT_PRODUCT
มักจะเป็นการคำนวณที่
มีประสิทธิภาพ แต่กรณีส่วนใหญ่มีความแตกต่างกันน้อยมาก อย่างไรก็ตาม หาก
แอปพลิเคชันมีความละเอียดอ่อนด้านประสิทธิภาพสูง DOT_PRODUCT
อาจช่วยได้
ในการปรับแต่งประสิทธิภาพ
ข้อมูลที่ไม่ใช่ค่ามาตรฐาน
หากคุณมีชุดข้อมูลที่ไม่ได้ทำให้การฝังเวกเตอร์เป็นมาตรฐาน
การใช้ DOT_PRODUCT
เป็นระยะทางก็ไม่ถูกต้องในทางคณิตศาสตร์
วัดระยะทางเนื่องจากผลิตภัณฑ์แบบจุดไม่ได้วัดระยะทาง แล้วแต่กรณี
เกี่ยวกับวิธีการสร้างการฝัง และประเภทการค้นหาที่ต้องการ
การวัดระยะทาง COSINE
หรือ EUCLIDEAN
ทำให้เกิด
ผลการค้นหาที่เป็นนามธรรมที่ดีกว่าการวัดระยะทางอื่นๆ
การทดสอบกับ COSINE
หรือ EUCLIDEAN
อาจ
เป็นสิ่งจำเป็นในการพิจารณาว่าวิธีใดเหมาะกับกรณีการใช้งานของคุณที่สุด
ไม่แน่ใจว่าข้อมูลได้รับการทำให้เป็นมาตรฐานหรือไม่ได้ปรับให้เป็นมาตรฐาน
หากไม่แน่ใจว่าข้อมูลได้รับการปรับให้เป็นมาตรฐานหรือไม่ และต้องการใช้
DOT_PRODUCT
เราขอแนะนำให้ใช้ COSINE
แทน
COSINE
เหมือนกับ DOT_PRODUCT
ที่มีการปรับรูปแบบมาตรฐานในตัว
ระยะทางวัดโดยใช้ช่วงCOSINE
ตั้งแต่ 0
ถึง 2
ผลลัพธ์
ที่อยู่ใกล้กับ 0
แสดงว่าเวกเตอร์คล้ายกันมาก
กรองเอกสารล่วงหน้า
ในการกรองเอกสารล่วงหน้าก่อนที่จะพบเพื่อนบ้านที่อยู่ใกล้ที่สุด คุณสามารถรวม
การค้นหาที่คล้ายกันกับโอเปอเรเตอร์ข้อความค้นหาอื่นๆ and
และ
สนับสนุนตัวกรองผสม or
รายการ โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับตัวกรองช่องที่รองรับได้ที่โอเปอเรเตอร์การค้นหา
Python
Node.js
// Similarity search with pre-filter // Requires composite vector index const preFilteredVectorQuery: VectorQuery = coll .where("color", "==", "red") .findNearest({ vectorField: "embedding_field", queryVector: [3.0, 1.0, 2.0], limit: 5, distanceMeasure: "EUCLIDEAN", }); const vectorQueryResults = await preFilteredVectorQuery.get();
ดึงข้อมูลระยะทางเวกเตอร์ที่คำนวณ
คุณสามารถดึงระยะทางเวกเตอร์ที่คำนวณโดยการกำหนด
ชื่อพร็อพเพอร์ตี้เอาต์พุต distance_result_field
ในการค้นหา FindNearest
เป็น
ที่แสดงในตัวอย่างต่อไปนี้
Python
Node.js
const vectorQuery: VectorQuery = coll.findNearest( { vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN', distanceResultField: 'vector_distance' }); const snapshot: VectorQuerySnapshot = await vectorQuery.get(); snapshot.forEach((doc) => { console.log(doc.id, ' Distance: ', doc.get('vector_distance')); });
หากต้องการใช้มาสก์ช่องเพื่อแสดงผลชุดย่อยของช่องเอกสารพร้อมกับ distanceResultField
คุณจะต้องใส่ค่า distanceResultField
ในมาสก์ของช่องด้วย ดังที่แสดงในตัวอย่างต่อไปนี้
Python
Node.js
const vectorQuery: VectorQuery = coll .select('color', 'vector_distance') .findNearest({ vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN', distanceResultField: 'vector_distance' });
ระบุเกณฑ์ระยะทาง
คุณสามารถระบุเกณฑ์ความคล้ายคลึงกันที่จะแสดงเฉพาะเอกสารภายในองค์ประกอบ ลักษณะการทำงานของช่องเกณฑ์จะขึ้นอยู่กับการวัดระยะทาง ที่คุณเลือก
- ระยะทาง
EUCLIDEAN
และCOSINE
จำกัดเกณฑ์สำหรับเอกสารในตำแหน่ง ระยะทางน้อยกว่าหรือเท่ากับเกณฑ์ที่ระบุ ระยะทางเหล่านี้ การวัดจะลดลงเมื่อเวกเตอร์คล้ายกันมากขึ้น - ระยะทาง
DOT_PRODUCT
จำกัดเกณฑ์สำหรับเอกสารที่มีระยะทางเท่ากับ มากกว่าหรือเท่ากับเกณฑ์ที่ระบุ ระยะห่างของผลิตภัณฑ์แบบจุด จะเพิ่มขึ้นเมื่อเวกเตอร์คล้ายกันมากขึ้น
ตัวอย่างต่อไปนี้แสดงวิธีระบุเกณฑ์ระยะทางเพื่อแสดงผลเอกสารที่ใกล้ที่สุด 10 รายการที่ห่างออกไปไม่เกิน 4.5 หน่วยโดยใช้เมตริกระยะทาง EUCLIDEAN
Python
Node.js
const vectorQuery: VectorQuery = coll.findNearest({ vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN', distanceThreshold: 4.5 }); const snapshot: VectorQuerySnapshot = await vectorQuery.get(); snapshot.forEach((doc) => { console.log(doc.id); });
ข้อจำกัด
โปรดทราบข้อจำกัดต่อไปนี้ขณะที่คุณทำงานกับการฝังเวกเตอร์
- มิติข้อมูลการฝังที่สนับสนุนสูงสุดคือ 2048 หากต้องการจัดเก็บดัชนีที่ใหญ่กว่า ให้ใช้ การลดลงของมิติข้อมูล
- จำนวนเอกสารสูงสุดที่จะแสดงจากคำค้นหาใกล้เคียงที่สุดคือ 1,000 รายการ
- การค้นหาเวกเตอร์ไม่รองรับ Listener ของสแนปชอตแบบเรียลไทม์
- เฉพาะไลบรารีของไคลเอ็นต์ Python และ Node.js เท่านั้นที่รองรับการค้นหาเวกเตอร์
ขั้นตอนถัดไป
- อ่านเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับ Cloud Firestore
- ทำความเข้าใจการอ่านและการเขียนในวงกว้าง