0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amazon Quickのナレッジベース機能をOpenAPI連携で自由にチューニングする

0
Last updated at Posted at 2026-05-20

概要

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),
    }

やっていることは単純で:

  1. リクエストからクエリとモデル指定を取得
  2. モデルのエイリアス解決(nova-2-liteのような短い名前をARNに変換)
  3. Bedrockのretrieve_and_generate APIを呼び出し
  4. レスポンスから回答と引用元を抽出して返却

モデル切り替えの仕組み

リクエストボディの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側の設定

  1. Quickの管理画面でアクション(カスタムプラグイン)を追加
  2. openapi.jsonをアップロード
  3. APIキーを設定
  4. 完了。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チューニングの自由度」を両立したい場合に、この構成はかなり実用的だと思う。


※ 本記事の内容は個人の見解であり、所属する組織の公式見解ではありません。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?