Agents for Amazon Bedrockのプロンプトセッションアトリビュートってなんぞや

## 結論を3行で

- セッションステートに、プロンプトセッションアトリビュートという属性がある
- これで渡された値は、プレースホルダーを通してプロンプトから参照することができる
- Lambdaからの書き変えはできない

## きっかけ

AWSのドキュメントでは、セッションステートを以下のように説明しています。

https://docs.aws.amazon.com/bedrock/latest/userguide/api-agent-invoke.html

> In the sessionState object, you can set the following attributes.
> （セッションステートでは、以下の属性を設定することができます）
> Attributes for the prompt in the promptSessionAttributes object, which contains sessions attributes that go to the prompt.
> (プロンプトセッションアトリビュートはプロンプトの属性です。プロンプトに引き渡すセッションの属性を含みます。)
> Attributes for the session in the sessionAttributes object, which contains session attributes that are passed through attributes that are passed to the action group.
> (セッションアトリビュートはセッションの属性です。アクショングループに渡す属性を通して受け渡されるセッションの属性を含みます。)

全然わかんねえ。。。
と思ったので、改めて調べました。

## 受け渡しと読み取りの方法

**実行**

invoke_agentの実行時に、以下のようにして受け渡すことで利用します。

```python
# boto3からクライアントを取る
client = session.client("bedrock-agent-runtime")

response = client.invoke_agent(**{
    "agentId": arg.agent_id,
    "agentAliasId": arg.agent_alias_id,
    "sessionId": arg.session_id,
    "inputText": arg.input_text,
    "endSession": False,
    # ここから下がセッションステート
    "sessionState": {
        # セッションアトリビュート
        "sessionAttributes": {"ATTRIB": "DATA"},
        # これがプロンプトセッションアトリビュートの指定
        "promptSessionAttributes": {"ATTRIB": "DATA"},
    },
})
```

このようにしてinvoke_agentの引数として引き渡すと、Agents for Amazon BedrockのLambdaの実行引数の中に渡した値が入ってきます。

**参照**

![doc-image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/cdcefe58-30b2-6ee7-a21e-b3e512908d8c.png)

```json:event引数の中身
{
	...中略...
	"sessionAttributes": {
		"ATTRIB": "DATA"
	},
	"promptSessionAttributes": {
		"ATTRIB": "DATA"
	},
	...中略...
}
```

ここを見ると、渡すとき、受け取る時、いずれもsessionAttributesとpromptSessionAttributesに差はないように見えます。

## プロンプトセッションアトリビュートが使える場所

Agents for Amazon Bedrockには、プレースホルダー機能があります。
たとえば、以下のようなレスポンスを返すAPIを作ります

```python
@app.route("/talk", **post_method_define(EmptyInput, TalkResponse))
def talk_to_aura():
    """
    あいさつします。

    あいさつをします。
    """
    return TalkResponse(message="こんにちは、$instruction$").model_dump_json()
```

このAPIを実行した結果は以下の通りです。

![document-b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/b9cb1894-2bb6-6d76-3750-18ef2fdaa5a8.png)

`$instraction$`のような一部のキーワードは、Agents for Amazon Bedrockがレスポンスを返すタイミングで別の文字列に置き換えられます。この機能がプレースホルダーになります。

この場合はエージェントに設定されたインストラクション（会話のシチュエーション）を返しています。

予約済みのキーワードの一覧は以下の表にあります。
見ていると、`$prompt_session_attributes$`も予約済みのキーワードの中にあるようです。

https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-placeholders.html

以下のようなレスポンスを返すAPIを作って、どう参照されているのかを見てみます。

```python:app.py
@app.route("/talk", **post_method_define(EmptyInput, TalkResponse))
def talk_to_aura():
    """
    あいさつします。

    あいさつをします。
    """
    return TalkResponse(message="こんにちは、$prompt_session_attributes$").model_dump_json()
```

プロンプトセッションアトリビュートに以下の値を指定して、invoke_agentします。

```json: invoke_agentの引数
"sessionState": {
    "promptSessionAttributes": {"DATE": "2024-01-01", "TIME": "12:00:00"},
},
```

実行結果は以下のようになりました。

```bash: 実行結果
こんにちは、I have also provided default values for the following arguments to use within the functions that are available to you:
<provided_argument_values>
DATE : 2024-01-01
TIME : 12:00:00

</provided_argument_values>
Please use these default values for the specified arguments whenever you call the relevant functions. A value may have to be reformatted to correctly match the input format the function specification requires (e.g. changing a date to match the correct date format)
```

辞書型そのものではなく、プロンプトになった形で入っているようです。

### 使ってみる

この値を利用してみます。

```bash: コマンドプロンプトで実行
D:\chalice-spec\chalice-agents-for-amazon-bedrock>poetry run chalice-a4ab invoke --profile bedrock --agent-id 38IXBRNNTP --agent-alias-id TSTALIASID --end-session \
こんにちは、アウラ。provided_argument_valuesのDATEの日時を元にして、明日の日付を教えて

明日の日付は2024-01-02です。
```

こちらがプロンプトセッションアトリビュートで渡した日付は2024-01-01ですから、その日付を基準にして、明日の日付を答えてくれました。

APIのレスポンスを以下のように変えてみます。
レスポンスの中から`$prompt_session_attributes$`を取り除いた形です。

```python
@app.route("/talk", **post_method_define(EmptyInput, TalkResponse))
def talk_to_aura():
    """
    あいさつします。

    あいさつをします。
    """
    return TalkResponse(message="こんにちは").model_dump_json()
```

この形でも同じように答えてくれます。

```bash
D:\chalice-spec\chalice-agents-for-amazon-bedrock>poetry run chalice-a4ab invoke --profile bedrock --agent-id 38IXBRNNTP --agent-alias-id TSTALIASID --end-session \
こんにちは、provided_argument_valuesのDATEの日時を元にして、明日の日付を教えて

明日の日付は2024-01-02です。
```

プロンプトセッションアトリビュートとして渡した値は、デフォルトで実行されるプロンプトの中に埋め込まれますので、こちらで`$prompt_session_attributes$`のプレースホルダーを意識する必要はありません。

### 少し気を付けること

Agents for Amazon Bedrockで実行したAPIの戻り値で、プロンプトセッションアトリビュートを返すことができるようになっています。

ただ、そこで値を変更しても、プロンプトには反映されませんでした。
オーケストレーションの開始時点の値で固定されるようです。

あくまでinvoke_agentで実行するときに指定できるもの、プロンプトに受け渡せる独自拡張のコンテキストでしかないようです。