1
1

Converse API と Streamlit で質問回答アプリを作ってみる

Last updated at Posted at 2024-09-14

長らく ToDo リストに入りっぱなしだった Amazon Bedrock の Converse API を試してみる。

いきなりコード

Streamlit と boto3 で Converse するアプリのコード
converse.py
import boto3
import streamlit as st


def bedrock_converse(modelId, messages, system, inferenceConfig):
    '''
    Amazon Bedrock の Converse API を呼び出します。
    '''
    bedrock = boto3.client(
        service_name='bedrock-runtime',
        region_name='us-east-1',
    )

    # Converse API の実行
    try:
        converse_response = bedrock.converse(
            modelId=modelId,
            messages=messages,
            system=system,
            inferenceConfig=inferenceConfig
        )
    except Exception as e:
        st.error(f"例外が発生しました: {e}")
    else:
        st.success("呼び出しが成功しました!")
    finally:
        return converse_response


def set_modelId():
    '''
    モデルを選択します。
    '''

    # サイドバーでmodelIdを選択できるようにする
    st.sidebar.header("モデルの選択")

    # モデルの選択
    # Titan、Corere Command、および Large 以前の Mistral はシステムプロンプトをサポートしていないため、ここでは除外
    # また、Opus はオンデマンドスループットをサポートしていないため同じく除外
    modelId = st.sidebar.selectbox(
        "Select a model",
        [
            "anthropic.claude-v2:1",
            "anthropic.claude-3-haiku-20240307-v1:0",
            "anthropic.claude-3-sonnet-20240229-v1:0",
            "anthropic.claude-3-5-sonnet-20240620-v1:0",
            "cohere.command-r-v1:0",
            "cohere.command-r-plus-v1:0",
            "meta.llama2-13b-chat-v1",
            "meta.llama2-70b-chat-v1",
            "meta.llama3-8b-instruct-v1:0",
            "meta.llama3-70b-instruct-v1:0",
            "mistral.mistral-small-2402-v1:0",
            "mistral.mistral-large-2402-v1:0"
        ],
        index=1
    )
    return modelId


def set_inferenceConfig():
    '''
    推論パラメーターを設定します。
    '''

    # maxTokens, temperature, topP を設定できるようにする
    st.sidebar.header("パラメーターの設定")

    maxTokens = st.sidebar.selectbox(
        "最大トークン",
        [
            1024,
            2048,
            4096
        ]
    )
    temperature = st.sidebar.slider(
        "創造性(temperature)",
        min_value=0.0,
        max_value=1.0,
        value=0.5,
        step=0.1
    )
    topP = st.sidebar.slider(
        "多様性(Top P)",
        min_value=0.0,
        max_value=1.0,
        value=0.9,
        step=0.01
    )

    return maxTokens, temperature, topP


def set_otherSettings():
    '''
    その他の設定を行います。
    '''

    # 回答文字数など、その他の設定を行えるようにする
    st.sidebar.header("その他の設定")

    # 回答文字数の設定
    # max_response_lengthを複数選択できるようにする
    max_response_length = st.sidebar.selectbox(
        "回答の最大文字数",
        (100,200,300,400,500,1000,2000)
    )

    return max_response_length


def main():
    '''
    メイン処理です。
    '''

    st.title("Amazon Bedrock Converse API Test")
    st.write("[Converse API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html) を使用すると、複数のモデルで共通の呼び出し方法を使うことができます。")
    sample_code = '''
        converse_response = bedrock.converse(
            modelId=modelId,
            messages=messages,
            system=system,
            inferenceConfig=inferenceConfig
        )    
    '''
    st.code(sample_code, language='python')

    # modelIdの設定
    modelId = set_modelId()

    # 高度な設定
    if st.sidebar.toggle("高度な設定"):
        # inferenceConfigの設定
        maxTokens, temperature, topP = set_inferenceConfig()

        # その他の設定
        max_response_length = set_otherSettings()
    else:
        # 高度な設定を選択しない場合のデフォルト値
        maxTokens = 1024
        temperature = 0.5
        topP = 0.9
        max_response_length = 100

    # inferenceConfigの設定
    inferenceConfig = {
        "maxTokens": maxTokens,
        "temperature": temperature,
        "topP": topP,
        "stopSequences":[]
    }

    # システムプロンプトを構築
    system_prompt = f'''
    あなたは古今東西の知識に通じた一流のAIアシスタントです。
    以下の規則に従って、ユーザーの質問に回答して下さい。

    - ユーザーが問い合わせた際の言語で回答して下さい。
    - 知識の範囲で回答できないことは、捏造せず、「知識がないので回答できない」と回答して下さい。
    - 回答は{max_response_length}文字以内に収めて下さい。
    - 参照元を示して下さい。ただし、存在しないリンク先を捏造してはいけません。また、参照元のリンクは、クリックにより辿れるようにしておいて下さい。
    - 回答はマークダウン記法で構造化して下さい。以下二例を示します。
    #### (回答タイトル)
    (概要)
    - (要点1)
    - (要点2)
    '''

    system = [
        {
            "text": system_prompt
        }
    ]

    # ユーザープロンプトを構築
    user_prompt = st.text_input("質問を入力して下さい:", "")

    # Bedrock の呼び出し
    if st.button("送信") and user_prompt:
        messages = [
            {
                "role": "user",
                "content": [
                    {
                        "text": user_prompt
                    }
                ]
            }
        ]
        converse_response = bedrock_converse(modelId, messages, system, inferenceConfig)
        st.write(converse_response["output"]["message"]["content"][0]["text"])

    else:
        st.write("Waiting for user input...")

if __name__ == "__main__":
    main()

テスト

スクリーンショット 2024-09-15 1.07.41.png

いい感じ。

所感

モデルごとの書き方の差異を考える必要がないので、単純に楽。モデルごとに出力を比較することも容易になった。

あと、Bedrock 関係ないけどやっぱり Streamlit は便利。シンプルなコードでそこそこの UI が作れるし、触ってて楽しい。

1
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
1
1