評価

プロンプトを変更して1回試してみたところ答えが良く見えたので、そのままリリースしたら、1週間後にユーザーが静かに悪化したケースに当たった。評価(evaluationの略)はその解決策です。AI機能が機能しているかの反復可能なテストであり、入力と良い出力がどのようなものかを対にしたセットで、毎回同じ方法で採点されるため、変更が実際に役に立つかどうかを判断できます。モデルは確率的なブラックボックスで、同じ質問に実行のたびに異なる答えを返すため、測定が唯一の知る方法です。そしてこの規律こそが、デモと製品を分ける多くの要素です。
目視評価がなぜ失敗するのか
AI の答えを手で確認するのは最初は問題がないように感じます。プロンプトを実行し、返答を読んで、良く見えるので先に進みます。問題は、3つのことがあなたに静かに働きかけており、すでにそのすべてに出会っているということです。
次の3つがあります:
- 出力は変動します。 同じプロンプトでも実行のたびに異なる答えを返すため、1つの良い結果は次の実行も良い結果になることを約束しません。
- 変更は回帰を引き起こします。 1つのケースを修正するプロンプト編集は、多くの場合、見ていない別のケースを壊します。
- スケーラビリティがありません。 5つの答えは読むことができます。行を変更するたびに500の答えを読むことはできません。
これらはいずれも、あなたが何か間違ったことをしたことを意味しません。目視評価がこのサイズの仕事には不向きなツールであることを意味しており、それを行うより良い方法があります。
評価セットを構築する
評価セットはテストケースのリストです。各ケースには、入力と、その入力の良い出力がどのようなものかがあります。小さく始めてください。共通の状況といくつかのトリッキーなエッジケースをカバーする10から20のケースは、何もないより遠かに有用で、野生での新しい失敗を発見するときにセットを拡大できます。
eval_set = [
{"input": "食べ物が冷たく遅かった。", "expected": "NEGATIVE"},
{"input": "人生最高の食事です!", "expected": "POSITIVE"},
{"input": "それは良かった、特に特別なことはなかった。", "expected": "NEUTRAL"},
# ...発見するときに実際のケースとエッジケースを追加します
]ユーザーが悪い答えを報告した場合、それが与えるべき出力とともに、セットに追加してください。その後、評価セットは、あなたが繰り返したくないすべての間違いの成長するメモリになります。修正したバグは保つテストになるのと同じ方法です。
採点方法
異なるタスクは異なる採点が必要なため、最初のステップは、期待する答えの種類にチェックを一致させることです。
- 完全一致は1つの正しい答えがある場合に機能します。分類ラベル、抽出されたフィールド、はい、またはいいえ。出力を期待値と直接比較します。
- 基準ベースの採点は、サマリーや返答のように1つの正しい答えがない場合に機能します。出力が条件を満たしているかをチェックします。サマリーが重要な事実に言及しているか。50語未満か。トーンは丁寧か。
- LLMジャッジは、基準に対して出力をスコアリングするために、2番目のモデル呼び出しを使用します。シンプルなチェックが取得できない曖昧な品質の質問にスケーリングしますが、ジャッジ自体はモデルであり、間違う可能性があり、今後は人間の判断に対してそれをサニティチェックします。
# 評価セット上での完全一致採点
def run_evals(eval_set, classify):
passed = 0
for test in eval_set:
output = classify(test["input"])
if output == test["expected"]:
passed += 1
else:
print(f'FAIL: "{test["input"]}" -> got {output}, wanted {test["expected"]}')
print(f"{passed}/{len(eval_set)} passed")完全一致は始めるために最も親切な場所であり、以前の章から分類と抽出の仕事に完璧に適合します。LLM ジャッジのアイデアが機能する理由は、答えが基準を満たしているかどうかをスポットするは、多くの場合、答えを生成するのが簡単だったことよりも簡単な予測であり、エッセイを書くのは簡単だった方法をレビューすることと同じです。しかし、ジャッジは同じ欠陥を持つ別の予測子であり、そのスコアを有用な推定として扱い、明確なルーブリックを与え、時々サンプルで自分の成績をチェックしてください。
すべての変更で実行する
評価セットは、実際に実行した場合にのみ有用です。プロンプトをコードのように扱ってください。プロンプト、モデル、または取得の変更を出荷する前に、評価を実行し、スコアを前のスコアと比較してください。数値が低下した場合、1つの手テストがたまたま良く見えたとしても、回帰を引き起こしました。
これはプロンプトエンジニアリングを推測から、自信を持って反復できるものに変えます。何かを変更し、測定し、より高くスコアされるものを保ち、より低くスコアされるものを破棄します。これは通常のソフトウェアを信頼できるようにするのと同じループで、AI機能のファジーな部分に適用されます。
スコアが低下した場合、回帰を引き起こしました。1つの幸運な手テストはセットをオーバーライドしません。毎回数値をタイブレーカーにしてください。
実践で
最後のセクションからの run_evals 関数は、小さければ、完全で有効なeval ハーネスです。分類器と評価セットを指し、合格するケースの数を教え、どのケースが失敗しているかを正確に示します。
run_evals(eval_set, classify_review)
# FAIL: "それは良かった、特に特別なことはなかった。" -> got POSITIVE, wanted NEUTRAL
# 2/3 passedその1つの失敗行は、十数の成功した手テストより価値があります。実際の弱点を指し、修正して再測定できるようになったためです。最終章、安全と限界は、本物のユーザーの前に、これのいずれかを置く前に設計に対するリスクをカバーします。
run_evalsのような小さなハーネスは既に食い込んでいます。スコアと、正確に壊れたケースを提供します。1つを修正して、再度実行して、数値が移動するのを見てください。次に、実ユーザーが到着する前に、安全と限界が保護するものをカバーします。 
