メインコンテンツへスキップ
このガイドでは、EvaluationLogger を使用して既存の Python または TypeScript のコードから予測とスコアを記録し、完全なデータセットや scorer 一式を最初に定義しなくても Weave でモデル性能を評価する方法を説明します。 この方法は、データセット全体やすべての scorer を最初に定義できない複雑な workflow で特に役立ちます。 あらかじめ定義した DatasetScorer オブジェクトの list が必要な標準の Evaluation オブジェクトとは異なり、EvaluationLogger では個々の予測とそれに関連するスコアを、利用可能になった時点で段階的にログできます。
より構造化された評価をご希望ですか?事前定義されたデータセットと scorer を備えた、より定型的な評価フレームワークを使用したい場合は、Weave の標準 Evaluation フレームワークを参照してください。EvaluationLogger は柔軟性を重視している一方、標準フレームワークは構造とガイダンスを提供します。

基本的なワークフロー

以下の手順に従うと、予測ごとのスコアと、Weave UI で確認できる集計済みサマリーを含む完全な評価が Weave に記録されます。
  1. ロガーを初期化する: EvaluationLogger のインスタンスを作成し、必要に応じて modeldataset に関するメタデータを指定します。省略した場合、Weave はデフォルトを使用します。
    LLM Call (たとえば OpenAI) のトークン使用量とコストを記録するには、LLMを呼び出す前に EvaluationLogger を初期化してください。 先にLLMを呼び出してから予測をログしても、Weave はトークンとコストのデータを取得しません。
  2. 予測をログする: システムの各入力/出力ペアに対して log_prediction() を呼び出します。
  3. スコアをログする: 返された ScoreLogger を使用して、その予測に対する log_score() を呼び出します。1つの予測に対して複数のスコアをログできます。
  4. 予測を完了する: 予測を確定するため、スコアをログしたら必ず finish() を呼び出します。
  5. サマリーをログする: すべての予測の処理が完了したら、log_summary() を呼び出してスコアを集計し、必要に応じてカスタムメトリクスを追加します。
予測に対して finish() を呼び出した後は、その予測にそれ以上スコアをログできません。
このワークフローを示す Python の例については、基本例を参照してください。出力とすべてのスコアが一度に利用可能な場合、Python ユーザーは log_example() を使用して手順 2~4 を 1 回の呼び出しにまとめることができます。

基本的な例

次の例は、既存のコードにインラインで EvaluationLogger を使用して予測とスコアをログする方法を示しています。
user_model モデル関数を定義し、入力のリストに適用します。各例について:
  • 入力と出力は log_prediction を使用してログします。
  • 正確性スコア (correctness_score) は log_score を使ってログします。
  • finish() はその予測のログ記録を完了します。
最後に、log_summary は集計メトリクスを記録し、Weave での自動スコア要約をトリガーします。
import weave
from openai import OpenAI
from weave import EvaluationLogger

weave.init('your-team/your-project')

# トークントラッキングを確実にするため、モデルを呼び出す前に EvaluationLogger を初期化する
eval_logger = EvaluationLogger(
    model="my_model",
    dataset="my_dataset"
)

# 入力データの例(任意のデータ構造を使用できます)
eval_samples = [
    {'inputs': {'a': 1, 'b': 2}, 'expected': 3},
    {'inputs': {'a': 2, 'b': 3}, 'expected': 5},
    {'inputs': {'a': 3, 'b': 4}, 'expected': 7},
]

# OpenAI を使用したモデルロジックの例
@weave.op
def user_model(a: int, b: int) -> int:
    oai = OpenAI()
    response = oai.chat.completions.create(
        messages=[{"role": "user", "content": f"What is {a}+{b}?"}],
        model="gpt-4o-mini"
    )
    # レスポンスを何らかの方法で使用する(ここでは簡略化のため a + b を返すだけ)
    return a + b

# 例を反復処理し、予測してログする
for sample in eval_samples:
    inputs = sample["inputs"]
    model_output = user_model(**inputs) # 入力を kwargs として渡す

    # 予測の入力と出力をログする
    pred_logger = eval_logger.log_prediction(
        inputs=inputs,
        output=model_output
    )

    # この予測のスコアを計算してログする
    expected = sample["expected"]
    correctness_score = model_output == expected
    pred_logger.log_score(
        scorer="correctness", # スコアラーのシンプルな文字列名
        score=correctness_score
    )

    # この特定の予測のログ記録を完了する
    pred_logger.finish()

# 評価全体の最終サマリーをログする。
# Weave は上記でログした 'correctness' スコアを自動集計する。
summary_stats = {"subjective_overall_score": 0.8}
eval_logger.log_summary(summary_stats)

print("評価のログ記録が完了しました。Weave UI で結果を確認してください。")

log_example() を使用した簡易ログ記録

log_example() を使用すると、入力、1 つの出力、スコアを 1 回の呼び出しでログできます。この便利なメソッドは、log_prediction()log_score()finish() を 1 つのステップにまとめたものです。バッチ評価やオフライン評価のように、ログする入力、モデル出力、スコアがすでにそろっている場合に便利です。
import weave
from weave import EvaluationLogger

weave.init('your-team-name/your-project-name')

eval_logger = EvaluationLogger(
    model="my_model",
    dataset="my_dataset"
)

eval_samples = [
    {'inputs': {'a': 1, 'b': 2}, 'expected': 3},
    {'inputs': {'a': 2, 'b': 3}, 'expected': 5},
    {'inputs': {'a': 3, 'b': 4}, 'expected': 7},
]

for sample in eval_samples:
    inputs = sample['inputs']
    output = inputs['a'] + inputs['b']

    eval_logger.log_example(
        inputs=inputs,
        output=output,
        scores={"correctness": output == sample['expected']}
    )

eval_logger.log_summary({"avg_score": 1.0})
前の log_example() 呼び出しは、次と同等です:
pred = eval_logger.log_prediction(inputs=inputs, output=output)
pred.log_score(scorer="correctness", score=output == sample['expected'])
pred.finish()
Weave TypeScript SDK では log_example() は使用できません。TypeScript ユーザーは、基本例 に示されている logPrediction()logScore() のパターンを使用してください。

高度な使い方

EvaluationLogger は、基本的なワークフローを超えて、より複雑な評価シナリオに対応できる柔軟なパターンを提供します。以下のセクションでは、コンテキストマネージャーを使った自動的なリソース管理、モデル実行とログすることの分離、リッチメディアデータの活用、複数のモデル評価の比較表示などの高度な手法を紹介します。

コンテキストマネージャーを使用する

EvaluationLogger は、予測とスコアの両方でコンテキストマネージャー (with 文) をサポートしています。これにより、コードをより簡潔に保ち、リソースを自動的にクリーンアップし、LLM judge call のようなネストされた操作をより適切にトラッキングできます。 このコンテキストで with 文を使用する主な利点は次のとおりです。
  • コンテキストを抜ける際に finish() が自動的に呼び出される。
  • ネストされた LLM call の token と cost の tracking が向上する。
  • prediction コンテキスト内で、モデル実行後に output を設定できる。
import openai
import weave

weave.init("nested-evaluation-example")
oai = openai.OpenAI()

# logger を初期化します
ev = weave.EvaluationLogger(
    model="gpt-4o-mini",
    dataset="joke_dataset"
)

user_prompt = "Tell me a joke"

# prediction ではコンテキストマネージャーを使用するため、finish() を呼び出す必要はありません
with ev.log_prediction(inputs={"user_prompt": user_prompt}) as pred:
    # コンテキスト内でモデル呼び出しを実行します
    result = oai.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": user_prompt}],
    )

    # モデル呼び出し後に output を設定します
    pred.output = result.choices[0].message.content

    # 単純なスコアをログします
    pred.log_score("correctness", 1.0)
    pred.log_score("ambiguity", 0.3)
    
    # LLM call が必要なスコアでは、ネストされたコンテキストマネージャーを使用します
    with pred.log_score("llm_judge") as score:
        judge_result = oai.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "Rate how funny the joke is from 1-5"},
                {"role": "user", "content": pred.output},
            ],
        )
        # 計算後にスコア値を設定します
        score.value = judge_result.choices[0].message.content

# 'with' ブロックを抜けると finish() が自動的に呼び出されます

ev.log_summary({"avg_score": 1.0})
このパターンにより、ネストされたすべての操作が親 prediction にひも付けられてトラッキングされるため、Weave UI で正確なトークン使用量 と cost data を確認できます。
生のデータセットを log_predictioninputs として渡すと、Weave は評価の run ごとにデータを再インポートします。そのため重複データが保存され、データセットが大きい場合や、多数の評価で再利用する場合には容量の無駄になることがあります。 この重複を避けるには、評価を実行する前にデータセットを Weave に公開し、その公開済みデータセットの行を inputs として渡してください。Weave はデータを再インポートする代わりに、公開済みの行への参照を内部参照として解決します。これにより、標準の Evaluation フレームワーク と同様に、各予測が Weave UI 内の特定のデータセット行にリンクされるようになります。 次の例では、データセットを公開して EvaluationLogger からそれにリンクし、その後は他のデータセットと同様に取得して反復処理します。
import weave
from weave import EvaluationLogger

weave.init("your-team-name/your-project-name")

# データセットを公開します(必要なのは一度だけです)
dataset = weave.Dataset(
    name="my_eval_dataset",
    rows=[
      {"question": "What is the capitol of France?", "expected": "Paris"},
      {"question": "What U.S. state is Seattle in?", "expected": "Washington"},
      {"question": "In what country is Mount Fuji located in?", "expected": "Japan"},
    ],
)
weave.publish(dataset)

# 公開済みデータセットを取得します
dataset = weave.ref("my_eval_dataset").get()

ログする前に出力を取得する

まずモデルの出力を計算し、その後で予測とスコアを個別にログできます。これにより、評価ロジックとロギングロジックが分離され、システムの異なる部分で予測生成とスコアリングを処理する場合に、コードのテストや保守がしやすくなります。
# トークン トラッキング を確実に行うため、モデルを呼び出す前に EvaluationLogger を初期化します
ev = EvaluationLogger(
    model="example_model",
    dataset="example_dataset"
)

# トークン トラッキング のため、モデル出力(例: OpenAI への Call)はロガーの初期化後に実行する必要があります
outputs = [your_output_generator(**inputs) for inputs in your_dataset]
preds = [ev.log_prediction(inputs, output) for inputs, output in zip(your_dataset, outputs)]
for pred, output in zip(preds, outputs):
    pred.log_score(scorer="greater_than_5_scorer", score=output > 5)
    pred.log_score(scorer="greater_than_7_scorer", score=output > 7)
    pred.finish()

ev.log_summary()

リッチメディアをログする

入力、出力、スコアには、画像、動画、オーディオ、構造化された表データなどのリッチメディアを含めることができます。リッチメディアをログすると、Weave UI でスコアと並べて実際の内容を確認できるため、マルチモーダルモデルの定性的な分析に役立ちます。log_prediction または log_score メソッドに dict またはメディアオブジェクトを渡すだけです。
import io
import wave
import struct
from PIL import Image
import random
from typing import Any
import weave

def generate_random_audio_wave_read(duration=2, sample_rate=44100):
    n_samples = duration * sample_rate
    amplitude = 32767  # 16 ビットの最大振幅

    buffer = io.BytesIO()

    # バッファに wave データを書き込む
    with wave.open(buffer, 'wb') as wf:
        wf.setnchannels(1)
        wf.setsampwidth(2)  # 16 ビット
        wf.setframerate(sample_rate)

        for _ in range(n_samples):
            sample = random.randint(-amplitude, amplitude)
            wf.writeframes(struct.pack('<h', sample))

    # 先頭から読み取れるように、バッファを先頭に巻き戻す
    buffer.seek(0)

    # Wave_read オブジェクトを返す
    return wave.open(buffer, 'rb')

rich_media_dataset = [
    {
        'image': Image.new(
            "RGB",
            (100, 100),
            color=(
                random.randint(0, 255),
                random.randint(0, 255),
                random.randint(0, 255),
            ),
        ),
        "audio": generate_random_audio_wave_read(),
    }
    for _ in range(5)
]

@weave.op
def your_output_generator(image: Image.Image, audio) -> dict[str, Any]:
    return {
        "result": random.randint(0, 10),
        "image": image,
        "audio": audio,
    }

ev = EvaluationLogger(model="example_model", dataset="example_dataset")

for inputs in rich_media_dataset:
    output = your_output_generator(**inputs)
    pred = ev.log_prediction(inputs, output)
    pred.log_score(scorer="greater_than_5_scorer", score=output["result"] > 5)
    pred.log_score(scorer="greater_than_7_scorer", score=output["result"] > 7)

ev.log_summary()

複数の評価をログして比較する

EvaluationLogger を使用すると、複数の評価をログして Weave UI で並べて比較できます。これは、同じデータセットに対して異なるモデルがどのように機能するかを評価する際に役立ちます。
  1. 以下のコードサンプルを実行します。
  2. Weave UI で Evals タブにアクセスします。
  3. 比較したい eval を選択します。
  4. Compare ボタンをクリックします。Compare ビューでは、次のことができます。
    • 追加または削除する Evals を選択する。
    • 表示または非表示にするメトリクスを選択する。
    • 特定の例をページで切り替えながら、同じデータセット内の同じ入力に対して各モデルがどのような結果を返したかを確認する。
比較の詳細については、Comparisons を参照してください。
import weave

models = [
    "model1",
    "model2",
     {"name": "model3", "metadata": {"coolness": 9001}}
]

for model in models:
    # トークンを取得するには、モデル呼び出しの前に EvaluationLogger を初期化する必要があります
    ev = EvaluationLogger(
        name="comparison-eval",
        model=model, 
        dataset="example_dataset",
        scorers=["greater_than_3_scorer", "greater_than_5_scorer", "greater_than_7_scorer"],
        eval_attributes={"experiment_id": "exp_123"}
    )
    for inputs in your_dataset:
        output = your_output_generator(**inputs)
        pred = ev.log_prediction(inputs=inputs, output=output)
        pred.log_score(scorer="greater_than_3_scorer", score=output > 3)
        pred.log_score(scorer="greater_than_5_scorer", score=output > 5)
        pred.log_score(scorer="greater_than_7_scorer", score=output > 7)
        pred.finish()

    ev.log_summary()
Evals タブ
Compare ビュー

使用上のヒント

以下のヒントは、EvaluationLogger を最大限に活用するのに役立ちます。
  • 各予測の後は、すぐに finish() を呼び出してください。
  • log_summary を使用して、個々の予測に紐づかないメトリクス (たとえば、全体のレイテンシ) を記録します。
  • リッチメディアのログ記録は、定性的な分析に最適です。