Mit dem KI-fähigen BigQuery DataFrames-Paket Informationen aus strukturierten und unstrukturierten Daten gewinnen

1. Übersicht

In diesem Lab verwenden Sie BigQuery DataFrames aus einem Python-Notebook in BigQuery Studio, um mit Python Erkenntnisse aus Daten zu gewinnen. Generative KI von Google nutzen, um unstrukturierte Textdaten zu analysieren und zu visualisieren

Sie erstellen ein Python-Notebook, um eine öffentliche Datenbank mit Kundenbeschwerden zu kategorisieren und zusammenzufassen. Diese kann an beliebige unstrukturierte Textdaten angepasst werden.

Ziele

Aufgaben in diesem Lab:

  • Python-Notebooks in BigQuery Studio aktivieren und verwenden
  • Verbindung zu BigQuery mit dem BigQuery DataFrames-Paket herstellen
  • Einbettungen aus unstrukturierten Textdaten mit BigQuery ML und einer Verbindung zu einem Texteinbettungsendpunkt in Vertex AI erstellen
  • Einbettungen mit BigQuery ML clustern
  • Cluster mit einem LLM über BigQuery ML zusammenfassen

2. Voraussetzungen

  • Ein Browser, z. B. Chrome oder Firefox
  • Ein Google Cloud-Projekt mit aktivierter Abrechnung

Hinweis

Wenn Sie der Anleitung in diesem Codelab folgen möchten, benötigen Sie ein Google Cloud-Projekt mit aktiviertem BigQuery Studio und einem verknüpften Abrechnungskonto.

  1. Wählen Sie in der Google Cloud Console auf der Seite zur Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.
  2. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für ein Projekt aktiviert ist
  3. Folgen Sie der Anleitung unter BigQuery Studio für die Asset-Verwaltung aktivieren.

BigQuery Studio vorbereiten

Leeres Notebook erstellen und mit einer Laufzeit verbinden

  1. Rufen Sie BigQuery Studio in der Google Cloud Console auf.
  2. Klicken Sie neben der Schaltfläche + auf das .
  3. Wählen Sie Python-Notebook aus.
  4. Schließen Sie die Vorlagenauswahl.
  5. Wählen Sie + Code aus, um eine neue Codezelle zu erstellen.
  6. Installieren Sie die neueste Version des BigQuery DataFrames-Pakets über die Codezelle.Geben Sie den folgenden Befehl ein.
    %pip install --upgrade bigframes --quiet
    
    Klicken Sie auf die Schaltfläche 🞂 oder drücken Sie Umschalt + Eingabetaste, um die Codezelle auszuführen.

3. Öffentliches Dataset lesen

Initialisieren Sie das BigQuery DataFrames-Paket, indem Sie Folgendes in einer neuen Codezelle ausführen:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

Hinweis: In diesem Tutorial verwenden wir den experimentellen „Modus für partielle Sortierung“, der in Verbindung mit pandas-ähnlicher Filterung effizientere Abfragen ermöglicht. Einige pandas-Funktionen, für die eine strikte Reihenfolge oder ein Index erforderlich ist, funktionieren möglicherweise nicht.

Datenbank für Verbraucherbeschwerden

Die Consumer Complaint Database (Datenbank für Verbraucherbeschwerden) wird über das Programm für öffentliche Datasets in Google Cloud in BigQuery bereitgestellt. Diese Sammlung von Beschwerden über Finanzprodukte und ‑dienstleistungen für Verbraucher wird vom US Consumer Financial Protection Bureau erhoben.

Fragen Sie in BigQuery die Tabelle bigquery-public-data.cfbp_complaints.complaint_database ab, um die Consumer Complaint Database zu analysieren. Mit der Methode bigframes.pandas.read_gbq() können Sie einen DataFrame aus einem Abfragestring oder einer Tabellen-ID erstellen.

Führen Sie den folgenden Code in einer neuen Codezelle aus, um einen DataFrame mit dem Namen „feedback“ zu erstellen:

feedback = bpd.read_gbq(
    "bigquery-public-data.cfpb_complaints.complaint_database"
)

Grundlegende Informationen zu einem DataFrame abrufen

Mit der Methode DataFrame.peek() können Sie eine kleine Stichprobe der Daten herunterladen.

Führen Sie diese Zelle aus:

feedback.peek()

Erwartete Ausgabe:

  date_received                  product ... timely_response  consumer_disputed complaint_id  
0    2014-03-05  Bank account or service ...            True              False       743665   
1    2014-01-21  Bank account or service ...            True              False       678608   
2    2020-12-31          Debt collection ...            True               <NA>      4041190   
3    2014-02-12          Debt collection ...            True              False       714350   
4    2015-02-23          Debt collection ...            True              False      1251358   

Hinweis: Für head() ist eine Sortierung erforderlich und es ist im Allgemeinen weniger effizient als peek(), wenn Sie eine Stichprobe von Daten visualisieren möchten.

Wie bei pandas können Sie mit der Property DataFrame.dtypes alle verfügbaren Spalten und die entsprechenden Datentypen aufrufen. Sie werden auf pandas-kompatible Weise bereitgestellt.

Führen Sie diese Zelle aus:

feedback.dtypes

Erwartete Ausgabe:

date_received                   date32[day][pyarrow]
product                              string[pyarrow]
subproduct                           string[pyarrow]
issue                                string[pyarrow]
subissue                             string[pyarrow]
consumer_complaint_narrative         string[pyarrow]
company_public_response              string[pyarrow]
company_name                         string[pyarrow]
state                                string[pyarrow]
zip_code                             string[pyarrow]
tags                                 string[pyarrow]
consumer_consent_provided            string[pyarrow]
submitted_via                        string[pyarrow]
date_sent_to_company            date32[day][pyarrow]
company_response_to_consumer         string[pyarrow]
timely_response                              boolean
consumer_disputed                            boolean
complaint_id                         string[pyarrow]
dtype: object

Mit der Methode DataFrame.describe() werden einige grundlegende Statistiken aus dem DataFrame abgefragt. Da dieser DataFrame keine numerischen Spalten enthält, wird eine Zusammenfassung der Anzahl der Werte, die nicht null sind, und der Anzahl der eindeutigen Werte angezeigt.

Führen Sie diese Zelle aus:

# Exclude some of the larger columns to make the query more efficient.
feedback.drop(columns=[
  "consumer_complaint_narrative",
  "company_public_response",
  "company_response_to_consumer",
]).describe()

Erwartete Ausgabe:

         product  subproduct    issue  subissue  company_name    state ... timely_response  consumer_disputed  complaint_id
count    3458906     3223615  3458906   2759004       3458906  3417792 ...         3458906             768399       3458906
nunique       18          76      165       221          6694       63 ...               2                  2       3458906

4. Daten analysieren

Bevor Sie sich die tatsächlichen Beschwerden ansehen, können Sie die Daten mit den Pandas-ähnlichen Methoden im DataFrame visualisieren.

DataFrame visualisieren

Es gibt mehrere integrierte Visualisierungsmethoden wie DataFrame.plot.hist(). Da dieser DataFrame hauptsächlich String- und boolesche Daten enthält, können wir zuerst einige Aggregationen durchführen, um mehr über die verschiedenen Spalten zu erfahren.

Zählen Sie, wie viele Beschwerden aus den einzelnen Bundesstaaten eingehen.

complaints_by_state = (
  feedback.groupby(
    "state", as_index=False,
  ).size()
  .rename(columns={"size": "total_complaints"})
  .sort_values(by="total_complaints", ascending=False)
)

Konvertieren Sie die Daten mit der Methode DataFrame.to_pandas() in einen Pandas DataFrame.

complaints_pd = complaints_by_state.head(10).to_pandas()

Verwenden Sie Pandas-Visualisierungsmethoden für diesen heruntergeladenen DataFrame.

complaints_pd.plot.bar(x="state", y="total_complaints")

Balkendiagramm mit Kalifornien als Bundesstaat mit den meisten Beschwerden

Mit anderen Datasets verknüpfen

Bisher haben Sie sich Beschwerden nach Bundesstaat angesehen. Dabei geht jedoch wichtiger Kontext verloren. Einige Bundesstaaten haben mehr Einwohner als andere. Sie können die Daten mit einem Bevölkerungs-Dataset wie der American Community Survey des US Census Bureau und der bigquery-public-data.geo_us_boundaries.states-Tabelle zusammenführen.

us_states = bpd.read_gbq("bigquery-public-data.geo_us_boundaries.states")
us_survey = bpd.read_gbq("bigquery-public-data.census_bureau_acs.state_2020_5yr")

# Ensure there are leading 0s on GEOIDs for consistency across tables.
us_states = us_states.assign(
    geo_id=us_states["geo_id"].str.pad(2, fillchar="0")
)

us_survey = us_survey.assign(
    geo_id=us_survey["geo_id"].str.pad(2, fillchar="0")
)

Bei der American Community Survey werden Bundesstaaten anhand der GEOID identifiziert. Führen Sie einen Join mit der Tabelle „states“ aus, um die Bevölkerung nach zweistelligem Bundesstaatscode zu erhalten.

pops = us_states.set_index("geo_id")[["state"]].join(
  us_survey.set_index("geo_id")[["total_pop"]]
)

Führen Sie diese Daten nun mit der Beschwerdedatenbank zusammen, um die Bevölkerung mit der Anzahl der Beschwerden zu vergleichen.

complaints_and_pops = complaints_by_state.set_index("state").join(
    pops.set_index("state")
)

Erstellen Sie ein Streudiagramm, um die Bevölkerungszahlen der Bundesstaaten mit der Anzahl der Beschwerden zu vergleichen.

(
  complaints_and_pops
  .to_pandas()
  .plot.scatter(x="total_pop", y="total_complaints")
)

ein Streudiagramm, in dem die Bevölkerung mit den Beschwerden verglichen wird

Beim Vergleich der Bevölkerung mit der Anzahl der Beschwerden scheinen einige Bundesstaaten Ausreißer zu sein. Es bleibt dem Leser überlassen, diese Punkte mit Punktlabels zu kennzeichnen. Stellen Sie außerdem einige Hypothesen auf, warum das so sein könnte (z.B. unterschiedliche demografische Merkmale, unterschiedliche Anzahl von Finanzdienstleistungsunternehmen usw.), und testen Sie sie.

5. Einbettungen berechnen

Häufig sind wichtige Informationen in unstrukturierten Daten wie Text, Audio oder Bildern verborgen. In diesem Beispiel sind viele der nützlichen Informationen in der Beschwerdedatenbank im Textinhalt der Beschwerde enthalten.

Mit KI und traditionellen Techniken wie der Stimmungsanalyse, „Bag of Words“ und Word2Vec lassen sich einige quantitative Informationen aus unstrukturierten Daten extrahieren. In jüngerer Zeit können Modelle für „Vektoreinbettung“, die eng mit LLMs verwandt sind, eine Folge von Gleitkommazahlen erstellen, die die semantischen Informationen von Text darstellen.

Untermenge der Datenbank auswählen

Für die Ausführung eines Vektoreinbettungsmodells werden mehr Ressourcen benötigt als für andere Vorgänge. Um Kosten und Kontingentprobleme zu reduzieren, wählen Sie für den Rest dieser Anleitung eine Teilmenge der Daten aus.

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

feedback = bpd.read_gbq(
    "bigquery-public-data.cfpb_complaints.complaint_database"
)

# Note: if not using ordering_mode = "partial", you must specify these in read_gbq
# for these to affect query efficiency.
# feedback = bpd.read_gbq(
#    "bigquery-public-data.cfpb_complaints.complaint_database",
#     columns=["consumer_complaint_narrative"],
#     filters= [
#         ("consumer_complaint_narrative", "!=", ""),
#         ("date_received", "==", "2022-12-01")])

feedback.shape

Am 01.12.2022 wurden etwa 1.000 Beschwerden eingereicht, verglichen mit fast 3,5 Millionen Zeilen in der Gesamtdatenbank (siehe feedback.shape).

Wählen Sie nur die Daten für den 01.12.2022 und nur die Spalte consumer_complaint_narrative aus.

import datetime

feedback = feedback[
    # Filter rows by passing in a boolean Series.
    (feedback["date_received"] == datetime.date(2022, 12, 1))
    & ~(feedback["date_received"].isnull())
    & ~(feedback["consumer_complaint_narrative"].isnull())
    & (feedback["consumer_complaint_narrative"] != "")
    & (feedback["state"] == "CA")

    # Uncomment the following if using free credits for a workshop.
    # Billing accounts with free credits have limited Vertex AI quota.
    # & (feedback["product"] == "Mortgage")
][
    # Filter columns by passing in a list of strings.
    ["consumer_complaint_narrative"]
]

feedback.shape

Für die Methode drop_duplicates von pandas ist eine vollständige Sortierung der Zeilen erforderlich, da entweder die erste oder die letzte übereinstimmende Zeile ausgewählt und der zugehörige Index beibehalten wird.

Aggregieren Sie stattdessen mit einem Aufruf der Methode groupby, um Zeilen zu deduplizieren.

feedback = (
  feedback.groupby("consumer_complaint_narrative", as_index=False)
  .size()
)[["consumer_complaint_narrative"]]

feedback.shape

Einbettungen generieren

BigQuery DataFrames generiert Einbettungsvektoren über die TextEmbeddingGenerator-Klasse. Dies basiert auf der ML.GENERATE_EMBEDDING-Methode in BigQuery ML, die die von Vertex AI bereitgestellten Texteinbettungsmodelle aufruft.

from bigframes.ml.llm import TextEmbeddingGenerator

embedding_model = TextEmbeddingGenerator(
    model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)

So sehen Einbettungen aus. Diese Vektoren stellen die semantische Bedeutung des Texts dar, wie sie vom Texteinbettungsmodell verstanden wird.

feedback_embeddings.peek()

Erwartete Ausgabe:

                        ml_generate_embedding_result  \
0  [ 7.36380890e-02  2.11779331e-03  2.54309829e-...   
1  [-1.10935252e-02 -5.53950183e-02  2.01338865e-...   
2  [-7.85628427e-03 -5.39347418e-02  4.51385677e-...   
3  [ 0.02013054 -0.0224789  -0.00164843  0.011354...   
4  [-1.51684484e-03 -5.02693094e-03  1.72322839e-...   

Diese Vektoren haben viele Dimensionen. Sehen Sie sich einen einzelnen Einbettungsvektor an:

feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]

Die Generierung von Embeddings erfolgt im Rahmen eines Vertrags mit „teilweisem Erfolg“. Das bedeutet, dass einige Zeilen möglicherweise Fehler enthalten und kein Einbettungsvektor generiert wird. Fehlermeldungen werden in der Spalte 'ml_generate_embedding_status' angezeigt. Ein leerer Wert bedeutet, dass keine Fehler vorliegen.

Filtern Sie die Einbettungen, sodass nur Zeilen ohne Fehler enthalten sind.

mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape

6. Clustering mit Texteinbettungen

Clustern Sie die Einbettungen jetzt mit dem k-Means-Algorithmus. Verwenden Sie für diese Demo eine beliebige Anzahl von Gruppen (auch als Zentroiden bezeichnet). Bei einer Lösung in Produktionsqualität sollte die Anzahl der Zentroiden mit einer Technik wie der Silhouettenmethode optimiert werden.

from bigframes.ml.cluster import KMeans

num_clusters = 5
cluster_model = KMeans(n_clusters=num_clusters)
cluster_model.fit(valid_embeddings["ml_generate_embedding_result"])
clusters = cluster_model.predict(valid_embeddings)
clusters.peek()

Entfernen Sie alle Einbettungsfehler.

mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]

Sehen Sie sich die Verteilung der Kommentare pro Schwerpunkt an.

clusters.groupby("CENTROID_ID").size()

7. Cluster zusammenfassen

Geben Sie einige Kommentare ein, die mit jedem Schwerpunkt verbunden sind, und bitten Sie Gemini, die Beschwerden zusammenzufassen. Prompt Engineering ist ein aufstrebendes Gebiet, aber es gibt gute Beispiele im Internet, z. B. unter https://www.promptingguide.ai/.

from bigframes.ml.llm import GeminiTextGenerator

preamble = "What is the main concern in this list of user complaints:"
suffix = "Write the main issue using a formal tone."

# Now let's sample the raw comments and get the LLM to summarize them.
prompts = []
for centroid_id in range(1, num_clusters + 1):
  cluster = clusters[clusters["CENTROID_ID"] == centroid_id]
  comments = "\n".join(["- {0}".format(x) for x in cluster.content.peek(40)])
  prompts.append("{}:\n{}\n{}".format(preamble, comments, suffix))

prompt_df = bpd.DataFrame(prompts)
gemini = GeminiTextGenerator(model_name="gemini-1.5-flash-001")
issues = gemini.predict(X=prompt_df, temperature=0.0)
issues.peek()

Mit Gemini einen Bericht aus den Zusammenfassungen erstellen

from IPython.display import display, Markdown

prompt = "Turn this list of issues into a short, concise report:"
for value in issues["ml_generate_text_llm_result"]:
  prompt += "- {}".format(value)
prompt += "Using a formal tone, write a markdown text format report."

summary_df = bpd.DataFrame(([prompt]))
summary = gemini.predict(X=summary_df, temperature=0.0)

report = (summary["ml_generate_text_llm_result"].values[0])
display(Markdown(report))

8. Bereinigen

Wenn Sie für diese Anleitung ein neues Google Cloud-Projekt erstellt haben, können Sie es löschen, um zusätzliche Gebühren für erstellte Tabellen oder andere Ressourcen zu vermeiden.

9. Glückwunsch!

Sie haben strukturierte und unstrukturierte Daten mit BigQuery DataFrames analysiert. Dabei haben Sie die öffentlichen Datasets von Google Cloud, Python-Notebooks in BigQuery Studio, BigQuery ML, Vertex AI und die Funktionen für die Umwandlung von natürlicher Sprache in Python in BigQuery Studio kennengelernt. Fantastisch!

Nächste Schritte