メインコンテンツへスキップ
Weave では、Scorers は AI の出力を評価し、評価メトリクスを返すために使われます。AI の出力を受け取り、それを解析し、結果を格納した辞書を返します。必要に応じて入力データを参照として利用でき、評価から得られた説明や推論内容などの追加情報を出力することもできます。
Scorers は評価時に weave.Evaluation オブジェクトへ渡されます。Weave には 2 種類の Scorers があります:
  1. 関数ベースの Scorers: @weave.op でデコレートされたシンプルな Python 関数。
  2. クラスベースの Scorers: より複雑な評価のために weave.Scorer を継承する Python クラス。
Scorers は必ず辞書を返します。また、複数のメトリクスや入れ子のメトリクスに加えて、LLM 評価器が推論内容として返すテキストのような非数値の値も返すことができます。

独自の Scorer を作成する

すぐに使える Scorer このガイドではカスタム Scorer の作成方法を説明しますが、Weave にはすぐに使用できるさまざまな事前定義済み Scorerローカル SLM Scorerが用意されており、次のようなものが含まれます。

関数ベースのスコアラー

これらは @weave.op デコレータを付けた関数で、辞書を返します。次のようなシンプルな評価に適しています。
import weave

@weave.op
def evaluate_uppercase(text: str) -> dict:
    return {"text_is_uppercase": text.isupper()}

my_eval = weave.Evaluation(
    dataset=[{"text": "HELLO WORLD"}],
    scorers=[evaluate_uppercase]
)
評価を実行すると、evaluate_uppercase はテキストがすべて大文字かどうかをチェックします。

クラスベースの Scorer

追加の Scorer メタデータを保持したい場合、LLM 評価用に異なるプロンプトを試したい場合、または関数を複数回呼び出したい場合など、より高度な評価には Scorer クラスを使用できます。要件:
  1. weave.Scorer を継承する。
  2. @weave.op デコレータを付けた score メソッドを定義する。
  3. score メソッドは辞書を返さなければならない。
例:
import weave
from openai import OpenAI
from weave import Scorer

llm_client = OpenAI()

class SummarizationScorer(Scorer):
    model_id: str = "gpt-4o"
    system_prompt: str = "Evaluate whether the summary is good."

    @weave.op
    def some_complicated_preprocessing(self, text: str) -> str:
        processed_text = "Original text: \n" + text + "\n"
        return processed_text

    @weave.op
    def call_llm(self, summary: str, processed_text: str) -> dict:
        res = llm_client.chat.completions.create(
            messages=[
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": (
                    f"Analyze how good the summary is compared to the original text."
                    f"Summary: {summary}\n{processed_text}"
                )}])
        return {"summary_quality": res}

    @weave.op
    def score(self, output: str, text: str) -> dict:
        """Score the summary quality.

        Args:
            output: The summary generated by an AI system
            text: The original text being summarized
        """
        processed_text = self.some_complicated_preprocessing(text)
        eval_result = self.call_llm(summary=output, processed_text=processed_text)
        return {"summary_quality": eval_result}

evaluation = weave.Evaluation(
    dataset=[{"text": "The quick brown fox jumps over the lazy dog."}],
    scorers=[summarization_scorer])
このクラスは、要約を元のテキストと比較することで、その要約の品質を評価します。

Scorer の動作

Scorer のキーワード引数

Scorer は、AI システムからの出力と、データセット行からの入力データの両方にアクセスできます。
  • Input: Scorer でデータセット行のデータ(たとえば "label""target" 列)を使いたい場合は、scorer の定義に labeltarget というキーワード引数を追加するだけで、簡単に scorer から参照できるようにできます。
たとえば、データセット内の "label" という列を使いたい場合、scorer 関数(または score クラスメソッド)は次のような引数リストを持ちます:
@weave.op
def my_custom_scorer(output: str, label: int) -> dict:
    ...
Weave の Evaluation が実行されると、AI システムの出力は output 引数に渡されます。Evaluation は、追加の scorer の引数名をデータセット列名に自動的にマッチさせようとします。Scorer の引数やデータセット列名をカスタマイズするのが難しい場合は、列マッピングを使用できます(詳細は後述)。
  • Output: AI システムの出力にアクセスするには、scorer 関数のシグネチャに output 引数を含めてください。

column_map による列名のマッピング

score メソッドの引数名が、データセット内の列名と一致しない場合があります。このような場合は、column_map を使って対応できます。クラスベースの scorer を使う場合は、scorer クラスを初期化する際に、Scorercolumn_map 属性に辞書を渡します。この辞書は、score メソッドの引数名をデータセットの列名に対応付けます。形式は {scorer_keyword_argument: dataset_column_name} です。例:
import weave
from weave import Scorer

# 要約するニュース記事のデータセット
dataset = [
    {"news_article": "The news today was great...", "date": "2030-04-20", "source": "Bright Sky Network"},
    ...
]

# Scorer クラス
class SummarizationScorer(Scorer):

    @weave.op
    def score(self, output, text) -> dict:
        """
            output: LLM の要約システムからの出力要約
            text: 要約対象のテキスト
        """
        ...  # 要約の品質を評価する

# `text` 引数を `news_article` データ列にマッピングする column_map を指定して scorer を作成
scorer = SummarizationScorer(column_map={"text" : "news_article"})
これで、score メソッド内の text 引数には、news_article データセット列からのデータが渡されるようになります。補足:
  • 列をマッピングする別の同等の方法として、Scorer を継承し、score メソッドをオーバーロードして列を明示的にマッピングすることもできます。
import weave
from weave import Scorer

class MySummarizationScorer(SummarizationScorer):

    @weave.op
    def score(self, output: str, news_article: str) -> dict:  # 型ヒントを追加
        # score メソッドをオーバーロードし、列を手動でマッピングする
        return super().score(output=output, text=news_article)

スコアリング用プロンプトから op の変数にアクセスする

LLM-as-a-judge 型スコアラー向けのスコアリング用プロンプトでは、op の変数を参照できます。これらの値は、スコアラーの run が実行されると自動的に抽出されます。 次のような関数の場合:
@weave.op
def summarize_article(article: str, max_length: int) -> str:
    # 要約ロジックをここに記述
    return summary
使用可能な変数は次のとおりです。
VariableDescription
{article}入力引数 article の値
{max_length}入力引数 max_length の値
{inputs}すべての入力引数を含む JSON 辞書
{output}あなたの op が返す値
スコアリングプロンプトの例:
このサマリーの品質を評価してください。

元の記事: {article}
サマリー: {output}
要求された最大長: {max_length}

以下の基準に基づいて、1〜10のスケールでサマリーを評価してください:
- 正確性: 記事の内容を正確に表現しているか?
- 網羅性: 重要なポイントを網羅しているか?
- 簡潔性: 適切に簡潔にまとめられているか?

評価と理由をJSONオブジェクトで返してください。

スコアラーの最終サマリー

評価中、スコアラーはデータセットの各行に対して計算されます。評価全体の最終スコアを出すために、出力の返り値の型に応じて動作する auto_summarize を用意しています。
  • 数値列に対しては平均値を計算
  • 真偽値列に対しては件数と割合を計算
  • その他の列タイプは無視されます
Scorer クラスの summarize メソッドをオーバーライドして、最終スコアの計算方法を独自に定義できます。summarize 関数は次のような引数を想定しています:
  • 単一のパラメータ score_rows: これは辞書のリストであり、それぞれの辞書には、データセットの単一行に対して score メソッドが返したスコアが含まれます。
  • サマリー(集約)済みスコアを含む辞書を返す必要があります。
なぜこれは便利なのか?データセットに対するスコアの最終値を決める前に、すべての行をスコアリングする必要がある場合に役立ちます。
class MyBinaryScorer(Scorer):
    """
    Returns True if the full output matches the target, False if not
    """

    @weave.op
    def score(self, output, target):
        return {"match": output == target}

    def summarize(self, score_rows: list) -> dict:
        full_match = all(row["match"] for row in score_rows)
        return {"full_match": full_match}
この例では、デフォルトの auto_summarize は True の件数と割合を返したはずです。
さらに詳しく知りたい場合は、CorrectnessLLMJudge の実装を参照してください。

Call への scorer の適用

Weave の op に scorer を適用するには、オペレーションの結果とトラッキング情報の両方にアクセスできる .call() メソッドを使用します。これにより、scorer の結果を Weave のデータベース内の特定の call と関連付けることができます。 .call() メソッドの使い方の詳細については、Calling Ops ガイドを参照してください。
基本的な例を次に示します。
# 結果と Call オブジェクトの両方を取得
result, call = generate_text.call("Say hello")

# scorer を適用
score = await call.apply_scorer(MyScorer())
同じ call に複数の scorer を適用することもできます。
# 複数の scorer を並列で適用
await asyncio.gather(
    call.apply_scorer(quality_scorer),
    call.apply_scorer(toxicity_scorer)
)
注意:
  • scorer の結果は自動的に Weave のデータベースに保存されます
  • scorer はメインのオペレーションが完了した後に非同期で実行されます
  • UI で scorer の結果を確認するか、API 経由でクエリできます
scorer を guardrail や monitor として使用する方法についての詳細情報(本番運用のベストプラクティスや完全なサンプルを含む)は、Guardrails and Monitors ガイド を参照してください。

preprocess_model_input を使用する

評価時に、データセットのサンプルがモデルに渡される前に変更するには、preprocess_model_input パラメータを使用できます。 使い方と例については、評価前にデータセットの行を整形するための preprocess_model_input の使用 を参照してください。

スコア分析

このセクションでは、1つのコール、複数のコール、および特定のスコアラーでスコアリングされたすべてのコールについて、スコアを分析する方法を説明します。

単一の Call のスコアを分析する

単一 Call の API

1件の Call を取得するには、get_call メソッドを使用します。
client = weave.init("my-project")

# 単一のcallを取得する
call = client.get_call("call-uuid-here")

# スコアを含むcallのフィードバックを取得する
feedback = list(call.feedback)

単一 Call の UI

Call Scores タブ
個々の Call のスコアは、Call の詳細ページの「Scores」タブに表示されます。

複数の Call のスコアを分析する

複数 Call API

複数の Call を取得するには、get_calls メソッドを使用します。
client = weave.init("my-project")

# 複数のcallを取得する - 任意のフィルターを使用してフィードバックを含める
calls = client.get_calls(..., include_feedback=True)

# callを反復処理してスコアを含むフィードバックにアクセスする
for call in calls:
    feedback = list(call.feedback)

複数 Call 用 UI

Multiple Calls Tab
複数の Call のスコアは、トレーステーブルの「Scores」列に表示されます。

特定の Scorer がスコアリングしたすべての Call を分析する

特定の Scorer がスコアリングしたすべての Call(API)

特定の Scorer がスコアリングしたすべての Call を取得するには、get_calls メソッドを使用します。
client = weave.init("my-project")

# スコアラーの任意のバージョンによってスコアリングされたすべての呼び出しを取得するには、スコアラー名(通常はクラス名)を使用します
calls = client.get_calls(scored_by=["MyScorer"], include_feedback=True)

# 特定バージョンのスコアラーによってスコアリングされたすべての呼び出しを取得するには、完全な ref を使用します
# ref はスコアラーオブジェクトまたは UI から取得できます。
calls = client.get_calls(scored_by=[myScorer.ref.uri()], include_feedback=True)

# 呼び出しをイテレートして、スコアを含むフィードバックにアクセスします
for call in calls:
    feedback = list(call.feedback)

Scorer ごとのすべての Call を UI で確認する

最後に、特定の Scorer によってスコア付けされたすべての Call を確認したい場合は、UI の Scorers タブにアクセスし、「Programmatic Scorer」タブを選択します。対象の Scorer をクリックして、Scorer の詳細ページを開きます。
Scorer Details Page
次に、Scores セクションの下にある View Traces ボタンをクリックして、その Scorer によってスコア付けされたすべての Call を表示します。
Filtered Calls to Scorer Version
デフォルトでは、選択したバージョンの Scorer に対する Call が表示されます。バージョンのフィルタを削除すると、その Scorer の任意のバージョンでスコア付けされたすべての Call を確認できます。
Filtered Calls to Scorer Name