メインコンテンツへスキップ
評価は、変更を加えたあとにアプリケーションを一連のサンプルに対してテストすることで、アプリケーションを反復的に改善していくのに役立ちます。Weave は、Model クラスと Evaluation クラスによる評価の追跡を第一級にサポートしています。これらの API は前提を最小限に抑えて設計されており、幅広いユースケースに柔軟に対応できます。 Evals hero

学習内容

このガイドでは、次の内容を学びます。
  • Model をセットアップする
  • LLM の応答をテストするためのデータセットを作成する
  • モデル出力を期待される出力と比較するためのスコアリング関数を定義する
  • スコアリング関数と追加のビルトインスコアラーを使って、モデルをデータセットに対して評価する
  • Weave UI で評価結果を確認する

前提条件

  • W&B アカウント
  • Python 3.8 以上または Node.js 18 以上
  • 必要なパッケージがインストールされていること:
    • Python: pip install weave openai
    • TypeScript: npm install weave openai
  • 環境変数として設定した OpenAI の APIキー

必要なライブラリと関数をインポートする

次のライブラリをスクリプトにインポートします。
import json
import openai
import asyncio
import weave
from weave.scorers import MultiTaskBinaryClassificationF1

Model を構築する

Weave では、Models はオブジェクトであり、モデルやエージェントの振る舞い(ロジック、プロンプト、パラメータ)と、そのバージョン管理されたメタデータ(パラメータ、コード、マイクロ設定)を両方とも保持します。これにより、信頼性をもって追跡・比較・評価しながら、反復的に改善できます。 Model をインスタンス化すると、Weave がその設定と挙動を自動的に記録し、変更があったときにバージョンを更新します。これにより、反復しながら時間の経過に伴うパフォーマンスを追跡できます。 ModelModel をサブクラス化し、1 つの入力例を受け取ってレスポンスを返す predict 関数定義を実装することで宣言します。 次のサンプルのモデルは、OpenAI を使って、渡された文からエイリアンフルーツの名前、色、風味を抽出します。
class ExtractFruitsModel(weave.Model):
    model_name: str
    prompt_template: str

    @weave.op()
    async def predict(self, sentence: str) -> dict:
        client = openai.AsyncClient()

        response = await client.chat.completions.create(
            model=self.model_name,
            messages=[
                {"role": "user", "content": self.prompt_template.format(sentence=sentence)}
            ],
        )
        result = response.choices[0].message.content
        if result is None:
            raise ValueError("No response from model")
        parsed = json.loads(result)
        return parsed
ExtractFruitsModel クラスは(サブクラスとして)weave.Model を継承しており、Weave がインスタンス化されたオブジェクトを追跡できるようにしています。@weave.op は predict 関数をデコレートし、その入力と出力を追跡します。 Model オブジェクトは次のようにインスタンス化できます。
# チーム名とプロジェクト名を設定
weave.init('<team-name>/eval_pipeline_quickstart')

model = ExtractFruitsModel(
    model_name='gpt-3.5-turbo-1106',
    prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}'
)

sentence = "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy."

print(asyncio.run(model.predict(sentence)))
# Jupyter Notebook を使用している場合は、次を実行:
# await model.predict(sentence)

データセットを作成する

次に、モデルを評価するためのデータセットが必要です。 Dataset は Weave オブジェクトとして保存されたサンプル(例)の集合です 次のサンプルデータセットでは、3 つの入力文とその正解(labels)を定義し、それらをスコアリング関数が読み取れる JSON テーブル形式に整形します。 この例ではコード内でサンプルのリストを構築していますが、実行中のアプリケーションから 1 件ずつログとして記録することもできます。
sentences = ["There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.",
"Pounits are a bright green color and are more savory than sweet.",
"Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."]
labels = [
    {'fruit': 'neoskizzles', 'color': 'purple', 'flavor': 'candy'},
    {'fruit': 'pounits', 'color': 'bright green', 'flavor': 'savory'},
    {'fruit': 'glowls', 'color': 'pale orange', 'flavor': 'sour and bitter'}
]
examples = [
    {'id': '0', 'sentence': sentences[0], 'target': labels[0]},
    {'id': '1', 'sentence': sentences[1], 'target': labels[1]},
    {'id': '2', 'sentence': sentences[2], 'target': labels[2]}
]
次に、weave.Dataset() クラスを使ってデータセットを作成し、公開します:
weave.init('eval_pipeline_quickstart')
dataset = weave.Dataset(name='fruits', rows=examples)
weave.publish(dataset)

カスタムスコアリング関数を定義する

Weave 評価を使用する場合、Weave は output と比較するための target を必要とします。次のスコアリング関数は 2 つの辞書(targetoutput)を受け取り、出力がターゲットと一致しているかどうかを示すブール値の辞書を返します。@weave.op() デコレータによって、Weave はこのスコアリング関数の実行を追跡できます。
@weave.op()
def fruit_name_score(target: dict, output: dict) -> dict:
    return {'correct': target['fruit'] == output['fruit']}
独自のスコアリング関数を作成する方法については、Scorers ガイドを参照してください。 一部のアプリケーションでは、カスタムの Scorer クラスを作成したい場合があります。たとえば、特定のパラメータ(チャットモデルやプロンプトなど)、行ごとのスコアリング、およびスコアの集約計算を備えた標準化された LLMJudge クラスを作成することが考えられます。詳しくは、次章の RAG アプリケーションのモデルベース評価 にある Scorer クラス定義に関するチュートリアルを参照してください。

組み込みスコアラーを使って評価を実行する

カスタムのスコアリング関数に加えて、Weave の組み込みスコアラーも利用できます。次の評価では、weave.Evaluation() が前のセクションで定義した fruit_name_score 関数と、F1 スコアを計算する組み込みスコアラー MultiTaskBinaryClassificationF1 を使用します。 次の例では、ExtractFruitsModelfruits データセット上で評価し、これら 2 つのスコアリング関数を使ってスコアを計算し、その結果を Weave にログします。
weave.init('eval_pipeline_quickstart')

evaluation = weave.Evaluation(
    name='fruit_eval',
    dataset=dataset, 
    scorers=[
        MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]), 
        fruit_name_score
    ],
)
print(asyncio.run(evaluation.evaluate(model)))
# if you're in a Jupyter Notebook, run:
# await evaluation.evaluate(model)
Python スクリプトから実行する場合は、asyncio.run を使用する必要があります。一方、Jupyter Notebook から実行する場合は、await を直接使用できます。

完全なサンプル

import json
import asyncio
import openai
import weave
from weave.scorers import MultiTaskBinaryClassificationF1

# Weaveを一度初期化する
weave.init('eval_pipeline_quickstart')

# 1. モデルを定義する
class ExtractFruitsModel(weave.Model):
    model_name: str
    prompt_template: str

    @weave.op()
    async def predict(self, sentence: str) -> dict:
        client = openai.AsyncClient()
        response = await client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": self.prompt_template.format(sentence=sentence)}],
        )
        result = response.choices[0].message.content
        if result is None:
            raise ValueError("No response from model")
        return json.loads(result)

# 2. モデルをインスタンス化する
model = ExtractFruitsModel(
    model_name='gpt-3.5-turbo-1106',
    prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}'
)

# 3. データセットを作成する
sentences = ["There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.",
"Pounits are a bright green color and are more savory than sweet.",
"Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them."]
labels = [
    {'fruit': 'neoskizzles', 'color': 'purple', 'flavor': 'candy'},
    {'fruit': 'pounits', 'color': 'bright green', 'flavor': 'savory'},
    {'fruit': 'glowls', 'color': 'pale orange', 'flavor': 'sour and bitter'}
]
examples = [
    {'id': '0', 'sentence': sentences[0], 'target': labels[0]},
    {'id': '1', 'sentence': sentences[1], 'target': labels[1]},
    {'id': '2', 'sentence': sentences[2], 'target': labels[2]}
]

dataset = weave.Dataset(name='fruits', rows=examples)
weave.publish(dataset)

# 4. スコアリング関数を定義する
@weave.op()
def fruit_name_score(target: dict, output: dict) -> dict:
    return {'correct': target['fruit'] == output['fruit']}

# 5. 評価を実行する
evaluation = weave.Evaluation(
    name='fruit_eval',
    dataset=dataset,
    scorers=[
        MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]),
        fruit_name_score
    ],
)
print(asyncio.run(evaluation.evaluate(model)))

評価結果を確認する

Weave は各予測とスコアのトレースを自動的に取得します。評価時に表示されるリンクをクリックして、Weave UI で結果を確認します。 Evaluation results

Weave 評価についてさらに学ぶ

次のステップ

検索拡張生成(RAG)の評価について学ぶには、RAG アプリケーションを構築してください。