Analisar dados multimodais com SQL e Python

Este tutorial mostra como analisar dados multimodais usando consultas SQL e funções definidas pelo usuário (UDFs) do Python.

Este tutorial usa o catálogo de produtos do conjunto de dados público da loja de animais de estimação Cymbal.

Objetivos

  • Use valores ObjectRef para armazenar dados de imagem com dados estruturados em uma tabela padrão do BigQuery.
  • Gere texto com base nos dados de imagem de uma tabela padrão usando a função AI.GENERATE_TABLE.
  • Transforme imagens atuais para criar novas usando um UDF do Python.
  • Divida PDFs em partes para análise posterior usando uma UDF do Python.
  • Use um modelo do Gemini e a função ML.GENERATE_TEXT para analisar os dados de PDF fragmentados.
  • Gere embeddings com base nos dados de imagem de uma tabela padrão usando a função ML.GENERATE_EMBEDDING.
  • Processe dados multimodais ordenados usando matrizes de valores ObjectRef.

Custos

Neste documento, você usará os seguintes componentes faturáveis do 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.

Para gerar uma estimativa de custo baseada na projeção de uso, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para um teste gratuito.

Para mais informações, consulte as seguintes páginas de preços:

Antes de começar

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. Enable the BigQuery, BigQuery Connection, Cloud Storage, and Vertex AI APIs.

    Enable the APIs

Funções exigidas

Para conseguir as permissões necessárias para concluir este tutorial, peça ao administrador para conceder a você os seguintes papéis do IAM:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias por meio de papéis personalizados ou de outros papéis predefinidos.

Configurar

Nesta seção, você vai criar o conjunto de dados, a conexão, as tabelas e os modelos usados neste tutorial.

Criar um conjunto de dados

Crie um conjunto de dados do BigQuery para conter os objetos que você criou neste tutorial:

  1. No console Google Cloud , acesse a página BigQuery.

    Acessar o BigQuery

  2. No painel Explorer, selecione seu projeto.

  3. Expanda a opção Ações e clique em Criar conjunto de dados. O painel Criar conjunto de dados é aberto.

  4. Em ID do conjunto de dados, digite cymbal_pets.

  5. Clique em Criar conjunto de dados.

Criar um bucket

Crie um bucket do Cloud Storage para armazenar objetos transformados:

  1. Acessar a página Buckets.

    Acessar buckets

  2. Clique em Criar.

  3. Na página Criar um bucket, na seção Começar, insira um nome globalmente exclusivo que atenda aos requisitos de nome de bucket.

  4. Clique em Criar.

Crie uma conexão

Crie uma Conexão de recursos do Cloud e tenha acesso à conta de serviço da conexão. O BigQuery usa a conexão para acessar objetos no Cloud Storage:

  1. Acessar a página do BigQuery.

    Ir para o BigQuery

  2. No painel Explorer, clique em Adicionar dados.

    A caixa de diálogo Adicionar dados é aberta.

  3. No painel Filtrar por, na seção Tipo de fonte de dados, selecione Aplicativos empresariais.

    Como alternativa, no campo Pesquisar fontes de dados, você pode inserir Vertex AI.

  4. Na seção Fontes de dados em destaque, clique em Vertex AI.

  5. Clique no card da solução Vertex AI Models: BigQuery Federation.

  6. Na lista Tipo de conexão, selecione Modelos remotos da Vertex AI, funções remotas e BigLake (recurso do Cloud).

  7. No campo ID da conexão, digite cymbal_conn.

  8. Clique em Criar conexão.

  9. Clique em Ir para conexão.

  10. No painel Informações da conexão, copie o ID da conta de serviço para uso em uma etapa seguinte.

Conceder permissões para a conta de serviço do portal

Conceda à conta de serviço da conexão as funções adequadas para acessar outros serviços. É necessário conceder essas funções no mesmo projeto que você criou ou selecionou na seção Antes de começar. Conceder as funções em um projeto diferente resulta no erro bqcx-1234567890-xxxx@gcp-sa-bigquery-condel.iam.gserviceaccount.com does not have the permission to access resource.

Conceder permissões no bucket do Cloud Storage

Conceda à conta de serviço acesso para usar os objetos no bucket que você criou:

  1. Acessar a página Buckets.

    Acessar buckets

  2. Clique no nome do bucket que você criou.

  3. Clique em Permissões.

  4. Clique em CONCEDER ACESSO. A caixa de diálogo Conceder acesso é aberta.

  5. No campo Novos principais, digite o ID da conta de serviço que você copiou anteriormente.

  6. No campo Selecionar papel, escolha Cloud Storage e, em seguida, Usuário de objetos do Storage.

  7. Clique em Salvar.

Conceder permissões para usar modelos da Vertex AI

Conceda à conta de serviço acesso para usar os modelos da Vertex AI:

  1. Acessar a página AM e administrador

    Acessar IAM e administrador

  2. Clique em CONCEDER ACESSO. A caixa de diálogo Conceder acesso é aberta.

  3. No campo Novos principais, digite o ID da conta de serviço que você copiou anteriormente.

  4. No campo Selecionar um papel, selecione Vertex AI e, em seguida, selecione Usuário da Vertex AI.

  5. Clique em Salvar.

Criar as tabelas de dados de exemplo

Crie tabelas para armazenar as informações dos produtos de animais de estimação da Cymbal.

Criar a tabela products

Crie uma tabela padrão com as informações dos produtos de animais de estimação da Cymbal:

  1. No console Google Cloud , acesse a página BigQuery.

    Acessar o BigQuery

  2. No editor de consultas, execute a seguinte consulta para criar a tabela products:

    LOAD DATA OVERWRITE cymbal_pets.products
    FROM
      FILES(
        format = 'avro',
        uris = [
          'gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/tables/products/products_*.avro']);

Criar a tabela product_images

Crie uma tabela de objetos que contenha as imagens dos produtos de animais de estimação da Cymbal:

  • No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a tabela 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);

Criar a tabela product_manuals

Crie uma tabela de objetos que contenha os manuais de produtos da Cymbal pets:

  • No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a tabela 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']);

Criar um modelo de geração de texto

Crie um modelo remoto do BigQuery ML que represente um modelo da Vertex AI Gemini:

  • No editor de consultas da página do BigQuery, execute a seguinte consulta para criar o modelo remoto:

    CREATE OR REPLACE MODEL `cymbal_pets.gemini`
      REMOTE WITH CONNECTION `us.cymbal_conn`
      OPTIONS (ENDPOINT = 'gemini-2.0-flash');

Criar um modelo de geração de embedding

Crie um modelo remoto do BigQuery ML que represente um modelo de incorporação multimodal da Vertex AI:

  • No editor de consultas da página do BigQuery, execute a seguinte consulta para criar o modelo remoto:

    CREATE OR REPLACE MODEL `cymbal_pets.embedding_model`
      REMOTE WITH CONNECTION `us.cymbal_conn`
      OPTIONS (ENDPOINT = 'multimodalembedding@001');

Criar uma tabela products_mm com dados multimodais

Crie uma tabela products_mm que contenha uma coluna image preenchida com imagens de produtos da tabela de objetos product_images. A coluna image criada é uma coluna STRUCT que usa o formato ObjectRef.

  1. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a tabela products_mm e preencher a coluna image:

    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;
  2. No editor de consultas da página do BigQuery, execute a consulta abaixo para conferir os dados da coluna image:

    SELECT product_name, image
    FROM cymbal_pets.products_mm`

    Os resultados são semelhantes aos seguintes:

    +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+
    | 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}}     |
    +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+
    | ...                            | ...                                  | ...           |                               | ...                                            |
    +--------------------------------+--------------------------------------+-----------------------------------------------+------------------------------------------------+
    

Gerar informações do produto usando um modelo Gemini

Use um modelo do Gemini para gerar os seguintes dados dos produtos da loja de animais de estimação:

  • Adicione uma coluna image_description à tabela products_mm.
  • Preencha as colunas animal_type, search_keywords e subcategory da tabela products_mm.
  • Execute uma consulta que retorne uma descrição de cada marca de produto e também uma contagem do número de produtos dessa marca. A descrição da marca é gerada pela análise das informações de todos os produtos da marca, incluindo as imagens.
  1. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar e preencher a coluna 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));
  2. No editor de consulta da página do BigQuery, execute a consulta a seguir para atualizar as colunas animal_type, search_keywords e subcategory com os dados gerados:

    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;
  3. No editor de consultas da página do BigQuery, execute a consulta a seguir para conferir os dados gerados:

    SELECT
      product_name,
      image_description,
      animal_type,
      search_keywords,
      subcategory,
    FROM cymbal_pets.products_mm;

    Os resultados são semelhantes aos seguintes:

    +--------------------------------+-------------------------------------+-------------+------------------------+------------------+
    | 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          |                  |
    +--------------------------------+-------------------------------------+-------------+------------------------+------------------+
    | ...                            | ...                                 | ...         |  ...                   | ...              |
    +--------------------------------+-------------------------------------+-------------+------------------------+------------------+
    
  4. No editor de consultas da página do BigQuery, execute a consulta a seguir para gerar uma descrição de cada marca de produto e também uma contagem do número de produtos dessa marca:

    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;

    Os resultados são semelhantes aos seguintes:

    +--------------+-------------------------------------+-----+
    | 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.. |     |
    +--------------+-------------------------------------+-----+
    |  ...         | ...                                 |...  |
    +--------------+-------------------------------------+-----+
    

Criar uma UDF Python para transformar imagens de produtos

Crie uma UDF Python para converter imagens de produtos em tons de cinza.

O UDF do Python usa bibliotecas de código aberto e também usa a execução paralela para transformar várias imagens simultaneamente.

  1. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a 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
    """;

Transformar imagens de produtos

Crie a tabela products_grayscale com uma coluna ObjectRef que contenha os caminhos de destino e os autorizados para imagens em tons de cinza. O caminho de destino é derivado do caminho da imagem original.

Depois de criar a tabela, execute a função to_grayscale para criar as imagens em tons de cinza, gravá-las em um bucket do Cloud Storage e retornar os valores ObjectRefRuntime com URLs de acesso e metadados para as imagens em tons de cinza.

  1. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a tabela 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;

    Substitua BUCKET pelo nome do bucket que você criou.

  2. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar as imagens em tons de cinza, gravá-las em um bucket do Cloud Storage e retornar valores ObjectRefRuntime com URLs de acesso e metadados para as imagens em tons de cinza:

    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;

    Os resultados são semelhantes aos seguintes:

    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | 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"}}                 |
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |  ...                                                                                                                                                                  |
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    

Criar uma UDF Python para dividir dados de PDF

Crie um UDF do Python para dividir os objetos PDF que contêm os manuais de produtos da Cymbal Pets em várias partes.

Os PDFs geralmente são muito grandes e podem não caber em uma única chamada para um modelo de IA generativa. Ao dividir os PDFs, você pode armazenar os dados em um formato pronto para modelagem, facilitando a análise.

  1. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a 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
    """;

Analisar dados de PDFs

Execute a função chunk_pdf para dividir os dados do PDF na tabela product_manuals e crie uma tabela product_manual_chunk_strings que contenha um bloco de PDF por linha. Use um modelo do Gemini nos dados product_manual_chunk_strings para resumir as informações legais encontradas nos manuais do produto.

  1. No editor de consultas da página do BigQuery, execute a consulta a seguir para criar a tabela 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;
  2. No editor de consultas da página BigQuery, execute a consulta a seguir para analisar os dados do PDF usando um modelo do 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));

    Os resultados são semelhantes aos seguintes:

    +-------------------------------------------------------------------------------------------------------------------------------------------+
    | 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:**                                                                                                         |
    +-------------------------------------------------------------------------------------------------------------------------------------------+
    | ...                                                                                                                                       |
    +-------------------------------------------------------------------------------------------------------------------------------------------+
    

Gere embeddings de dados de imagem e use-as para retornar imagens semelhantes usando a pesquisa de vetor.

Em um cenário de produção, recomendamos criar um índice vetorial antes de executar uma pesquisa vetorial. Um índice vetorial permite realizar a pesquisa de vetor mais rapidamente, com a desvantagem de reduzir o recall e, portanto, retornar resultados mais aproximados.

  1. No editor de consultas da página do BigQuery, execute a seguinte consulta para criar a tabela 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 ()
    );
  2. No editor de consultas da página do BigQuery, execute a consulta a seguir para realizar uma pesquisa vetorial e retornar imagens de produtos semelhantes à imagem de entrada especificada:

    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)
      ))
    );

    Os resultados são semelhantes aos seguintes:

    +-----------------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+
    | 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--------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+
    | ...             | ...             | ...            | ...                                          | ...                | ...                           | ...                                            | ...            |
    +-----------------+-----------------+----------------+----------------------------------------------+--------------------+-------------------------------+------------------------------------------------+----------------+
    

Processar dados multimodais ordenados usando matrizes de valores ObjectRef

Nesta seção, mostramos como concluir as seguintes tarefas:

  1. Recrie a tabela product_manuals para que ela contenha um arquivo PDF do manual do produto Crittercuisine 5000 e arquivos PDF de cada página desse manual.
  2. Crie uma tabela que mapeia o manual para os blocos. O valor ObjectRef que representa o manual completo é armazenado em uma coluna STRUCT<uri STRING, version STRING, authorizer STRING, details JSON>>. Os valores ObjectRef que representam as páginas do manual são armazenados em uma coluna ARRAY<STRUCT<uri STRING, version STRING, authorizer STRING, details JSON>>.
  3. Analise uma matriz de valores ObjectRef para retornar um único valor gerado.
  4. Analisa uma matriz de valores ObjectRef separadamente e retorna um valor gerado para cada valor da matriz.

Como parte das tarefas de análise, você converte a matriz de valores ObjectRef em uma lista ordenada de valores ObjectRefRuntime e, em seguida, transmite essa lista a um modelo Gemini, especificando os valores ObjectRefRuntime como parte do comando. Os valores ObjectRefRuntime fornecem URLs assinados que o modelo usa para acessar as informações do objeto no Cloud Storage.

Siga estas etapas para processar dados multimodais ordenados usando matrizes de valores ObjectRef:

  1. Acessar a página do BigQuery.

    Acessar o BigQuery

  2. No editor de consultas, execute a seguinte consulta para recriar a tabela 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']);
  3. No editor de consultas, execute a seguinte consulta para gravar dados de PDF na tabela 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;
  4. No editor de consultas, execute a seguinte consulta para conferir os dados do PDF na tabela map_manual_to_chunks:

    SELECT *
    FROM cymbal_pets.map_manual_to_chunks;

    Os resultados são semelhantes aos seguintes:

    +-------------------------------------+--------------------------------+-----------------------------------+------------------------------------------------------+-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+
    | 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}}             |
    |                                     |                                |                                   |                                                      +-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+
    |                                     |                                |                                   |                                                      | ...                                       | ...                             |  ...                               | ...                                                   |
    +-------------------------------------+--------------------------------+-----------------------------------+------------------------------------------------------+-------------------------------------------+---------------------------------+------------------------------------+-------------------------------------------------------+
    
  5. No editor de consultas, execute a consulta a seguir para gerar uma única resposta de um modelo Gemini com base na análise de uma matriz de valores 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));

    Os resultados são semelhantes aos seguintes:

    +-------------------------------------------+
    | 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. |
    +-------------------------------------------+
    
  6. No editor de consultas, execute a consulta a seguir para gerar várias respostas de um modelo Gemini com base na análise de uma matriz de valores 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));

    Os resultados são semelhantes aos seguintes:

    +-----------------------------------------------+-------------------------------------------+----------------------------------------------------+
    | 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.                        |
    +-----------------------------------------------+-------------------------------------------+----------------------------------------------------+
    

Limpar

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.