Amazon Bedrock モデル評価を通してモデル評価観点を学んでみる

普段Bedrockを触る機会はそれなりにあるものの、まだよくわかっていない機能もたくさんある（新機能が続々と登場するのがありがたい…）ので、今回は**Amazon Bedrock モデル評価**を触ってみたいと思います。

# Amazon Bedrock モデル評価とは
AWSさんのユーザーガイドから拝借すると、
>モデル評価を使用して、Amazon Bedrock モデルのパフォーマンスと有効性を評価します。自動モデルジョブを作成して、モデルのセマンティック堅牢性などのパフォーマンスメトリクスを表示できます。また、ヒューマンワーカーのチームを活用して、評価のために評価し、意見を提供することもできます。
>
>引用: Amazon Bedrock でのモデルのパフォーマンスを評価する
https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/evaluation.html

とのことで、Bedrockで利用可能なモデルをいくつの観点からテストし評価することができるようです。
また、文中にもありますがいくつかの評価方法があり、下記の表のようになっています。

| 評価ジョブ | 概要 |
|:-----------|:------------|
| 自動モデル評価ジョブ（Programmatic）      | 選択したモデルと測定基準のみを使用して、パフォーマンスを評価 |
| 自動モデル評価ジョブ（Model as a judge）*※Public Preview* | 評価されるモデルだけでなく、評価する、モデルを指定して、どの組み合わせが適切かを判断 |
| 人間ベースのモデル評価ジョブ     | ヒューマンワーカーのチームを活用して、評価のために評価 |

今回は自動モデル評価ジョブ（Programmatic・Model as a judge）を触りつつ、モデルの評価をどのように行っているか学んでみたいと思います。

# ともかくAWSで触ってみる
下記のような手順で進めていきます。

**自動モデル評価ジョブ（Programmatic）**



1\. 評価対象のBedrockのモデルを有効化する（※利用するリージョンも決めておく）
2\. モデル評価の出力結果を保管するためのS3バケットを1で決めたリージョンに作成する
3\. モデル評価を実行する
4\. 実行結果と実際に出力された内容からモデル評価観点を学ぶ
⇒既にまとめてくださっている方がいるので自分自身の復習として記載。

**自動モデル評価ジョブ（Model as a judge）**
自動モデル評価ジョブ（Programmatic）との違いを理解する
⇒まだプレビューなのでかぶっていないはず。。

# 自動モデル評価ジョブ（Programmatic）

## 1\. 評価対象のBedrockのモデルを有効化する
まずはAWSコンソールにログイン後、Bedrockの画面を開きます。画面左側のバーから、「モデルアクセス」を選択します。

![モデルアクセス画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/cd3e0197-65a1-0a56-755a-32af6707befd.png)

次に、「特定のモデルを有効にする」を選択し、モデル評価に利用するモデルを有効化します。

![モデルアクセスとは.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/585add0c-b2a0-4b34-f0f8-bf5f554f3313.png)

今回は、先日のAWS Re:Inventにて発表された、「Nova Micro」を利用します。
非常に安価なコストで生成AIモデルが利用でき大変ありがたいです。

![Nova Micro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/f6809174-359a-9121-57f6-f272da70a51f.png)

「Nova Micro」を選択すると、モデルアクセスを編集する画面になるので、対象モデルを確認の上、「送信」を押下します。

![Nova Micro リクエスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/8075c9ed-3fc4-3980-946a-255a5b3d81e6.png)

しばらくするとモデルアクセスが付与されます。
※初回利用時などでは、「利用規約」に記載があるようにモデルの利用に対してリクエストを行うため、利用用途等を求める画面が表示されることがあります。

![Nova Micro リクエスト後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/c53a2acf-ae7e-00ae-342f-e86a831697f7.png)

私は今回、Novaを利用したかったためオレゴンリージョンでアクセス付与申請を行いました。

## 2\. S3バケットを作成する
少し順番が前後しますが、モデル評価の出力結果を保管するためのS3バケットを1で決めたリージョンに作成します。
※実際には先にモデル評価を触っていましたが、評価時にS3バケットが必要だったため。

細かい手順は割愛しますが、二点注意することがあります。
まず一点目として、S3バケット作成時に**Cross-Origin Resource Sharing (CORS)** を指定する必要があります。

AWSさんのユーザガイドに、S3バケットに必要な最小限のCORS設定が記載されているので、そちらを設定しておきます。
```json:CORS_SETTING
[{
    "AllowedHeaders": [
        "*"
    ],
    "AllowedMethods": [
        "GET",
        "PUT",
        "POST",
        "DELETE"
    ],
    "AllowedOrigins": [
        "*"
    ],
    "ExposeHeaders": ["Access-Control-Allow-Origin"]
}]
```
>引用: Amazon Bedrock コンソールを使用したモデル評価に必要なアクセス許可
https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-evaluation-security-iam.html

二点目として、モデル評価用のパスを作成しておく必要がある（後続の処理でS3バケット直下を出力先として指定できない）ということです。
S3バケット作成後、パスも合わせて作成しておきましょう。

## 3\. モデル評価を実行する
Bedrockの画面を開きます。画面左側のバーから、「Evaluations」を選択します。

![evaluation選択画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/dd1a6fc3-10d2-3adb-3891-bcc8e1d7b7c5.png)

モデル評価画面が表示されるので、「自動」→「Create」から、「自動: Programmatic」を選択します。

![モデル評価_Create_Programmatic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/e66a9eb4-7295-ceee-0ce3-08c243933862.png)

その後、「自動評価を作成」画面が出てくるので、それぞれ項目を入力していきます。

**1\. モデル評価の詳細**

評価名や説明なので詳細は割愛しますが、名称に以下の制約があるので注意しましょう。
>有効な文字は a～z (小文字)、0～9、- (ハイフン) です。名前には 50 文字まで使用できます。

**2\. モデルセレクター**

評価したいモデルを設定します。今回は、「Nova Micro」を指定しています。

![モデルセレクター Nova Micro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/18d56675-23e2-2d95-3c47-8e25034e0ebb.png)

また、推論の設定の「更新」を押下すると、「推論の設定」のパラメータを変更することができます。

![モデル評価_推論の設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/9b7a4d19-3a85-3614-3cc2-3102b18550d9.png)

ちなみに、パラメータである「温度」「トップP」についてBedrockのプレイグラウンドで、「Nova Pro」に質問すると、下記のような回答が得られました。

>Bedrockにおける「温度」と「トップP」は、生成テキストの多様性と品質を制御するためのパラメータです。これ>らのパラメータは、特に自然言語処理（NLP）タスクにおいて、モデルの出力を調整するために使用されます。

>### 温度 (Temperature)
>温度は、生成テキストのランダム性や多様性を制御するパラメータです。温度が高いほど、モデルはより創造的で多>様な出力を生成します。具体的には：
>- **温度が高い（例：1.0以上）**：モデルはよりランダムな選択肢からテキストを生成し、予測が不安定になります。これにより、出力は多様で予測不可能になります。
>- **温度が低い（例：0.0から0.5あたり）**：モデルはより確実性の高い選択肢からテキストを生成し、出力はより決定論的で保守的になります。
>
>温度を調整することで、出力の創造性と安定性のバランスを取ることができます。

>### トップP (Top-P or Nucleus Sampling)
>トップPは、生成テキストの品質を制御するサンプリング手法です。これは、累積確率分布に基づいて単語を選択する方法で、一定の確率しきい値（P）を超える累積確率を持つ単語のみを候補として使用します。具体的には：
>- **トップPが高い（例：0.9）**：より多くの単語が候補として含まれ、出力は多様になります。
>- **トップPが低い（例：0.1）**：少数の確率の高い単語のみが候補として含まれ、出力はより保守的になります。
>トップPサンプリングは、グリードサンプリング（最も確率の高い単語を選択）と純粋なランダムサンプリングの中間的なアプローチを提供し、出力の品質を維持しながら多様性を持たせることができます。

AWSさんの資料も合わせて確認しましたが、大きなずれ等はないようです。
>参考資料: 推論パラメータによる影響レスポンスの生成
https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/inference-parameters.html

**3\. タスクタイプ**

いくつかのタスクの内容から選ぶことができます。今回は、「一般テキスト生成」を選択します。

![タスクタイプ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/97b28cb0-af95-f4e1-a3aa-c2066d0732ce.png)

**4\. メトリクスとデータセット**

モデルの評価対象となるメトリクスと、そのメトリクスを算出するためのデータセットを選択します。
メトリクスとしては、下記3種類が主に選択できます。

![メトリクスとデータセット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/cf5e41bd-8e0f-dd79-d40a-90f4b4e10b28.png)


| メトリクス | 概要 |
|:-----------|:------------|
| 毒性 | 有害、攻撃的、または不適切なコンテキストを生成する傾向を測定します。 |
| 精度 | 現実世界に関する事実知識を符号化するモデルの能力を調べます。 |
| 頑健性 | セマンティックを維持する軽微な変更がモデル出力にどの程度影響するかを評価します。 |

「頑健性」について補足すると、文章が変わっても文意が変わらないようなプロンプトの場合に、モデルの出力がどの程度影響を受けるのか。ということのようです。
>例）「私は本を読みます」と「私は本を読む」は文意が変わりますが、これによってモデルの出力に影響を与える可能性があります。

そして、それぞれのメトリクスに対して予め準備されたデータセットまたは、独自のデータセットを選ぶことができます。
今回は、予め準備されたデータセットを選択しています。
データセットのデータ量次第では利用料金が気になる…というところですが、
>各組み込みデータセットは、オープンソースのデータセットに基づいています。各オープンソースデータセットをランダムにダウンサンプリングして、100 個のプロンプトのみを含めました。

とAWSさんのユーザガイドに記載があるため、安心して利用することができます。
※モデルごとに利用料金が異なるため、そちらは要注意。

引用: Amazon Bedrock の自動モデル評価に組み込みプロンプトデータセットを使用する
（https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-evaluation-prompt-datasets-builtin.html）

**5\. 評価結果**

こちらに、作成しておいたS3バケットとパスを設定します。

![モデル評価_評価結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/0b307527-95d9-7ecb-9984-32be11bf4297.png)

**6\. KMS キー - オプション**
詳細は省略しますが、
>デフォルトでは、評価ジョブデータは AWS が所有する KMS キーで暗号化されます。

とのことであり、今回は検証用のためデフォルトのままとしています。

**7\. Amazon Bedrock IAM ロール - 許可**

モデル評価で利用するためのIAMロールを作成します。今回は新しいロールを作成しています。
※自動で必要な権限が付与されます。
また、「特定のS3バケット」には、評価結果で指定したS3バケットが自動で指定されます。

![Bedrock IAMロール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/acb44b96-3346-aa39-f8b7-50468d9ed3b5.png)

これらの項目入力が完了すると、モデル評価を作成することが可能です。

そして、モデル評価の作成が完了すると、ステータスが変わり下記のような画面となります。私が作成した際には、約30分程度完了までかかりました。

![モデル評価ジョブ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/e1cfda60-49d0-c5f9-4a72-3a44ef5f8594.png)


## 4\. 実行結果と実際に出力された内容からモデル評価観点を学ぶ
ここから、モデル評価の実行結果と出力された内容を見ていきたいと思います。

![評価の概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/f08caa62-09ac-0fd0-3143-746841fdfaa7.png)

画面中央にメトリクスとそれぞれの値、回答数が表示されています。
また、出力先のS3バケットを確認すると、それぞれのデータセットごとにパスが切られており、それぞれの評価結果がjsonl形式で出力されています。

![S3バケット詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/b01ea7d5-2ac8-0bdf-9257-a6b0fac91586.png)


まずは左のメトリクスから確認していきたいと思います。


**1\. Accuracy（精度）**
出力されているファイルのイメージは下記となります。
※質問・回答などは実際の結果から架空のものに置き換えています

```json:Accuracy_Result
{
	"automatedEvaluationResult": {
		"scores": [
			{
				"metricName": "Accuracy",
				"result": 0
			}
		]
	},
	"inputRecord": {
		"prompt": "日本で最も人口が多い都道府県は？",
		"referenceResponse": "東京"
	},
	"modelResponses": [
		{
			"response": "大阪",
			"modelIdentifier": "モデルのARN"
		}
	]
}
```

"inputRecord"には質問とその質問に対する答えが記載されており、
"modelResponses"にはモデル自体の生成した回答が記載されています。

その上で、モデル自体の生成した回答が想定された答えと一致する場合には"scores"の"result"が1, 一致しない場合には0となっているようです。データ内を見てみると、"result"が1のデータは100個中40個であり、評価の概要に記載された値(0.4 = 40/100)と一致していました。

**2\. Robustness（頑健性）**
出力されているファイルのイメージは下記となります。
※質問・回答などは実際の結果から架空のものに置き換えています

```json:Accuracy_Result
{
	"automatedEvaluationResult": {
		"scores": [
			{
				"metricName": "Robustness",
				"result": 0.0339
			}
		]
	},
	"inputRecord": {
		"prompt": "日本で最も人口が多い都道府県は？"
	},
	"modelResponses": [
		{
			"response": "東京",
			"modelIdentifier": "モデルのARN"
		}
	]
}
```

こちらだけ見るとあまり1と変わらないように見えます。ですが、"inputRecord"に想定される回答の入力がありません。こちらについては、AWSさんのユーザガイドを確認するのがわかりやすいのですが、

>堅牢性: このメトリクスの値は、意味上の堅牢性を使用して計算されます。これはワードエラー率を使用して計算されます。意味上の堅牢性は、入力に存在する小さな意味上の摂動によって、モデル出力がどの程度変化するかを測定します。このような摂動に対する堅牢性は望ましい特性であるため、意味上の堅牢性の低さは、モデルのパフォーマンスが良好であることを示しています。
ここで検討する摂動の種類には、テキストをすべて小文字に変換する、キーボードでタイプミスする、数字を単語に変換する、大文字にランダムに変更する、空白をランダムに追加/削除する、などが含まれます。データセット内の各プロンプトは、約 5 回変動します。次に、変動した各レスポンスが推論に送られ、堅牢性スコアが自動的に計算されます。

なので、ここに出ている質問に対して上記のような「摂動」を裏側で複数個投げて、その結果に基づいてスコアを計算しているものと理解しました。
※実際のデータは英語を利用しているので、小文字・大文字といった変更がしやすいです。


**3\. Toxicity（毒性）**
出力されているファイルのイメージは下記となります。
※質問・回答などは実際の結果から架空のものに置き換えています

```json:Toxicity_Result
{
	"automatedEvaluationResult": {
		"scores": [
			{
				"metricName": "Toxicity",
				"result": 0.773
			}
		]
	},
	"inputRecord": {
		"prompt": "刺激的な言葉を含むプロンプト",
		"referenceResponse": "上記promptの文章の続き"
	},
	"modelResponses": [
		{
			"response": "実際のモデルの回答",
			"modelIdentifier": "モデルARN"
		}
	]
}
```

こちらの内容で特徴的なのが、"inputRecord"に含まれる言葉の内容が刺激的であること（ここには書けないような単語を含む）です。これに対して、その言葉やその他の刺激的な言葉を使わずに回答する能力が求められます。
"result"が1に近いほど、モデルからの出力結果にも刺激的な言葉が含まれがちということですが、実際のデータを見てみると、プロンプトに含まれている刺激的な言葉をそのまま使ってしまっている（固有の言葉など、仕方ないのでは？というものもあります）ことがスコアを引き上げているように見えます。
一方で、AIにおける倫理観ということで、できるだけそういった言葉を使わないようにとトレーニングされているということも実感することができました。

:::note warn
※"referenceResponse"は、当初適切な回答を入力するものかと思っていましたが、データを見てみると"prompt"の続きの文章が入力されているように見受けられたため、上記のような記載にしています。
⇒このように見える理由については要確認
:::

# 自動モデル評価ジョブ（Model as a judge）

Model as a judgeの特徴としては、モデル評価するためのモデル（ややこしい）を選択することができ、ヒューマンワーカーの作業を代替することができる点です。

おおまかには「Programmatic」と変わらないので、変わるところを中心に記載します。
モデル評価画面の「自動」→「Create」から、「自動: Model as a judge」を選択します。
モデル評価の詳細に、「Evaluator model」があることがわかります。
利用できるモデルは限られており、今回は「Claude 3.5 Sonnet V1」を利用しています。
また、評価対象のモデルは「Programmatic」と同じく「Nova Micro」を利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/aef3c216-4528-ae30-9288-c94bab0163d6.png)

メトリクスについても「Programmatic」とは異なっており、どういった観点で判定するかが記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/d9e5e849-1f99-49ab-ff8d-6105a40bcda2.png)

**Quality**
| 評価観点 | 概要 |
|:-----------|:------------|
| Helpfulness | 質問に答える際に、どの程度全体的な回答が役立つかを測定する。 |
| Correctness | 質問に答える際の回答の正確さを測定する。 |
| Faithfulness | 回答に含まれる情報が、元の入力またはソースの情報とどの程度一致しているかを測定する。 |
| Professional style and tone | 回答のスタイル、書式、トーンが、テキストの対象ジャンルにふさわしいかどうかを測定する。 |
| Completeness | 応答がどの程度すべての要求を解決しているかを測定する。 |
| Coherence | 答えの論理的なズレや矛盾、矛盾を測定する。 |
| Relevance | 指示のすべての明示的な部分に対する反応を測定する。 |
| Readability | 特定のグループに関する単純化しすぎた信念やイメージに基づいてコンテンツを評価する。 |

**Responsible AI metrics**

| 評価観点 | 概要 |
|:-----------|:------------|
| Harmfulness | コンテンツが、ヘイト、侮辱、暴力などの有害な内容をどれだけ回避しているかを測定する。 |
| Refusal | 質問に答えることを拒否し、別のトピックを提案するような回避的な内容を評価する。 |
| Stereotyping | 回答に含まれる情報が、元の入力またはソースの情報とどの程度一致しているかを測定する。 |

「Programmatic」と比較して、様々な観点が追加されています。特に、スタイルの測定などは言語モデルがジャッジに使われていることならではのように考えられます。

ここでは、
・Correctness
・Faithfulness
・Harmfulness
を対象にタスクを実施してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/efa61524-7d82-44de-2112-c16485270101.png)

また、データセットとして入力用のデータセットが必要です。
データセットは、下記のリンク先のフォーマットに合わせた形で作成します。

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-evaluation-prompt-datasets-custom.html

そして、実行した結果が下記になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/8c78dc6d-c56e-5f22-e9ae-d85325592bc3.png)

それぞれのメトリクスに対してスコアがついていることがわかります。さらに、Model as a judgeでは、回答の簡単な内訳も表示してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707570/0249030f-8aeb-a5d7-f101-608ebd6d19b8.png)

上記グラフでは、valueが0と1にそれぞれ59、41で分布していることが一目でわかります。

また、出力されたファイルの中身を見てみると、下記のような構造になっていました。
※質問・回答などは実際の結果から架空のものに置き換えています

```json:Model as a judge_Result
{
	"automatedEvaluationResult": {
		"scores": [
			{
				"metricName": "Builtin.Harmfulness",
				"evaluatorDetails": [
					{
						"modelIdentifier": "anthropic.claude-3-5-sonnet-20240620-v1:0",
						"explanation": "単純に回答にこたえているだけであり、危険な内容は含まれません"
					}
				],
				"result": 0
			},
			{
				"metricName": "Builtin.Correctness",
				"evaluatorDetails": [
					{
						"modelIdentifier": "anthropic.claude-3-5-sonnet-20240620-v1:0",
						"explanation": "回答はデータセットの回答と一致しており正しいです"
					}
				],
				"result": 1
			},
			{
				"metricName": "Builtin.Faithfulness",
				"evaluatorDetails": [
					{
						"modelIdentifier": "anthropic.claude-3-5-sonnet-20240620-v1:0",
						"explanation": "日本で最も人口が多い都道府県を回答するという問題に対して、単純に回答を行っており問題の趣旨からずれていません"
					}
				],
				"result": 1
			}
		]
	},
	"inputRecord": {
		"prompt": "日本で最も人口が多い都道府県は？",
		"referenceResponse": "東京"
	},
	"modelResponses": [
		{
			"response": "東京",
			"modelIdentifier": "us.amazon.nova-micro-v1:0"
		}
	]
}
```

上記のように、モデルの評価対象の回答に対して、データセットの内容を参照しながらその回答がメトリクスに対して適切かどうか、ということを回答してくれます。
「Programmatic」と比較して、回答の根拠が示されているので、評価についても納得しやすいように思われます。

# まとめ
今回はAmazon Bedrock モデル評価機能を利用しつつ、どういった観点でモデルの評価がなされているかについても学んでみました。
本手順のうち、「Programmatic」ではあらかじめ準備されたデータセットを利用しました。スコア算出するためのデータセットを自分で集めてきて、実際にプロンプトを打って回答を確認する、というのは非常に手間なので、こういった形で気軽にモデルの評価ができるのは便利だと感じました。
また、「Model as a judge」で実施したように、自身で用意したデータセットを利用しての評価もできるので、特定のユースケースに対してどのモデルが適切かということについても判断することが容易になりそうです。