コンテンツへスキップ

【前編】DjangoからAWS Bedrock Knowledge Bases (RAG) を呼び出す実装例

現在、多くのプロダクトでRAG(検索拡張生成)の導入が進んでいますが、DjangoアプリケーションにAWS Bedrockを統合する際の実装パターンにはいくつかの選択肢があります。

本記事では、**「開発者(Developer)」**の視点から、Djangoを使ってAWS Bedrock Knowledge Basesを呼び出すための最短ルートと、実運用で重要となる「マルチテナント(会社ごとのナレッジ分離)」の設計について解説します。

TL;DR(結論)

  • 最短ルート: DjangoアプリからBedrock RAGを呼ぶなら bedrock-agent-runtimeretrieve_and_generate APIを使うのが最も実装コストが低い。
  • マルチテナント設計: 会社ごとにナレッジを分離するなら、DB(例: KnowledgeBaseSettings)に knowledge_base_id を持たせて動的に切り替える設計が安全。
  • 本番運用の勘所: リージョンの統一、適切な例外処理、設定の外出し(ARN/ID)が品質を左右する。

1. BedrockのAPIは2種類ある:問い合わせ用と管理用

実装に入る前に、混乱しやすいBoto3のクライアント種別について整理しておきます。このリポジトリの実装では、Bedrockを以下の2系統で使い分けています。

  • 問い合わせ(RAG実行):bedrock-agent-runtime
    • ユーザー質問 → 検索 → 生成 → 回答 のフローを担当します。今回の記事(前編)はこちらに集中します。
  • 管理(KB作成/同期):bedrock-agent
    • Knowledge Base作成、Data Source作成、Ingestion(同期)開始を担当します。これらは次回の「後編」で解説します。

2. 最小のRAG呼び出し(Knowledge Base固定)

まずは、最もシンプルな実装例を見てみましょう。「特定のKnowledge Base(KB)に対して質問を投げ、回答を得る」だけの関数です。

retrieve_and_generate APIを使用することで、「検索(Retrieve)」と「生成(Generate)」を1回のリクエストでまとめて実行できます。

Python

import boto3

def ask_bedrock(question: str) -> str:
    """
    固定のKnowledge Baseに対してRAGを実行する最小サンプル
    """
    # ランタイムクライアントの作成
    # ※リージョンは実際にKBを作成したリージョンを指定してください
    kb = boto3.client("bedrock-agent-runtime", region_name="ap-northeast-1")

    response = kb.retrieve_and_generate(
        input={"text": question},
        retrieveAndGenerateConfiguration={
            "type": "KNOWLEDGE_BASE",
            "knowledgeBaseConfiguration": {
                # 実際には環境変数などで管理することを推奨
                "knowledgeBaseId": "KB_ID_EXAMPLE_123456", 
                "modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-3-5-sonnet-YYYYMMDD-v1:0",
            },
        },
    )
    
    # UI/APIに返すテキスト部分のみを抽出
    return response["output"]["text"]

実装のポイント

  • シンプルさ: 検索クエリを投げてContextを取得し、それをLLMに投げる…という手順を自前で書く必要がありません。
  • レスポンス: response["output"]["text"] を返すだけで、チャットUIやAPIレスポンスとして利用可能です。

3. 会社(Company)ごとにKBを切り替える(マルチテナントRAG)

SaaSなどを開発する場合、「A社のユーザーにはA社のマニュアルから回答させたい(B社の情報は絶対に出さない)」という要件が発生します。

これを実現するために、データベースにKBの設定情報を持たせる設計例を紹介します。

モデル設計のイメージ

DjangoのModelとして KnowledgeBaseSettings を用意し、会社(Company)モデルと紐づけます。

  • company: Companyモデルへの外部キー
  • knowledge_base_id: その会社用のKB ID
  • region_name: リージョン(会社によってデータの置き場所が違う場合に備える)

実装コード

Python

import boto3
from django.conf import settings
from accounts.models import KnowledgeBaseSettings

def ask_bedrock_company(question: str, company) -> str:
    """
    会社ごとのKnowledge Base IDを使用してRAGを実行する
    """
    # DBからその会社の設定を取得
    kb_settings = KnowledgeBaseSettings.objects.get(company=company)

    # クライアント作成(リージョンも設定から取得可能にする)
    kb = boto3.client(
        "bedrock-agent-runtime",
        region_name=kb_settings.region_name or "ap-northeast-1",
    )

    response = kb.retrieve_and_generate(
        input={"text": question},
        retrieveAndGenerateConfiguration={
            "type": "KNOWLEDGE_BASE",
            "knowledgeBaseConfiguration": {
                # DBに保存されたKB IDを使用
                "knowledgeBaseId": kb_settings.knowledge_base_id,
                "modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-3-5-sonnet-YYYYMMDD-v1:0",
            },
        },
    )
    return response["output"]["text"]

なぜDBにIDを持つのが良いのか

  1. データ漏洩リスクの低減: アプリケーションロジックでIDを切り替えることで、物理的・論理的にナレッジへのアクセスを分離できます。
  2. 運用の分離: KBの作成や同期といった運用タスクを、アプリの問い合わせロジックから切り離せます。
  3. 拡張性: 後述する「会社追加時のKB自動作成」と組み合わせることで、スケーラブルな運用が可能になります。

4. 例外処理と設定管理(本番運用のために)

プロトタイプでは気になりませんが、本番運用では「例外処理」と「設定の持ち方」が品質を左右します。

例外処理の重要性

Bedrock呼び出しは外部API通信であるため、タイムアウトや権限エラー、あるいは「KBがまだ作成されていない」といった状況が起こり得ます。

try-except で例外を捕捉し、ログを残すことは必須ですが、**「呼び出し元に何を返すか」**も重要です。

  • None を返すとフロントエンドがクラッシュする可能性があります。
  • 「現在ナレッジベースを準備中です」や「検索に失敗しました」といった、ユーザーフレンドリーなエラーメッセージを返す設計にしておきましょう。
  • ログには必ず company_id や(マスクした上で)knowledge_base_id を紐づけて、どこのテナントで問題が起きているか追跡できるようにします。

設定の持ち方(推奨)

設定項目推奨される保管場所理由
BEDROCK_REGION環境変数 / Django settings基本的なリージョンは統一されていることが多いため
MODEL_ARN環境変数 / Django settingsモデルのバージョンアップ時に一括で切り替えるため
knowledge_base_idDB (各テナントの設定)会社ごとに異なるため
data_source_idDB (各テナントの設定)同期処理などで使用するため
bucket_nameDB (各テナントの設定)会社ごとにS3バケットを分ける場合があるため

前編まとめ

  • DjangoでBedrock RAGを実装する場合、retrieve_and_generate が最も低コストです。
  • マルチテナントSaaSでは、DBに knowledge_base_id を持たせることで、セキュアかつ柔軟にナレッジを分離できます。
  • 本番リリースに向けて、例外時の振る舞いと設定値の管理場所を整理しておきましょう。

次回の**【後編】**では、運用者向けに「会社追加時にKBを自動作成・同期(Ingestion)する方法」や「監視の勘所」について解説します。

最後までお読みいただき、心より感謝申し上げます。

大河原潤

大河原 潤

AI開発専門家

ブーム以前からAI研究に携わる、本物の専門家。「AIに使われる」のではなく、「AIを使いこなす」確かな技術力を提供します。

【アカデミックな裏付け】

  • カリフォルニア大学リバーサイド校 博士前期課程修了(研究分野:測度論、経路積分)
  • アメリカ数学会のジャーナルに論文発表

【社会的に認められた専門性】

  • AI関連書籍:『誤解だらけの人工知能』(2018年)、『AI×Web3の未来』(2023年)
  • プログラミング専門書:実務的な技術書を2冊出版(確かな実装力の証明)
  • 100社以上のAI導入コンサルティング実績、特許売却経験あり

より具体的な開発事例や実装の詳細は、下記ページでご紹介しております。