1. Panoramica
In questo lab utilizzerai BigQuery DataFrames da un notebook Python in BigQuery Studio per ottenere informazioni dai dati utilizzando Python. Utilizza l'IA generativa di Google per analizzare e visualizzare i dati di testo non strutturato.
Creerai un notebook Python per classificare e riepilogare un database pubblico dei reclami dei clienti. Questo approccio può essere adattato per funzionare su qualsiasi dato di testo non strutturato.
Obiettivi
In questo lab imparerai a:
- Attivare e utilizzare i notebook Python in BigQuery Studio
- Connettiti a BigQuery utilizzando il pacchetto BigQuery DataFrames
- Creare embedding da dati di testo non strutturati utilizzando BigQuery ML e la connessione a un endpoint di embedding di testo in Vertex AI
- Embedding di cluster utilizzando BigQuery ML
- Riepilogare i cluster con un LLM tramite BigQuery ML
2. Requisiti
Prima di iniziare
Per seguire le istruzioni di questo codelab, devi disporre di un progetto Google Cloud con BigQuery Studio abilitato e di un account di fatturazione collegato.
- Nella console Google Cloud, nella pagina di selezione del progetto, seleziona o crea un progetto Google Cloud
- Verifica che la fatturazione sia attivata per il tuo progetto Google Cloud. Scopri come verificare se la fatturazione è abilitata in un progetto
- Segui le istruzioni per abilitare BigQuery Studio per la gestione degli asset.
Prepara BigQuery Studio
Crea un blocco note vuoto e connettilo a un runtime.
- Vai a BigQuery Studio nella console Google Cloud.
- Fai clic sul pulsante ▼ accanto al pulsante +.
- Seleziona Blocco note Python.
- Chiudi il selettore dei modelli.
- Seleziona + Codice per creare una nuova cella di codice.
- Installa la versione più recente del pacchetto BigQuery DataFrames dalla cella di codice.Digita il seguente comando.
Fai clic sul pulsante 🞂 o premi Maiusc + Invio per eseguire la cella di codice.%pip install --upgrade bigframes --quiet
3. Leggere un set di dati pubblico
Inizializza il pacchetto BigQuery DataFrames eseguendo il seguente codice in una nuova cella di codice:
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
Nota: in questo tutorial utilizziamo la "modalità di ordinamento parziale" sperimentale, che consente query più efficienti se utilizzata con il filtro simile a pandas. Alcune funzionalità di pandas che richiedono un ordinamento o un indice rigoroso potrebbero non funzionare.
Consumer Complaint Database
Il database dei reclami dei consumatori è fornito su BigQuery tramite il programma per i set di dati pubblici di Google Cloud. Si tratta di una raccolta di reclami relativi a prodotti e servizi finanziari per i consumatori e i dati vengono raccolti dal Consumer Financial Protection Bureau degli Stati Uniti.
In BigQuery, esegui una query sulla tabella bigquery-public-data.cfbp_complaints.complaint_database per analizzare il database dei reclami dei consumatori. Utilizza il metodo bigframes.pandas.read_gbq()
per creare un DataFrame da una stringa di query o dall'ID tabella.
Esegui il seguente codice in una nuova cella di codice per creare un DataFrame denominato "feedback":
feedback = bpd.read_gbq(
"bigquery-public-data.cfpb_complaints.complaint_database"
)
Scopri informazioni di base su un DataFrame
Utilizza il metodo DataFrame.peek()
per scaricare un piccolo campione di dati.
Esegui questa cella:
feedback.peek()
Output previsto:
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
Nota: head()
richiede l'ordinamento ed è in genere meno efficiente di peek()
se vuoi visualizzare un campione di dati.
Come per pandas, utilizza la proprietà DataFrame.dtypes
per visualizzare tutte le colonne disponibili e i relativi tipi di dati corrispondenti. Questi sono esposti in modo compatibile con pandas.
Esegui questa cella:
feedback.dtypes
Output previsto:
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
Il metodo DataFrame.describe()
esegue query su alcune statistiche di base del DataFrame. Poiché questo DataFrame non contiene colonne numeriche, mostra un riepilogo del conteggio dei valori non null e del numero di valori distinti.
Esegui questa cella:
# 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()
Output previsto:
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. Esplorazione dei dati
Prima di esaminare i reclami effettivi, utilizza i metodi simili a Pandas nel DataFrame per visualizzare i dati.
Visualizza il DataFrame
Esistono diversi metodi di visualizzazione integrati, come DataFrame.plot.hist(). Poiché questo DataFrame contiene principalmente dati di stringa e booleani, possiamo prima eseguire alcune aggregazioni per saperne di più sulle varie colonne.
Conta il numero di reclami ricevuti da ogni stato.
complaints_by_state = (
feedback.groupby(
"state", as_index=False,
).size()
.rename(columns={"size": "total_complaints"})
.sort_values(by="total_complaints", ascending=False)
)
Convertilo in un DataFrame Pandas utilizzando il metodo DataFrame.to_pandas()
.
complaints_pd = complaints_by_state.head(10).to_pandas()
Utilizza i metodi di visualizzazione di Pandas su questo DataFrame scaricato.
complaints_pd.plot.bar(x="state", y="total_complaints")
Eseguire l'unione con altri set di dati
In precedenza, esaminavi i reclami per stato, ma questo approccio non tiene conto di un contesto importante. Alcuni stati hanno una popolazione più grande di altri. Esegui l'unione con un set di dati sulla popolazione, ad esempio l'American Community Survey del Census Bureau degli Stati Uniti e la tabella bigquery-public-data.geo_us_boundaries.states
.
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")
)
L'American Community Survey identifica gli stati tramite GEOID. Esegui l'unione con la tabella degli stati per ottenere la popolazione in base al codice di stato di due lettere.
pops = us_states.set_index("geo_id")[["state"]].join(
us_survey.set_index("geo_id")[["total_pop"]]
)
Ora unisci questa tabella al database dei reclami per confrontare la popolazione con il numero di reclami.
complaints_and_pops = complaints_by_state.set_index("state").join(
pops.set_index("state")
)
Crea un grafico a dispersione per confrontare la popolazione degli stati con il numero di reclami.
(
complaints_and_pops
.to_pandas()
.plot.scatter(x="total_pop", y="total_complaints")
)
Un paio di stati sembrano essere valori anomali se si confronta la popolazione con il numero di reclami. Lasciamo al lettore il compito di tracciare i punti con le etichette per identificarli. Allo stesso modo, formula alcune ipotesi sul perché potrebbe essere così (ad es. dati demografici diversi, numero diverso di società di servizi finanziari e così via) e testale.
5. Calcola gli incorporamenti
Spesso le informazioni importanti sono nascoste in dati non strutturati, come testo, audio o immagini. In questo esempio, molte delle informazioni utili nel database dei reclami sono contenute nel testo del reclamo.
L'AI e le tecniche tradizionali, come l'analisi del sentiment, il "bag of words" e word2vec, possono estrarre alcune informazioni quantitative dai dati non strutturati. Più di recente, i modelli di "embedding vettoriale", strettamente correlati agli LLM, possono creare una sequenza di numeri in virgola mobile che rappresentano le informazioni semantiche del testo.
Seleziona un sottoinsieme del database
L'esecuzione di un modello di incorporamento vettoriale utilizza più risorse rispetto ad altre operazioni. Per ridurre i costi e i problemi di quota, seleziona un sottoinsieme di dati per il resto di questo tutorial.
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
Il 1° dicembre 2022 sono stati inviati circa 1000 reclami rispetto ai quasi 3,5 milioni di righe nel database totale (controlla con feedback.shape
).
Seleziona solo i dati relativi al 01-12-2022 e solo la colonna consumer_complaint_narrative
.
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
Il metodo drop_duplicates
di pandas richiede un ordinamento totale delle righe perché tenta di selezionare la prima o l'ultima riga corrispondente e di conservare l'indice associato.
Esegui l'aggregazione con una chiamata al metodo groupby
per deduplicare le righe.
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
Genera embedding
I DataFrame di BigQuery generano vettori di embedding tramite la classe TextEmbeddingGenerator. Si basa sul metodo ML.GENERATE_EMBEDDING
in BigQuery ML, che chiama i modelli di embedding del testo forniti da Vertex AI.
from bigframes.ml.llm import TextEmbeddingGenerator
embedding_model = TextEmbeddingGenerator(
model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)
Dai un'occhiata a come sono fatti gli embedding. Questi vettori rappresentano il significato semantico del testo così come è compreso dal modello di embedding del testo.
feedback_embeddings.peek()
Output previsto:
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-...
Questi vettori hanno molte dimensioni. Dai un'occhiata a un singolo vettore di incorporamento:
feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]
La generazione di embedding avviene in base a un contratto di "successo parziale". Ciò significa che alcune righe potrebbero contenere errori e non generare un'evidenziazione. I messaggi di errore vengono visualizzati nella colonna 'ml_generate_embedding_status'
. Vuoto significa che non sono presenti errori.
Filtra le istanze incorporate in modo da includere solo le righe in cui non si è verificato alcun errore.
mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape
6. Cluster utilizzando gli incorporamenti di testo
Ora raggruppa le rappresentazioni distribuite utilizzando k-means. Per questa demo, utilizza un numero arbitrario di gruppi (noti anche come centroidi). Una soluzione di qualità di produzione deve ottimizzare il numero di centroidi utilizzando una tecnica come il metodo Silhouette.
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()
Rimuovi eventuali errori di incorporamento.
mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]
Dai un'occhiata e scopri la distribuzione dei commenti per centroide.
clusters.groupby("CENTROID_ID").size()
7. Riepiloga i cluster
Inserisci alcuni commenti associati a ciascun centroide e chiedi a Gemini di riassumere i reclami. Il prompt engineering è un'area emergente, ma esistono buoni esempi su internet, come 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()
Utilizza Gemini per scrivere un report dai riepiloghi.
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. Esegui la pulizia
Se hai creato un nuovo progetto Google Cloud per questo tutorial, puoi eliminarlo per evitare addebiti aggiuntivi per le tabelle o altre risorse create.
9. Complimenti!
Hai analizzato dati strutturati e non strutturati utilizzando BigQuery DataFrames. Lungo il percorso, hai esplorato i set di dati pubblici di Google Cloud, i notebook Python in BigQuery Studio, BigQuery ML, Vertex AI e le funzionalità di BigQuery Studio per il passaggio dal linguaggio naturale a Python. Ottimo lavoro.
Passaggi successivi
- Prova a generare codice Python nel tuo notebook. I notebook Python in BigQuery Studio sono basati su Colab Enterprise. Suggerimento: trovo molto utile chiedere aiuto per la generazione dei dati di test.
- Esplora i notebook di esempio per BigQuery DataFrames su GitHub.
- Crea una pianificazione per eseguire un blocco note in BigQuery Studio.
- Esegui il deployment di una funzione remota con BigQuery DataFrames per integrare i pacchetti Python di terze parti con BigQuery.