「RAGって良さそうだけど、構築も運用も重そう…」と思っていた自分が、Amazon S3 Vector(S3 Vectors) という “新しめの選択肢” を見つけて、AWS上でRAGを一から構築した記録です。
この記事のゴール:
同じ質問に対して
- RAGなし(LLM単体)
- RAGあり(S3 Vectorで検索→Bedrockで生成)
の結果がどう変わるかを確認すること。
1. 結論: RAGは “賢くする” より “根拠を持たせる”
- RAGなし:それっぽく話す。でも根拠がない。話が長くなる。
- RAGあり:資料の内容に引っ張られて、回答がスパッと決まる。根拠も出せる。
2. 今回の構成
- Amazon S3(通常バケット):元のテキスト文書を置く
- Amazon S3 Vectors(Vector bucket / Index):ベクトル(埋め込み)を保存・検索
-
AWS Lambda:
- 文書を読み、埋め込みを作って S3 Vectors に Put
- 質問を埋め込みにして S3 Vectors で Query
- 検索結果(snippet)をプロンプトに入れて Bedrock で回答生成
-
Amazon Bedrock:
- 埋め込み:Titan Text Embeddings v2
- 生成:Amazon Nova(Invoke API)
3. 構築の流れ(4ステップ)
Step 1: S3に検証用ドキュメントを置く
まずはRAGに食べさせる文書が必要です。
今回は動作確認が目的なので、検証用に “架空の理論” を書いたテキストを用意しました。
クラウド温泉最適化理論(Cloud Onsen Optimization Theory)は、架空のIT団体「日本デジタル温泉協会(JDHA)」が2022年に提唱した理論である。
この理論によると、クラウドシステムの可用性は「温泉に入った回数」と相関関係があるとされている。
具体的には、エンジニアが月に3回以上温泉に入ると、システム障害の発生率が約42%低下すると説明されている。
JDHAの発表では、
・露天風呂:障害対応力が向上
・サウナ:アーキテクチャ設計力が向上
・水風呂:コスト最適化判断が早くなる
といった効果があるとされている。
また、クラウド温泉最適化理論では「us-east-1リージョンでデプロイしたシステムは、箱根温泉との相性が最も良い」という説も紹介されている。
なお、日本デジタル温泉協会および本理論は実在せず、この文章はRAG動作確認のために作成された完全な架空コンテンツである。
Step 2: 文書を埋め込みにして S3 Vectors に登録(PutVectors)
Lambdaでやることは以下の3つです。
- S3から文書を読む
- Bedrock(埋め込みモデル)に投げる
- 得たベクトルを S3 Vectors に
PutVectorsで入れる
Step 3: 質問も埋め込みにして S3 Vectors で検索(QueryVectors)
質問文を同じ埋め込みモデルでベクトル化して、QueryVectors を実行します。
成功するとレスポンスが得られ、snippet として質問文に近しい文書が取れます。(距離 distance: 0.1503... も返ってきます)
Step 4:検索結果(snippet)をプロンプトに入れて Bedrock で回答生成
検索結果の snippet をそのままプロンプトに入れて、生成モデル(Nova)で回答生成します。
成功すると、以下のようなRAGありの回答と sources(根拠)が一緒に返ります。
"body": "{
"query": "クラウド温泉最適化理論は実在しますか?",
"answer": "クラウド温泉最適化理論は架空の理論です。資料によると、架空のIT団体「日本デジタル温泉協会(JDHA)」が2022年に提唱した理論とされています。したがって、実在する理論ではありません。",
"sources": [{
"key": "sample_01#0",
"distance": 0.15030241012573242,
"snippet": "クラウド温泉最適化理論(Cloud Onsen Optimization Theory)は、・・・
}]
}"
4. 実行結果: RAGなし vs RAGあり
4-1. RAGあり(検索→生成)
質問:クラウド温泉最適化理論は実在しますか?
回答:
「クラウド温泉最適化理論は架空の理論です。資料によると、架空のIT団体「日本デジタル温泉協会(JDHA)」が2022年に提唱した理論とされています。したがって、実在する理論ではありません。」
sources(抜粋)として、sample_01#0 と snippet が返る:
- key:
sample_01#0/ distance:0.1503... - snippet: 「架空のIT団体…が提唱した理論である」
→ “資料がそう言っているからそう答える” になっています。
4-2. RAGなし(LLM単体)
同じ質問でも、RAGなしでは以下のようになります。
「「クラウド温泉最適化理論」という用語は、私が知る限りでは、現時点で実在する科学理論や技術ではありません。温泉や温泉の最適化に関連する理論や技術は、いくつか存在しますが、それらは一般的に「温泉の源泉開発」や「温泉の効能と効果の研究」、「温泉施設の効率的な運営」などの分野で議論されています。クラウドコンピューティングや人工知能といった分野と温泉を関連付けた「クラウド温泉最適化理論」という概念が提案されたり、研究されたりしている可能性はありますが、そのような用語が学術界や産業界で広く認知されているわけではありません。もしあなたが特定の分野や研究で「クラウド温泉最適化理論」という用語に出会った場合は、その文脈や背景情報を提供していただければ、より具体的な回答ができるかもしれません。」
→ 間違ってはいませんが、“根拠がないので慎重に長くなる”。
これは業務でもよく見る挙動で、「安全運転の一般論」になります。
5. 踏んだエラーまとめ(原因→対処)
新機能あるあるですが、順番に踏み抜きました。
ただ、この“踏み抜きログ”が一番学びになりました。
5-1. 次元不一致:1536 vs 1024
- エラー:
vector must have length 1536, but has length 1024
原因:
- S3 Vectors の Index を 1536 次元で作っていた
- しかし Titan Text Embeddings v2 の出力は 1024(デフォルト)だった
対処:
- Indexを 1024 次元で作り直す
- あるいは、埋め込みモデル側の次元を合わせる(ただし Titan v2 は 1536 をサポートしないため不可能)
5-2. “1536にしたい”と思って Titan v2 に投げたら Malformed
- エラー:
Malformed input request: ... please reformat your input
原因:
- Titan v2 は 1536 次元を受け付けない(選べるのは 1024/512/256)
対処:
- 1536 を捨てて 1024 に統一する
- 「S3 VectorsのIndex次元」と「埋め込み次元」は必ず揃える
5-3. Claudeを使おうとして system ロールで怒られる
- エラー:
messages: Unexpected role "system". The Messages API accepts a top-level system parameter...
原因:
- ClaudeのMessages形式では、
systemをmessages内に入れない -
systemはトップレベルに置く必要がある
対処:
-
systemをトップレベルへ移動 - ただしこの後、別の壁が待っていました
5-4. Anthropicの “use case details 未提出”
- エラー:
Model use case details have not been submitted... Fill out the Anthropic use case details form...
原因:
- アカウント側で Anthropic の利用前提(ユースケース申請)が未完了
対処:
- フォーム提出(今回は「すぐ進めたい」ので別モデルへ切り替え)
5-5. Novaに切り替えたら messages 必須で怒られる
- エラー:
required key [messages] not found
原因:
- Nova の Invoke API は
messagesを必須とするスキーマ - こちらが
inputText形式で投げていた
対処:
-
messages+inferenceConfig形式に変更 - 生成モデルごとに “ボディの形” が違うことを痛感
6. 「AIと壁打ちしながら進めた」実感
今回の構築はAIと壁打ちしながら進めていきました。
その特徴としては、単に手順書をなぞるのではなく、仕様差分(次元、モデルの入力スキーマ、事前申請) に次々ぶつかったことでした。
AIに
- 「このエラーの意味は?」
- 「どこを直すべき?」
- 「モデルごとに入力形式が違うのはなぜ?」
を投げ続けたことで、"内容を腹落ちさせながら進められた" ことが大きかったです。
7. おわりに
今回の検証で得た学びは以下のとおりです。
- RAGなしは、うまく喋るが、根拠がない
- RAGありは、根拠があるので、結論が出せる
- S3 Vectors を使うと、従来のRAGより “構成が軽く” 始めやすい
そして何より、
新機能は情報が少なくて当然なので、エラーは敵ではなく教材だということ。
次は、この構成をベースに
- もう少しデータを増やしてみる
- distance(類似度)で「自信がない時は不明と言う」ガードを入れる
- あるいは別のモデルにも差し替える
など、実験の幅を広げていきたいと思います。
この記事が「自分も触ってみようかな」のきっかけになれば嬉しいです。
