Databricks Certified Generative AI Engineer Associate 教科書
第2章 データ準備(Data Preparation, 14%)
🎯 この節の学習目標
RAGパイプラインの最初の実務作業が、ソース文書からのテキスト抽出です。ここで文字化けした、順序が崩れた、あるいは本文以外のノイズだらけのテキストを作ってしまうと、その後のチャンキング・埋め込み・検索・生成のすべてが劣化します。いわゆる garbage in, garbage out です。
重要なのは、「PDF」とひとくくりにせず、文書の実体がどんな形式かを見極めてから手法を選ぶことです。試験でも「この形式の文書には何を使うべきか」という選択問題が出題されます。
PDFには大きく2種類あり、必要な技術がまったく異なります。
| PDFの種類 | 実体 | 適切な手法 | 代表的ツール |
|---|---|---|---|
| テキスト埋め込み型 | 文字データがPDF内部に格納されている(コピー&ペーストできる) | PDFパーサーで直接テキストを取り出す | pypdf、pdfplumber など |
| スキャン画像型 | ページが画像として格納されている(文字を選択できない) | OCR(光学文字認識)が必要。パーサーでは何も取れない | Tesseract等のOCRエンジン、OCR内蔵のパースサービス |
Pythonでの最小例は次のとおりです。
# テキスト埋め込み型PDFの抽出(pypdf)
from pypdf import PdfReader
reader = PdfReader("/Volumes/prod/hr_qa/raw_docs/policy.pdf")
text = "\n".join(page.extract_text() for page in reader.pages)
実務では両者が混在するコーパスも多いため、「抽出結果がほぼ空のページはスキャン画像型とみなしてOCRに回す」といった振り分けを行います。また、unstructured のような汎用ライブラリは、PDF・HTML・Word・PowerPointなど多形式を統一的に扱い、要素(タイトル、段落、表など)の種類付きで抽出できるため、混在コーパスの処理によく使われます。
📝 試験のポイント
「スキャンされたPDF(画像ベースのPDF)からテキストを取得したい」という問いにはOCRが正解です。pypdfのような通常のパーサーを選ばせる誤答が並びます。逆に、テキスト埋め込み型のPDFにOCRをかけるのは、精度・コストの面で不利な過剰処理です。「文字を選択できるか否か」を見分けの基準として覚えましょう。
Databricksは、文書パースをプラットフォーム機能として提供する ai_parse_document 関数を持っています。SQLまたはPythonから呼び出し、Volume上のPDF等の非構造化文書からテキストや構造(要素・レイアウト)を抽出できます。AI(視覚モデル)ベースのパースであるため、複雑なレイアウトの文書にも対応しやすいのが特徴です。
-- SQLからVolume上の文書をパースする例
SELECT
path,
ai_parse_document(content) AS parsed
FROM READ_FILES('/Volumes/prod/hr_qa/raw_docs/', format => 'binaryFile');
外部ライブラリを持ち込まずに、Volume上の文書 → Deltaテーブルへのパース結果格納までをDatabricks内で完結できる点が利点です。試験対策としては、「Databricksネイティブの文書パース手段として ai_parse_document がある」と知っていれば十分です。
WebページやイントラネットのHTMLをソースにする場合、課題はタグの除去だけではありません。HTMLには、ナビゲーションメニュー、ヘッダー、フッター、サイドバー、広告、Cookieバナーなど、本文と無関係なボイラープレートが大量に含まれます。これらを索引化すると、どのページにも同じ文言(「ホームに戻る」「プライバシーポリシー」等)が含まれることになり、検索結果がノイズで汚染されます。
BeautifulSoup などのHTMLパーサーで、本文領域(<main> や <article> タグ、本文用のclass)だけを選択的に抽出し、<nav>、<footer>、<script> 等を除去するのが基本です。
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
for tag in soup(["nav", "footer", "header", "script", "style", "aside"]):
tag.decompose() # ボイラープレートを除去
main = soup.find("main") or soup.body
text = main.get_text(separator="\n", strip=True)
💼 例:製品ドキュメントサイトの取り込み
製品マニュアルサイト(HTML)をRAGに取り込んだところ、「〇〇の設定方法は?」という質問に対して、どのページにも共通のフッター文言を含むチャンクばかりが検索上位に並んでしまいました。原因は全ページ共通のナビゲーション・フッターを本文と一緒に索引化していたことです。<article> 要素のみを抽出する処理に変更したところ、検索結果に本文チャンクが並ぶようになり回答品質が改善しました。「共通部分の除去」は抽出段階の必須処理です。
抽出で品質差が出やすいのが、表と文書構造の扱いです。
📝 試験のポイント
試験では「文書形式と抽出手法の対応」が問われます。整理すると:テキスト埋め込みPDF→パーサー(pypdf等)/スキャンPDF→OCR/HTML→タグ除去・本文抽出(BeautifulSoup等)/表を含む文書→表構造を保持できるツール。また「抽出後のテキストに見出し・構造を残す方が後続処理に有利」という方向性の選択肢は正解になりやすいと覚えておきましょう。
✅ この節のまとめ
問1. 紙の契約書をスキャンして作成されたPDF(文字の選択・コピーができない)をRAGのソースにしたい。テキストを取得する手法として適切なのはどれか。
正解:B
文字を選択できないPDFはページが画像として格納されており、テキストデータを持ちません。pypdfのようなパーサー(A)は埋め込みテキストを読む道具なので、ほぼ空の結果しか返せません。BeautifulSoup(C)はHTML用です。バイナリのPDFを文字コードでデコード(D)しても意味のあるテキストは得られません。画像から文字を認識するOCRが唯一の適切な手段です。
問2. 社内WikiのHTMLページ群をRAGに取り込んだところ、どの質問に対しても各ページ共通のナビゲーションメニューやフッターを含むチャンクが検索上位に並び、回答品質が低い。最も適切な対処はどれか。
正解:C
原因はインデックスがボイラープレートで汚染されていることなので、データ側の修正(抽出処理の改善と再インデックス)が根本対処です。A・Dはノイズを含んだままの弥縫策で、かえってプロンプトのノイズが増えます。Bは検索段階の問題に対して生成側を変えており、原因に対処していません。
問3. 料金表や仕様表など多数の表を含む製品カタログPDFをRAG化する。検索・回答品質を保つための抽出方針として最も適切なのはどれか。
正解:C
表は「どの値がどの行・列に属すか」が意味のすべてであり、構造が崩れたテキストは検索品質を下げます。pdfplumber、unstructured、ai_parse_documentなど表構造を扱えるツールで抽出し、構造が伝わる形式で保持するのが定石です。Aは料金・仕様という中核情報を捨ててしまい、Bは表の意味を壊します。Dはツールで自動化可能なので誤りです。
問4. Unity CatalogのVolumeに格納した多様なレイアウトのPDF文書を、外部ライブラリを追加せずDatabricksのネイティブ機能でパースしてDeltaテーブルに格納したい。利用を検討すべき機能はどれか。
正解:A
ai_parse_documentはSQL/Pythonから呼び出せるDatabricksの文書パース関数で、PDF等の非構造化文書からテキスト・構造を抽出できます。Bはファイル取り込み時のスキーマ推定、Cはテーブルの変更差分の取得、DはファイルからテーブルへのロードのためのSQLで、いずれもPDFの内容をテキスト化する機能ではありません。