1. Présentation
Dans cet atelier, vous allez utiliser BigQuery DataFrames à partir d'un notebook Python dans BigQuery Studio pour obtenir des insights à partir de données à l'aide de Python. Utilisez l'IA générative de Google pour analyser et visualiser les données textuelles non structurées.
Vous allez créer un notebook Python pour catégoriser et résumer une base de données publique de réclamations de clients. Vous pouvez l'adapter à n'importe quelle donnée textuelle non structurée.
Objectifs
Dans cet atelier, vous allez apprendre à effectuer les tâches suivantes :
- Activer et utiliser des notebooks Python dans BigQuery Studio
- Se connecter à BigQuery à l'aide du package BigQuery DataFrames
- Créer des embeddings à partir de données textuelles non structurées à l'aide de BigQuery ML et d'une connexion à un point de terminaison d'embedding de texte dans Vertex AI
- Ensembles d'engrammes de cluster à l'aide de BigQuery ML
- Résumer des clusters avec un LLM via BigQuery ML
2. Conditions requises
Avant de commencer
Pour suivre les instructions de cet atelier de programmation, vous aurez besoin d'un projet Google Cloud dans lequel BigQuery Studio est activé et d'un compte de facturation associé.
- Dans la console Google Cloud, sur la page du sélecteur de projet, sélectionnez ou créez un projet Google Cloud.
- Assurez-vous que la facturation est activée pour votre projet Google Cloud. Découvrez comment vérifier si la facturation est activée sur un projet.
- Suivez les instructions pour activer BigQuery Studio pour la gestion des éléments.
Préparer BigQuery Studio
Créez un notebook vide et associez-le à un environnement d'exécution.
- Accédez à BigQuery Studio dans la console Google Cloud.
- Cliquez sur le bouton ▼ à côté du bouton +.
- Sélectionnez Notebook Python.
- Fermez le sélecteur de modèle.
- Sélectionnez + Code pour créer une cellule de code.
- Installez la dernière version du package BigQuery DataFrames à partir de la cellule de code.Saisissez la commande suivante.
Cliquez sur le bouton 🞂 ou appuyez sur Maj+Entrée pour exécuter la cellule de code.%pip install --upgrade bigframes --quiet
3. Lire un ensemble de données public
Initialisez le package BigQuery DataFrames en exécutant le code suivant dans une nouvelle cellule de code:
import bigframes.pandas as bpd
bpd.options.bigquery.ordering_mode = "partial"
Remarque: dans ce tutoriel, nous utilisons le mode d'ordonnancement partiel expérimental, qui permet d'effectuer des requêtes plus efficaces lorsqu'il est utilisé avec un filtrage semblable à celui de pandas. Certaines fonctionnalités pandas qui nécessitent un tri ou un indice stricts peuvent ne pas fonctionner.
Base de données des réclamations des consommateurs
La base de données des réclamations des consommateurs est disponible dans BigQuery via le programme d'ensembles de données publics de Google Cloud. Il s'agit d'un ensemble de plaintes concernant les produits et services financiers destinés aux consommateurs. Les données sont collectées par le Consumer Financial Protection Bureau des États-Unis.
Dans BigQuery, interrogez la table bigquery-public-data.cfbp_complaints.complaint_database pour analyser la base de données des réclamations des consommateurs. Utilisez la méthode bigframes.pandas.read_gbq()
pour créer un DataFrame à partir d'une chaîne de requête ou d'un ID de table.
Exécutez le code suivant dans une nouvelle cellule de code pour créer un DataFrame nommé "feedback":
feedback = bpd.read_gbq(
"bigquery-public-data.cfpb_complaints.complaint_database"
)
Découvrir des informations de base sur un DataFrame
Utilisez la méthode DataFrame.peek()
pour télécharger un petit échantillon des données.
Exécutez cette cellule:
feedback.peek()
Résultat attendu :
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
Remarque: head()
nécessite un tri et est généralement moins efficace que peek()
si vous souhaitez visualiser un échantillon de données.
Tout comme avec pandas, utilisez la propriété DataFrame.dtypes
pour afficher toutes les colonnes disponibles et les types de données correspondants. Ils sont exposés de manière compatible avec pandas.
Exécutez cette cellule:
feedback.dtypes
Résultat attendu :
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
La méthode DataFrame.describe()
interroge certaines statistiques de base du DataFrame. Étant donné que ce DataFrame ne contient aucune colonne numérique, il affiche un récapitulatif du nombre de valeurs non nulles et du nombre de valeurs distinctes.
Exécutez cette cellule:
# 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()
Résultat attendu :
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. Explorer les données
Avant de vous pencher sur les réclamations, utilisez les méthodes semblables à celles de Pandas sur le DataFrame pour visualiser les données.
Visualiser le DataFrame
Il existe plusieurs méthodes de visualisation intégrées, comme DataFrame.plot.hist(). Étant donné que ce DataFrame contient principalement des données de chaîne et booléennes, nous pouvons d'abord effectuer une agrégation pour en savoir plus sur les différentes colonnes.
Comptez le nombre de réclamations reçues de chaque État.
complaints_by_state = (
feedback.groupby(
"state", as_index=False,
).size()
.rename(columns={"size": "total_complaints"})
.sort_values(by="total_complaints", ascending=False)
)
Convertissez-le en DataFrame pandas à l'aide de la méthode DataFrame.to_pandas()
.
complaints_pd = complaints_by_state.head(10).to_pandas()
Utilisez les méthodes de visualisation pandas sur ce DataFrame téléchargé.
complaints_pd.plot.bar(x="state", y="total_complaints")
Associer des ensembles de données
Auparavant, vous examiniez les réclamations par État, mais vous perdiez ainsi un contexte important. Certains États ont une population plus importante que d'autres. Associez-les à un ensemble de données sur la population, tel que l'enquête sur la communauté américaine du Bureau du recensement des États-Unis et la table 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 identifie les États par GEOID. Joignez la table des États pour obtenir la population par code d'État à deux lettres.
pops = us_states.set_index("geo_id")[["state"]].join(
us_survey.set_index("geo_id")[["total_pop"]]
)
Associez-la maintenant à la base de données des réclamations pour comparer la population au nombre de réclamations.
complaints_and_pops = complaints_by_state.set_index("state").join(
pops.set_index("state")
)
Créez un nuage de points pour comparer la population des États au nombre de plaintes.
(
complaints_and_pops
.to_pandas()
.plot.scatter(x="total_pop", y="total_complaints")
)
Quelques États semblent être des valeurs aberrantes lorsque l'on compare la population au nombre de réclamations. Il est laissé au lecteur de les identifier en les étiquetant. De même, formulez des hypothèses pour expliquer ce résultat (par exemple, différentes données démographiques, différents nombres d'entreprises de services financiers, etc.) et testez-les.
5. Calculer des embeddings
Des informations importantes sont souvent cachées dans des données non structurées, telles que du texte, de l'audio ou des images. Dans cet exemple, la plupart des informations utiles de la base de données des réclamations se trouvent dans le contenu textuel de la réclamation.
L'IA et les techniques traditionnelles, telles que l'analyse du sentiment, le "bag of words" et word2vec, peuvent extraire certaines informations quantitatives à partir de données non structurées. Plus récemment, les modèles de "représentation vectorielle continue", qui sont étroitement liés aux LLM, peuvent créer une séquence de nombres à virgule flottante représentant les informations sémantiques du texte.
Sélectionner un sous-ensemble de la base de données
L'exécution d'un modèle d'embedding vectoriel utilise plus de ressources que d'autres opérations. Pour réduire les coûts et les problèmes de quota, sélectionnez un sous-ensemble des données pour le reste de ce tutoriel.
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
Environ 1 000 plaintes ont été envoyées le 01/12/2022, contre près de 3,5 millions de lignes dans la base de données totale (vérifiez avec feedback.shape
).
Sélectionnez uniquement les données du 1er décembre 2022 et la colonne 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
La méthode drop_duplicates
de pandas nécessite un tri total des lignes, car elle tente de sélectionner la première ou la dernière ligne correspondante et de conserver l'index qui lui est associé.
Agrégez plutôt les données à l'aide d'un appel à la méthode groupby
pour dédupliquer les lignes.
feedback = (
feedback.groupby("consumer_complaint_narrative", as_index=False)
.size()
)[["consumer_complaint_narrative"]]
feedback.shape
Générer des embeddings
BigQuery DataFrames génère des vecteurs d'embedding via la classe TextEmbeddingGenerator. Il s'agit de la méthode ML.GENERATE_EMBEDDING
, dans BigQuery ML, qui appelle les modèles d'embedding textuel fournis par Vertex AI.
from bigframes.ml.llm import TextEmbeddingGenerator
embedding_model = TextEmbeddingGenerator(
model_name="text-embedding-004"
)
feedback_embeddings = embedding_model.predict(feedback)
Découvrez à quoi ressemblent les embeddings. Ces vecteurs représentent la signification sémantique du texte telle qu'elle est comprise par le modèle d'embedding textuel.
feedback_embeddings.peek()
Résultat attendu :
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-...
Ces vecteurs comportent de nombreuses dimensions. Examinons un seul vecteur d'embedding:
feedback_embeddings["ml_generate_embedding_result"].peek().iloc[0]
La génération d'embeddings fonctionne selon un contrat de "succès partiel". Cela signifie que certaines lignes peuvent contenir des erreurs et ne pas générer d'encapsulation. Les messages d'erreur sont exposés dans la colonne 'ml_generate_embedding_status'
. Si le champ est vide, cela signifie qu'aucune erreur ne s'affiche.
Filtrez les représentations vectorielles continues pour n'inclure que les lignes où aucune erreur ne s'est produite.
mask = feedback_embeddings["ml_generate_embedding_status"] == ""
valid_embeddings = feedback_embeddings[mask]
valid_embeddings.shape
6. Créer des clusters à l'aide de représentations vectorielles continues de texte
Maintenant, regroupez les représentations vectorielles continues à l'aide de k-moyennes. Pour cette démonstration, utilisez un nombre arbitraire de groupes (ou centroïdes). Une solution de qualité de production doit ajuster le nombre de centroïdes à l'aide d'une technique telle que la méthode 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()
Supprimez les échecs d'embedding.
mask = clusters["ml_generate_embedding_status"] == ""
clusters = clusters[mask]
Consultez la distribution des commentaires par centre de gravité.
clusters.groupby("CENTROID_ID").size()
7. Résumer les clusters
Fournissez des commentaires associés à chaque centroid et demandez à Gemini de résumer les réclamations. L'ingénierie des requêtes est un domaine émergent, mais il existe de bons exemples sur Internet, comme 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()
Utilisez Gemini pour rédiger un rapport à partir des résumés.
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. Effectuer un nettoyage
Si vous avez créé un projet Google Cloud pour ce tutoriel, vous pouvez le supprimer pour éviter que des frais supplémentaires ne soient facturés pour les tables ou d'autres ressources créées.
9. Félicitations !
Vous avez analysé des données structurées et non structurées à l'aide de BigQuery DataFrames. Au cours de ce tutoriel, vous avez découvert les ensembles de données publics de Google Cloud, les notebooks Python dans BigQuery Studio, BigQuery ML, Vertex AI et les fonctionnalités de BigQuery Studio permettant de passer du langage naturel au langage Python. Bravo !
Étapes suivantes
- Essayez de générer du code Python dans votre notebook. Les notebooks Python dans BigQuery Studio sont fournis par Colab Enterprise. Remarque: Je trouve que demander de l'aide pour générer des données de test est très utile.
- Découvrez les exemples de notebooks pour BigQuery DataFrames sur GitHub.
- Créez un planning pour exécuter un notebook dans BigQuery Studio.
- Déployez une fonction distante avec BigQuery DataFrames pour intégrer des packages Python tiers à BigQuery.