1
0

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 Bedrock ナレッジベースでメタデータを使ってフィルタリングする

Last updated at Posted at 2025-01-11

Amazon Bedrock ナレッジベースのメタデータ

やりたいこと

手動メタデータフィルタリングで、バージョンにあったドキュメントを検索し回答する。

構築

前提

ナレッジベースを Aurora で構築済

必要なファイルの準備

aws-cli-1.pdf と aws-cli-1.md.metadata.json

aws-cli-1.pdf は AWS のドキュメントからダウンロード。

aws-cli-1.pdf.metadata.json は次の通りとする。

aws-cli-1.pdf.metadata.json
{
	"metadataAttributes": {
		"target": "aws-cli",
		"ver": 1
	}
}

aws-cli-2.pdf と aws-cli-2.md.metadata.json

aws-cli-2.pdf は AWS のドキュメントからダウンロード。

aws-cli-2.pdf.metadata.json は次の通りとする。

aws-cli-2.pdf.metadata.json
{
	"metadataAttributes": {
		"target": "aws-cli",
		"ver": 2
	}
}

準備したファイルを S3 へアップロード

次の通り、aws-cli 配下にアップロードする。
スクリーンショット 2025-01-10 16.04.25.png

Aurora にカラムを追加

クエリエディタよりずまずは、現在のカラムを確認します。この状態では、target と ver のカラムは存在しません。
スクリーンショット 2025-01-10 17.02.10.png

target と ver のカラムを追加します。
スクリーンショット 2025-01-10 17.04.36.png

target と ver のカラムが追加されたことを確認しておきます。
スクリーンショット 2025-01-10 17.04.18.png

ナレッジベースでデータを同期

ナレッジベースでデータを同期します。
スクリーンショット 2025-01-10 17.08.52.png

同期が完了しました。
スクリーンショット 2025-01-10 17.29.23.png

API の作成

今回は、streamlit を使っています。

  • ポイント1: メタデータ
    • AWS CLI のバージョンはユーザーに選択できるようする
  • ポイント2: パラメータ
    • ユーザーで調節可能にする。(一貫性を持たせた回答にしたい場合は、埋め込みで良い)
  • ポイント3: promptTemplate
    • ナレッジベースに検索結果が存在する場合は、参照したドキュメントのタイトルとどのページに記載があったかを記載する
    • ナレッジベースに検索結果が存在しない場合は、【参考情報】と記載して回答する
retrieve_and_generate.py
import os
import boto3
import streamlit as st

def initialize_bedrock_client():
    region = "us-west-2"
    kb_id = "<ナレッジベースId>"
    client = boto3.client("bedrock-agent-runtime", region_name=region)
    return client, kb_id

def query_knowledge_base(client, kb_id, input_text, ver, temperature, top_p):
    filter = {
        "equals": {"key": "ver", "value": ver}
    }

    response = client.retrieve_and_generate(
        input={"text": input_text},
        retrieveAndGenerateConfiguration={
            "knowledgeBaseConfiguration": {
                "generationConfiguration": {
                    "promptTemplate": {
                        "textPromptTemplate": """
    
                        以下の検索結果を参考に回答してください:

                        '$search_results$'

                        回答フォーマット:
                        ---
                        【参照ドキュメント】
                        - 参照したドキュメントのタイトルを記載
                        - 参照したドキュメントのページ

                        【回答】
                        具体的な回答内容
                        ---

                        注意事項:
                        - 検索結果が存在する場合は、必ず参照したドキュメントのタイトルとどのページに記載されているかを記載すること
                        - 検索結果が存在しない場合は、「【参考情報】」と記載して回答すること
                        - 回答は上記のフォーマットに従って構造化すること
                        """
                    },
                    "inferenceConfig": {
                        "textInferenceConfig": {
                            "maxTokens": 4000,
                            "temperature": temperature,
                            "topP": top_p
                        }
                    }
                },
                "knowledgeBaseId": kb_id,
                "modelArn": "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0",
                "retrievalConfiguration": {
                    "vectorSearchConfiguration": {
                        "filter": filter,
                        "numberOfResults": 5,
                    }
                },
            },
            "type": "KNOWLEDGE_BASE",
        },
    )
    
    return response["output"]["text"]

def main():
    st.title("AWS Bedrock Knowledge Base Query")
    
    # Initialize Bedrock client
    client, kb_id = initialize_bedrock_client()
    
    # Sidebar configurationså
    with st.sidebar:
        st.header("メタデータ")
        ver = st.selectbox("AWS CLI バージョン:", options=[2, 1], index=0)
        
        st.subheader("パラメータ")
        temperature = st.slider("温度", min_value=0.0, max_value=1.0, value=0.1, step=0.1)
        top_p = st.slider("トップ P", min_value=0.0, max_value=1.0, value=0.9, step=0.1)
    
    # Main area
    input_text = st.text_area("質問を入力してください:")
    
    if st.button("検索"):
        with st.spinner("回答を生成中..."):
            try:
                response_text = query_knowledge_base(client, kb_id, input_text, ver, temperature, top_p)
                st.write("### 回答")
                st.write(response_text)
            except Exception as e:
                st.error(f"エラーが発生しました: {str(e)}")

if __name__ == "__main__":
    main()

実行

次の通り実行します。

python3 -m streamlit run bedrock.py --server.port 8080

AWS CLI の実行結果

AWS CLI のインストール方法がしっかり返ってきました。ただし、どのページに記載があったかの記載は若干曖昧でもっと他の点で考慮が必要な気がします。

スクリーンショット 2025-01-11 17.05.45.png

bedrock.gif

Azure CLI の実行結果

Azure CLI はナレッジベースにないので、promptTemplate に指示したとおり【参考情報】として返ってきました。
スクリーンショット 2025-01-11 17.11.53.png

おまけ

retrieve_and_generate_stream 版

retrieve_and_generate_stream.py
import os
import boto3
import streamlit as st

def initialize_bedrock_client():
    region = "us-west-2"
    kb_id = "<ナレッジベース Id>"
    client = boto3.client("bedrock-agent-runtime", region_name=region)
    return client, kb_id

def query_knowledge_base(client, kb_id, input_text, ver, temperature, top_p):
    filter = {
        "equals": {
            "key": "ver", 
            "value": str(ver),
        }
    }

    response = client.retrieve_and_generate_stream(
        input={"text": input_text},
        retrieveAndGenerateConfiguration={
            "knowledgeBaseConfiguration": {
                "generationConfiguration": {
                    "promptTemplate": {
                        "textPromptTemplate": """
                        以下の検索結果を参考に回答してください:

                        '$search_results$'

                        回答フォーマット:
                        ---
                        【参照ドキュメント】
                        - 参照したドキュメントのタイトルを記載
                        - 参照したドキュメントのページ

                        【回答】
                        具体的な回答内容
                        ---

                        注意事項:
                        - 検索結果が存在する場合は、必ず参照したドキュメントのタイトルとどのページに記載されているかを記載すること
                        - 検索結果が存在しない場合は、「【参考情報】」と記載して回答すること
                        - 回答は上記のフォーマットに従って構造化すること
                        """
                    },
                    "inferenceConfig": {
                        "textInferenceConfig": {
                            "maxTokens": 4000,
                            "temperature": temperature,
                            "topP": top_p
                        }
                    }
                },
                "knowledgeBaseId": kb_id,
                "modelArn": "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0",
                "retrievalConfiguration": {
                    "vectorSearchConfiguration": {
                        "filter": filter,
                        "numberOfResults": 5,
                    }
                },
            },
            "type": "KNOWLEDGE_BASE",
        },
    )
    
    return response.get("stream")

def main():
    st.title("AWS Bedrock Knowledge Base Query")
    
    # Initialize Bedrock client
    client, kb_id = initialize_bedrock_client()
    
    # Sidebar configurations
    with st.sidebar:
        st.header("メタデータ")
        ver = st.selectbox("AWS CLI バージョン:", options=[2, 1], index=0)
        
        st.subheader("パラメータ")
        temperature = st.slider("温度", min_value=0.0, max_value=1.0, value=0.1, step=0.1)
        top_p = st.slider("トップ P", min_value=0.0, max_value=1.0, value=0.9, step=0.1)
    
    # Main area
    input_text = st.text_area("質問を入力してください:")
    
    if st.button("検索"):
        with st.spinner("回答を生成中..."):
            try:
                stream = query_knowledge_base(client, kb_id, input_text, ver, temperature, top_p)
                if stream:
                    placeholder = st.empty()
                    full_response = ""
                    for event in stream:
                        if "output" in event:
                            chunk = event['output']['text']
                            full_response += chunk
                            placeholder.markdown(full_response)
            except Exception as e:
                st.error(f"エラーが発生しました: {str(e)}")

if __name__ == "__main__":
    main()
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?