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

独自のスコアラーを作成する

すぐに使えるスコアラー このガイドではカスタムスコアラーの作成方法を紹介しますが、Weave には、すぐに使用できるさまざまな組み込みスコアラーローカル SLM スコアラーも用意されています。たとえば、次のようなものがあります。

関数ベースのスコアラー

これらは、辞書を返す @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:
        """要約の品質を評価します。

        Args:
            output: AI システムによって生成された要約
            text: 要約対象の元のテキスト
        """
        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])
このクラスは、要約を元のテキストと比較して、その品質を評価します。

Scorersの仕組み

Scorer のキーワード引数

Scorer は、AI システムの出力とデータセット行の入力データの両方にアクセスできます。
  • Input: “label” 列や “target” 列など、データセット行のデータを Scorer で使いたい場合は、Scorer の定義に label または target のキーワード引数を追加するだけで、そのデータを簡単に Scorer から利用できます。
たとえば、データセット内の “label” という列を使いたい場合、Scorer 関数 (または score クラス method) のパラメーターリストは次のようになります。
@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 method の引数名が、データセット内の列名と一致しないことがあります。その場合は column_map を使って対応できます。クラスベースの Scorer を使用している場合は、Scorer クラスの初期化時に辞書を Scorercolumn_map 属性に渡します。この辞書は、score method の引数名をデータセットの列名に対応付けるもので、形式は {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` データ列に対応付ける列マッピングを持つ Scorer を作成
scorer = SummarizationScorer(column_map={"text" : "news_article"})
これで、score method の text 引数は news_article データセット列のデータを受け取ります。メモ:
  • 列をマッピングする別の同等の方法として、Scorer をサブクラス化し、score method をオーバーライドして列を明示的にマッピングすることもできます。
import weave
from weave import Scorer

class MySummarizationScorer(SummarizationScorer):

    @weave.op
    def score(self, output: str, news_article: str) -> dict:  # タイプヒントを追加
        # score method をオーバーライドして列を手動でマッピング
        return super().score(output=output, text=news_article)

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

LLM-as-a-judge scorer のスコアリングプロンプトでは、op の変数を参照できます。これらの値は、scorer の実行時に自動的に自動抽出されます。 次のような関数の場合:
@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 method をオーバーライドして、最終スコアを計算する独自の方法を指定できます。summarize function では、次の内容を想定しています。
  • 1つのパラメーター score_rows: これは辞書のリストで、各辞書にはデータセットの1行に対して score method が返したスコアが含まれます。
  • 集計したスコアを含む辞書を返す必要があります。
これが役立つ理由データセットの最終的なスコア値を決める前に、すべての行をスコアリングする必要がある場合に役立ちます。
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 にスコアラーを適用する

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

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

preprocess_model_input を使用する

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

スコア分析

このセクションでは、特定の scorer が付けた単一の call、複数の call、またはすべての call のスコアを分析する方法を説明します。

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

単一Call API

単一のCallのcallsを取得するには、get_call methodを使用します。
client = weave.init("my-project")

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

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

単一callのUI

callのScoresタブ
個々のcallのスコアは、Call details パネルの「Scores」タブに表示されます。

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

複数のCalls API

複数のcallに対するcallsを取得するには、get_calls method を使用できます。
client = weave.init("my-project")

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

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

複数の Calls の UI

複数の Calls タブ
複数の Calls の score は、トレース表の「Scores」列に表示されます。

特定の Scorer がスコア付けしたすべての Calls を分析する

Scorer ごとのすべての Calls API

特定の Scorer でスコア付けされたすべての Calls を取得するには、get_calls method を使用できます。
client = weave.init("my-project")

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

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

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

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

最後に、特定の Scorer によってスコア付けされたすべての Calls を確認するには、UI の Scorers タブにアクセスし、“Programmatic Scorer” タブを選択します。Scorer をクリックして、Scorer の詳細ページを開きます。
Scorer の詳細ページ
次に、Scores の下にある View Traces ボタンをクリックして、Scorer によってスコア付けされたすべての Calls を表示します。
Scorer バージョンでフィルターされた Calls
デフォルトでは、選択した Scorer のバージョンが表示されます。バージョンのフィルターを解除すると、Scorer の任意のバージョンによってスコア付けされたすべての Calls を確認できます。
Scorer 名でフィルターされた Calls