Analyser des données multimodales avec SQL et Python
Ce tutoriel explique comment analyser des données multimodales à l'aide de requêtes SQL et de fonctions définies par l'utilisateur (UDF) Python.
Ce tutoriel utilise le catalogue de produits de l'ensemble de données public de la boutique pour animaux de compagnie Cymbal.
Objectifs
- Utilisez des valeurs
ObjectRef
pour stocker des données d'image avec des données structurées dans une table standard BigQuery. - Générez du texte à partir des données d'image d'une table standard à l'aide de la fonction
AI.GENERATE_TABLE
. - Transformez des images existantes pour créer de nouvelles images à l'aide d'une fonction définie par l'utilisateur Python.
- Divisez les fichiers PDF en sections pour une analyse plus approfondie à l'aide d'une fonction définie par l'utilisateur Python.
- Utilisez un modèle Gemini et la fonction
ML.GENERATE_TEXT
pour analyser les données PDF segmentées. - Générez des embeddings basés sur les données d'image d'une table standard à l'aide de la fonction
ML.GENERATE_EMBEDDING
. - Traitez des données multimodales ordonnées à l'aide de tableaux de valeurs
ObjectRef
.
Coûts
Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :
- BigQuery: you incur costs for the data that you process in BigQuery.
- BigQuery Python UDFs: you incur costs for using Python UDFs.
- Cloud Storage: you incur costs for the objects stored in Cloud Storage.
- Vertex AI: you incur costs for calls to Vertex AI models.
Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.
Pour en savoir plus, consultez les pages des tarifs suivantes:
- Tarifs de BigQuery
- Tarifs des fonctions définies par l'utilisateur Python de BigQuery
- Tarifs de Cloud Storage
- Tarification de Vertex AI
Avant de commencer
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the BigQuery, BigQuery Connection, Cloud Storage, and Vertex AI APIs.
Rôles requis
Pour obtenir les autorisations nécessaires pour suivre ce tutoriel, demandez à votre administrateur de vous accorder les rôles IAM suivants:
-
Créer une connexion :
Administrateur de connexion BigQuery (
roles/bigquery.connectionAdmin
) -
Accordez des autorisations au compte de service de la connexion :
Administrateur de projet IAM (
roles/resourcemanager.projectIamAdmin
) -
Créez un bucket Cloud Storage :
Administrateur de l'espace de stockage (
roles/storage.admin
) -
Créez des ensembles de données, des modèles, des fonctions définies par l'utilisateur et des tables, et exécutez des jobs BigQuery :
Administrateur BigQuery (
roles/bigquery.admin
) -
Créez des URL qui vous permettent de lire et de modifier des objets Cloud Storage :
Administrateur d'ObjectRef BigQuery (
roles/bigquery.objectRefAdmin
)
Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.
Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.
Configurer
Dans cette section, vous allez créer l'ensemble de données, la connexion, les tables et les modèles utilisés dans ce tutoriel.
Créer un ensemble de données
Créez un ensemble de données BigQuery pour contenir les objets que vous créez dans ce tutoriel:
Dans la console Google Cloud , accédez à la page BigQuery.
Dans le volet Explorer, sélectionnez votre projet.
Développez l'option
Actions, puis cliquez sur Créer un ensemble de données. Le volet Créer un ensemble de données s'ouvre.Dans le champ ID de l'ensemble de données, saisissez
cymbal_pets
.Cliquez sur Créer un ensemble de données.
Créer un bucket
Créez un bucket Cloud Storage pour stocker les objets transformés:
Accédez à la page Buckets.
Cliquez sur
Créer.Sur la page Créer un bucket, dans la section Premiers pas, saisissez un nom unique qui répond aux exigences de dénomination des buckets.
Cliquez sur Créer.
Créer une connexion
Créez une connexion de ressource cloud et obtenez le compte de service de la connexion. BigQuery utilise cette connexion pour accéder aux objets de Cloud Storage:
Accédez à la page BigQuery.
Dans le volet Explorateur, cliquez sur
Ajouter des données.La boîte de dialogue Ajouter des données s'ouvre.
Dans le volet Filtrer par, dans la section Type de source de données, sélectionnez Applications d'entreprise.
Vous pouvez également saisir
Vertex AI
dans le champ Rechercher des sources de données.Dans la section Sources de données sélectionnées, cliquez sur Vertex AI.
Cliquez sur la fiche de solution Modèles Vertex AI: fédération BigQuery.
Dans la liste Type de connexion, sélectionnez Modèles distants Vertex AI, fonctions distantes et BigLake (ressource Cloud).
Dans le champ ID de connexion, saisissez
cymbal_conn
.Cliquez sur Créer une connexion.
Cliquez sur Accéder à la connexion.
Dans le volet Informations de connexion, copiez l'ID du compte de service à utiliser à l'étape suivante.
Accorder des autorisations au compte de service de la connexion
Attribuez au compte de service de la connexion les rôles appropriés pour accéder à d'autres services. Vous devez accorder ces rôles dans le projet que vous avez créé ou sélectionné dans la section Avant de commencer. L'attribution des rôles dans un autre projet génère l'erreur bqcx-1234567890-xxxx@gcp-sa-bigquery-condel.iam.gserviceaccount.com
does not have the permission to access resource
.
Accorder des autorisations sur le bucket Cloud Storage
Accordez au compte de service l'accès aux objets du bucket que vous avez créé:
Accédez à la page Buckets.
Cliquez sur le nom du bucket que vous avez créé.
Cliquez sur Autorisations.
Cliquez sur
Accorder l'accès. La boîte de dialogue Accorder l'accès s'ouvre.Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service que vous avez copié précédemment.
Dans le champ Sélectionner un rôle, sélectionnez Cloud Storage, puis Utilisateur d'objets Storage.
Cliquez sur Enregistrer.
Accorder des autorisations pour utiliser les modèles Vertex AI
Accordez au compte de service l'accès aux modèles Vertex AI:
Accédez à la page IAM et administration.
Cliquez sur
Accorder l'accès. La boîte de dialogue Accorder l'accès s'ouvre.Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service que vous avez copié précédemment.
Dans le champ Sélectionner un rôle, sélectionnez Vertex AI, puis Utilisateur Vertex AI.
Cliquez sur Enregistrer.
Créer les tables d'exemples de données
Créez des tables pour stocker les informations sur les produits pour animaux de compagnie de Cymbal.
Créer la table products
Créez une table standard contenant les informations sur les produits pour animaux de compagnie de Cymbal:
Dans la console Google Cloud , accédez à la page BigQuery.
Dans l'éditeur de requêtes, exécutez la requête suivante pour créer la table
products
:LOAD DATA OVERWRITE cymbal_pets.products FROM FILES( format = 'avro', uris = [ 'gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/tables/products/products_*.avro']);
Créer la table product_images
Créez une table d'objets contenant les images des produits pour animaux de compagnie de Cymbal:
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la table
product_images
:CREATE OR REPLACE EXTERNAL TABLE cymbal_pets.product_images WITH CONNECTION `us.cymbal_conn` OPTIONS ( object_metadata = 'SIMPLE', uris = ['gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/*.png'], max_staleness = INTERVAL 30 MINUTE, metadata_cache_mode = AUTOMATIC);
Créer la table product_manuals
Créez une table d'objets contenant les manuels des produits pour animaux de compagnie de Cymbal:
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la table
product_manuals
:CREATE OR REPLACE EXTERNAL TABLE cymbal_pets.product_manuals WITH CONNECTION `us.cymbal_conn` OPTIONS ( object_metadata = 'SIMPLE', uris = ['gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/documents/*.pdf']);
Créer un modèle de génération de texte
Créez un modèle distant BigQuery ML représentant un modèle Gemini Vertex AI:
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer le modèle distant:
CREATE OR REPLACE MODEL `cymbal_pets.gemini` REMOTE WITH CONNECTION `us.cymbal_conn` OPTIONS (ENDPOINT = 'gemini-2.0-flash');
Créer un modèle de génération d'embeddings
Créez un modèle distant BigQuery ML représentant un modèle d'embedding multimodal Vertex AI:
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer le modèle distant:
CREATE OR REPLACE MODEL `cymbal_pets.embedding_model` REMOTE WITH CONNECTION `us.cymbal_conn` OPTIONS (ENDPOINT = 'multimodalembedding@001');
Créer une table products_mm
avec des données multimodales
Créez une table products_mm
contenant une colonne image
renseignée avec des images de produits de la table d'objets product_images
. La colonne image
créée est une colonne STRUCT
qui utilise le format ObjectRef
.
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la table
products_mm
et renseigner la colonneimage
:CREATE OR REPLACE TABLE cymbal_pets.products_mm AS SELECT products.* EXCEPT (uri), ot.ref AS image FROM cymbal_pets.products INNER JOIN cymbal_pets.product_images ot ON ot.uri = products.uri;
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour afficher les données de la colonne
image
:SELECT product_name, image FROM cymbal_pets.products_mm`
Les résultats ressemblent à ce qui suit :
+--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+ | product_name | image.uri | image.version | image.authorizer | image.details | +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+ | AquaClear Aquarium Background | gs://cloud-samples-data/bigquery/ | 1234567891011 | myproject.region.myconnection | {"gcs_metadata":{"content_type":"image/png", | | | tutorials/cymbal-pets/images/ | | | "md5_hash":"494f63b9b137975ff3e7a11b060edb1d", | | | aquaclear-aquarium-background.png | | | "size":1282805,"updated":1742492680017000}} | +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+ | AquaClear Aquarium | gs://cloud-samples-data/bigquery/ | 2345678910112 | myproject.region.myconnection | {"gcs_metadata":{"content_type":"image/png", | | Gravel Vacuum | tutorials/cymbal-pets/images/ | | | "md5_hash":"b7bfc2e2641a77a402a1937bcf0003fd", | | | aquaclear-aquarium-gravel-vacuum.png | | | "size":820254,"updated":1742492682411000}} | +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+ | ... | ... | ... | | ... | +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+
Générer des informations produit à l'aide d'un modèle Gemini
Utilisez un modèle Gemini pour générer les données suivantes pour les produits de la animalerie:
- Ajoutez une colonne
image_description
au tableauproducts_mm
. - Renseignez les colonnes
animal_type
,search_keywords
etsubcategory
de la tableproducts_mm
. - Exécutez une requête qui renvoie une description de chaque marque de produits, ainsi qu'un nombre de produits de cette marque. La description de la marque est générée en analysant les informations sur les produits de cette marque, y compris les images des produits.
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer et renseigner la colonne
image_description
:CREATE OR REPLACE TABLE cymbal_pets.products_mm AS SELECT product_id, product_name, brand, category, subcategory, animal_type, search_keywords, price, description, inventory_level, supplier_id, average_rating, image, image_description FROM AI.GENERATE_TABLE( MODEL `cymbal_pets.gemini`, ( SELECT ('Can you describe the following image?', OBJ.GET_ACCESS_URL(image, 'r')) AS prompt, * FROM cymbal_pets.products_mm ), STRUCT('image_description STRING' AS output_schema));
Dans l'éditeur de requêtes de la page BigQuery, exécutez la requête suivante pour mettre à jour les colonnes
animal_type
,search_keywords
etsubcategory
avec les données générées:UPDATE cymbal_pets.products_mm p SET p.animal_type = s.animal_type, p.search_keywords = s.search_keywords, p.subcategory = s.subcategory FROM ( SELECT animal_type, search_keywords, subcategory, uri FROM AI.GENERATE_TABLE( MODEL `cymbal_pets.gemini`, ( SELECT ( 'For the image of a pet product, concisely generate the following metadata.' '1) animal_type and 2) 5 SEO search keywords, and 3) product subcategory', OBJ.GET_ACCESS_URL(image, 'r'), description) AS prompt, image.uri AS uri, FROM cymbal_pets.products_mm ), STRUCT( 'animal_type STRING, search_keywords ARRAY<STRING>, subcategory STRING' AS output_schema, 100 AS max_output_tokens)) ) s WHERE p.image.uri = s.uri;
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour afficher les données générées:
SELECT product_name, image_description, animal_type, search_keywords, subcategory, FROM cymbal_pets.products_mm;
Les résultats ressemblent à ce qui suit :
+--------------------------------+-------------------------------------+-------------+------------------------+------------------+ | product_name | image.description | animal_type | search_keywords | subcategory | +--------------------------------+-------------------------------------+-------------+------------------------+------------------+ | AquaClear Aquarium Background | The image shows a colorful coral | fish | aquarium background | aquarium decor | | | reef backdrop. The background is a | | fish tank backdrop | | | | blue ocean with a bright light... | | coral reef decor | | | | | | underwater scenery | | | | | | aquarium decoration | | +--------------------------------+-------------------------------------+-------------+------------------------+------------------+ | AquaClear Aquarium | The image shows a long, clear | fish | aquarium gravel vacuum | aquarium | | Gravel Vacuum | plastic tube with a green hose | | aquarium cleaning | cleaning | | | attached to one end. The tube... | | aquarium maintenance | | | | | | fish tank cleaning | | | | | | gravel siphon | | +--------------------------------+-------------------------------------+-------------+------------------------+------------------+ | ... | ... | ... | ... | ... | +--------------------------------+-------------------------------------+-------------+------------------------+------------------+
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour générer une description de chaque marque de produits, ainsi qu'un nombre de produits de cette marque:
SELECT brand, brand_description, cnt FROM AI.GENERATE_TABLE( MODEL `cymbal_pets.gemini`, ( SELECT brand, COUNT(*) AS cnt, ( 'Use the images and text to give one concise brand description for a website brand page.' 'Return the description only.', ARRAY_AGG(OBJ.GET_ACCESS_URL(image, 'r')), ARRAY_AGG(description), ARRAY_AGG(category), ARRAY_AGG(subcategory)) AS prompt FROM cymbal_pets.products_mm GROUP BY brand ), STRUCT('brand_description STRING' AS output_schema)) ORDER BY cnt DESC;
Les résultats ressemblent à ce qui suit :
+--------------+-------------------------------------+-----+ | brand | brand.description | cnt | +--------------+-------------------------------------+-----+ | AquaClear | AquaClear is a brand of aquarium | 33 | | | and pond care products that offer | | | | a wide range of solutions for... | | +--------------+-------------------------------------+-----+ | Ocean | Ocean Bites is a brand of cat food | 28 | | Bites | that offers a variety of recipes | | | | and formulas to meet the specific.. | | +--------------+-------------------------------------+-----+ | ... | ... |... | +--------------+-------------------------------------+-----+
Créer une fonction définie par l'utilisateur Python pour transformer les images de produits
Créez une fonction définie par l'utilisateur Python pour convertir les images produit en niveaux de gris.
La fonction définie par l'utilisateur Python utilise des bibliothèques Open Source et une exécution parall��le pour transformer plusieurs images simultanément.
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la UDF
to_grayscale
:CREATE OR REPLACE FUNCTION cymbal_pets.to_grayscale(src_json STRING, dst_json STRING) RETURNS STRING LANGUAGE python WITH CONNECTION `us.cymbal_conn` OPTIONS (entry_point='to_grayscale', runtime_version='python-3.11', packages=['numpy', 'opencv-python']) AS """ import cv2 as cv import numpy as np from urllib.request import urlopen, Request import json # Transform the image to grayscale. def to_grayscale(src_ref, dst_ref): src_json = json.loads(src_ref) srcUrl = src_json["access_urls"]["read_url"] dst_json = json.loads(dst_ref) dstUrl = dst_json["access_urls"]["write_url"] req = urlopen(srcUrl) arr = np.asarray(bytearray(req.read()), dtype=np.uint8) img = cv.imdecode(arr, -1) # 'Load it as it is' # Convert the image to grayscale gray_image = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Send POST request to the URL _, img_encoded = cv.imencode('.png', gray_image) req = Request(url=dstUrl, data=img_encoded.tobytes(), method='PUT', headers = { "Content-Type": "image/png", }) with urlopen(req) as f: pass return dst_ref """;
Transformer les images de produits
Créez la table products_grayscale
avec une colonne ObjectRef
contenant les chemins de destination et les autoriseurs pour les images en niveaux de gris. Le chemin de destination est dérivé du chemin d'image d'origine.
Une fois la table créée, exécutez la fonction to_grayscale
pour créer les images en niveaux de gris, les écrire dans un bucket Cloud Storage, puis renvoyer des valeurs ObjectRefRuntime
contenant des URL d'accès et des métadonnées pour les images en niveaux de gris.
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la table
products_grayscale
:CREATE OR REPLACE TABLE cymbal_pets.products_grayscale AS SELECT product_id, product_name, image, OBJ.MAKE_REF( CONCAT('gs://BUCKET/cymbal-pets-images/grayscale/', REGEXP_EXTRACT(image.uri, r'([^/]+)$')), 'us.cymbal_conn') AS gray_image FROM cymbal_pets.products_mm;
Remplacez
BUCKET
par le nom du bucket que vous avez créé.Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer les images en niveaux de gris, les écrire dans un bucket Cloud Storage, puis renvoyer des valeurs
ObjectRefRuntime
contenant des URL d'accès et des métadonnées pour les images en niveaux de gris:SELECT cymbal_pets.to_grayscale( TO_JSON_STRING(OBJ.GET_ACCESS_URL(image, 'r')), TO_JSON_STRING(OBJ.GET_ACCESS_URL(gray_image, 'rw'))) FROM cymbal_pets.products_grayscale;
Les résultats ressemblent à ce qui suit :
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | f0 | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | {"access_urls":{"expiry_time":"2025-04-26T03:00:48Z", | | "read_url":"https://storage.googleapis.com/mybucket/cymbal-pets-images%2Fgrayscale%2Focean-bites-salmon-%26-tuna-cat-food.png?additional_read URL_information", | | "write_url":"https://storage.googleapis.com/myproject/cymbal-pets-images%2Fgrayscale%2Focean-bites-salmon-%26-tuna-cat-food.png?additional_write URL_information"}, | | "objectref":{"authorizer":"myproject.region.myconnection","uri":"gs://myproject/cymbal-pets-images/grayscale/ocean-bites-salmon-&-tuna-cat-food.png"}} | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | {"access_urls":{"expiry_time":"2025-04-26T03:00:48Z", | | "read_url":"https://storage.googleapis.com/mybucket/cymbal-pets-images%2Fgrayscale%2Ffluffy-buns-guinea-pig-tunnel.png?additional _read URL_information", | | "write_url":"https://storage.googleapis.com/myproject/cymbal-pets-images%2Fgrayscale%2Focean-bites-salmon-%26-tuna-cat-food.png?additional_write_URL_information"}, | | "objectref":{"authorizer":"myproject.region.myconnection","uri":"gs://myproject/cymbal-pets-images%2Fgrayscale%2Ffluffy-buns-guinea-pig-tunnel.png"}} | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ... | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Créer une fonction définie par l'utilisateur Python pour diviser les données PDF
Créez une fonction définie par l'utilisateur Python pour diviser les objets PDF contenant les manuels des produits Cymbal en plusieurs parties.
Les fichiers PDF sont souvent très volumineux et peuvent ne pas tenir dans un seul appel à un modèle d'IA générative. En segmentant les fichiers PDF, vous pouvez stocker les données PDF dans un format prêt à être modélisé pour faciliter l'analyse.
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la UDF
chunk_pdf
:-- This function chunks the product manual PDF into multiple parts. -- The function accepts an ObjectRefRuntime value for the PDF file and the chunk size. -- It then parses the PDF, chunks the contents, and returns an array of chunked text. CREATE OR REPLACE FUNCTION cymbal_pets.chunk_pdf(src_json STRING, chunk_size INT64, overlap_size INT64) RETURNS ARRAY<STRING> LANGUAGE python WITH CONNECTION `us.cymbal_conn` OPTIONS (entry_point='chunk_pdf', runtime_version='python-3.11', packages=['pypdf']) AS """ import io import json from pypdf import PdfReader # type: ignore from urllib.request import urlopen, Request def chunk_pdf(src_ref: str, chunk_size: int, overlap_size: int) -> str: src_json = json.loads(src_ref) srcUrl = src_json["access_urls"]["read_url"] req = urlopen(srcUrl) pdf_file = io.BytesIO(bytearray(req.read())) reader = PdfReader(pdf_file, strict=False) # extract and chunk text simultaneously all_text_chunks = [] curr_chunk = "" for page in reader.pages: page_text = page.extract_text() if page_text: curr_chunk += page_text # split the accumulated text into chunks of a specific size with overlaop # this loop implements a sliding window approach to create chunks while len(curr_chunk) >= chunk_size: split_idx = curr_chunk.rfind(" ", 0, chunk_size) if split_idx == -1: split_idx = chunk_size actual_chunk = curr_chunk[:split_idx] all_text_chunks.append(actual_chunk) overlap = curr_chunk[split_idx + 1 : split_idx + 1 + overlap_size] curr_chunk = overlap + curr_chunk[split_idx + 1 + overlap_size :] if curr_chunk: all_text_chunks.append(curr_chunk) return all_text_chunks """;
Analyser des données PDF
Exécutez la fonction chunk_pdf
pour diviser les données PDF dans la table product_manuals
, puis créez une table product_manual_chunk_strings
contenant un bloc PDF par ligne. Utilisez un modèle Gemini sur les données product_manual_chunk_strings
pour résumer les informations légales figurant dans les manuels des produits.
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour créer la table
product_manual_chunk_strings
:CREATE OR REPLACE TABLE cymbal_pets.product_manual_chunk_strings AS SELECT chunked FROM cymbal_pets.product_manuals, UNNEST (cymbal_pets.chunk_pdf( TO_JSON_STRING( OBJ.GET_ACCESS_URL(OBJ.MAKE_REF(uri, 'us.cymbal_conn'), 'r')), 1000, 100 )) as chunked;
Dans l'éditeur de requêtes de la page BigQuery, exécutez la requête suivante pour analyser les données PDF à l'aide d'un modèle Gemini:
SELECT ml_generate_text_llm_result FROM ML.GENERATE_TEXT( MODEL `cymbal_pets.gemini`, ( SELECT ( 'Can you summarize the product manual as bullet points? Highlight the legal clauses', chunked) AS prompt, FROM cymbal_pets.product_manual_chunk_strings ), STRUCT( TRUE AS FLATTEN_JSON_OUTPUT));
Les résultats ressemblent à ce qui suit :
+-------------------------------------------------------------------------------------------------------------------------------------------+ | ml_generate_text_llm_result | +-------------------------------------------------------------------------------------------------------------------------------------------+ | ## CritterCuisine Pro 5000 Automatic Pet Feeder Manual Summary: | | | | **Safety:** | | | | * **Stability:** Place feeder on a level, stable surface to prevent tipping. | | * **Power Supply:** Only use the included AC adapter. Using an incompatible adapter can damage the unit and void the warranty. | | * **Cord Safety:** Keep the power cord out of reach of pets to prevent chewing or entanglement. | | * **Children:** Supervise children around the feeder. This is not a toy. | | * **Pet Health:** Consult your veterinarian before using an automatic feeder if your pet has special dietary needs, health conditions, or | +-------------------------------------------------------------------------------------------------------------------------------------------+ | ## Product Manual Summary: | | | | **6.3 Manual Feeding:** | | | | * Press MANUAL button to dispense a single portion (Meal 1 size). **(Meal Enabled)** | | | | **6.4 Recording a Voice Message:** | | | | * Press and hold VOICE button. | | * Speak clearly into the microphone (up to 10 seconds). | | * Release VOICE button to finish recording. | | * Briefly press VOICE button to play back the recording. | | * To disable the voice message, record a blank message (hold VOICE button for 10 seconds without speaking). **(Meal Enabled)** | | | | **6.5 Low Food Level Indicator:** | +-------------------------------------------------------------------------------------------------------------------------------------------+ | ... | +-------------------------------------------------------------------------------------------------------------------------------------------+
Générer des embeddings et effectuer une recherche vectorielle
Générez des embeddings à partir de données d'image, puis utilisez-les pour renvoyer des images similaires à l'aide de la recherche vectorielle.
Dans un scénario de production, nous vous recommandons de créer un index vectoriel avant d'exécuter une recherche vectorielle. Un index vectoriel vous permet d'effectuer la recherche vectorielle plus rapidement, avec le compromis de réduire le rappel et donc de renvoyer des résultats plus approximatifs.
Dans l'éditeur de requêtes de la page BigQuery, exécutez la requête suivante pour créer la table
products_embeddings
:CREATE OR REPLACE TABLE cymbal_pets.products_embedding AS SELECT product_id, ml_generate_embedding_result as embedding, content as image FROM ML.GENERATE_EMBEDDING( MODEL `cymbal_pets.embedding_model`, ( SELECT OBJ.GET_ACCESS_URL(image, 'r') as content, image, product_id FROM cymbal_pets.products_mm ), STRUCT () );
Dans l'éditeur de requête de la page BigQuery, exécutez la requête suivante pour effectuer une recherche vectorielle afin de renvoyer des images de produits similaires à l'image d'entrée donnée:
SELECT * FROM VECTOR_SEARCH( TABLE cymbal_pets.products_embedding, 'embedding', (SELECT ml_generate_embedding_result as embedding FROM ML.GENERATE_EMBEDDING( MODEL `cymbal_pets.embedding_model`, (SELECT OBJ.FETCH_METADATA(OBJ.MAKE_REF('gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/cozy-naps-cat-scratching-post-with-condo.png', 'us.cymbal_conn')) as content) )) );
Les résultats ressemblent à ce qui suit :
+-----------------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+ | query.embedding | base.product_id | base.embedding | base.image.uri | base.image.version | base.image.authorizer | base.image.details | distance | +-----------------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+ | -0.0112330541 | 181 | -0.0112330541 | gs://cloud-samples-data/bigquery/ | 12345678910 | myproject.region.myconnection | {"gcs_metadata":{"content_type": | 0.0 | | 0.0142525584 | | 0.0142525584 | tutorials/cymbal-pets/images/ | | | "image/png","md5_hash":"21234567hst16555w60j", | | | 0.0135886827 | | 0.0135886827 | cozy-naps-cat-scratching-post-with-condo.png | | | "size":828318,"updated":1742492688982000}} | | | 0.0149955815 | | 0.0149955815 | | | | | | | ... | | ... | | | | | | | | | | | | | | | | | | | | | | | | +-----------------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+ | -0.0112330541 | 187 | -0.0190353896 | gs://cloud-samples-data/bigquery/ | 23456789101 | myproject.region.myconnection | {"gcs_metadata":{"content_type": | 0.4216330832.. | | 0.0142525584 | | 0.0116206668 | tutorials/cymbal-pets/images/ | | | "image/png","md5_hash":"7328728fhakd9937djo4", | | | 0.0135886827 | | 0.0136198215 | cozy-naps-cat-scratching-post-with-bed.png | | | "size":860113,"updated":1742492688774000}} | | | 0.0149955815 | | 0.0173457414 | | | | | | | ... | | ... | | | | | | | | | | | | | | | | | | | | | | | | +---------C--------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+ | ... | ... | ... | ... | ... | ... | ... | ... | +-----------------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+
Traiter des données multimodales ordonnées à l'aide de tableaux de valeurs ObjectRef
Ce guide vous explique comment effectuer les tâches suivantes :
- Recréez le tableau
product_manuals
afin qu'il contienne à la fois un fichier PDF pour le manuel produitCrittercuisine 5000
et des fichiers PDF pour chaque page de ce manuel. - Créez un tableau qui met en correspondance le manuel avec ses segments. La valeur
ObjectRef
représentant le manuel complet est stockée dans une colonneSTRUCT<uri STRING, version STRING, authorizer STRING, details JSON>>
. Les valeursObjectRef
qui représentent les pages de manuel sont stockées dans une colonneARRAY<STRUCT<uri STRING, version STRING, authorizer STRING, details JSON>>
. - Analysez un tableau de valeurs
ObjectRef
pour renvoyer une seule valeur générée. - Analysez un tableau de valeurs
ObjectRef
séparément et renvoyez une valeur générée pour chaque valeur du tableau.
Dans le cadre des tâches d'analyse, vous convertissez le tableau de valeurs ObjectRef
en liste ordonnée de valeurs ObjectRefRuntime
, puis transmettez cette liste à un modèle Gemini, en spécifiant les valeurs ObjectRefRuntime
dans la requête. Les valeurs ObjectRefRuntime
fournissent des URL signées que le modèle utilise pour accéder aux informations sur les objets dans Cloud Storage.
Pour traiter des données multimodales ordonnées à l'aide de tableaux de valeurs ObjectRef
, procédez comme suit:
Accédez à la page BigQuery.
Dans l'éditeur de requêtes, exécutez la requête suivante pour recréer la table
product_manuals
:CREATE OR REPLACE EXTERNAL TABLE `cymbal_pets.product_manuals` WITH CONNECTION `us.cymbal_conn` OPTIONS ( object_metadata = 'SIMPLE', uris = [ 'gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/documents/*.pdf', 'gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/document_chunks/*.pdf']);
Dans l'éditeur de requêtes, exécutez la requête suivante pour écrire des données PDF dans la table
map_manual_to_chunks
:-- Extract the file and chunks into a single table. -- Store the chunks in the chunks column as array of ObjectRefs (ordered by page number) CREATE OR REPLACE TABLE cymbal_pets.map_manual_to_chunks AS SELECT ARRAY_AGG(m1.ref)[0] manual, ARRAY_AGG(m2.ref ORDER BY m2.ref.uri) chunks FROM cymbal_pets.product_manuals m1 JOIN cymbal_pets.product_manuals m2 ON REGEXP_EXTRACT(m1.uri, r'.*/([^.]*).[^/]+') = REGEXP_EXTRACT(m2.uri, r'.*/([^.]*)_page[0-9]+.[^/]+') GROUP BY m1.uri;
Dans l'éditeur de requêtes, exécutez la requête suivante pour afficher les données PDF dans la table
map_manual_to_chunks
:SELECT * FROM cymbal_pets.map_manual_to_chunks;
Les résultats ressemblent à ce qui suit :
+-------------------------------------+--------------------------------+-----------------------------------+------------------------------------------------------+-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+ | manual.uri | manual.version | manual.authorizer | manual.details | chunks.uri | chunks.version | chunks.authorizer | chunks.details | +-------------------------------------+--------------------------------+-----------------------------------+------------------------------------------------------+-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+ | gs://cloud-samples-data/bigquery/ | 1742492785900455 | myproject.region.myconnection | {"gcs_metadata":{"content_type":"application/pef", | gs://cloud-samples-data/bigquery/ | 1745875761227129 | myproject.region.myconnection | {"gcs_metadata":{"content_type":"application/pdf", | | tutorials/cymbal-pets/documents/ | | | "md5_hash":"c9032b037693d15a33210d638c763d0e", | tutorials/cymbal-pets/documents/ | | | "md5_hash":"5a1116cce4978ec1b094d8e8b49a1d7c", | | crittercuisine_5000_user_manual.pdf | | | "size":566105,"updated":1742492785941000}} | crittercuisine_5000_user_manual_page1.pdf | | | "size":504583,"updated":1745875761266000}} | | | | | +-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+ | | | | | crittercuisine_5000_user_manual_page1.pdf | 1745875760613874 | myproject.region.myconnection | {"gcs_metadata":{"content_type":"application/pdf", | | | | | | tutorials/cymbal-pets/documents/ | | | "md5_hash":"94d03ec65d28b173bc87eac7e587b325", | | | | | | crittercuisine_5000_user_manual_page2.pdf | | | "size":94622,"updated":1745875760649000}} | | | | | +-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+ | | | | | ... | ... | ... | ... | +-------------------------------------+--------------------------------+-----------------------------------+------------------------------------------------------+-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+
Dans l'éditeur de requête, exécutez la requête suivante pour générer une seule réponse à partir d'un modèle Gemini basé sur l'analyse d'un tableau de valeurs
ObjectRef
:WITH manuals AS ( SELECT OBJ.GET_ACCESS_URL(manual, 'r') AS manual, ARRAY( SELECT OBJ.GET_ACCESS_URL(chunk, 'r') AS chunk FROM UNNEST(m1.chunks) AS chunk WITH OFFSET AS idx ORDER BY idx ) AS chunks FROM cymbal_pets.map_manual_to_chunks AS m1 ) SELECT ml_generate_text_llm_result AS Response FROM ML.GENERATE_TEXT( MODEL `cymbal_pets.gemini`, ( SELECT ( 'Can you provide a page by page summary for the first 3 pages of the attached manual? Only write one line for each page. The pages are provided in serial order', manuals.chunks) AS prompt, FROM manuals ), STRUCT(TRUE AS FLATTEN_JSON_OUTPUT));
Les résultats ressemblent à ce qui suit :
+-------------------------------------------+ | Response | +-------------------------------------------+ | Page 1: This manual is for the | | CritterCuisine Pro 5000 automatic | | pet feeder. | | Page 2: The manual covers safety | | precautions, what's included, | | and product overview. | | Page 3: The manual covers assembly, | | initial setup, and programming the clock. | +-------------------------------------------+
Dans l'éditeur de requête, exécutez la requête suivante pour générer plusieurs réponses à partir d'un modèle Gemini basé sur l'analyse d'un tableau de valeurs
ObjectRef
:WITH input_chunked_objrefs AS ( SELECT row_id, offset, chunk_ref FROM ( SELECT ROW_NUMBER() OVER () AS row_id, * FROM `cymbal_pets.map_manual_to_chunks` ) AS indexed_table LEFT JOIN UNNEST(indexed_table.chunks) AS chunk_ref WITH OFFSET ), get_access_urls AS ( SELECT row_id, offset, chunk_ref, OBJ.GET_ACCESS_URL(chunk_ref, 'r') AS ObjectRefRuntime FROM input_chunked_objrefs ), valid_get_access_urls AS ( SELECT * FROM get_access_urls WHERE ObjectRefRuntime['runtime_errors'] IS NULL ), ordered_output_objrefruntime_array AS ( SELECT ARRAY_AGG(ObjectRefRuntime ORDER BY offset) AS ObjectRefRuntimeArray FROM valid_get_access_urls GROUP BY row_id ) SELECT page1_summary, page2_summary, page3_summary FROM AI.GENERATE_TABLE( MODEL `cymbal_pets.gemini`, ( SELECT ( 'Can you provide a page by page summary for the first 3 pages of the attached manual? Only write one line for each page. The pages are provided in serial order', ObjectRefRuntimeArray) AS prompt, FROM ordered_output_objrefruntime_array ), STRUCT( 'page1_summary STRING, page2_summary STRING, page3_summary STRING' AS output_schema));
Les résultats ressemblent à ce qui suit :
+-----------------------------------------------+-------------------------------------------+----------------------------------------------------+ | page1_summary | page2_summary | page3_summary | +-----------------------------------------------+-------------------------------------------+----------------------------------------------------+ | This manual provides an overview of the | This section explains how to program | This page covers connecting the feeder to Wi-Fi | | CritterCuisine Pro 5000 automatic pet feeder, | the feeder's clock, set feeding | using the CritterCuisine Connect app, remote | | including its features, safety precautions, | schedules, copy and delete meal settings, | feeding, managing feeding schedules, viewing | | assembly instructions, and initial setup. | manually feed your pet, record | feeding logs, receiving low food alerts, | | | a voice message, and understand | updating firmware, creating multiple pet profiles, | | | the low food level indicator. | sharing access with other users, and cleaning | | | | and maintaining the feeder. | +-----------------------------------------------+-------------------------------------------+----------------------------------------------------+
Effectuer un nettoyage
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.