Ähnlichkeitsvektorsuche in Bigtable durchführen, indem die K-nächsten Nachbarn ermittelt werden

Mit der Suche nach Ähnlichkeitsvektoren können Sie ähnliche Konzepte und kontextbezogene Bedeutungen in Ihren Bigtable-Daten ermitteln. Das bedeutet, dass Sie beim Filtern nach Daten, die in einem bestimmten Schlüsselbereich gespeichert sind, relevantere Ergebnisse erhalten. Beispiele für Anwendungsfälle:

  • Posteingangssuche, bei der Sie Nachrichten für einen bestimmten Nutzer semantisch abgleichen möchten
  • Anomalieerkennung innerhalb eines Bereichs von Sensoren
  • Abrufen der relevantesten Dokumente innerhalb einer Reihe bekannter Schlüssel für die Retrieval-Augmented Generation (RAG)

Auf dieser Seite wird beschrieben, wie Sie mit den Vektorfunktionen „Kosinus-Distanz“ und „Euklidische Distanz“ in GoogleSQL für Bigtable eine Ähnlichkeitsvektorsuche in Bigtable ausführen, um die K-nächsten Nachbarn zu finden. Bevor Sie diese Seite lesen, sollten Sie sich mit den folgenden Konzepten vertraut machen:

  • Euklidischer Abstand: Misst die kürzeste Entfernung zwischen zwei Vektoren.
  • Kosinus-Distanz: Der Kosinus des Winkels zwischen zwei Vektoren.
  • K-Nearest-Neighbor (KNN): Ein überwachter Algorithmus für maschinelles Lernen, der zur Lösung von Klassifizierungs- oder Regressionsproblemen verwendet wird.

Bigtable unterstützt die Funktionen COSINE_DISTANCE() und EUCLIDEAN_DISTANCE(), die auf Vektoreinbettungen angewendet werden und mit denen Sie den KNN der Eingabeeinbettung ermitteln können.

Mit den Vertex AI Text Embedding APIs können Sie Ihre Bigtable-Daten als Vektoreinbettungen generieren und speichern. Sie können diese Vektoreinbettungen dann als Eingabeparameter in Ihrer Abfrage angeben, um die nächsten Vektoren im n-dimensionalen Raum zu finden und nach semantisch ähnlichen oder ähnlichen Elementen zu suchen.

Beide Distanzfunktionen nehmen die Argumente vector1 und vector2 vom Typ array<> an. Sie müssen dieselben Dimensionen haben und dieselbe Länge. Weitere Informationen zu diesen Funktionen finden Sie hier:

Der Code auf dieser Seite zeigt, wie Sie Einbettungen erstellen, in Bigtable speichern und dann eine KNN-Suche durchführen.

Im Beispiel auf dieser Seite werden EUCLIDEAN_DISTANCE() und die Bigtable-Clientbibliothek für Python verwendet. Sie können jedoch auch COSINE_DISTANCE() und jede Clientbibliothek verwenden, die GoogleSQL für Bigtable unterstützt, z. B. die Bigtable-Clientbibliothek für Java.

Hinweise

Führen Sie die folgenden Schritte aus, bevor Sie die Codebeispiele ausprobieren.

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die folgende IAM-Rolle zuzuweisen, um die Berechtigungen zum Lesen und Schreiben in Bigtable zu erhalten.

  • Bigtable-Nutzer (roles/bigtable.user) der Bigtable-Instanz, an die Sie Anfragen senden möchten

Umgebung einrichten

  1. Laden Sie die Bigtable-Clientbibliothek für Python herunter und installieren Sie sie. Wenn Sie GoogleSQL für Bigtable-Funktionen verwenden möchten, müssen Sie python-bigtable Version 2.26.0 oder höher verwenden. Eine Anleitung, einschließlich der Einrichtung der Authentifizierung, finden Sie unter Python-Hallo-Welt-Programm.

  2. Wenn Sie noch keine Bigtable-Instanz haben, folgen Sie der Anleitung unter Instanz erstellen.

  3. Geben Sie Ihre Ressourcen-IDs an. Ersetzen Sie beim Ausführen des Codes die folgenden Platzhalter durch die IDs Ihres Google Cloud-Projekts, Ihrer Bigtable-Instanz und Ihrer Tabelle:

    • PROJECT_ID
    • INSTANCE_ID
    • TABLE_ID

Tabelle zum Speichern von Text, Einbettungen und Suchbegriff erstellen

Erstellen Sie eine Tabelle mit zwei Spaltenfamilien.

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

Texte mit einem vortrainierten Basismodell von Vertex einbetten

Generieren Sie den Text und die Einbettungen, die in Bigtable gespeichert werden sollen, zusammen mit den zugehörigen Schlüsseln. Weitere Informationen finden Sie unter Texteinbettungen abrufen oder Multimodale Einbettungen abrufen.

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

Funktionen definieren, mit denen Sie in Byte-Objekte konvertieren können

Bigtable ist für Schlüssel/Wert-Paare optimiert und speichert Daten in der Regel als Byte-Objekte. Weitere Informationen zum Entwerfen Ihres Datenmodells für Bigtable finden Sie unter Best Practices für Schemadesign.

Sie müssen die von Vertex zurückgegebenen Einbettungen konvertieren, die in Python als Liste von Gleitkommazahlen gespeichert sind. Sie konvertieren jedes Element in die Big-Endian-IEEE-754-Gleitkommadarstellung und verketten sie dann miteinander. Das wird mit der folgenden Funktion erreicht.

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)

Einbettungen in Bigtable schreiben

Konvertieren Sie die Einbettungen in Byte-Objekte, erstellen Sie eine Mutation und schreiben Sie die Daten dann in 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)

Die Vektoren werden als binärcodierte Daten gespeichert, die mithilfe einer Konvertierungsfunktion vom Typ BYTES in ARRAY<FLOAT32> aus Bigtable gelesen werden können.

Hier ist die SQL-Abfrage:

SELECT _key, TO_VECTOR32(data['embedding']) AS embedding
FROM table WHERE _key LIKE 'store123%';

In Python können Sie die GoogleSQL-Funktion COSINE_DISTANCE verwenden, um die Ähnlichkeit zwischen Ihren Text-Embeddings und den von Ihnen angegebenen Suchbegriffen zu ermitteln. Da diese Berechnung einige Zeit in Anspruch nehmen kann, verwenden Sie den asynchronen Datenclient der Python-Clientbibliothek, um die SQL-Abfrage auszuführen.

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()

Die zurückgegebene Antwort ist eine generierte Textbeschreibung, die Bigtable beschreibt.

Nächste Schritte