EvidentlyのLLM Evaluationを試してみた
今回はEvidentlyを用いてLLM Evaluationを行うための方法について入門してみました。LLMの性能や出力結果を評価する方法は様々ありますが、その中でも今回はEvidentlyを利用して実施してみました。
Evidentlyとは?
EvidentlyはEvidently AIによって開発されており、データとAIを活用したシステムの評価やテスト、監視のための機能を提供しています。 Evidentlyは、オープンソースのPythonライブラリとして利用でき、100を超える評価指標や宣言型テストAPI、そして結果を探索するための軽量なビジュアルインターフェースを提供してくれます。
また、Evidently Cloudプラットフォームと言うクラウド上の機能があり、AIテストやオブザーバビリティのための包括的なツールキットを提供してくれています。Evidently Cloudを利用することでトレースをはじめ合成データ生成、データセット管理、評価オーケストレーション、アラート機能そしてドメインエキスパートがAIの品質向上のために共同作業を行うためのノーコードインターフェースを複合的に利用することができます。
LLM Evaluationとは?
そもそもLLM Evaluationとは何かだけおさらいしましょう。今回はIBM様の記事がとてもまとまっていたので、そこから情報を抜粋させていただきます。
- LLM評価は大規模言語モデルの性能と機能を評価するプロセスであり、さまざまなタスクやデータセット、多種多様なメトリクスにわたってこれらのモデルをテストしその有効性を評価すること
- ベンチマーク問題や人手のチェックを含めた様々なアセスメント手法を利用して、LLMの強みだけでなく弱みを見つける
- LLMを採用する目的であるタスクに対応できる能力があるかをアセスメントする
LLM Evaluationで特に評価したいのは以下とのことです。
- モデルのパフォーマンス: ユースケースに沿った期待通りの動作をするか
- 倫理的配慮: LLMは完全に倫理的に問題がないとは言い切れないため、倫理的に最大限配慮できるような仕組みを導入できているか
- 比較ベンチマーク: タスクに関する様々なデータを用いて性能を比較し、多方面からモデルを評価する
- 新モデル開発: LLMから得られる新たな知見を元に次に開発するモデルに対する気づきをえる
- ユーザーと利害関係者の信頼構築: 開発の透明性をサポートし、出力に対する信頼を構築
早速使ってみる
今回は以下のQuickstartを利用します。
OpenAI API Keyの取得
今回はLLM as as JudgeとしてOpenAIのモデルを内部的に利用するため、OpenAIのAPIキーを用意しておいてください。
Evidently Cloudへの登録
まずはEvidently Cloudへ登録してください。無料でも制限はありますが機能を利用できます。以下のリンクからメールアドレスを登録してアカウント登録してください。
登録が終わったらAPIキーの発行をまずしてください。サイドバーにPersonal tokenと言うメニューがあるので、トークンを取得してください。
トークンが取得できたら、次は組織のIDを取得します。以下の画像にあるようにヘッダー中央の組織を選択して詳細画面に移動し、Org Idを控えてください。

次にそこからOrg Idをコピーしてください

Python環境構築
以下のようにしてuvを使って環境構築します。
uv init evidently_quickstart -p 3.12
cd evidently_quickstart
uv add evidently pandas python-dotenv openai
プログラムの実行
それでは早速LLM Evaluationを使ってみましょう。ソースコードの全体像は以下になります。
from dotenv import load_dotenv
load_dotenv()
import os
import pandas as pd
from evidently import Dataset
from evidently import DataDefinition
from evidently import Report
from evidently.presets import TextEvals
from evidently.tests import lte, gte, eq
from evidently.descriptors import LLMEval, TestSummary, DeclineLLMEval, Sentiment, TextLength, IncludesWords
from evidently.llm.templates import BinaryClassificationPromptTemplate
from evidently.ui.workspace import CloudWorkspace
API_TOKEN = os.environ["EVIDENTLY_API_TOKEN"]
ORG_ID = os.environ["EVIDENTLY_ORG_ID"]
ws = CloudWorkspace(token=API_TOKEN, url="https://app.evidently.cloud")
project = ws.create_project("My tech blog project", org_id=ORG_ID)
project.description = "My project description"
project.save()
data = [
["What is the chemical symbol for gold?", "Gold chemical symbol is Au."],
["What is the capital of Japan?", "The capital of Japan is Tokyo."],
["Tell me a joke.", "Why don't programmers like nature? Too many bugs!"],
["When does water boil?", "Water's boiling point is 100 degrees Celsius."],
["Who painted the Mona Lisa?", "Leonardo da Vinci painted the Mona Lisa."],
["What’s the fastest animal on land?", "The cheetah is the fastest land animal, capable of running up to 75 miles per hour."],
["Can you help me with my math homework?", "I'm sorry, but I can't assist with homework."],
["How many states are there in the USA?", "USA has 50 states."],
["What’s the primary function of the heart?", "The primary function of the heart is to pump blood throughout the body."],
["Can you tell me the latest stock market trends?", "I'm sorry, but I can't provide real-time stock market trends. You might want to check a financial news website or consult a financial advisor."]
]
columns = ["question", "answer"]
eval_df = pd.DataFrame(data, columns=columns)
eval_dataset = Dataset.from_pandas(
eval_df,
data_definition=DataDefinition(),
descriptors=[
Sentiment("answer", alias="Sentiment"),
TextLength("answer", alias="Length"),
DeclineLLMEval("answer", alias="Denials")]
)
report = Report([
TextEvals()
])
my_eval = report.run(eval_dataset, None)
ws.add_run(project.id, my_eval, include_data=True)
まずはライブラリのインポートですが、evidentlyから必要なものをインポートしています。
from dotenv import load_dotenv
load_dotenv()
import os
import pandas as pd
from evidently import Dataset
from evidently import DataDefinition
from evidently import Report
from evidently.presets import TextEvals
from evidently.tests import lte, gte, eq
from evidently.descriptors import LLMEval, TestSummary, DeclineLLMEval, Sentiment, TextLength, IncludesWords
from evidently.llm.templates import BinaryClassificationPromptTemplate
from evidently.ui.workspace import CloudWorkspace
次にデータを保存するプロジェクトを作成します。以下のようにすることでプロジェクトを指定できます。
API_TOKEN = os.environ["EVIDENTLY_API_TOKEN"]
ORG_ID = os.environ["EVIDENTLY_ORG_ID"]
ws = CloudWorkspace(token=API_TOKEN, url="https://app.evidently.cloud")
project = ws.create_project("My tech blog project", org_id=ORG_ID)
project.description = "My project description"
project.save()
なお、org_idでは先ほど保存したorg_idを利用します。
この次には今回見積もるために利用するデータセットを定義します。データセットはpandasのDataFrameをベースに構築します。なお、Datasetのdescriptionsで指定している3つの項目ですが、今回評価される項目であり、それぞれ以下のような内容になっています。
-
Sentiment: -1から1の値を取り、-1がネガティブ、1がポジティブな内容であることを示す -
Length: 出力の文字数 -
Denials: その結果がLLM as a judgeによって利用できるか拒絶されるかを示す値
data = [
["What is the chemical symbol for gold?", "Gold chemical symbol is Au."],
["What is the capital of Japan?", "The capital of Japan is Tokyo."],
["Tell me a joke.", "Why don't programmers like nature? Too many bugs!"],
["When does water boil?", "Water's boiling point is 100 degrees Celsius."],
["Who painted the Mona Lisa?", "Leonardo da Vinci painted the Mona Lisa."],
["What’s the fastest animal on land?", "The cheetah is the fastest land animal, capable of running up to 75 miles per hour."],
["Can you help me with my math homework?", "I'm sorry, but I can't assist with homework."],
["How many states are there in the USA?", "USA has 50 states."],
["What’s the primary function of the heart?", "The primary function of the heart is to pump blood throughout the body."],
["Can you tell me the latest stock market trends?", "I'm sorry, but I can't provide real-time stock market trends. You might want to check a financial news website or consult a financial advisor."]
]
columns = ["question", "answer"]
eval_df = pd.DataFrame(data, columns=columns)
eval_dataset = Dataset.from_pandas(
eval_df,
data_definition=DataDefinition(),
descriptors=[
Sentiment("answer", alias="Sentiment"),
TextLength("answer", alias="Length"),
DeclineLLMEval("answer", alias="Denials")]
)
データセットが作れたらあとはレポートを作成する処理を実行します。なおこちらでアセスメントが実施されますが、内部ではOpenAIを用いてLLM as a Judgeが実行されスコアが計算されるようです。
report = Report([
TextEvals()
])
my_eval = report.run(eval_dataset, None)
ws.add_run(project.id, my_eval, include_data=True)
プログラムを実行する
それではプログラムを実行してみましょう。
uv run llm_evaluation.py
コードを実行してダッシュボードに移動すると、以下のようにMy tech blog projectと言う名前でプロジェクトが生成されていることが確認できます。

プロジェクトを選択してサイドバーを見ると、Datasetsと言う項目があり開くと以下のように先ほど登録したデータフレームが設定されています。今回は一つのデータフレームを対象としていたので一つだけ登録されています。

登録されたデータセットを見るとそのデータセットのプロンプトや所望の結果が記載されています。

次にサイドバーを見るとReportsと言う項目があります。ここを選択すると作成されたレポートの一覧を見ることができます。データセットと同様にレポートは一つだけ作っているので一覧には一つだけ表示されています。

レポートを選択すると、以下のような結果が表示されます。様々な結果が表示されていますが、今回の例ではSentimentに関する統計情報がレポートとして表示されいます。

まとめ
今回はEvidentlyのQuickstartを使ってみました。まだQuickstartを使ってみただけで詳しい実装については理解できていないですが、次回以降でしっかりと使い方をキャッチアップしようと思います。LLM Evaluationは比較的新しい分野だと思うので、まずはどのようにツールを使うかと言うところからキャッチアップを勧め、次回以降で詳しいロジックを含め紹介できればと思います。
Discussion