Ähnlichkeitsvektorsuche in Bigtable durchführen indem sie die K-nächsten Nachbarn

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:

  • Suche im Posteingang, um einen semantischen Abgleich von Nachrichten durchzuführen für einen bestimmten Nutzer
  • Anomalieerkennung innerhalb eines Bereichs von Sensoren
  • Abrufen der relevantesten Dokumente innerhalb eines Satzes bekannter Schlüssel für Retrieval Augmented Generation (RAG)

Auf dieser Seite wird beschrieben, wie Sie eine Suche nach Ähnlichkeitsvektoren in Bigtable mithilfe der Kosinus-Distanz und der euklidischen Distanz Vektorfunktionen in GoogleSQL for Bigtable um die nächsten K-Nachbarn zu finden. Bevor Sie diese Seite lesen, sollten Sie sich mit den folgenden Konzepten vertraut machen:

Bigtable unterstützt die COSINE_DISTANCE()- und EUCLIDEAN_DISTANCE()-Funktionen, die mit Vektoreinbettungen arbeiten, finden Sie den KNN der Eingabeeinbettung.

Mit den Vertex AI-APIs für Texteinbettungen können Sie als Vektoreinbettungen. Sie können dann Vektoreinbettungen als Eingabeparameter in Ihre Abfrage ein, um den nächsten Vektoren im n-dimensionalen Raum um, um nach semantisch ähnlichen oder ähnlichen Elemente.

Beide Distanzfunktionen nehmen die Argumente vector1 und vector2 vom Typ array<> an. Sie müssen aus denselben Dimensionen bestehen und dieselbe Länge haben. 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. 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.

Hinweis

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

Erforderliche Rollen

Um die Berechtigungen zu erhalten, die Sie zum Lesen und Schreiben Bigtable enthält, bitten Sie Ihren Administrator, Ihnen die folgende IAM-Rolle zu gewähren. Rolle.

  • 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. Um GoogleSQL for Bigtable-Funktionen zu verwenden, muss die 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 keine Bigtable-Instanz haben, führen Sie die Schritte 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 des Textes, der Einbettungen und der Wortgruppe 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

Text und Einbettungen zum Speichern in Bigtable generieren 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. Die folgende Funktion erreicht dies.

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 dann die zu Bigtable hinzufügen.

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 die Verarbeitung dieser Berechnung einige Zeit in Anspruch nehmen kann, verwenden Sie die Python- asynchronen Daten der Clientbibliothek Kunde 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, beschreibt Bigtable.

Nächste Schritte