メインコンテンツへスキップ
評価主導の LLM アプリケーション開発 では、一貫性のある厳選された例を使ってその挙動を体系的に測定することで、LLM アプリケーションを継続的に改善できます。
Weave では、ワークフローの中核となるのが Evaluation オブジェクト で、次を定義します。Evaluation を定義したら、それを Model オブジェクト、または LLM アプリケーションのロジックを含む任意のカスタム関数に対して実行できます。.evaluate() を呼び出すたびに、評価 run が実行されます。Evaluation オブジェクトは設計図、各 run はその設定のもとでアプリケーションがどのように動作するかを測定したものだと考えてください。
評価を始めるには、次の step を完了してください。
  1. Evaluation オブジェクトを作成する
  2. テスト例のデータセットを定義する
  3. スコアリング関数を定義する
  4. 評価するモデルまたは関数を定義する
  5. 評価を実行する
評価コードの完全なサンプルは こちら で確認できます。高度な評価機能 についても、保存済みビュー命令型評価 などを含めて学べます。

1. Evaluation オブジェクトを作成する

Evaluation オブジェクトの作成は、評価の設定を行う最初のステップです。Evaluation は、サンプルデータ、スコアリングロジック、必要に応じた前処理で構成されます。後でこれを使用して、1 つ以上の評価を実行します。 Weave は各サンプルを受け取り、それをアプリケーションに通して、複数のカスタムスコアリング関数で出力を採点します。これにより、アプリケーションのパフォーマンスを把握できるようになり、個々の出力やスコアを詳しく確認できる充実した UI も利用できます。

(任意) カスタム名の設定

評価フローでは、カスタマイズ可能な名前が 2 種類あります。

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

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

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

特定の評価 run (evaluate() の呼び出し) に名前を付けるには、display_name を含む __weave 辞書を使用します。これにより、その 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 キーワード引数が必要ですが、それ以外の引数はユーザー定義で、データセット内のサンプルから取得されます。引数名に対応する辞書キーに基づいて、必要なキーだけが渡されます。
scorer が output 引数を想定しているのに受け取れていない場合は、従来の model_output キーを使用している可能性がないか確認してください。修正するには、scorer 関数を更新して、キーワード引数として output を使用するようにします。
次の scorer 関数 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 辞書は、prompt の値に基づいて MyModel を評価するために、match_score1match_score2 の スコアリング関数 で使用されます。また、custom function の function_to_evaluate に対しても使用されます。Model と function の両方の評価は、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("What is the capitol of France?")))
評価のメイン画像

評価の高度な使い方

評価前にデータセットの行を整形する

preprocess_model_input 関数は、モデルの予測関数に渡す前の入力にのみ適用されます。scorer 関数には、前処理が適用されていない元のデータセット例が常に渡されます。
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 データセットを評価で使用する cookbook を参照してください。

保存済みビュー

Evals の表の設定、フィルター、並べ替え順を、よく使う設定にすばやくアクセスできるよう、保存済みビュー として保存できます。保存済みビューは、UI と Python SDK で設定およびアクセスできます。詳細は Saved Views を参照してください。

命令型評価 (EvaluationLogger)

より柔軟な評価フレームワークを使いたい場合は、Weave の EvaluationLogger をご覧ください。EvaluationLogger は Python と TypeScript の両方で利用でき、複雑なワークフローにも柔軟に対応できます。一方、標準の評価フレームワークは、より明確な構造とガイダンスを提供します。