
【GenU完全攻略 #4】GenU × RAG 基礎編——ナレッジベース構築と検索の仕組み
GenUのRAG機能を使うと、社内ドキュメントや業務データをAIが参照しながら回答できるようになる。
この記事ではBedrock Knowledge Baseの構成要素・データソースの種類・検索の仕組みを整理して、GenUでRAGを動かすまでの全体像をつかむ。
GenUのRAGとは
GenUのRAG(Retrieval-Augmented Generation)は、Amazon Bedrock Knowledge Baseを使ってドキュメントを検索し、その内容をもとにLLMが回答を生成する仕組み。
ユーザーの質問
↓
Knowledge Base(ドキュメント検索)
↓
関連チャンクを取得
↓
LLM(Claudeなど)が回答を生成
↓
引用元とともに回答を返す
LLM単体では「自社の就業規則は?」「先月の会議で決まったことは?」といった社内固有の情報は答えられない。Knowledge Baseに社内ドキュメントを登録することで、LLMがそれを参照して回答できるようになる。
Knowledge Baseの構成要素
Bedrock Knowledge Baseは3つの要素で構成される。
1. データソース
ドキュメントの保存場所。GenUが対応している主なデータソース:
| データソース | 用途 |
|---|---|
| Amazon S3 | PDFやWordファイルをバケットに置く。最も基本的な構成 |
| Web Crawler | 指定URLをクロールしてページ内容を取り込む |
| Confluence | Confluenceスペースのページを直接取り込む |
| SharePoint | SharePointサイトのドキュメントを取り込む |
社内ドキュメントをS3に置く構成が最もシンプルで安定している。
2. チャンク
ドキュメントを検索に適したサイズに分割したもの。Knowledge Baseはドキュメントをチャンク単位で管理・検索する。
チャンク分割の戦略:
| 戦略 | 内容 | 向いている場面 |
|---|---|---|
| 固定サイズ | 指定したトークン数で分割 | ドキュメントの構造が不規則な場合 |
| セマンティック | 意味の区切りで分割 | 意味のまとまりで検索したい場合 |
| 階層型 | 小チャンク+親チャンクの2階層 | 精度と文脈のバランスを取りたい場合 |
チャンクサイズは検索精度に直結する。小さすぎると文脈が失われ、大きすぎると無関係な内容が混入する。
3. ベクトルDB
チャンクをベクトル(数値の配列)に変換して保存するデータベース。GenUではデフォルトでAmazon OpenSearch Serverlessが使われる。
ドキュメント → Embeddings(ベクトル化) → OpenSearch Serverlessに保存
↓
質問 → Embeddings(ベクトル化) → 類似ベクトルを検索 → 関連チャンクを取得
ベクトル検索はキーワード検索と異なり、意味的な類似性で検索できる。「有給休暇の申請方法」と「休みの取り方」が類似ドキュメントとして返ってくる。
GenUのCDK設定でKnowledge Baseを有効にする
GenUのKnowledge Base設定は cdk.json で管理する。
{
"context": {
"ragEnabled": true,
"knowledgeBaseId": "XXXXXXXXXX",
"embeddingModelId": "amazon.titan-embed-text-v2:0"
}
}
既存のKnowledge BaseのIDを指定する構成と、CDKでKnowledge Baseを新規作成する構成の2パターンがある。GenUのリポジトリには cdk/lib/construct/rag.ts にKnowledge Base構築のコードが含まれている。
検索の仕組み
セマンティック検索とハイブリッド検索
Knowledge Baseはデフォルトでセマンティック検索(ベクトル検索)を使う。OpenSearch Serverlessではハイブリッド検索(ベクトル検索+キーワード検索)も選択できる。
| 検索方式 | 特徴 | 向いている場面 |
|---|---|---|
| セマンティック | 意味的な類似性で検索 | 表現が多様な質問・概念的な検索 |
| ハイブリッド | セマンティック+キーワード | 固有名詞・型番が含まれる検索 |
「型番ABC-123の仕様は?」のような固有名詞を含む質問はキーワード検索が効果的で、ハイブリッドが有利になる。
retrieve_and_generateとretrieve
GenUのRAGはBedrock APIの2つの呼び出し方に対応している。
retrieve_and_generate: 検索から回答生成まで一括で行う
response = bedrock_agent_runtime.retrieve_and_generate(
input={"text": "有給休暇の申請方法を教えて"},
retrieveAndGenerateConfiguration={
"type": "KNOWLEDGE_BASE",
"knowledgeBaseConfiguration": {
"knowledgeBaseId": "XXXXXXXXXX",
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0"
}
}
)
retrieve: 検索だけを行い、LLMへの投入はアプリ側で制御する
response = bedrock_agent_runtime.retrieve(
knowledgeBaseId="XXXXXXXXXX",
retrievalQuery={"text": "有給休暇の申請方法を教えて"},
retrievalConfiguration={
"vectorSearchConfiguration": {"numberOfResults": 5}
}
)
GenUはデフォルトで retrieve_and_generate を使う。メタデータフィルタリングなどカスタム制御が必要な場合は retrieve を使ってアプリ側で組み立てる(次回の記事で詳しく扱う)。
GenUからRAGを呼び出す流れ
GenUのチャット画面でRAGモードを選択すると、以下の流れで動く。
1. ユーザーがチャットで質問を入力
↓
2. GenUのバックエンド(Lambda)が質問を受け取る
↓
3. Bedrock Knowledge BaseにretrieveまたはR&Gリクエストを送る
↓
4. Knowledge BaseがOpenSearch Serverlessで類似チャンクを検索
↓
5. チャンクとユーザーの質問をLLMに渡す
↓
6. LLMが回答を生成(引用元のS3パスも含む)
↓
7. チャット画面に回答と引用元が表示される
引用元のファイル名とページ番号が表示されるため、ユーザーが元のドキュメントを確認できる。
チャンク設計のポイント
RAGの精度はチャンク設計に大きく依存する。
チャンクサイズの目安:
- 小さすぎる(100トークン以下): 文脈が途切れて回答精度が落ちる
- 大きすぎる(1000トークン以上): 無関係な内容が混入して精度が落ちる
- 推奨は300〜500トークン
ドキュメント構造との整合:
FAQドキュメントなら「質問+回答」を1チャンクにまとめる。マニュアルなら章単位でチャンクを区切る。ドキュメントの読まれ方に合わせてチャンク境界を設計すると精度が上がる。
オーバーラップの活用:
チャンク境界で文脈が切れないようにオーバーラップ(前後のチャンクと重複させる領域)を設定できる。デフォルトの20%前後が一般的。
まとめ
- GenUのRAGはBedrock Knowledge Baseを使ってドキュメント検索から回答生成まで行う
- Knowledge Baseの構成要素は「データソース・チャンク・ベクトルDB」の3つ
- データソースはS3が最もシンプル。Confluence・SharePointにも対応
- 検索はセマンティック検索が基本。固有名詞が多い場合はハイブリッド検索が有効
- チャンクサイズは300〜500トークンが目安。ドキュメント構造に合わせて設計する
retrieve_and_generateで一括処理、retrieveでカスタム制御できる
次回は retrieve を使ったメタデータフィルタリングで部署別アクセス制御を実装する。
← 第3回:GenUの閉域構成——VPCエンドポイントでPrivate環境に閉じ込める | 第5回:GenU × RAG 実践編——メタデータフィルタリングで部署別アクセス制御を実装する →