検索拡張生成パイプラインで PDF を解析する
このチュートリアルでは、解析された PDF コンテンツに基づいて検索拡張生成(RAG)パイプラインを作成するプロセスについて説明します。
財務ドキュメントなどの PDF ファイルは、複雑な構造とテキスト、図、表が混在しているため、RAG パイプラインで使用するのが難しい場合があります。このチュートリアルでは、BigQuery ML の機能と Document AI のレイアウト パーサーを組み合わせて、PDF ファイルから抽出された重要な情報に基づいて RAG パイプラインを構築する方法について説明します。
または、Colab Enterprise ノートブックを使用してこのチュートリアルを実施することもできます。
目標
このチュートリアルでは、次のタスクについて説明します。
- Cloud Storage バケットを作成し、サンプル PDF ファイルをアップロードする。
- Cloud リソース接続を作成し、BigQuery から Cloud Storage と Vertex AI に接続できるようにする。
- PDF ファイルにオブジェクト テーブルを作成し、BigQuery で PDF ファイルを使用できるようにします。
- PDF ファイルの解析に使用できる Document AI プロセッサの作成。
- Document AI API を使用して BigQuery からドキュメント プロセッサにアクセスできるようにするリモートモデルを作成する。
- リモートモデルと
ML.PROCESS_DOCUMENT
関数を使用して、PDF コンテンツをチャンクに解析し、そのコンテンツを BigQuery テーブルに書き込む。 ML.PROCESS_DOCUMENT
関数によって返された JSON データから PDF コンテンツを抽出し、そのコンテンツを BigQuery テーブルに書き込む。- BigQuery から Vertex AI
text-embedding-004
エンベディング生成モデルを使用できるようにするリモートモデルを作成する。 - リモートモデルと
ML.GENERATE_EMBEDDING
関数を使用して、解析された PDF コンテンツからエンベディングを生成し、それらのエンベディングを BigQuery テーブルに書き込む。エンベディングは、PDF コンテンツの数値表現であり、PDF コンテンツに対してセマンティック検索と取得を実行できます。 - エンベディングで
VECTOR_SEARCH
関数を使用して、意味的に類似した PDF コンテンツを識別する。 - BigQuery から Vertex AI
gemini-1.5-flash
テキスト生成モデルを使用できるようにするリモートモデルを作成する。 - リモートモデルと
ML.GENERATE_TEXT
関数を使用してテキストを生成し、ベクトル検索の結果からプロンプト入力を補強して結果を改善することで、検索拡張生成(RAG)を行う。
料金
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
- BigQuery: You incur costs for the data that you process in BigQuery.
- Vertex AI: You incur costs for calls to Vertex AI models.
- Document AI: You incur costs for calls to the Document AI API.
- Cloud Storage: You incur costs for object storage in Cloud Storage.
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
詳細については、次の料金ページをご覧ください。
始める前に
-
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, Vertex AI, Document AI, and Cloud Storage APIs.
必要なロール
Cloud Storage バケットとオブジェクトを作成するには、
roles/storage.storageAdmin
ロールのメンバーシップが必要です。Document AI プロセッサを作成するには、
roles/documentai.editor
ロールのメンバーシップが必要です。接続を作成するには、
roles/bigquery.connectionAdmin
ロールのメンバーシップが必要です。接続のサービス アカウントに権限を付与するには、
roles/resourcemanager.projectIamAdmin
ロールのメンバーシップが必要です。このチュートリアルで、残りの BigQuery オペレーションに必要となる IAM 権限は、次の 2 つのロールに含まれています。
- BigQuery データ編集者(
roles/bigquery.dataEditor
)。モデル、テーブル、インデックスを作成するためのロールです。 - BigQuery ユーザー(
roles/bigquery.user
)。BigQuery ジョブを実行するためのロールです。
- BigQuery データ編集者(
データセットの作成
ML モデルを格納する BigQuery データセットを作成します。
Google Cloud コンソールで [BigQuery] ページに移動します。
[エクスプローラ] ペインで、プロジェクト名をクリックします。
「アクションを表示」> [データセットを作成] をクリックします。
[データセットを作成する] ページで、次の操作を行います。
[データセット ID] に「
bqml_tutorial
」と入力します。[ロケーション タイプ] で [マルチリージョン] を選択してから、[US (米国の複数のリージョン)] を選択します。
一般公開データセットは
US
マルチリージョンに保存されています。わかりやすくするため、データセットを同じロケーションに保存します。残りのデフォルトの設定は変更せず、[データセットを作成] をクリックします。
接続を作成する
クラウド リソース接続を作成し、接続のサービス アカウントを取得します。同じロケーションに接続を作成します。
次のオプションのいずれかを選択します。
コンソール
BigQuery ページに移動します。
接続を作成するには、[
追加] をクリックし、続いて [外部データソースへの接続] をクリックします。[接続タイプ] リストで、[Vertex AI リモートモデル、リモート関数、BigLake(Cloud リソース)] を選択します。
[接続 ID] フィールドに接続の名前を入力します。
[接続を作成] をクリックします。
[接続へ移動] をクリックします。
[接続情報] ペインで、後の手順で使用するサービス アカウント ID をコピーします。
bq
コマンドライン環境で接続を作成します。
bq mk --connection --location=REGION --project_id=PROJECT_ID \ --connection_type=CLOUD_RESOURCE CONNECTION_ID
--project_id
パラメータは、デフォルト プロジェクトをオーバーライドします。以下を置き換えます。
REGION
: 接続のリージョンPROJECT_ID
: 実際の Google Cloud プロジェクト IDCONNECTION_ID
: 接続の ID
接続リソースを作成すると、BigQuery は、一意のシステム サービス アカウントを作成し、それを接続に関連付けます。
トラブルシューティング: 次の接続エラーが発生した場合は、Google Cloud SDK を更新します。
Flags parsing error: flag --connection_type=CLOUD_RESOURCE: value should be one of...
後の手順で使用するため、サービス アカウント ID を取得してコピーします。
bq show --connection PROJECT_ID.REGION.CONNECTION_ID
出力は次のようになります。
name properties 1234.REGION.CONNECTION_ID {"serviceAccountId": "connection-1234-9u56h9@gcp-sa-bigquery-condel.iam.gserviceaccount.com"}
Terraform
google_bigquery_connection
リソースを使用します。
BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、クライアント ライブラリの認証を設定するをご覧ください。
次の例では、US
リージョンに my_cloud_resource_connection
という名前の Cloud リソース接続を作成します。
Google Cloud プロジェクトで Terraform 構成を適用するには、次のセクションの手順を完了します。
Cloud Shell を準備する
- Cloud Shell を起動します。
-
Terraform 構成を適用するデフォルトの Google Cloud プロジェクトを設定します。
このコマンドは、プロジェクトごとに 1 回だけ実行する必要があります。これは任意のディレクトリで実行できます。
export GOOGLE_CLOUD_PROJECT=PROJECT_ID
Terraform 構成ファイルに明示的な値を設定すると、環境変数がオーバーライドされます。
ディレクトリを準備する
Terraform 構成ファイルには独自のディレクトリ(ルート モジュールとも呼ばれます)が必要です。
-
Cloud Shell で、ディレクトリを作成し、そのディレクトリ内に新しいファイルを作成します。ファイルの拡張子は
.tf
にする必要があります(例:main.tf
)。このチュートリアルでは、このファイルをmain.tf
とします。mkdir DIRECTORY && cd DIRECTORY && touch main.tf
-
チュートリアルを使用している場合は、各セクションまたはステップのサンプルコードをコピーできます。
新しく作成した
main.tf
にサンプルコードをコピーします。必要に応じて、GitHub からコードをコピーします。Terraform スニペットがエンドツーエンドのソリューションの一部である場合は、この方法をおすすめします。
- 環境に適用するサンプル パラメータを確認し、変更します。
- 変更を保存します。
-
Terraform を初期化します。これは、ディレクトリごとに 1 回だけ行う必要があります。
terraform init
必要に応じて、最新バージョンの Google プロバイダを使用する場合は、
-upgrade
オプションを使用します。terraform init -upgrade
変更を適用する
-
構成を確認して、Terraform が作成または更新するリソースが想定どおりであることを確認します。
terraform plan
必要に応じて構成を修正します。
-
次のコマンドを実行し、プロンプトで「
yes
」と入力して、Terraform 構成を適用します。terraform apply
Terraform に「Apply complete!」のメッセージが表示されるまで待ちます。
- Google Cloud プロジェクトを開いて結果を表示します。Google Cloud コンソールの UI でリソースに移動して、Terraform によって作成または更新されたことを確認します。
サービス アカウントへのアクセスを許可する
次のオプションのいずれかを選択します。
コンソール
[IAM と管理] ページに移動
[
アクセス権を付与] をクリックします。[プリンシパルを追加] ダイアログが開きます。
[新しいプリンシパル] フィールドに、前の手順でコピーしたサービス アカウント ID を入力します。
[ロールを選択] フィールドで、[Document AI] を選択し、[Document AI 閲覧者] を選択します。
[別の役割を追加] をクリックします。
[ロールを選択] フィールドで、[Cloud Storage] を選択し、続いて [Storage オブジェクト閲覧者] を選択します。
[別のロールを追加] をクリックします。
[ロールを選択] フィールドで、[Vertex AI]、[Vertex AI ユーザー] の順に選択します。
[保存] をクリックします。
gcloud
gcloud projects add-iam-policy-binding
コマンドを実行します。
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
次のように置き換えます。
PROJECT_NUMBER
: プロジェクトの番号MEMBER
: 先ほどコピーしたサービス アカウント ID。
サンプル PDF を Cloud Storage にアップロードする
サンプル PDF を Cloud Storage にアップロードする手順は次のとおりです。
scf23.pdf
サンプル PDF をダウンロードするには、https://www.federalreserve.gov/publications/files/scf23.pdf にアクセスし、ダウンロードアイコン をクリックします。- Cloud Storage バケットを作成する。
scf23.pdf
ファイルをバケットにアップロードします。
オブジェクト テーブルを作成する
Cloud Storage 内の PDF ファイルにオブジェクト テーブルを作成します。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで次のステートメントを実行します。
CREATE OR REPLACE EXTERNAL TABLE `bqml_tutorial.pdf` WITH CONNECTION `LOCATION.CONNECTION_ID` OPTIONS( object_metadata = 'SIMPLE', uris = ['gs://BUCKET/scf23.pdf']);
次のように置き換えます。
LOCATION
: 接続のロケーション。CONNECTION_ID
: BigQuery 接続の ID。Google Cloud コンソールで接続の詳細を表示する場合、
CONNECTION_ID
は、[接続 ID] に表示される完全修飾接続 ID の最後のセクションの値になります(例:projects/myproject/locations/connection_location/connections/myconnection
)。BUCKET
:scf23.pdf
ファイルを含む Cloud Storage バケット。uri
オプションの完全な値は['gs://mybucket/scf23.pdf']
に似ています。
ドキュメント プロセッサを作成する
us
マルチリージョンの Layout Parser プロセッサに基づいてドキュメント プロセッサを作成します。
ドキュメント プロセッサのリモートモデルを作成する
Document AI プロセッサにアクセスするリモートモデルを作成します。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで次のステートメントを実行します。
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');
次のように置き換えます。
LOCATION
: 接続のロケーション。CONNECTION_ID
: BigQuery 接続の ID。Google Cloud コンソールで接続の詳細を表示する場合、
CONNECTION_ID
は、[接続 ID] に表示される完全修飾接続 ID の最後のセクションの値になります(例:projects/myproject/locations/connection_location/connections/myconnection
)。PROCESSOR_ID
: ドキュメント プロセッサ ID。この値を確認するには、プロセッサの詳細を表示し、[基本情報] セクションの [ID] 行を確認します。
PDF ファイルをチャンクに分割して解析する
ドキュメント プロセッサと ML.PROCESS_DOCUMENT
関数を使用して PDF ファイルをチャンクに解析し、そのコンテンツをテーブルに書き込みます。ML.PROCESS_DOCUMENT
関数は、PDF チャンクを JSON 形式で返します。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで、次のステートメントを実行します。
CREATE or REPLACE TABLE
bqml_tutorial.chunked_pdf
AS ( SELECT * FROM ML.PROCESS_DOCUMENT( MODELbqml_tutorial.parser_model
, TABLEbqml_tutorial.pdf
, PROCESS_OPTIONS => (JSON '{"layout_config": {"chunking_config": {"chunk_size": 250}}}') ) );
PDF チャンクデータを個別の列に解析する
ML.PROCESS_DOCUMENT
関数によって返された JSON データから PDF コンテンツとメタデータ情報を抽出し、そのコンテンツをテーブルに書き込みます。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで次のステートメントを実行して、PDF コンテンツを解析します。
CREATE OR REPLACE TABLE
bqml_tutorial.parsed_pdf
AS ( 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 );クエリエディタで次のステートメントを実行して、解析された PDF コンテンツのサブセットを表示します。
SELECT * FROM `bqml_tutorial.parsed_pdf` ORDER BY id LIMIT 5;
出力は次のようになります。
+-----------------------------------+------+------------------------------------------------------------------------------------------------------+-------------------+-----------------+---------------+ | 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 | +-----------------------------------+------+------------------------------------------------------------------------------------------------------+-------------------+-----------------+---------------+
エンベディング生成用のリモートモデルを作成する
ホストされる Vertex AI テキスト エンベディング生成モデルを表すリモートモデルを作成します。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで次のステートメントを実行します。
CREATE OR REPLACE MODEL `bqml_tutorial.embedding_model` REMOTE WITH CONNECTION `LOCATION.CONNECTION_ID` OPTIONS (ENDPOINT = 'text-embedding-004');
次のように置き換えます。
LOCATION
: 接続のロケーション。CONNECTION_ID
: BigQuery 接続の ID。Google Cloud コンソールで接続の詳細を表示する場合、
CONNECTION_ID
は、[接続 ID] に表示される完全修飾接続 ID の最後のセクションの値になります(例:projects/myproject/locations/connection_location/connections/myconnection
)。
エンベディングを生成する
解析された PDF コンテンツのエンベディングを生成し、テーブルに書き込みます。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで次のステートメントを実行します。
CREATE OR REPLACE TABLE `bqml_tutorial.embeddings` AS SELECT * FROM ML.GENERATE_EMBEDDING( MODEL `bqml_tutorial.embedding_model`, TABLE `bqml_tutorial.parsed_pdf` );
ベクトル検索を実行する
解析された PDF コンテンツに対してベクトル検索を実行します。
次のクエリは、テキスト入力を受け取り、ML.GENERATE_EMBEDDING
関数を使用してその入力のエンベディングを作成し、VECTOR_SEARCH
関数を使用して入力エンベディングを最も類似した PDF コンテンツ エンベディングと照合します。結果は、入力に最も意味的に類似する上位 10 個の PDF チャンクです。
[BigQuery] ページに移動します。
クエリエディタで、次の SQL ステートメントを実行します。
SELECT query.query, base.id AS pdf_chunk_id, base.content, distance FROM VECTOR_SEARCH( TABLE `bqml_tutorial.embeddings`, 'ml_generate_embedding_result', ( SELECT ml_generate_embedding_result, content AS query FROM ML.GENERATE_EMBEDDING( MODEL `bqml_tutorial.embedding_model`, ( SELECT 'Did the typical family net worth increase? If so, by how much?' AS content) ) ), top_k => 10, OPTIONS => '{"fraction_lists_to_search": 0.01}') ORDER BY distance DESC;
出力は次のようになります。
+-------------------------------------------------+--------------+------------------------------------------------------------------------------------------------------+---------------------+ | query | pdf_chunk_id | content | distance | +-------------------------------------------------+--------------+------------------------------------------------------------------------------------------------------+---------------------+ | Did the typical family net worth increase? ,... | c9 | ## Assets | 0.31113668174119469 | | | | | | | | | The homeownership rate increased slightly between 2019 and 2022, to 66.1 percent. For ... | | +-------------------------------------------------+--------------+------------------------------------------------------------------------------------------------------+---------------------+ | Did the typical family net worth increase? ,... | c50 | # Box 3. Net Housing Wealth and Housing Affordability | 0.30973592073929113 | | | | | | | | | For families that own their primary residence ... | | +-------------------------------------------------+--------------+------------------------------------------------------------------------------------------------------+---------------------+ | Did the typical family net worth increase? ,... | c50 | 3 In the 2019 SCF, a small portion of the data collection overlapped with early months of | 0.29270064592817646 | | | | the COVID- ... | | +-------------------------------------------------+--------------+------------------------------------------------------------------------------------------------------+---------------------+
テキスト生成用のリモートモデルを作成する
ホストされる Vertex AI テキスト生成モデルを表すリモートモデルを作成します。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで次のステートメントを実行します。
CREATE OR REPLACE MODEL `bqml_tutorial.text_model` REMOTE WITH CONNECTION `LOCATION.CONNECTION_ID` OPTIONS (ENDPOINT = 'gemini-1.5-flash-002');
次のように置き換えます。
LOCATION
: 接続のロケーション。CONNECTION_ID
: BigQuery 接続の ID。Google Cloud コンソールで接続の詳細を表示する場合、
CONNECTION_ID
は、[接続 ID] に表示される完全修飾接続 ID の最後のセクションの値になります(例:projects/myproject/locations/connection_location/connections/myconnection
)。
ベクトル検索の結果で拡張されたテキストを生成する
エンベディングでベクトル検索を実行して、意味的に類似した PDF コンテンツを特定します。次に、ベクトル検索結果で ML.GENERATE_TEXT
関数を使用してプロンプト入力を補強し、テキスト生成結果を改善します。この場合、クエリは PDF チャンクの情報を使用して、過去 10 年間の家族の純資産の変化に関する質問に回答します。
Google Cloud コンソールで [BigQuery] ページに移動します。
クエリエディタで、次のステートメントを実行します。
SELECT ml_generate_text_llm_result AS generated FROM ML.GENERATE_TEXT( MODEL `bqml_tutorial.text_model`, ( SELECT 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 and reference: %s", base.content, base.uri), ',\n')) AS prompt, FROM VECTOR_SEARCH( TABLE `bqml_tutorial.embeddings`, 'ml_generate_embedding_result', ( SELECT ml_generate_embedding_result, content AS query FROM ML.GENERATE_EMBEDDING( MODEL `bqml_tutorial.embedding_model`, ( SELECT 'Did the typical family net worth change? How does this compare the SCF survey a decade earlier?' AS content ) ) ), top_k => 10, OPTIONS => '{"fraction_lists_to_search": 0.01}') ), STRUCT(512 AS max_output_tokens, TRUE AS flatten_json_output) );
出力は次のようになります。
+-------------------------------------------------------------------------------+ | generated | +-------------------------------------------------------------------------------+ | Between the 2019 and 2022 Survey of Consumer Finances (SCF), real median | | family net worth surged 37 percent to $192,900, and real mean net worth | | increased 23 percent to $1,063,700. This represents the largest three-year | | increase in median net worth in the history of the modern SCF, exceeding the | | next largest by more than double. In contrast, between 2010 and 2013, real | | median net worth decreased 2 percent, and real mean net worth remained | | unchanged. | +-------------------------------------------------------------------------------+
クリーンアップ
- 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.