PDF files, such as financial documents, can be challenging to use in RAG
pipelines because of their complex structure and mix of text, figures, and
tables. This tutorial shows you how to use the
ML.PROCESS_DOCUEMNT function
in combination with Document AI's layout parser to build a RAG pipeline
based on key information extracted from a PDF file.
Objectives
This tutorial covers the following tasks:- Creating a Cloud resource connection so that you can connect to Cloud Storage and Vertex AI from BigQuery.
- Create a Cloud Storage bucket and upload a sample PDF file.
- Creating an object table over the PDF file to make the PDF file available in BigQuery.
- Create a Document AI processor that you can use to parse the PDF file.
- Creating a remote model that lets you use the Document AI API to access the document processor from BigQuery.
- Using the remote model with the
ML.PROCESS_DOCUMENTfunction to parse the PDF contents into chunks and then write that content to a BigQuery table. - Extracting PDF content from the JSON data returned by the
ML.PROCESS_DOCUMENTfunction, and then writing that content to a BigQuery table. - Generate embeddings from the parsed PDF content, and then write those embeddings to a BigQuery table. Embeddings are numerical representations of the PDF content that enable you to perform semantic search and retrieval on the PDF content.
- Use the
VECTOR_SEARCHfunction on the embeddings to identify semantically similar PDF content. - Perform retrieval-augmented generation (RAG) by using the
AI.GENERATEfunction to generate text, using vector search results to augment the prompt input and improve results.
Costs
In this document, you use the following billable components of Cloud de Confiance by S3NS:
- BigQuery: You incur costs for the data that you process in BigQuery.
- Gemini Enterprise Agent Platform: You incur costs for calls to Agent Platform models.
- Document AI: You incur costs for calls to the Document AI API.
- Cloud Storage: You incur costs for object storage in Cloud Storage.
When you finish the tasks that are described in this document, you can avoid continued billing by deleting the resources that you created. For more information, see Clean up.
Before you begin
Console
-
In the Cloud de Confiance console, on the project selector page, select or create a Cloud de Confiance project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Cloud de Confiance project.
Enable the BigQuery, BigQuery Connection, Vertex AI, Document AI, and Cloud Storage APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.-
Make sure that you have the following role or roles on the project: Storage Admin, Document AI Editor, BigQuery Admin, Project IAM Admin
Check for the roles
-
In the Cloud de Confiance console, go to the IAM page.
Go to IAM - Select the project.
-
In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.
- For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.
Grant the roles
-
In the Cloud de Confiance console, go to the IAM page.
Go to IAM - Select the project.
- Click Grant access.
-
In the New principals field, enter your user identifier. This is typically the identifier for a user in a workforce identity pool. For details, see Represent workforce pool users in IAM policies, or contact your administrator.
- Click Select a role, then search for the role.
- To grant additional roles, click Add another role and add each additional role.
- Click Save.
-
gcloud
-
Install the Google Cloud CLI.
-
Configure the gcloud CLI to use your federated identity.
For more information, see Sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init -
Create or select a Cloud de Confiance project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Create a Cloud de Confiance project:
gcloud projects create PROJECT_ID
Replace
PROJECT_IDwith a name for the Cloud de Confiance project you are creating. -
Select the Cloud de Confiance project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_IDwith your Cloud de Confiance project name.
-
Verify that billing is enabled for your Cloud de Confiance project.
Enable the BigQuery, BigQuery Connection, Vertex AI, Document AI, and Cloud Storage APIs:
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.gcloud services enable bigquery.googleapis.com
bigqueryconnection.googleapis.com aiplatform.googleapis.com documentai.googleapis.com storage.googleapis.com -
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/storage.admin, roles/documentai.editor, roles/bigquery.admin, roles/resourcemanager.projectIamAdmingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Replace the following:
PROJECT_ID: Your project ID.USER_IDENTIFIER: The identifier for your user account. For examples, see Represent workforce pool users in IAM policies.ROLE: The IAM role that you grant to your user account.
Create a dataset
Create a BigQuery dataset to store your ML model.
Console
In the Cloud de Confiance console, go to the BigQuery page.
In the Explorer pane, click your project name.
Click View actions > Create dataset
On the Create dataset page, do the following:
For Dataset ID, enter
bqml_tutorial.For Location type, select Multi-region, and then select US.
Leave the remaining default settings as they are, and click Create dataset.
bq
To create a new dataset, use the
bq mk --dataset command.
Create a dataset named
bqml_tutorialwith the data location set toUS.bq mk --dataset \ --location=US \ --description "BigQuery ML tutorial dataset." \ bqml_tutorial
Confirm that the dataset was created:
bq ls
API
Call the datasets.insert
method with a defined dataset resource.
{ "datasetReference": { "datasetId": "bqml_tutorial" } }
Create a connection
Create a Cloud resource connection and get the connection's service account. Create the connection in the same location.
You can skip this step if you either have a default connection configured, or you have the BigQuery Admin role.
Select one of the following options:Console
Go to the BigQuery page.
In the left pane, click Explorer:

If you don't see the left pane, click Expand left pane to open the pane.
In the Explorer pane, expand your project name, and then click Connections.
On the Connections page, click Create connection.
For Connection type, choose Vertex AI remote models, remote functions, BigLake and Spanner (Cloud Resource).
In the Connection ID field, enter a name for your connection.
For Location type, select a location for your connection. The connection should be colocated with your other resources such as datasets.
Click Create connection.
Click Go to connection.
In the Connection info pane, copy the service account ID for use in a later step.
SQL
Use the CREATE CONNECTION statement:
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, enter the following statement:
CREATE CONNECTION [IF NOT EXISTS] `CONNECTION_NAME` OPTIONS ( connection_type = "CLOUD_RESOURCE", friendly_name = "FRIENDLY_NAME", description = "DESCRIPTION" );
Replace the following:
-
CONNECTION_NAME: the name of the connection in either thePROJECT_ID.LOCATION.CONNECTION_ID,LOCATION.CONNECTION_ID, orCONNECTION_IDformat. If the project or location are omitted, then they are inferred from the project and location where the statement is run. -
FRIENDLY_NAME(optional): a descriptive name for the connection. -
DESCRIPTION(optional): a description of the connection.
-
Click Run.
For more information about how to run queries, see Run an interactive query.
bq
In a command-line environment, create a connection:
bq mk --connection --location=REGION --project_id=PROJECT_ID \ --connection_type=CLOUD_RESOURCE CONNECTION_ID
The
--project_idparameter overrides the default project.Replace the following:
REGION: your connection regionPROJECT_ID: your Cloud de Confiance project IDCONNECTION_ID: an ID for your connection
When you create a connection resource, BigQuery creates a unique system service account and associates it with the connection.
Troubleshooting: If you get the following connection error, update the Google Cloud SDK:
Flags parsing error: flag --connection_type=CLOUD_RESOURCE: value should be one of...
Retrieve and copy the service account ID for use in a later step:
bq show --connection PROJECT_ID.REGION.CONNECTION_ID
The output is similar to the following:
name properties 1234.REGION.CONNECTION_ID {"serviceAccountId": "connection-1234-9u56h9@gcp-sa-bigquery-condel.s3ns-system.iam.gserviceaccount.com"}
Python
Before trying this sample, follow the Python setup instructions in the BigQuery quickstart using client libraries. For more information, see the BigQuery Python API reference documentation.
To authenticate to BigQuery, set up Application Default Credentials. For more information, see Set up authentication for client libraries.
Before running code samples, set the GOOGLE_CLOUD_UNIVERSE_DOMAIN environment
variable to s3nsapis.fr.
Node.js
Before trying this sample, follow the Node.js setup instructions in the BigQuery quickstart using client libraries. For more information, see the BigQuery Node.js API reference documentation.
To authenticate to BigQuery, set up Application Default Credentials. For more information, see Set up authentication for client libraries.
Before running code samples, set the GOOGLE_CLOUD_UNIVERSE_DOMAIN environment
variable to s3nsapis.fr.
Terraform
Use the
google_bigquery_connection
resource.
To authenticate to BigQuery, set up Application Default Credentials. For more information, see Set up authentication for client libraries.
The following example creates a Cloud resource connection named
my_cloud_resource_connection in the US region:
To apply your Terraform configuration in a Cloud de Confiance project, complete the steps in the following sections.
Prepare Cloud Shell
- Launch Cloud Shell.
-
Set the default Cloud de Confiance project where you want to apply your Terraform configurations.
You only need to run this command once per project, and you can run it in any directory.
export GOOGLE_CLOUD_PROJECT=PROJECT_ID
Environment variables are overridden if you set explicit values in the Terraform configuration file.
Prepare the directory
Each Terraform configuration file must have its own directory (also called a root module).
-
In Cloud Shell, create a directory and a new
file within that directory. The filename must have the
.tfextension—for examplemain.tf. In this tutorial, the file is referred to asmain.tf.mkdir DIRECTORY && cd DIRECTORY && touch main.tf
-
If you are following a tutorial, you can copy the sample code in each section or step.
Copy the sample code into the newly created
main.tf.Optionally, copy the code from GitHub. This is recommended when the Terraform snippet is part of an end-to-end solution.
- Review and modify the sample parameters to apply to your environment.
- Save your changes.
-
Initialize Terraform. You only need to do this once per directory.
terraform init
Optionally, to use the latest Google provider version, include the
-upgradeoption:terraform init -upgrade
Apply the changes
-
Review the configuration and verify that the resources that Terraform is going to create or
update match your expectations:
terraform plan
Make corrections to the configuration as necessary.
-
Apply the Terraform configuration by running the following command and entering
yesat the prompt:terraform apply
Wait until Terraform displays the "Apply complete!" message.
- Open your Cloud de Confiance project to view the results. In the Cloud de Confiance console, navigate to your resources in the UI to make sure that Terraform has created or updated them.
Grant access to the service account
Select one of the following options:
Console
Go to the IAM & Admin page.
Click Grant Access.
The Add principals dialog opens.
In the New principals field, enter the service account ID that you copied earlier.
In the Select a role field, select Document AI, and then select Document AI Viewer.
Click Add another role.
In the Select a role field, select Cloud Storage, and then select Storage Object Viewer.
Click Add another role.
In the Select a role field, select Vertex AI, and then select Vertex AI User.
Click Save.
gcloud
Use the
gcloud projects add-iam-policy-binding command:
gcloud projects add-iam-policy-binding 'PROJECT_NUMBER' --member='serviceAccount:MEMBER' --role='roles/documentai.viewer' --condition=None gcloud projects add-iam-policy-binding 'PROJECT_NUMBER' --member='serviceAccount:MEMBER' --role='roles/storage.objectViewer' --condition=None gcloud projects add-iam-policy-binding 'PROJECT_NUMBER' --member='serviceAccount:MEMBER' --role='roles/aiplatform.user' --condition=None
Replace the following:
PROJECT_NUMBER: your project number.MEMBER: the service account ID that you copied earlier.
Upload the sample PDF to Cloud Storage
To upload the sample PDF to Cloud Storage, follow these steps:
- Download the
scf23.pdfsample PDF by going to https://www.federalreserve.gov/publications/files/scf23.pdf and clicking download . - Create a Cloud Storage bucket.
- Upload the
scf23.pdffile to the bucket.
Create an object table
Create an object table over the PDF file in Cloud Storage:
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, run the following statement:
CREATE OR REPLACE EXTERNAL TABLE `bqml_tutorial.pdf` WITH CONNECTION `LOCATION.CONNECTION_ID` OPTIONS( object_metadata = 'SIMPLE', uris = ['gs://BUCKET/scf23.pdf']);
Replace the following:
LOCATION: the connection location.CONNECTION_ID: the ID of your BigQuery connection.When you view the connection details in the Cloud de Confiance console, the
CONNECTION_IDis the value in the last section of the fully qualified connection ID that is shown in Connection ID, for exampleprojects/myproject/locations/connection_location/connections/myconnection.BUCKET: the Cloud Storage bucket containing thescf23.pdffile. The fullurioption value should look similar to['gs://mybucket/scf23.pdf'].
Create a document processor
Create a document processor
based on the layout parser processor
in the us multi-region. Copy the prediction endpoint from the
Processor details page to use in the next section.
Create the remote model for the document processor
Create a remote model to access the Document AI processor:
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, run the following statement:
CREATE OR REPLACE MODEL `bqml_tutorial.parser_model` REMOTE WITH CONNECTION `LOCATION.CONNECTION_ID` OPTIONS(remote_service_type = 'CLOUD_AI_DOCUMENT_V1', document_processor = 'PROCESSOR_ID');
Replace the following:
LOCATION: the connection location.CONNECTION_ID: the ID of your BigQuery connection.When you view the connection details in the Cloud de Confiance console, the
CONNECTION_IDis the value in the last section of the fully qualified connection ID that is shown in Connection ID, for exampleprojects/myproject/locations/connection_location/connections/myconnection.PROCESSOR_ID: the document processor ID. To find this value, view the processor details, and then look at the ID row in the Basic Information section.
Parse the PDF file into chunks
Use the document processor with the ML.PROCESS_DOCUMENT function to parse the
PDF file into chunks, and then write that content to a table. The
ML.PROCESS_DOCUMENT function returns the PDF chunks in JSON format.
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, run the following statement:
CREATE or REPLACE TABLE
bqml_tutorial.chunked_pdfAS ( SELECT * FROM ML.PROCESS_DOCUMENT( MODELbqml_tutorial.parser_model, TABLEbqml_tutorial.pdf, PROCESS_OPTIONS => (JSON '{"layout_config": {"chunking_config": {"chunk_size": 250}}}') ) );
Parse the PDF chunk data into separate columns
Extract the PDF content and metadata information from the JSON data returned
by the ML.PROCESS_DOCUMENT function, and then write that content to a
table:
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, run the following statement to parse the PDF content:
CREATE OR REPLACE TABLE
bqml_tutorial.parsed_pdfAS ( SELECT uri, JSON_EXTRACT_SCALAR(json , '$.chunkId') AS id, JSON_EXTRACT_SCALAR(json , '$.content') AS content, JSON_EXTRACT_SCALAR(json , '$.pageFooters[0].text') AS page_footers_text, JSON_EXTRACT_SCALAR(json , '$.pageSpan.pageStart') AS page_span_start, JSON_EXTRACT_SCALAR(json , '$.pageSpan.pageEnd') AS page_span_end FROMbqml_tutorial.chunked_pdf, UNNEST(JSON_EXTRACT_ARRAY(ml_process_document_result.chunkedDocument.chunks, '$')) json );In the query editor, run the following statement to view a subset of the parsed PDF content:
SELECT * FROM `bqml_tutorial.parsed_pdf` ORDER BY id LIMIT 5;
The output is similar to the following:
+-----------------------------------+------+------------------------------------------------------------------------------------------------------+-------------------+-----------------+---------------+ | uri | id | content | page_footers_text | page_span_start | page_span_end | +-----------------------------------+------+------------------------------------------------------------------------------------------------------+-------------------+-----------------+---------------+ | gs://mybucket/scf23.pdf | c1 | •BOARD OF OF FEDERAL GOVERN NOR RESERVE SYSTEM RESEARCH & ANALYSIS | NULL | 1 | 1 | | gs://mybucket/scf23.pdf | c10 | • In 2022, 20 percent of all families, 14 percent of families in the bottom half of the usual ... | NULL | 8 | 9 | | gs://mybucket/scf23.pdf | c100 | The SCF asks multiple questions intended to capture whether families are credit constrained, ... | NULL | 48 | 48 | | gs://mybucket/scf23.pdf | c101 | Bankruptcy behavior over the past five years is based on a series of retrospective questions ... | NULL | 48 | 48 | | gs://mybucket/scf23.pdf | c102 | # Percentiles of the Distributions of Income and Net Worth | NULL | 48 | 49 | +-----------------------------------+------+------------------------------------------------------------------------------------------------------+-------------------+-----------------+---------------+
Generate embeddings
Generate embeddings for the parsed PDF content and then write them to a table:
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, run the following statement:
CREATE OR REPLACE TABLE `bqml_tutorial.embeddings` AS ( SELECT *, AI.EMBED(content, endpoint => 'text-embedding-005').result AS embedding FROM bqml_tutorial.parsed_pdf );
Run a vector search
Run a vector search against the parsed PDF content.
The following query takes text input, creates an embedding for that input
using the AI.EMBED function, and then uses the VECTOR_SEARCH
function to match the input embedding with the most similar PDF content
embeddings. The results are the top ten PDF chunks that are most related
to changes in family net worth.
Go to the BigQuery page.
In the query editor, run the following SQL statement:
SELECT distance, base.id AS chunk_id, base.page_span_start AS start_page, base.page_span_end AS end_page, base.content FROM VECTOR_SEARCH( TABLE `bqml_tutorial.embeddings`, 'embedding', query_value => AI.EMBED( 'Did the typical family net worth increase? If so, by how much?', endpoint => 'text-embedding-005').result, top_k => 3, OPTIONS => '{"fraction_lists_to_search": 0.01}') ORDER BY distance DESC;
The output is similar to the following:
+----------+----------+------------+----------+-----------------------------------+ | distance | chunk_id | start_page | end_page | content | +----------+----------+------------+----------+-----------------------------------+ | 0.645685 | 26 | 17 | 18 | 18 Between the first quarter of | | | | | | 2019 and the first quarter of... | +----------+----------+------------+----------+-----------------------------------+ | 0.602665 | 30 | 19 | 21 | ## Net Worth by Family | | | | | | Characteristics... | +----------+----------+------------+----------+-----------------------------------+ | 0.599438 | 24 | 17 | 21 | # Net Worth | | | | | | The net improvements in... | +----------+----------+------------+----------+-----------------------------------+
Generate text augmented by vector search results
Perform a vector search on the embeddings to identify semantically similar
PDF content, and then use the AI.GENERATE function with the vector
search results to augment the prompt input and improve the text generation
results. In this case, the query uses information from the PDF chunks to answer
a question about the change in family net worth over the past decade.
In the Cloud de Confiance console, go to the BigQuery page.
In the query editor, run the following statement:
SELECT AI.GENERATE( CONCAT('Did the typical family net worth change? How does this compare the SCF survey a decade earlier? Be concise and use the following context:', STRING_AGG(FORMAT("context: %s", base.content), ',\n') ) ).result AS response FROM VECTOR_SEARCH( TABLE `bqml_tutorial.embeddings`, 'embedding', query_value => AI.EMBED( 'Did the typical family net worth increase? If so, by how much?', endpoint => 'text-embedding-005').result, top_k => 3, OPTIONS => '{"fraction_lists_to_search": 0.01}')
The output is similar to the following:
+-------------------------------------------------------------------------+ | response | +-------------------------------------------------------------------------+ | Yes, the typical family net worth changed significantly. | | | | Real median net worth surged 37% between the 2019 and 2022 SCF surveys. | | This contrasts sharply with a decade earlier (2010-2013), when real | | median net worth decreased 2%. | +-------------------------------------------------------------------------+
Clean up
To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.
Delete the project
Delete a Cloud de Confiance project:
gcloud projects delete PROJECT_ID
What's next
- Learn more about the
ML.PROCESS_DOCUMENTfunction. - Learn more about performing semantic search and RAG.