1. Visão geral
Neste laboratório, você vai usar os DataFrames do BigQuery em um notebook Python no BigQuery Studio para gerar insights com base nos dados usando Python. Use a IA generativa do Google para analisar e visualizar dados de texto não estruturados.
Você vai criar um notebook Python para categorizar e resumir um banco de dados público de reclamações de clientes. Isso pode ser adaptado para funcionar com qualquer dado de texto não estruturado.
Objetivos
Neste laboratório, você aprenderá a fazer o seguinte:
- Ativar e usar notebooks Python no BigQuery Studio
- Conectar-se ao BigQuery usando o pacote BigQuery DataFrames
- Criar embeddings de dados de texto não estruturados usando o BigQuery ML e a conexão com um endpoint de incorporação de texto na Vertex AI
- Criar agrupamentos usando o BigQuery ML
- Resumir clusters com um LLM pelo BigQuery ML
2. Requisitos
- Use um navegador, como o Chrome ou o Firefox.
- Tenha um projeto do Google Cloud com o faturamento ativado.
Antes de começar
Para seguir as instruções neste codelab, você vai precisar de um projeto do Google Cloud com o BigQuery Studio ativado e uma conta de faturamento conectada.
- No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.
- Verifique se o faturamento está ativado para seu projeto do Google Cloud. Saiba como verificar se o faturamento está ativado em um projeto.
- Siga as instruções para Ativar o BigQuery Studio para gerenciamento de recursos.
Preparar o BigQuery Studio
Crie um notebook vazio e conecte-o a um ambiente de execução.
- Acesse o BigQuery Studio no console do Google Cloud.
- Clique no ▼ ao lado do botão +.
- Selecione Notebook Python.
- Feche o seletor de modelos.
- Selecione + Código para criar uma nova célula de código.
- Instale a versão mais recente do pacote BigQuery DataFrames na célula de código.Digite o comando a seguir.
Clique no botão 🞂 ou pressione Shift + Enter para executar a célula de código.%pip install --upgrade bigframes --quiet
3. Ler um conjunto de dados público
Inicie o pacote BigQuery DataFrames executando o seguinte em uma nova célula de código:
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
Observação: neste tutorial, usamos o "modo de ordenação parcial" experimental, que permite consultas mais eficientes quando usado com a filtragem semelhante ao pandas. Alguns recursos do pandas que exigem uma ordenação ou um índice rígido podem não funcionar.
Banco de dados de reclamações do consumidor
O banco de dados de reclamações do consumidor é fornecido no BigQuery pelo Programa de conjuntos de dados públicos do Google Cloud. Esta é uma coleção de reclamações sobre produtos e serviços financeiros do consumidor, e os dados são coletados pelo Departamento de Proteção Financeira ao Consumidor dos Estados Unidos.
No BigQuery, consulte a tabela bigquery-public-data.cfbp_complaints.complaint_database para analisar o banco de dados de reclamações do consumidor. Use o método bigframes.pandas.read_gbq()
para criar um DataFrame com base em uma string de consulta ou um ID de tabela.
Execute o seguinte em uma nova célula de código para criar um DataFrame chamado "feedback":
feedback = bpd.read_gbq(
"bigquery-public-data.cfpb_complaints.complaint_database"
)
Descobrir informações básicas sobre um DataFrame
Use o método DataFrame.peek()
para fazer o download de uma pequena amostra dos dados.
Execute esta célula:
feedback.peek()
Saída esperada:
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
Observação: head()
exige ordenação e geralmente é menos eficiente do que peek()
se você quiser visualizar uma amostra de dados.
Assim como no pandas, use a propriedade DataFrame.dtypes
para conferir todas as colunas disponíveis e os tipos de dados correspondentes. Eles são expostos de maneira compatível com pandas.
Execute esta célula:
feedback.dtypes
Saída esperada:
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
O método DataFrame.describe()
consulta algumas estatísticas básicas do DataFrame. Como esse DataFrame não contém colunas numéricas, ele mostra um resumo da contagem de valores não nulos e do número de valores distintos.
Execute esta célula:
# 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()
Saída esperada:
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. Como analisar os dados
Antes de analisar as reclamações reais, use os métodos semelhantes aos do pandas no DataFrame para visualizar os dados.
Visualizar o DataFrame
Há vários métodos de visualização integrados, como DataFrame.plot.hist(). Como esse DataFrame contém principalmente dados de string e booleano, podemos fazer algumas agregações para saber mais sobre as várias colunas.
Conte quantas reclamações são recebidas de cada estado.
complaints_by_state = (
feedback.groupby(
"state", as_index=False,
).size()
.rename(columns={"size": "total_complaints"})
.sort_values(by="total_complaints", ascending=False)
)
Converta isso em um DataFrame do pandas usando o método DataFrame.to_pandas()
.
complaints_pd = complaints_by_state.head(10).to_pandas()
Use os métodos de visualização do Pandas neste DataFrame transferido.
complaints_pd.plot.bar(x="state", y="total_complaints")
Mesclar com outros conjuntos de dados
Antes, você analisou as reclamações por estado, mas isso perde o contexto importante. Alguns estados têm populações maiores do que outros. Faça uma mesclagem com um conjunto de dados populacionais, como a Pesquisa da Comunidade Americana do Escritório do Censo dos EUA e a tabela 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")
)
A Pesquisa Comunitária Americana identifica os estados por GEOID. Faça a mesclagem com a tabela de estados para conferir a população por código de estado de duas letras.
pops = us_states.set_index("geo_id")[["state"]].join(
us_survey.set_index("geo_id")[["total_pop"]]
)
Agora, una isso ao banco de dados de reclamações para comparar a população com o número de reclamações.
complaints_and_pops = complaints_by_state.set_index("state").join(
pops.set_index("state")
)
Crie um diagrama de dispersão para comparar as populações dos estados com o número de reclamações.
(
complaints_and_pops
.to_pandas()
.plot.scatter(x="total_pop", y="total_complaints")
)
Alguns estados parecem ser valores discrepantes quando comparamos a população com o número de reclamações. Deixamos como exercício para o leitor plotar com rótulos de pontos para identificá-los. Da mesma forma, crie algumas hipóteses sobre por que isso pode estar acontecendo (por exemplo, diferentes dados demográficos, diferentes números de empresas de serviços financeiros etc.) e teste-as.
5. Calcular embeddings
Muitas vezes, informações importantes ficam ocultas em dados não estruturados, como texto, áudio ou imagens. Neste exemplo, muitas das informações úteis no banco de dados de reclamações estão no conteúdo de texto da reclamação.
A IA e as técnicas tradicionais, como a análise de sentimento, o "bag of words" e o word2vec, podem extrair algumas informações quantitativas de dados não estruturados. Mais recentemente, os modelos de "embedding de vetor", que são intimamente relacionados aos LLMs, podem criar uma sequência de números de ponto flutuante que representam as informações semânticas do texto.
Selecionar um subconjunto do banco de dados
A execução de um modelo de embedding de vetor usa mais recursos do que outras operações. Para reduzir custos e problemas de cota, selecione um subconjunto dos dados para o restante deste 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
Há cerca de 1.000 reclamações enviadas em 01/12/2022 em comparação com quase 3,5 milhões de linhas no banco de dados total (confira com feedback.shape
).
Selecione apenas os dados de 01/12/2022 e apenas a coluna 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
O método drop_duplicates
do pandas exige uma ordenação total das linhas porque tenta selecionar a primeira ou a última linha correspondente e preservar o índice associado a ela.
Em vez disso, faça a agregação com uma chamada para o método groupby
para remover duplicações de linhas.
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
Gerar embeddings
Os DataFrames do BigQuery geram vetores de incorporação usando a classe TextEmbeddingGenerator. Isso é baseado no método ML.GENERATE_EMBEDDING
, no BigQuery ML, que chama os modelos de incorporação de texto fornecidos pela Vertex AI.
from bigframes.ml.llm import TextEmbeddingGenerator
embedding_model = TextEmbeddingGenerator(
model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)
Confira como são as embeddings. Esses vetores representam o significado semântico do texto conforme é entendido pelo modelo de embedding de texto.
feedback_embeddings.peek()
Saída esperada:
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-...
Esses vetores têm muitas dimensões. Confira um único vetor de incorporação:
feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]
A geração de incorporações funciona com um contrato de "sucesso parcial". Isso significa que algumas linhas podem ter erros e não gerar uma incorporação. As mensagens de erro são expostas pela coluna 'ml_generate_embedding_status'
. Vazio significa que não há erros.
Filtre as inclusões para incluir apenas linhas em que não ocorreu nenhum erro.
mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape
6. Criar clusters usando embeddings de texto
Agora, faça a clusterização das embeddings usando k-means. Para esta demonstração, use um número arbitrário de grupos (ou centroides). Uma solução de qualidade de produção precisa ajustar o número de centroides usando uma técnica, como o método de silhueta.
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()
Remova todos os erros de incorporação.
mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]
Confira a distribuição de comentários por centroide.
clusters.groupby("CENTROID_ID").size()
7. Resumir os clusters
Forneça alguns comentários associados a cada centroide e peça para o Gemini resumir as reclamações. A engenharia de comando é uma área emergente, mas há bons exemplos na Internet, como 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()
Use o Gemini para criar um relatório com base nos resumos.
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. Limpar
Se você criou um projeto do Google Cloud para este tutorial, exclua-o para evitar cobranças adicionais de tabelas ou outros recursos criados.
9. Parabéns!
Você analisou dados estruturados e não estruturados usando DataFrames do BigQuery. No caminho, você conheceu os Conjuntos de dados públicos do Google Cloud, os notebooks Python no BigQuery Studio, o BigQuery ML, a Vertex AI e os recursos de linguagem natural para Python do BigQuery Studio. Ótimo trabalho!
Próximas etapas
- Tente gerar código Python no seu notebook. Os notebooks Python no BigQuery Studio são fornecidos pelo Colab Enterprise. Dica: acho que pedir ajuda para gerar dados de teste é muito útil.
- Confira os notebooks de exemplo para DataFrames do BigQuery no GitHub.
- Crie uma programação para executar um notebook no BigQuery Studio.
- Implante uma função remota com DataFrames do BigQuery para integrar pacotes de terceiros do Python ao BigQuery.