🧑⚖️
Vertex AI における LLM の評価
Gen AI 評価サービスの概要
Vertex AI では Gen AI 評価サービスを使うことで、生成AIモデルを評価することができます。このサービスの特徴は以下の通りです。
- LLM-as-a-Judgeアプローチを採用
- カスタマイズ可能な評価指標
- 定量的なスコアリング機能
評価の種類
Vertex AIでは、主に2つの評価アプローチを提供しています:
- ポイントワイズ評価:単一モデルの性能評価
- ペアワイズ評価:2つのモデルの比較評価
評価を行うための4ステップ
手順 1: 評価指標の定義
評価を始める前に、以下の3点を明確にする必要があります。
-
評価目標の特定
- 何を測定したいのか
- どのような改善を期待するのか
-
評価方法の選択
- ポイントワイズ評価:モデルの単独評価
- ペアワイズ評価:モデル間の比較
-
評価タスクの決定
- QA(質問応答)
- テキスト生成
- 要約
など
評価方法の選び方
パラダイム | 使用するタイミング |
---|---|
ポイントワイズ | 本番環境でのモデルの動作を把握します。 |
• 1 つのモデルの長所と短所を調べます。 | |
• チューニング時に重視する動作を特定します。 | |
• モデルのベースライン パフォーマンスを確認します。 | |
ペアワイズ | 本番環境にデプロイするモデルを決定します。 |
• モデルタイプを選択します。たとえば、Gemini-Pro と Claude 3 です。 | |
• さまざまなプロンプトから選択できます。 | |
• チューニングでベースライン モデルが改善されたかどうかを判断します。 |
手順 2: 評価データセットの準備
評価データセットは、pandas DataFrameとして準備する必要があります。重要なのは、評価タスクの種類によって必要なカラムが異なるという点です。
タスク別の必要カラム
評価タスクに応じて、以下のようなカラム構成が必要になります。
1. シングルターン会話の評価
# シングルターン会話用のデータセット例
eval_dataset = pd.DataFrame({
"context": ["ユーザーからの入力文"],
"instruction": ["システムプロンプト"], # オプション
"response": ["モデルの出力"], # オプション
})
2. マルチターン会話の評価
# マルチターン会話用のデータセット例
eval_dataset = pd.DataFrame({
"context": ["現在のユーザー入力"],
"history": ["過去の会話履歴"], # オプション
"instruction": ["システムプロンプト"], # オプション
"response": ["モデルの出力"], # オプション
})
3. 要約タスクの評価
# 要約タスク用のデータセット例
eval_dataset = pd.DataFrame({
"context": ["要約対象のテキスト"],
"reference": ["正解の要約文"], # 比較用の参照要約
"response": ["モデルの要約出力"], # オプション
})
評価データセットで使用可能なカラムの例
- https://cloud.google.com/vertex-ai/generative-ai/docs/models/evaluation-dataset?hl=ja
- https://cloud.google.com/vertex-ai/generative-ai/docs/models/evaluation-dataset
カラム名 | 説明 | 必須/オプション |
---|---|---|
context/prompt | LLMへの入力となるコンテキスト。要約タスクの場合は要約対象テキスト | オプション |
instruction | LLMへの指示やシステムプロンプト | オプション |
history | マルチターン会話の場合の過去の会話履歴 | オプション |
response | 評価対象のLLM出力。指定しない場合はLLMが生成 | オプション |
reference | 正解や理想的な出力。比較評価で使用 | オプション |
baseline_response | 比較評価時のベースラインとなる出力 | 比較評価時に使用 |
実装例:ECサイトのレビュー応答システムの評価
具体例を使って説明します。
ここでは、ECサイトのカスタマーサービスで使用するLLMの評価を例に説明します。
シナリオ設定
あるECサイトで、商品レビューに対する返信を自動化するシステムを開発しています。
システムの評価のため、以下のような観点でLLMの出力を確認したいとします:
- レビューの内容を適切に理解できているか
- 丁寧で適切な返信ができているか
- ネガティブなレビューにも適切に対応できているか
実装例1:シングルターンの評価データセット
# 単純な返信品質の評価
eval_dataset_simple = pd.DataFrame({
"context": [
"商品がとても良かったです!梱包も丁寧で感動しました。",
"注文から3週間経ちますが商品が届きません。とても困っています。",
"使い方が分からず困っています。説明書が分かりにくいです。"
],
"instruction": [
"""あなたはECサイトのカスタマーサービス担当です。
商品レビューに対して、以下の点に注意して返信してください:
- 感謝の気持ちを示す
- 具体的な内容に言及する
- 丁寧な言葉遣いを使用する""",
] * 3 # 3つのcontextに同じinstructionを使用
})
実装例2:マルチターンの評価データセット
# 会話の流れを含む評価
eval_dataset_multi = pd.DataFrame({
"context": [
"返金の手続きはどうすればいいですか?",
],
"history": [
"""
User: 商品が壊れていました。
Assistant: 大変申し訳ございません。商品の不具合とのこと、ご迷惑をおかけし申し訳ございません。具体的な状況を詳しくお聞かせいただけますでしょうか?
User: 開封時からボタンが反応しませんでした。
Assistant: 申し訳ございません。初期不良の可能性が高そうですね。返品・返金の対応をさせていただきたいのですが、よろしいでしょうか?
"""
],
"instruction": [
"""あなたはECサイトのカスタマーサービス担当です。
以下の点に注意して対応してください:
- 手続きの具体的な流れを説明する
- 必要な情報を明確に伝える
- 親身な対応を心がける"""
]
})
実装例3:理想的な返信との比較評価
# 返信品質を理想的な返信と比較
eval_dataset_compare = pd.DataFrame({
"context": [
"商品の色が写真と全然違います。がっかりです。"
],
"instruction": [
"""あなたはECサイトのカスタマーサービス担当です。
お客様の不満に対して適切に対応してください。"""
],
"reference": [
"""大変申し訳ございません。商品の色味が写真と異なっていたとのこと、
ご期待に添えず心よりお詫び申し上げます。
お手数ですが、以下の2点についてご確認させていただけますでしょうか?
1. ご使用のデバイスの画面設定
2. 撮影時の照明条件
それでも色味が大きく異なる場合は、返品・返金の対応をさせていただきます。
ご不便をおかけし申し訳ございませんが、ご希望の対応をお知らせください。"""
]
})
データセット作成時の注意点
1. データ形式の統一
-
全てのカラムで一貫したデータ形式を使用
-
文字列型での統一を推奨
# データ型の確認と変換 for col in eval_dataset.columns: if eval_dataset[col].dtype != 'object': eval_dataset[col] = eval_dataset[col].astype(str)
2. データ品質の確保
-
欠損値、不正な値の事前チェック
-
十分なサンプル数の確保
# 欠損値のチェック if eval_dataset.isnull().any().any(): print("警告: データセットに欠損値が含まれています") # データ数の確認 min_samples = 10 if len(eval_dataset) < min_samples: print(f"警告: サンプル数が推奨される最小数({min_samples})を下回っています")
手順3: 評価の実装と実行
引き続き、ECサイトのレビュー応答システムの例で説明していきます。
from vertexai.evaluation import EvalTask, MetricPromptTemplateExamples, PointwiseMetric
from vertexai.generative_models import GenerativeModel, HarmCategory, HarmBlockThreshold
# 評価指標の定義
metrics = [
MetricPromptTemplateExamples.Pointwise.TEXT_QUALITY, # 文章の品質
MetricPromptTemplateExamples.Pointwise.FLUENCY, # 文章の流暢さ
MetricPromptTemplateExamples.Pointwise.SAFETY, # 安全性
MetricPromptTemplateExamples.Pointwise.VERBOSITY, # 簡潔さ
]
# カスタム評価指標の追加(ECサイト用)
custom_metrics = PointwiseMetric(
metric="customer_service_quality",
metric_prompt_template="""
以下の返信を、カスタマーサービスの品質という観点で1-5で評価してください。
評価基準:
1: 不適切または無関係な返信
2: 基本的な対応はできているが不十分
3: 適切な対応ができている
4: 丁寧で親身な対応ができている
5: 極めて優れた対応で、顧客満足度の向上が期待できる
返信: {response}
""",
)
# 評価タスクの作成
eval_task = EvalTask(
dataset=eval_dataset_multi, # 先ほど作成したデータセット
metrics=[*metrics, custom_metrics],
experiment="customer-service-eval"
)
# モデルの設定
generation_config = {
"max_output_tokens": 1024, # 十分な長さの返信を許可
"temperature": 0.4, # 適度な創造性を維持
"top_p": 0.8, # 出力の多様性を確保
"top_k": 40 # 選択肢の幅を設定
}
safety_settings = {
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
}
model = GenerativeModel(
"gemini-1.5-pro",
generation_config=generation_config,
safety_settings=safety_settings
)
# 評価の実行
eval_result = eval_task.evaluate(
model=model,
prompt_template="""
{instruction}
顧客レビュー:
{context}
返信:
"""
)
手順4: 評価結果の解釈
評価結果の例と解釈
以下は、あるレビュー返信の評価結果例です。
EvalResult(
summary_metrics={
'row_count': 3,
'text_quality/mean': 5.0,
'text_quality/std': 'NaN',
'fluency/mean': 5.0,
'fluency/std': 'NaN',
'safety/mean': 'NaN',
'safety/std': 'NaN',
'verbosity/mean': 'NaN',
'verbosity/std': 'NaN',
'customer_service_quality/mean':
'NaN',
'customer_service_quality/std': 'NaN'
},
metrics_table=
context \
0 商品がとても良かったです!梱包も丁寧で感動しました。
1 注文から3週間経ちますが商品が届きません。とても困っています。
2 使い方が分からず困っています。説明書が分かりにくいです。
instruction \
0 あなたはECサイトのカスタマーサービス担当です。\n 商品レビューに対して、以...
1 あなたはECサイトのカスタマーサービス担当です。\n 商品レビューに対して、以...
2 あなたはECサイトのカスタマーサービス担当です。\n 商品レビューに対して、以...
prompt \
0 \n あなたはECサイトのカスタマーサービス担当です。\n 商品レビュー...
1 \n あなたはECサイトのカスタマーサービス担当です。\n 商品レビュー...
2 \n あなたはECサイトのカスタマーサービス担当です。\n 商品レビュー...
response \
0 ## 〇〇様\n\nこの度は、弊社商品をご購入いただき、誠にありがとうございます。\nまた、...
1 〇〇様\n\nこの度は、ご注文いただいた商品のお届けについて、ご心配をおかけしており、誠に申...
2 ## 〇〇様\n\nこの度は、弊社商品をご購入いただき、誠にありがとうございます。\nまた、...
text_quality/explanation text_quality/score \
0 Coherence: The response is coherent and easy t... 5.0
1 Error NaN
2 Error NaN
fluency/explanation fluency/score \
0 STEP 1: Assess grammar correctness:\nThe AI-ge... 5.0
1 Error NaN
2 Error NaN
safety/explanation safety/score verbosity/explanation verbosity/score \
0 Error None Error None
1 Error None Error None
2 Error None Error None
customer_service_quality/explanation customer_service_quality/score
0 Error None
1 Error None
2 Error None ,
metadata={
'experiment': 'customer-service-eval',
'experiment_run': '5bf6619b-93cd-4f88-ae64-200e4cfac994'
})
スコアの見方と改善ポイントの特定
-
テキスト品質(text_quality)のスコア解釈
- 4.5以上:優れた返信で改善の必要なし
- 3.5-4.4:良好だが改善の余地あり
- 2.5-3.4:基本的な改善が必要
- 2.5未満:大幅な改善が必要
-
流暢さ(fluency)の評価ポイント
# 流暢さスコアの分析 fluency_issues = eval_result.metrics_table[ eval_result.metrics_table['fluency/score'] < 3.0 ][['context', 'response', 'fluency/explanation']] print("改善が必要な返信例:") for _, row in fluency_issues.iterrows(): print(f"コンテキスト: {row['context']}") print(f"返信: {row['response']}") print(f"問題点: {row['fluency/explanation']}\n")
-
カスタマーサービス品質の分析
# サービス品質の平均スコアを計算 avg_cs_quality = eval_result.metrics_table['customer_service_quality/score'].mean() # スコア別の返信例を抽出 best_responses = eval_result.metrics_table[ eval_result.metrics_table['customer_service_quality/score'] > 4.5 ]['response'].tolist() print("優れた返信例:") for response in best_responses[:3]: # 上位3件を表示 print(f"\n{response}\n---")
実践での注意点
-
トークン数の制限
- 出力の最大トークン数を適切に設定
- 文章が途中で切れないよう注意
-
計算タスクの評価
- LLMは計算が苦手
- 評価プロンプトの特別なチューニングが必要
-
評価指標の選択
- タスクの性質に合わせた指標を選択
- 必要に応じてカスタム指標を追加
Discussion