メインコンテンツへスキップ
評価主導の LLM アプリケーション開発(Evaluation-driven LLM application development)は、一貫性のある厳選された例を使用してアプリケーションの挙動を体系的に測定することで、LLM アプリケーションを計画的に改善するのに役立ちます。
Weave におけるワークフローの核となるのは Evaluation オブジェクト であり、以下の内容を定義します。Evaluation を定義したら、Model オブジェクトや LLM アプリケーションロジックを含む任意のカスタム関数に対して実行できます。.evaluate() を呼び出すたびに 評価 run がトリガーされます。Evaluation オブジェクトを設計図、各 run をそのセットアップ下でのアプリケーションのパフォーマンス測定と考えると分かりやすいでしょう。
評価を開始するには、以下の手順を完了してください。
  1. Evaluation オブジェクトの作成
  2. 例となるデータセットの定義
  3. スコアリング関数の定義
  4. 評価対象のモデルまたは関数の定義
  5. 評価の実行
完全な評価コードのサンプルは こちら にあります。また、保存済みビュー命令的評価 などの 高度な評価機能 についても詳しく学ぶことができます。

1. Evaluation オブジェクトの作成

Evaluation オブジェクトの作成は、評価設定の最初のステップです。Evaluation は例となる データ、スコアリングロジック、およびオプションの事前処理で構成されます。これを後で 1 つ以上の評価を実行するために使用します。 Weave は各例を取得し、アプリケーションを介して実行し、複数のカスタムスコアリング関数で出力をスコアリングします。これにより、アプリケーションのパフォーマンスの全体像を把握できるだけでなく、個別の出力やスコアを掘り下げて確認できるリッチな UI を利用できます。

(オプション) カスタムネーミング

評価フローでは、2 種類の名前をカスタマイズできます。

Evaluation オブジェクトに名前を付ける

Evaluation オブジェクト自体に名前を付けるには、Evaluation クラスに evaluation_name パラメータを渡します。この名前は、コードや UI のリストで評価を識別するのに役立ちます。
evaluation = Evaluation(
    dataset=examples, scorers=[match_score1], evaluation_name="My Evaluation"
)

個別の評価 run に名前を付ける

特定の評価 run(evaluate() の呼び出し)に名前を付けるには、__weave 辞書で display_name を指定します。これは、その run に対して UI に表示される内容に影響します。
evaluation = Evaluation(
    dataset=examples, scorers=[match_score1]
)
evaluation.evaluate(model, __weave={"display_name": "My Evaluation Run"})

2. テスト例のデータセットを定義する

まず、評価対象となる例のコレクションを含む Dataset オブジェクトまたは例のリストを定義します。これらの例は、テスト駆動開発(TDD)のユニットテストと同様に、テストしたい失敗ケースであることがよくあります。
以下の例は、辞書のリストとして定義されたデータセットを示しています。
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

3. スコアリング関数の定義

次に、1 つ以上の スコアリング関数 を作成します。これらは Dataset 内の各例をスコアリングするために使用されます。
各スコアリング関数は output 引数を持ち、スコアを含む辞書を返す必要があります。オプションで、データセットの例から他の入力をに含めることもできます。スコアリング関数には output キーワード引数が必要ですが、その他の引数はユーザー定義であり、データセットの例から取得されます。引数名に基づいた辞書のキーを使用することで、必要なキーのみを取得します。
スコアラーが output 引数を期待しているのに受け取っていない場合は、レガシーな model_output キーを使用していないか確認してください。これを修正するには、スコアラー関数を更新して output をキーワード引数として使用するようにしてください。
以下のスコアラー関数の例 match_score1 は、スコアリングのために examples 辞書の expected 値を使用します。
import weave

# 例のコレクションを作成
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

# カスタムスコアリング関数を定義
@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    # ここにモデル出力をスコアリングするロジックを定義します
    return {'match': expected == output['generated_text']}

(オプション) カスタム Scorer クラスの定義

アプリケーションによっては、カスタム Scorer クラスを作成したい場合があります。例えば、特定のパラメータ(チャットモデル、プロンプトなど)、各行の特定のスコアリング、および集計スコアの特定の計算方法を持つ標準化された LLMJudge クラスを作成する場合などです。詳細については、RAG アプリケーションのモデルベース評価Scorer クラスの定義に関するチュートリアルを参照してください。

4. 評価対象のモデルまたは関数の定義

Model を評価するには、Evaluation を使用してそのモデルに対して evaluate を呼び出します。Models は、実験したいパラメータがあり、それを Weave で取得したい場合に使用します。
from weave import Model, Evaluation
import asyncio

class MyModel(Model):
    prompt: str

    @weave.op()
    def predict(self, question: str):
        # ここにLLM呼び出しを追加し、結果を返します
        return {'generated_text': 'Hello, ' + self.prompt}

model = MyModel(prompt='World')

evaluation = Evaluation(
    dataset=examples, scorers=[match_score1]
)
weave.init('intro-example') # weaveでのトラッキングを開始
asyncio.run(evaluation.evaluate(model))
これにより、各例に対して predict が実行され、各スコアリング関数で出力がスコアリングされます。

(オプション) 評価対象の関数を定義する

あるいは、@weave.op() でトラッキングされたカスタム関数を評価することもできます。
@weave.op
def function_to_evaluate(question: str):
    # ここにLLM呼び出しを追加し、結果を返します
    return  {'generated_text': 'some response'}

asyncio.run(evaluation.evaluate(function_to_evaluate))

5. 評価の実行

評価を実行するには、Evaluation オブジェクトの .evaluate() を呼び出します。
evaluation という名前の Evaluation オブジェクトと、評価対象の model という名前の Model オブジェクトがある場合、以下のコードで評価 run をインスタンス化します。
asyncio.run(evaluation.evaluate(model))

(オプション) 複数のトライアルを実行する

Evaluation オブジェクトに trials パラメータを設定することで、各例を複数回実行できます。
evaluation = Evaluation(
    dataset=examples,
    scorers=[match_score],
    trials=3
)
run は各例をモデルに 3 回渡し、各 run は個別にスコアリングされ、Weave に表示されます。

完全な評価コードのサンプル

以下のコードサンプルは、開始から終了までの完全な評価 run を示しています。examples 辞書は、match_score1 および match_score2 スコアリング関数によって、与えられた prompt の値に基づく MyModel、およびカスタム関数 function_to_evaluate を評価するために使用されます。Model と関数の両方の評価 run は、asyncio.run(evaluation.evaluate()) で呼び出されます。
from weave import Evaluation, Model
import weave
import asyncio
weave.init('intro-example')
examples = [
    {"question": "What is the capital of France?", "expected": "Paris"},
    {"question": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"question": "What is the square root of 64?", "expected": "8"},
]

@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

@weave.op()
def match_score2(expected: dict, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

class MyModel(Model):
    prompt: str

    @weave.op()
    def predict(self, question: str):
        # ここにLLM呼び出しを追加し、結果を返します
        return {'generated_text': 'Hello, ' + question + self.prompt}

model = MyModel(prompt='World')
evaluation = Evaluation(dataset=examples, scorers=[match_score1, match_score2])

asyncio.run(evaluation.evaluate(model))

@weave.op()
def function_to_evaluate(question: str):
    # ここにLLM呼び出しを追加し、結果を返します
    return  {'generated_text': 'some response' + question}

asyncio.run(evaluation.evaluate(function_to_evaluate))
Evals hero

高度な評価機能

評価前のデータセット行のフォーマット

preprocess_model_input 関数は、入力をモデルの予測関数に渡す前にのみ適用されます。スコアラー関数は、事前処理が適用されていないオリジナルのデータセットの例を常に受け取ります。
preprocess_model_input パラメータを使用すると、データセットの例を評価関数に渡す前に変換できます。これは、以下の場合に役立ちます。
  • フィールド名をモデルが期待する入力名にリネームする
  • データを正しい形式に変換する
  • フィールドを追加または削除する
  • 各例に追加データをロードする
以下は、preprocess_model_input を使用してフィールド名をリネームする方法を示す簡単な例です。
import weave
from weave import Evaluation
import asyncio

# データセットには "input_text" があるが、モデルは "question" を期待している
examples = [
    {"input_text": "What is the capital of France?", "expected": "Paris"},
    {"input_text": "Who wrote 'To Kill a Mockingbird'?", "expected": "Harper Lee"},
    {"input_text": "What is the square root of 64?", "expected": "8"},
]

@weave.op()
def preprocess_example(example):
    # input_text を question にリネーム
    return {
        "question": example["input_text"]
    }

@weave.op()
def match_score(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

@weave.op()
def function_to_evaluate(question: str):
    return {'generated_text': f'Answer to: {question}'}

# 事前処理を含む評価を作成
evaluation = Evaluation(
    dataset=examples,
    scorers=[match_score],
    preprocess_model_input=preprocess_example
)

# 評価を実行
weave.init('preprocessing-example')
asyncio.run(evaluation.evaluate(function_to_evaluate))
この例では、データセットに input_text フィールドが含まれていますが、評価関数は question 引数を期待しています。preprocess_example 関数はフィールド名をリネームすることで各例を変換し、評価が正しく動作するようにします。事前処理関数は以下の通りです。
  1. データセットから生の例を受け取ります
  2. モデルが期待するフィールドを持つ辞書を返します
  3. 評価関数に渡される前に各例に適用されます
これは、モデルが期待するものとは異なるフィールド名や構造を持つ外部データセットを扱う場合に特に役立ちます。

評価での HuggingFace データセットの使用

サードパーティのサービスやライブラリとのインテグレーションは継続的に改善されています。よりシームレスなインテグレーションを構築する間、Weave の評価で HuggingFace Datasets を使用するための一時的な回避策として preprocess_model_input を使用できます。現在のアプローチについては、評価での HuggingFace データセットの使用クックブック を参照してください。

保存済みビュー(Saved views)

Evals テーブルの設定、フィルタ、ソートを 保存済みビュー として保存し、好みのセットアップに素早くアクセスできます。保存済みビューは UI および Python SDK で設定・アクセスできます。詳細については、保存済みビュー を参照してください。

命令的評価(EvaluationLogger

より柔軟な評価フレームワークを好む場合は、Weave の EvaluationLogger を確認してください。EvaluationLogger は Python と TypeScript の両方で利用可能で、複雑なワークフローに対してより高い柔軟性を提供しますが、標準の評価フレームワークはより多くの構造とガイダンスを提供します。