AIの口に辞書を丸ごと詰め込むことはできない
ベクターデータベース(Vector DB)の威力を理解した上司は、過去10年間のすべての製品カタログ、従業員マニュアル、レポート(合計1000のPDFファイル)をあなたに手渡し、「これらをすべてベクトル化してデータベースに保存してくれ!」と命じました。
もし500ページのPDFを開き、そのままOpenAIにEmbedding処理をさせようとするとどうなるでしょうか?
OpenAIは即座に赤いエラー画面を表示します:TokenLimitExceeded(トークン上限超過)。
Embedding処理を行うにせよ、ChatGPTに文章を読ませるにせよ、すべてのAIモデルには脳の容量限界(Context Window、コンテキストウィンドウと呼ばれます)があります。 たとえ10万字を処理できると謳うモデルがあったとしても、500ページのマニュアルを丸ごと投げ込んで「234ページの保証条項は何ですか?」と質問すると、情報量が多すぎて「焦点がぼける」現象が発生し、細部を見落とすでしょう。これはAI業界で**「Lost in the middle(中間での迷子)」**効果と呼ばれています。
したがって、RAGシステムには絶対的な鉄則があります: 「AIにドキュメントを渡す前に、必ず『小さなチャンク(肉の切り身)』に分割しなければならない!」
これは子供にステーキを食べさせるようなものです。ステーキを丸ごと口に入れることはできません。一口サイズに切る必要があります。
知識加工生産ラインの2つの工程
LangChainは、完璧な自動化生産ラインツールを提供しており、以下の2つの工程に分かれています:
第一工程:Document Loaders(ドキュメントローダー)
これは「さまざまな形式のファイルを純粋なテキストに統一変換する」専門のロボット群です。
企業内のデータはPDF、Wordファイル、Notionウェブページなどに散らばっています。
LangChainは100種類以上のLoaderを提供しています!PyPDFLoader、Docx2txtLoader、WebBaseLoaderなど、呼び出すだけでこれらのファイルからテキストをきれいに抽出し、クリーンなPython文字列に変換します。
第二工程:Text Splitters(テキストスプリッター)
テキストがきれいに抽出されたら、次はこの「肉切り機」に入ります。 もし単に「500文字ごとに切る」と規定したら、悲惨な結果になるかもしれません。例えば「極速旋風3000型の保証期間は十年です」という文章が500文字目で「保証」の途中で切れてしまうと:
- チャンクA:
...極速旋風3000型の保 - チャンクB:
証期間は十年です...
このように切ると、これらのチャンクの意味は完全に壊れてしまいます!AIも混乱するでしょう。
そこでLangChainは非常に賢い肉切り機**RecursiveCharacterTextSplitterを提供しています。
これは切るときに「段落(改行)」や「句点」を優先的に切り目とします。もし文字数が足りない場合はOverlap(重複領域)**を追加します。つまり、チャンクAの終わりとチャンクBの始まりには少し重複したテキストがあり、意味が突然切れないようにします。
Vibe Prompt実践:自動肉切り機の構築
このデータ処理コードを手書きすると非常に面倒ですが、AIに詠唱するだけで数秒で完成します。
【RAGドキュメント処理自動化Prompt】 LangChainを使用してRAGシステムを開発しています。
company_manual.pdfというファイルがあります。 以下の「知識加工」プロセスを実行するPython関数を作成してください:
PyPDFLoaderを使用してこのPDFファイルをロードします。RecursiveCharacterTextSplitterを使用してドキュメントを分割します。- 分割パラメータ:各チャンクサイズ(chunk_size)は1000文字、重複文字数(chunk_overlap)は200文字に設定します。
- 最後に「合計で何チャンクに分割されたか」と「最初のチャンクの内容」を表示して確認します。
- コード構造をクリーンに保ち、日本語のコメントを付けてください。
AIが生成した知識加工スクリプト:
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
def process_pdf_document():
file_path = "company_manual.pdf"
print(f"正在載入文件:{file_path} ...")
try:
# 第一工程:PDFローダーを呼び出し、PDF全体を読み込む
loader = PyPDFLoader(file_path)
documents = loader.load()
print(f"✅ PDFロード成功!合計{len(documents)}ページ。")
# 第二工程:賢いテキスト分割機を設定
# chunk_size=1000 各チャンク約1000文字
# chunk_overlap=200 チャンク間に200文字の重複を設け、意味の断絶を防ぐ
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", "。", "!", " ", ""] # 段落や句点を優先的に切る
)
# 読み込んだPDFを肉切り機に投入!
print("テキスト分割中...")
chunks = text_splitter.split_documents(documents)
# 結果を表示
print("=========================================")
print(f"✅ 加工完了!このPDFは{len(chunks)}個のチャンクに正確に分割されました。")
print("=========================================")
print("【最初のチャンクの内容を試食】:")
print(chunks[0].page_content)
# 実際のRAGプロジェクトでは、これらのチャンクをEmbedding処理し、Chromaデータベースに保存します。
return chunks
except Exception as e:
print(f"🚨 ドキュメント処理中にエラーが発生しました:{e}")
# 関数を実行(company_manual.pdfが実際に存在する場合)
# chunks = process_pdf_document()
このコードを実行すれば、数百ページに及ぶ機密PDFマニュアルは、数千個の整然とした、適切な長さで意味が完結した「テキストブロック」に変わります。
さて、小さなブロックが手に入り、前章で学んだEmbedding技術も持っています。 次の章では、最も興奮するクライマックスを迎えます:すべてのブロックをつなぎ合わせ、究極のRAG質問応答ボットを召喚します!