ביצוע חיפוש וקטורי של דמיון ב-Bigtable על ידי מציאת השכנים הקרובים ביותר (K-nearest neighbors)
חיפוש דמיון וקטורי יכול לעזור לכם לזהות מושגים דומים ומשמעות הקשרית בנתוני Bigtable. המשמעות היא שהוא יכול לספק תוצאות רלוונטיות יותר כשמסננים נתונים שמאוחסנים בטווח מפתחות שצוין. דוגמאות לתרחישי שימוש:
- התאמה סמנטית של הודעות למשתמש מסוים בחיפוש בתיבת הדואר הנכנס.
- זיהוי אנומליות בטווח של חיישנים.
- אחזור המסמכים הרלוונטיים ביותר מתוך קבוצה של מפתחות ידועים לצורך יצירה משולבת-אחזור (RAG).
- התאמה אישית של תוצאות החיפוש כדי לשפר את חוויית החיפוש של המשתמשים. התוצאות מאוחזרות ומדורגות על סמך ההנחיות וההעדפות הקודמות שלהם שמאוחסנות ב-Bigtable.
- אחזור של שרשורי שיחה דומים כדי למצוא ולהציג שיחות קודמות שדומות מבחינת ההקשר לשיחה הנוכחית של המשתמש, כדי לספק חוויה מותאמת אישית יותר.
- ביטול כפילויות של הנחיות כדי לזהות הנחיות זהות או דומות מבחינה סמנטית שנשלחו על ידי אותו משתמש, וכדי להימנע מעיבוד באמצעות AI מיותר.
לפני שקוראים את הדף הזה, חשוב להבין את המושגים הבאים:
- מרחק אוקלידי: מדידת המרחק הקצר ביותר בין שני וקטורים.
- מרחק קוסינוס: מדידת הקוסינוס של הזווית בין שני וקטורים.
- K-nearest neighbors (KNN): אלגוריתם ללמידה חישובית מבוקרת שמשמש לפתרון בעיות סיווג או רגרסיה.
Bigtable תומך בפונקציות COSINE_DISTANCE() ו-EUCLIDEAN_DISTANCE(), שפועלות על הטמעות וקטוריות ומאפשרות למצוא את ה-KNN של ההטמעה של הקלט.
אתם יכולים להשתמש בממשקי ה-API של Gemini Enterprise Agent Platform text embeddings כדי ליצור ולאחסן את נתוני Bigtable כהטבעות וקטוריות. לאחר מכן, אפשר לספק את ההטמעות הווקטוריות האלה כפרמטר קלט בשאילתה כדי למצוא את הווקטורים הקרובים ביותר במרחב N-ממדי, ולחפש פריטים דומים או קשורים מבחינה סמנטית.
שתי פונקציות המרחק מקבלות את הארגומנטים vector1 ו-vector2, שהם מסוג array<> וחייבים לכלול את אותם המאפיינים ולהיות באותו האורך. לפרטים נוספים על הפונקציות האלה, אפשר לעיין במאמרים הבאים:
בדף הזה מופיע קוד שמראה איך ליצור הטמעות, לאחסן אותן ב-Bigtable ואז לבצע חיפוש KNN.
בדוגמה שבדף הזה נעשה שימוש ב-EUCLIDEAN_DISTANCE() ובספריית הלקוח של Bigtable ל-Python. עם זאת, אפשר להשתמש גם ב-COSINE_DISTANCE() ובכל ספריית לקוח שתומכת ב-GoogleSQL ל-Bigtable, כמו
ספריית הלקוח של Bigtable ל-Java.
לפני שמתחילים
לפני שמנסים את דוגמאות הקוד, צריך לבצע את הפעולות הבאות.
התפקידים הנדרשים
כדי לקבל את ההרשאות שדרושות לקריאה וכתיבה ב-Bigtable, צריך לבקש מהאדמין להקצות לכם את תפקיד ה-IAM הבא:
- Bigtable User
(
roles/bigtable.user) on the Bigtable instance that you want to send requests to
מגדירים את הסביבה
מורידים ומתקינים את ספריית הלקוח של Bigtable ל-Python. כדי להשתמש ב-GoogleSQL לפונקציות של Bigtable, צריך להשתמש בגרסה 2.26.0 ואילך של
python-bigtable. הוראות, כולל איך להגדיר אימות, זמינות במאמר Python hello world.אם אין לכם מופע Bigtable, פועלים לפי השלבים במאמר יצירת מופע.
מזהים את מזהי המשאבים. כשמריצים את הקוד, מחליפים את ה-placeholders הבאים במזהים של Google Cloud הפרויקט, מופע Bigtable והטבלה:
PROJECT_IDINSTANCE_IDTABLE_ID
יצירת טבלה לאחסון הטקסט, ההטמעות וביטוי החיפוש
יוצרים טבלה עם שתי קבוצות עמודות.
Python
from google.cloud import bigtable
from google.cloud.bigtable import column_family
client = bigtable.Client(project=PROJECT_ID, admin=True)
instance = client.instance(INSTANCE_ID)
table = instance.table(TABLE_ID)
column_families = {"docs":column_family.MaxVersionsGCRule(2), "search_phrase":column_family.MaxVersionsGCRule(2)}
if not table.exists():
table.create(column_families=column_families)
else:
print("Table already exists")
הטמעת טקסטים באמצעות מודל בסיסי שעבר אימון מראש מ-Agent Platform
יצירת הטקסט וההטמעות לאחסון ב-Bigtable יחד עם המפתחות המשויכים. מידע נוסף זמין במאמרים בנושא קבלת הטמעות של טקסט או קבלת הטמעות מולטימודאליות.
Python
from typing import List, Optional
from vertexai.language_models import TextEmbeddingInput, TextEmbeddingModel
from vertexai.generative_models import GenerativeModel
#defines which LLM that we should use to generate the text
model = GenerativeModel("gemini-1.5-pro-001")
#First, use generative AI to create a list of 10 chunks for phrases
#This can be replaced with a static list of text items or your own data
chunks = []
for i in range(10):
response = model.generate_content(
"Generate a paragraph between 10 and 20 words that is about about either
Bigtable or Generative AI"
)
chunks.append(response.text)
print(response.text)
#create embeddings for the chunks of text
def embed_text(
texts: List[str] = chunks,
task: str = "RETRIEVAL_DOCUMENT",
model_name: str = "text-embedding-004",
dimensionality: Optional[int] = 128,
) -> List[List[float]]:
"""Embeds texts with a pre-trained, foundational model."""
model = TextEmbeddingModel.from_pretrained(model_name)
inputs = [TextEmbeddingInput(text, task) for text in texts]
kwargs = dict(output_dimensionality=dimensionality) if dimensionality else {}
embeddings = model.get_embeddings(inputs, **kwargs)
return [embedding.values for embedding in embeddings]
embeddings = embed_text()
print("embeddings created for text phrases")
הגדרת פונקציות שמאפשרות המרה לאובייקטים של בייטים
Bigtable מותאם לצמדי מפתח-ערך ובדרך כלל מאחסן נתונים כאובייקטים של בייטים. מידע נוסף על תכנון מודל הנתונים ל-Bigtable זמין במאמר שיטות מומלצות לתכנון סכימה.
צריך להמיר את ההטמעות שמתקבלות מ-Agent Platform, שמאוחסנות כרשימה של מספרים ממשיים ב-Python. ממירים כל רכיב לפורמט נקודה צפה של IEEE 754 בשיטת big-endian, ואז משרשרים אותם. הפונקציה הבאה מבצעת את הפעולה הזו.
Python
import struct
def floats_to_bytes(float_list):
"""
Convert a list of floats to a bytes object, where each float is represented
by 4 big-endian bytes.
Parameters:
float_list (list of float): The list of floats to be converted.
Returns:
bytes: The resulting bytes object with concatenated 4-byte big-endian
representations of the floats.
"""
byte_array = bytearray()
for value in float_list:
packed_value = struct.pack('>f', value)
byte_array.extend(packed_value)
# Convert bytearray to bytes
return bytes(byte_array)
כתיבת ההטמעות ב-Bigtable
ממירים את ההטמעות לאובייקטים של בייטים, יוצרים מוטציה ואז כותבים את הנתונים ל-Bigtable.
Python
from google.cloud.bigtable.data import RowMutationEntry
from google.cloud.bigtable.data import SetCell
mutations = []
embeddings = embed_text()
for i, embedding in enumerate(embeddings):
print(embedding)
#convert each embedding into a byte object
vector = floats_to_bytes(embedding)
#set the row key which will be used to pull the range of documents (ex. doc type or user id)
row_key = f"doc_{i}"
row = table.direct_row(row_key)
#set the column for the embedding based on the byte object format of the embedding
row.set_cell("docs","embedding",vector)
#store the text associated with vector in the same key
row.set_cell("docs","text",chunks[i])
mutations.append(row)
#write the rows to Bigtable
table.mutate_rows(mutations)
ביצוע חיפוש KNN באמצעות GoogleSQL ל-Bigtable
הווקטורים מאוחסנים כנתונים מקודדים בינאריים שאפשר לקרוא מ-Bigtable באמצעות פונקציית המרה מהסוג BYTES לסוג ARRAY<FLOAT32>.
זו שאילתת ה-SQL:
SELECT _key, TO_VECTOR32(data['embedding']) AS embedding
FROM table WHERE _key LIKE 'store123%';
אפשר להשתמש בפונקציה COSINE_DISTANCE של GoogleSQL כדי למצוא את הדמיון בין הטמעות הטקסט לבין ביטויי החיפוש שאתם מספקים. החישוב הזה יכול לקחת זמן, ולכן כדאי להשתמש בלקוח הנתונים האסינכרוני של ספריית הלקוח של Python כדי להריץ את שאילתת ה-SQL.
Python
from google.cloud.bigtable.data import BigtableDataClientAsync
#first embed the search phrase
search_embedding = embed_text(texts=["Apache HBase"])
query = """
select _key, docs['text'] as description
FROM knn_intro
ORDER BY COSINE_DISTANCE(TO_VECTOR32(docs['embedding']), {search_embedding})
LIMIT 1;
"""
async def execute_query():
async with BigtableDataClientAsync(project=PROJECT_ID) as client:
local_query = query
async for row in await client.execute_query(query.format(search_embedding=search_embedding[0]), INSTANCE_ID):
return(row["_key"],row["description"])
await execute_query()
התשובה שמוחזרת היא תיאור טקסט שנוצר ומסביר מהו Bigtable.