1. Visão geral
Neste laboratório, você vai usar o BigQuery DataFrames de um notebook Python no BigQuery Studio para extrair insights dos 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 embedding de texto na Vertex AI
- Agrupar embeddings usando o BigQuery ML
- Resumir clusters com um LLM usando o 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 deste 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 de seletor de projetos, selecione ou crie um projeto do Google Cloud.
- Verifique se o faturamento está ativado para o 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 em ▼ ao lado do botão +.
- Selecione Notebook Python.
- Feche o seletor de modelos.
- Selecione + Código para criar uma célula de código.
- Instale a versão mais recente do pacote BigQuery DataFrames na célula de código. Digite o seguinte comando:
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
Inicialize o pacote do 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 filtragem semelhante ao pandas. Alguns recursos do pandas que exigem uma ordenação ou um índice estrito podem não funcionar.
Banco de dados de reclamações de consumidores
O Consumer Complaint Database (em inglês) é fornecido no BigQuery pelo Programa de conjuntos de dados públicos do Google Cloud. É uma coleção de reclamações sobre produtos e serviços financeiros para consumidores. Os dados são coletados pelo Consumer Financial Protection Bureau (CFPB, na sigla em inglês) dos Estados Unidos.
No BigQuery, consulte a tabela bigquery-public-data.cfbp_complaints.complaint_database para analisar o banco de dados de reclamações dos consumidores. 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 baixar uma pequena amostra dos dados.
Execute esta célula:
feedback.peek()
Resposta 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
Resposta 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()
Resposta 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 ao 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 booleanos, podemos primeiro fazer alguma agregação para saber mais sobre 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 métodos de visualização do pandas no DataFrame baixado.
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 um contexto importante. Alguns estados têm populações maiores que outros. Faça uma junção com um conjunto de dados de população, como a Pesquisa da Comunidade Americana do Bureau 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 da Comunidade Americana identifica os estados por GEOID. Faça uma junção com a tabela de estados para receber 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, junte 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 gráfico 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 outliers ao comparar a população com o número de reclamações. O leitor pode fazer um exercício para criar um gráfico com rótulos de pontos e identificar esses valores. Da mesma forma, crie algumas hipóteses sobre por que isso pode acontecer (por exemplo, diferentes dados demográficos, número diferente 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, grande parte das informações úteis no banco de dados de reclamações está contida no conteúdo de texto da reclamação.
A IA e as técnicas tradicionais, como análise de sentimentos, "saco de palavras" e word2vec, podem extrair algumas informações quantitativas de dados não estruturados. Mais recentemente, os modelos de "embedding de vetor", que estã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
Executar 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 denúncias 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 2022-12-01 e 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, agregue com uma chamada ao método groupby para remover linhas duplicadas.
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
Gerar embeddings
Os DataFrames do BigQuery geram vetores de embeddings usando a classe TextEmbeddingGenerator. Isso se baseia no método ML.GENERATE_EMBEDDING no BigQuery ML, que chama os embeddings 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 os embeddings. Esses vetores representam o significado semântico do texto conforme entendido pelo modelo de embedding de texto.
feedback_embeddings.peek()
Resposta 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 embedding:
feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]
A geração de incorporações opera sob 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 os encodings para incluir apenas as linhas em que nenhum erro ocorreu.
mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape
6. Agrupar usando embeddings de texto
Agora, agrupe os embeddings usando k-means. Para esta demonstração, use um número arbitrário de grupos (ou seja, 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 as falhas 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 ao Gemini para resumir as reclamações. A engenharia de comandos é uma área emergente, mas há bons exemplos na Internet, como https://www.promptingguide.ai/ (em inglês).
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()
Usar o Gemini para escrever 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 na nuvem do Google para este tutorial, exclua-o para evitar cobranças extras por tabelas ou outros recursos criados.
9. Parabéns!
Você analisou dados estruturados e não estruturados usando BigQuery DataFrames. Ao longo do 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 desenvolvidos pelo Colab Enterprise. Dica: acho muito útil pedir ajuda para gerar dados de teste.
- Confira os notebooks de exemplo do BigQuery DataFrames no GitHub.
- Crie um cronograma para executar um notebook no BigQuery Studio.
- Implante uma função remota com o BigQuery DataFrames para integrar pacotes Python de terceiros ao BigQuery.