概要
Amazon Quick(旧Quicksuite)の標準ナレッジベース連携では自由度がないため、
OpenAPI連携(アクション機能)を使ってBedrock Knowledge Baseを呼び出す構成にした。
結果、モデル切り替え・ログ出力・引用元制御が自由にできるようになった。
この記事の対象読者
- Amazon Quickを使っていて、RAGのナレッジベース機能の精度改善に悩んでいる人
- QuickのOpenAPI連携の実例を知りたい人
背景:Quick標準のナレッジベース連携の限界
Amazon QuickにはQuick Index/Spacesというナレッジベース機能がある。
S3にドキュメントをおきデータソース接続すれば、Quick chatから自然言語で検索できる。
セットアップは簡単だが、以下の点で「かゆいところに手が届かない」状態だった。
- 使用するLLMモデルを切り替えられない
- プロンプトや検索パラメータの調整ができない
- 引用元情報のフォーマットを制御できない
- Bedrock Guardrailsのような細かいフィルタリングができない
要するに、RAGの改善サイクルを回すための手段がほぼない。
解決策:OpenAPI連携で自前APIを挟む
QuickにはOpenAPIスキーマを登録して外部APIをアクションとして呼び出す機能がある。これを使えば、Quick chatのUIはそのまま活かしつつ、バックエンドの処理を自由に実装できる。
フロー
ユーザー → [Amazon Quick chat]
│
│ OpenAPI定義に基づきPOSTリクエスト
▼
[API Gateway] (/query)
│
│ x-api-keyによる認証
▼
[AWS Lambda]
│
│ retrieve_and_generate API呼び出し
▼
[Amazon Bedrock Knowledge Base]
│
│ S3上のドキュメントを検索 + 回答生成
▼
回答 + 引用元を返却
構成自体はシンプルで、Lambda 1関数 + API Gateway + OpenAPIスキーマだけ。
実装
Lambda関数
import json
import boto3
import os
bedrock_runtime = boto3.client("bedrock-agent-runtime", region_name="us-east-1")
KB_ID = os.environ.get("KB_ID", "XXXXXXXXXX")
MODEL_ARN = os.environ.get("MODEL_ARN", "arn:aws:bedrock:us-east-1:************:inference-profile/us.anthropic.claude-sonnet-4-6")
MODEL_ALIASES = {
"nova-2-lite": "arn:aws:bedrock:us-east-1:************:inference-profile/us.amazon.nova-2-lite-v1:0",
"claude-sonnet-4-5": "arn:aws:bedrock:us-east-1:************:inference-profile/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
"claude-sonnet-4-6": "arn:aws:bedrock:us-east-1:************:inference-profile/us.anthropic.claude-sonnet-4-6",
}
def handler(event, context):
body = json.loads(event.get("body", "{}"))
query = body.get("query", "")
if not query:
return {
"statusCode": 400,
"headers": {"Content-Type": "application/json"},
"body": json.dumps({"error": "query is required"})
}
# モデル解決の優先順位: エイリアス名 > 明示的ARN > デフォルト
model_key = body.get("model", "")
model_arn = MODEL_ALIASES.get(model_key) or body.get("model_arn", MODEL_ARN)
print(f"[INFO] query={query!r} model_key={model_key!r} model_arn={model_arn}")
resp = bedrock_runtime.retrieve_and_generate(
input={"text": query},
retrieveAndGenerateConfiguration={
"type": "KNOWLEDGE_BASE",
"knowledgeBaseConfiguration": {
"knowledgeBaseId": KB_ID,
"modelArn": model_arn,
},
},
)
answer = resp.get("output", {}).get("text", "")
citation = {"uri": "", "snippet": ""}
for c in resp.get("citations", []):
for ref in c.get("retrievedReferences", []):
loc = ref.get("location", {}).get("s3Location", {})
citation = {
"uri": loc.get("uri", ""),
"snippet": ref.get("content", {}).get("text", "")[:200]
}
break
if citation["uri"]:
break
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps({
"answer": answer,
"citations": citation,
"model_arn": model_arn
}, ensure_ascii=False),
}
やっていることは単純で:
- リクエストからクエリとモデル指定を取得
- モデルのエイリアス解決(
nova-2-liteのような短い名前をARNに変換) - Bedrockの
retrieve_and_generateAPIを呼び出し - レスポンスから回答と引用元を抽出して返却
モデル切り替えの仕組み
リクエストボディのmodelフィールドにエイリアス名を渡すだけで切り替わる。
| エイリアス | モデル |
|---|---|
nova-2-lite |
Amazon Nova 2 Lite |
claude-sonnet-4-5 |
Claude Sonnet 4.5 |
claude-sonnet-4-6 |
Claude Sonnet 4.6 |
Quick chatから「nova-2-liteを使って○○を教えて」と言えば、OpenAPIスキーマの
enum定義に基づいてQuickが自動的にmodelパラメータを設定してくれる。
用途に応じてコストと精度のトレードオフを取れるのが地味に便利。
OpenAPIスキーマ
Quickに登録するスキーマ。ここのdescriptionが重要
Quickがどのタイミングでこのアクションを呼ぶか判断する材料になる。
{
"openapi": "3.0.0",
"info": {
"title": "RAG Knowledge Base Query API",
"description": "Retrieves answers from the knowledge base using Retrieval-Augmented Generation. Queries documents indexed in Amazon Bedrock Knowledge Base and returns AI-generated answers with source citations.",
"version": "1.0.0"
},
"servers": [
{
"url": "https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod"
}
],
"paths": {
"/query": {
"post": {
"operationId": "queryKnowledgeBase",
"description": "Send a natural language query to the knowledge base and receive an AI-generated answer based on the indexed documents. The response includes the generated answer text and citation information showing which source documents were used.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["query"],
"properties": {
"query": {
"type": "string",
"description": "The natural language question to ask the knowledge base."
},
"model": {
"type": "string",
"description": "The AI model to use for generating the answer. Defaults to claude-sonnet-4-6 if not specified.",
"enum": ["nova-2-lite", "claude-sonnet-4-5", "claude-sonnet-4-6"]
}
}
}
}
}
},
"responses": {
"200": {
"description": "Successfully retrieved an answer with source citations.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"answer": { "type": "string" },
"citations": {
"type": "object",
"properties": {
"uri": { "type": "string" },
"snippet": { "type": "string" }
}
},
"model_arn": { "type": "string" }
}
}
}
}
},
"400": {
"description": "Bad request. The query parameter is missing or empty."
}
}
}
}
},
"security": [{ "apiKey": [] }],
"components": {
"securitySchemes": {
"apiKey": {
"type": "apiKey",
"name": "x-api-key",
"in": "header"
}
}
}
}
OpenAPI連携(カスタムプラグイン)の仕様について
今回利用しているOpenAPI連携は、AWSドキュメント上では「Amazon Q Businessカスタムプラグイン」として定義されている機能。
OpenAPI 3.0.0形式のスキーマを登録することで、Amazon Qが自然言語のリクエスト内容に応じて適切なAPIオペレーションを動的に判断し呼び出してくれる。
主な仕様上の制約:
- OpenAPIバージョンは3.0.0以上が必須
- 1プラグインあたり最大20のAPIオペレーションを定義可能
- リクエスト/レスポンスのメディアタイプは
application/jsonのみサポート - スキーマ内の
allOf/oneOf/anyOfや配列型は非サポート -
descriptionフィールドがプラグインの呼び出し判断に使われるため、ここの記述が精度に直結する
認証方式はAPIキー認証またはOAuth2に対応している。
今回はAPIキー(x-api-keyヘッダー)を使用した。
参考: Custom plugins for Amazon Q Business - AWS Documentation / Defining OpenAPI schemas for custom plugins
Quick側の設定
- Quickの管理画面でアクション(カスタムプラグイン)を追加
- openapi.jsonをアップロード
- APIキーを設定
- 完了。Quick chatからナレッジベースに関する質問をすると自動的にAPIが呼ばれる
動作確認
Quick chatで質問:
「災害時の顧客対応について教えて」
API側のレスポンス:
{
"answer": "災害時の顧客・取引先対応は以下により実施します。1. 状況報告:被害状況・事業継続状況の報告 2. 代替案提示:サービス・製品供給の代替案 3. 復旧見込み:復旧見込み・スケジュールの連絡 ...",
"citations": {
"uri": "s3://rag-********/XXX_XXX_災害時対応規定.pdf",
"snippet": "情報提供:要請に応じた情報提供・協力 ..."
},
"model_arn": "arn:aws:bedrock:us-east-1:************:inference-profile/us.anthropic.claude-sonnet-4-6"
}
CloudWatch Logsにはこんな感じで記録される:
[INFO] query='災害時の顧客対応について教えて' model_key='' model_arn=arn:aws:bedrock:us-east-1:************:inference-profile/us.anthropic.claude-sonnet-4-6
どのモデルがどれくらい使われているか、どんな質問が多いかが可視化できるので、改善のサイクルが回しやすい。
今後やりたいこと
- Bedrock Guardrailsの適用
- 複数ナレッジベース対応
まとめ
QuickのOpenAPI連携を使えば、チャットUIの開発なしにRAGのバックエンドだけを自前で制御できる。構成はLambda 1関数とOpenAPIスキーマだけなので、構築コストも低い。
「Quickの手軽さ」と「RAGチューニングの自由度」を両立したい場合に、この構成はかなり実用的だと思う。
※ 本記事の内容は個人の見解であり、所属する組織の公式見解ではありません。