メインコンテンツへスキップ
評価を使うと、変更後に一連のサンプルに対してアプリケーションをテストし、改善を重ねていけます。Weave は、Model クラスと Evaluation クラスによる評価のトラッキングをネイティブにサポートしています。API は前提を最小限に抑えて設計されているため、幅広いユースケースに柔軟に対応できます。 Evals hero

学べること:

このガイドでは、以下の方法を説明します。
  • Model を設定する
  • LLM の応答をテストするためのデータセットを作成する
  • モデルの出力を期待する出力と比較するスコアリング関数を定義する
  • スコアリング関数と追加の組み込み Scorer を使って、データセットに対するモデルの評価を実行する
  • 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 はその設定と振る舞いを自動的に取得し、変更があるたびにバージョンを更新します。これにより、反復改善を進めながら、時間の経過に伴うパフォーマンスをトラッキングできます。 Model は、Model をサブクラス化し、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) を受け取り、出力が target と一致するかどうかを示す真偽値の辞書を返します。@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 クラスの定義に関するチュートリアルを参照してください。

組み込み Scorer を使用して評価を実行する

カスタムのスコアリング関数に加えて、Weave の組み込み Scorerも使用できます。以下の評価では、weave.Evaluation() は前のセクションで定義した fruit_name_score 関数と、F1 スコアを計算する組み込みの MultiTaskBinaryClassificationF1 Scorer を使用します。 次の例では、2 つの関数によるスコアリングを使用して fruits データセット上で ExtractFruitsModel を評価し、その結果を 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)))
# Jupyter Notebook で実行している場合は、次を実行します:
# 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 で結果を確認できます。 評価結果

Weave の評価についてさらに詳しく見る

次のステップ

RAG アプリケーションを構築して、検索拡張生成の評価について学びましょう。