1. Descripción general
En este lab, usarás BigQuery DataFrames desde un notebook de Python en BigQuery Studio para obtener estadísticas a partir de datos con Python. Usa la IA generativa de Google para analizar y visualizar datos de texto no estructurado.
Crearás un notebook de Python para categorizar y resumir una base de datos pública de quejas de clientes. Esto se puede adaptar para funcionar en cualquier dato de texto no estructurado.
Objetivos
En este lab, aprenderás a realizar las siguientes tareas:
- Activa y usa notebooks de Python en BigQuery Studio
- Conéctate a BigQuery con el paquete BigQuery DataFrames
- Crea incorporaciones a partir de datos de texto no estructurados con BigQuery ML y la conexión a un extremo de incorporación de texto en Vertex AI
- Cómo usar las incorporaciones de clústeres con BigQuery ML
- Resume clústeres con un LLM a través de BigQuery ML
2. Requisitos
Antes de comenzar
Para seguir las instrucciones de este codelab, necesitarás un proyecto de Google Cloud con BigQuery Studio habilitado y una cuenta de facturación conectada.
- En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.
- Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud. Obtén información para verificar si la facturación está habilitada en un proyecto.
- Sigue las instrucciones para habilitar BigQuery Studio para la administración de recursos.
Prepara BigQuery Studio
Crea un notebook vacío y conéctalo a un entorno de ejecución.
- Ve a BigQuery Studio en la consola de Google Cloud.
- Haz clic en el ▼ junto al botón +.
- Selecciona Notebook de Python.
- Cierra el selector de plantillas.
- Selecciona + Código para crear una celda de código nueva.
- Instala la versión más reciente del paquete BigQuery DataFrames desde la celda de código.Escribe el siguiente comando.
Haz clic en el botón 🞂 o presiona Mayúsculas + Intro para ejecutar la celda de código.%pip install --upgrade bigframes --quiet
3. Lee un conjunto de datos públicos
Para inicializar el paquete BigQuery DataFrames, ejecuta lo siguiente en una celda de código nueva:
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
Nota: En este instructivo, usamos el "modo de ordenamiento parcial" experimental, que permite realizar consultas más eficientes cuando se usa con un filtrado similar al de pandas. Es posible que algunas funciones de pandas que requieren un orden o un índice estrictos no funcionen.
Base de datos de reclamos de consumidores
La base de datos de quejas de consumidores se proporciona en BigQuery a través del programa de conjuntos de datos públicos de Google Cloud. Esta es una recopilación de quejas sobre productos y servicios financieros para consumidores, y los datos los recopila la Oficina de Protección Financiera del Consumidor de Estados Unidos.
En BigQuery, consulta la tabla bigquery-public-data.cfbp_complaints.complaint_database para analizar la base de datos de quejas de consumidores. Usa el método bigframes.pandas.read_gbq()
para crear un DataFrame a partir de una cadena de consulta o un ID de tabla.
Ejecuta lo siguiente en una celda de código nueva para crear un DataFrame llamado “comentarios”:
feedback = bpd.read_gbq(
"bigquery-public-data.cfpb_complaints.complaint_database"
)
Descubre información básica sobre un DataFrame
Usa el método DataFrame.peek()
para descargar una pequeña muestra de los datos.
Ejecuta esta celda:
feedback.peek()
Resultado esperado:
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()
requiere orden y, por lo general, es menos eficiente que peek()
si deseas visualizar una muestra de datos.
Al igual que con pandas, usa la propiedad DataFrame.dtypes
para ver todas las columnas disponibles y sus tipos de datos correspondientes. Se exponen de una manera compatible con pandas.
Ejecuta esta celda:
feedback.dtypes
Resultado esperado:
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
El método DataFrame.describe()
consulta algunas estadísticas básicas del DataFrame. Como este DataFrame no contiene columnas numéricas, muestra un resumen del recuento de valores no nulos y la cantidad de valores distintos.
Ejecuta esta celda:
# 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()
Resultado esperado:
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. Cómo explorar los datos
Antes de analizar las quejas reales, usa los métodos similares a Pandas en el DataFrame para visualizar los datos.
Visualiza el DataFrame
Existen varios métodos de visualización integrados, como DataFrame.plot.hist(). Dado que este DataFrame contiene principalmente datos de cadenas y booleanos, primero podemos realizar una agregación para obtener más información sobre varias columnas.
Cuenta cuántas quejas se reciben 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)
)
Convierte esto en un DataFrame de Pandas con el método DataFrame.to_pandas()
.
complaints_pd = complaints_by_state.head(10).to_pandas()
Usa los métodos de visualización de Pandas en este DataFrame descargado.
complaints_pd.plot.bar(x="state", y="total_complaints")
Cómo unir con otros conjuntos de datos
Anteriormente, analizaste las quejas por estado, pero esto pierde contexto importante. Algunos estados tienen poblaciones más grandes que otros. Únete a un conjunto de datos de población, como la Encuesta sobre la comunidad estadounidense de la Oficina de Censos de EE.UU. y la tabla 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")
)
La Encuesta sobre la comunidad estadounidense identifica los estados por GEOID. Únete a la tabla de estados para obtener la población por código de estado de dos letras.
pops = us_states.set_index("geo_id")[["state"]].join(
us_survey.set_index("geo_id")[["total_pop"]]
)
Ahora, únete a la base de datos de reclamos para comparar la población con la cantidad de reclamos.
complaints_and_pops = complaints_by_state.set_index("state").join(
pops.set_index("state")
)
Crea un diagrama de dispersión para comparar las poblaciones estatales con la cantidad de reclamos.
(
complaints_and_pops
.to_pandas()
.plot.scatter(x="total_pop", y="total_complaints")
)
Algunos estados parecen ser valores atípicos cuando se compara la población con la cantidad de reclamos. Se deja como ejercicio para que el lector los grafique con etiquetas de punto para identificarlos. Del mismo modo, plantea algunas hipótesis sobre por qué podría ser así (p.ej., diferentes datos demográficos, diferente cantidad de empresas de servicios financieros, etc.) y pruébalas.
5. Cómo calcular las incorporaciones
A menudo, la información importante se oculta en datos no estructurados, como texto, audio o imágenes. En este ejemplo, gran parte de la información útil de la base de datos de reclamos se encuentra en el contenido de texto de la queja.
La IA y las técnicas tradicionales, como el análisis de sentimientos, el "bag of words" y word2vec, pueden extraer algunos datos cuantitativos de información no estructurados. Más recientemente, los modelos de "incorporación vectorial", que están estrechamente relacionados con los LLM, pueden crear una secuencia de números de punto flotante que representan la información semántica del texto.
Selecciona un subconjunto de la base de datos
Ejecutar un modelo de incorporación de vectores usa más recursos que otras operaciones. Para reducir los costos y los problemas de cuota, selecciona un subconjunto de los datos para el resto de este instructivo.
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
Hay alrededor de 1,000 reclamos enviados el 01/12/2022 en comparación con casi 3.5 millones de filas en la base de datos total (consulta con feedback.shape
).
Selecciona solo los datos del 1 de diciembre de 2022 y solo la columna 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
El método drop_duplicates
de pandas requiere un ordenamiento total de las filas porque intenta seleccionar la primera o la última fila coincidente y preservar el índice asociado con ella.
En su lugar, realiza una llamada al método groupby
para anular las filas duplicadas.
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
Genera embeddings
BigQuery DataFrames genera vectores de incorporación a través de la clase TextEmbeddingGenerator. Esto se basa en el método ML.GENERATE_EMBEDDING
, en BigQuery ML, que llama a los modelos de incorporación de texto que proporciona Vertex AI.
from bigframes.ml.llm import TextEmbeddingGenerator
embedding_model = TextEmbeddingGenerator(
model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)
Observa cómo se ven las incorporaciones. Estos vectores representan el significado semántico del texto tal como lo entiende el modelo de incorporación de texto.
feedback_embeddings.peek()
Resultado esperado:
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-...
Estos vectores tienen muchas dimensiones. Observa un solo vector de embedding:
feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]
La generación de incorporaciones funciona bajo un contrato de "éxito parcial". Esto significa que algunas filas pueden tener errores y no generar una incorporación. La columna 'ml_generate_embedding_status'
expone los mensajes de error. Si está vacío, significa que no hay errores.
Filtra las incorporaciones para incluir solo las filas en las que no se produjo ningún error.
mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape
6. Cómo crear clústeres con incorporaciones de texto
Ahora, agrupa las incorporaciones con k-means. Para esta demostración, usa una cantidad arbitraria de grupos (también conocidos como centroides). Una solución de calidad de producción debe ajustar la cantidad de centroides con una técnica como el método 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()
Quita los errores de incorporación.
mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]
Consulta la distribución de los comentarios por centroide.
clusters.groupby("CENTROID_ID").size()
7. Resume los clústeres
Agrega algunos comentarios asociados con cada centroide y pídele a Gemini que resuma las quejas. La ingeniería de instrucciones es un área emergente, pero hay buenos ejemplos en 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()
Usa Gemini para escribir un informe a partir de los resúmenes.
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. Limpia
Si creaste un proyecto de Google Cloud nuevo para este instructivo, puedes borrarlo para evitar cargos adicionales por las tablas o los demás recursos que creaste.
9. ¡Felicitaciones!
Analizaste datos estructurados y no estructurados con BigQuery DataFrames. A lo largo del camino, exploraste los conjuntos de datos públicos de Google Cloud, los notebooks de Python en BigQuery Studio, BigQuery ML, Vertex AI y las funciones de lenguaje natural a Python de BigQuery Studio. ¡Gran trabajo!
Próximos pasos
- Intenta generar código de Python en tu notebook. Los notebooks de Python en BigQuery Studio se ejecutan con Colab Enterprise. Sugerencia: Pídele ayuda para generar datos de prueba.
- Explora los notebooks de muestra de BigQuery DataFrames en GitHub.
- Crear un programa para ejecutar un notebook en BigQuery Studio
- Implementa una función remota con BigQuery DataFrames para integrar paquetes de Python de terceros con BigQuery.