前回のStudyはこちら:
はじめに
MLflow3がリリースされ、Databricks側でもDocumentの対応含めて様々な機能が実装されています。
GenAIエージェントやアプリの評価に関する機能も拡張されました。
特にMosaic AI Agent Evaluationからの機能統合がされていて使いやすくなっています。
今回は以下のサイト内容を一部改変しながらウォークスルーし、GenAIアプリケーションに対する評価・改善を試してみます。
試行はDatabricks Free Editionを利用しました。
MLflow3の評価およびモニタリング機能とは
以下に概要からクイックスタートの手順が記載されています。
MLflowの評価およびモニタリング機能は、生成AIアプリケーションのライフサイクル全体を通じて、その品質を体系的に測定、改善、維持するのに役立ちます。 開発から本番運用まで、同じ 品質のスコアラー を使用して、コストとレイテンシを管理しながら、アプリケーションが正確で信頼性の高い応答を提供できるようにします。
今回は、評価機能に焦点をあてて、アプリケーションの評価と改善のサイクルを試してみます。
アプリの評価と改善 実践
以下の内容を若干改変して実行していきます。
準備
ノートブックを作成し、必要なパッケージをインストールします。
%pip install "mlflow[databricks]>=3.1.1" openai
%restart_python
アプリケーションを作成する
まず、次のような機能をもったEメール生成アプリを作成します。
- CRMデータベースから顧客情報を取得
- 取得した情報に基づいてパーソナライズされたフォローアップEメールを作成
CRMデータの取得はMLflowの取得固有のスコアラーを有効にするためにspan_type="RETRIEVER"
でマークしています。
import mlflow
from openai import OpenAI
from mlflow.entities import Document
from typing import List, Dict
# OpenAI呼び出しの自動トレースを有効にする
mlflow.openai.autolog()
# 同じ資格情報を使用してOpenAI経由でDatabricks LLMに接続する
# あるいは、ここで独自のOpenAI資格情報を使用することもできます
mlflow_creds = mlflow.utils.databricks_utils.get_databricks_host_creds()
client = OpenAI(
api_key=mlflow_creds.token, base_url=f"{mlflow_creds.host}/serving-endpoints"
)
# シミュレートされたCRMデータベース
CRM_DATA = {
"Acme Corp": {
"contact_name": "アリス・チェン",
"recent_meeting": "月曜日に製品デモを行い、エンタープライズ機能に非常に興味を持っていました。彼らは次のことについて質問しました:高度な分析、リアルタイムダッシュボード、API統合、カスタムレポート、マルチユーザーサポート、SSO認証、データエクスポート機能、および500人以上のユーザー向けの価格設定",
"support_tickets": [
"Ticket #123: APIの遅延問題(先週解決済み)",
"Ticket #124: 一括インポートの機能リクエスト",
"Ticket #125: GDPRコンプライアンスに関する質問",
],
"account_manager": "サラ・ジョンソン",
},
"TechStart": {
"contact_name": "ボブ・マルティネス",
"recent_meeting": "先週の木曜日に初回の営業電話を行い、価格をリクエストしました",
"support_tickets": [
"Ticket #456: ログイン問題(オープン - クリティカル)",
"Ticket #457: パフォーマンスの低下が報告されました",
"Ticket #458: 彼らのCRMとの統合が失敗しています",
],
"account_manager": "マイク・トンプソン",
},
"Global Retail": {
"contact_name": "キャロル・ワン",
"recent_meeting": "昨日の四半期レビューで、プラットフォームのパフォーマンスに満足しています",
"support_tickets": [],
"account_manager": "サラ・ジョンソン",
},
}
# MLflowの事前定義されたRetrievalGroundednessスコアラーが機能するようにリトリーバースパンを使用する
@mlflow.trace(span_type="RETRIEVER")
def retrieve_customer_info(customer_name: str) -> List[Document]:
"""CRMデータベースから顧客情報を取得する"""
if customer_name in CRM_DATA:
data = CRM_DATA[customer_name]
return [
Document(
id=f"{customer_name}_meeting",
page_content=f"Recent meeting: {data['recent_meeting']}",
metadata={"type": "meeting_notes"},
),
Document(
id=f"{customer_name}_tickets",
page_content=f"Support tickets: {', '.join(data['support_tickets']) if data['support_tickets'] else 'No open tickets'}",
metadata={"type": "support_status"},
),
Document(
id=f"{customer_name}_contact",
page_content=f"Contact: {data['contact_name']}, Account Manager: {data['account_manager']}",
metadata={"type": "contact_info"},
),
]
return []
@mlflow.trace
def generate_sales_email(customer_name: str, user_instructions: str) -> Dict[str, str]:
"""顧客データと営業担当者の指示に基づいてパーソナライズされた営業メールを生成する"""
# 顧客情報を取得する
customer_docs = retrieve_customer_info(customer_name)
# 取得したコンテキストを結合する
context = "\n".join([doc.page_content for doc in customer_docs])
# 取得したコンテキストを使用してメールを生成する
prompt = f"""あなたは営業担当者です。以下の顧客情報に基づき、
顧客からのリクエストに対応した簡潔なフォローアップメールを作成してください。
顧客情報:
{context}
ユーザー指示: {user_instructions}
メールは簡潔かつパーソナライズされた内容にしてください。"""
response = client.chat.completions.create(
model="databricks-meta-llama-3-3-70b-instruct",
messages=[
{"role": "system", "content": "あなたは役に立つ営業アシスタントです。"},
{"role": "user", "content": prompt},
],
max_tokens=2000,
)
return {"email": response.choices[0].message.content}
# アプリケーションをテストする
result = generate_sales_email("Acme Corp", "商品デモの後にフォローアップして")
print(result["email"])
以下は、商品デモの後にアリスさんへフォローアップするメールの例です。
---
件名: エンタープライズ機能に関するフォローアップ
アリスさん
先日は、当社の製品デモにご参加いただき、誠にありがとうございました。エンタープライズ機能に対するご関心を記憶しています。この度、ご質問いただいた機能やサポートチケットに関する現在の状況についてご報告いたします。
1. **高度な分析とリアルタイムダッシュボード**:当社のソリューションは、詳細な分析とリアルタイムのデータ提供を可能とします。これにより、ビジネスのインサイトを深め、迅速な意思決定をサポートします。
2. **API統合**:APIを通じての統合は、システム間のシームレスなデータ交換を可能にします。この機能については、先週解決したAPIの遅延問題(Ticket #123)以来、さらなる最適化が行われています。
3. **カスタムレポートとマルチユーザーサポート**:ご要望に応え、カスタマイズ可能なレポート機能と複数ユーザーのサポートが提供可能です。これにより、チームのコラボレーションとレポートのカスタマイズが容易になります。
4. **SSO認証とデータエクスポート**:シングルサインオン(SSO)認証とデータエクスポート機能も提供しています。これらは、セキュリティとデータの可搬性を向上させるための重要な機能です。
5. **500人以上のユーザー向けの価格設定**:ご要望に応じて、エンタープライズプランの価格について詳細を提供します。請求に関する詳細な情報を別途送付します。
また、ご要望のあった一括インポートに関する機能リクエスト(Ticket #124)とGDPRコンプライアンスに関する質問(Ticket #125)についても、担当チームが対応中です。ご了承ください。
アカウントマネージャーのサラ・ジョンソンもご連絡先をご共有しております。ご不明な点や追加の質問がございましたら、いつでもお気軽にご連絡ください。サラはあなたのニーズに合わせたサポートを提供いたします。
今後ともどうぞよろしくお願い申し上げます。
---
[あなたの名前]
営業担当
[会社名]
[連絡先]
また、以下のようにトレース結果も得られます。
本番運用のトラフィックをシミュレートする
デモンストレーションの目的でトラフィックをシミュレートします。
実際には、使用状況のトレース トレース を使用して評価データセットを作成します。
まず、バージョン管理用にLoggedModelを作成・設定します。
# トレース管理をするLoggedModelを設定
active_model_info = mlflow.set_active_model(name="sales_email_v1")
実際にトラフィックを想定したシナリオを実行します。
# ガイドライン違反を意図したシナリオでベータテストのトラフィックをシミュレート
test_requests = [
{"customer_name": "Acme Corp", "user_instructions": "製品デモの後にフォローアップ"},
{"customer_name": "TechStart", "user_instructions": "サポートチケットの状況を確認"},
{"customer_name": "Global Retail", "user_instructions": "四半期レビューの要約を送信"},
{"customer_name": "Acme Corp", "user_instructions": "すべての製品機能、価格帯、実装スケジュール、およびサポートオプションを詳しく説明する非常に詳細なメールを書く"},
{"customer_name": "TechStart", "user_instructions": "彼らのビジネスに感謝する熱意のあるメールを送信"},
{"customer_name": "Global Retail", "user_instructions": "フォローアップメールを送信"},
{"customer_name": "Acme Corp", "user_instructions": "物事がどうなっているかを確認するために連絡"},
]
# リクエストを実行してトレースを記録する
print("プロダクション トラフィックをシミュレートしています...")
for req in test_requests:
try:
result = generate_sales_email(**req)
print(f"✓ {req['customer_name']} のメールを生成しました")
except Exception as e:
print(f"✗ {req['customer_name']} のエラー: {e}")
プロダクション トラフィックをシミュレートしています...
✓ Acme Corp のメールを生成しました
✓ TechStart のメールを生成しました
✓ Global Retail のメールを生成しました
✓ Acme Corp のメールを生成しました
✓ TechStart のメールを生成しました
✓ Global Retail のメールを生成しました
✓ Acme Corp のメールを生成しました
結果として、Versionがsales_email_v1
のLoggedModelにトレースが7件追加されました。
評価データセットを作成する
次に、トレースを評価データセットに変換します。
トレースから評価データセットを作成すると、評価結果がデータセットにリンクされ、データセットの経時的な変更を追跡してこのデータセットを使用して生成されたすべての評価結果を確認できます。
UIとSDKを使う方法と2種類ありますが、今回はSDKを使ってデータセットを作成します。
import mlflow
import mlflow.genai.datasets
import time
# 1. 評価データセットを作成
uc_schema = "workspace.default"
evaluation_dataset_table_name = "email_generation_eval"
# すでにデータセットがある場合は削除
try:
mlflow.genai.datasets.delete_dataset(
uc_table_name=f"{uc_schema}.{evaluation_dataset_table_name}",
)
except Exception as e:
print(f"評価データセットは存在しません: {e}")
# データセットを作成
eval_dataset = mlflow.genai.datasets.create_dataset(
uc_table_name=f"{uc_schema}.{evaluation_dataset_table_name}",
)
print(f"評価データセットを作成しました: {uc_schema}.{evaluation_dataset_table_name}")
# 2. sales_email_v1のトレースを全権取得
traces = mlflow.search_traces(
model_id=mlflow.get_active_model_id(),
order_by=["attributes.timestamp_ms DESC"],
)
print(f"エクスペリメントから {len(traces)} 件の成功したトレースが見つかりました")
# 3. トレースを評価データセットに追加
eval_dataset.merge_records(traces)
print(f"{len(traces)} 件のレコードを評価データセットに追加しました")
# データセットのプレビュー
df = eval_dataset.to_df()
print(f"\nデータセットのプレビュー:")
print(f"総レコード数: {len(df)}")
print("\nサンプルレコード:")
sample = df.iloc[0]
print(f"Inputs: {sample['inputs']}")
評価データセットを作成しました: workspace.default.email_generation_eval
エクスペリメントから 7 件の成功したトレースが見つかりました
7 件のレコードを評価データセットに追加しました
データセットのプレビュー:
総レコード数: 7
サンプルレコード:
Inputs: {'customer_name': 'Acme Corp', 'user_instructions': 'すべての製品機能、価格帯、実装スケジュール、およびサポートオプションを詳しく説明する非常に詳細なメールを書く'}
作成したデータセットの内容を確認してみましょう。
eval_dataset = mlflow.genai.datasets.get_dataset(
uc_table_name=f"{uc_schema}.{evaluation_dataset_table_name}",
)
display(eval_dataset.to_df())
7件のデータができているのが確認できます。
事前定義されたスコアラーで評価を実行する
次に、MLflowに用意されている 定義済みのスコアラー を使用して、生成AI アプリケーションの品質のさまざまな側面を自動的に評価してみましょう。
詳細については、 LLM ベースのスコアラー と コードベースのスコアラー のリファレンスページを参照してください。
今回は取得文書の正確性、関連性、回答の安全性に加えて、独自ガイドラインで定義した内容をチェックして評価します。
from mlflow.genai.scorers import (
RetrievalGroundedness,
RelevanceToQuery,
Safety,
Guidelines,
)
# スコアラーを変数として保存し、ステップ7で再利用できるようにします
email_scorers = [
RetrievalGroundedness(), # メール内容が取得したデータに基づいているかをチェック
Guidelines(
name="follows_instructions",
guidelines="生成されたメールは、リクエスト内のuser_instructions(ユーザー指示)に従っている必要があります。",
),
Guidelines(
name="concise_communication",
guidelines="メールは必ず簡潔かつ要点を押さえている必要があります。重要な文脈を失うことなく、主要なメッセージを効率的に伝えるべきです。",
),
Guidelines(
name="mentions_contact_name",
guidelines="メールの挨拶文で、顧客担当者のファーストネーム(例:Alice、Bob、Carol)を明示的に記載する必要があります。「Hello」や「Dear Customer」などの一般的な挨拶は不可とします。",
),
Guidelines(
name="professional_tone",
guidelines="メールはプロフェッショナルな口調で書かれている必要があります。",
),
Guidelines(
name="includes_next_steps",
guidelines="メールの最後に、具体的かつ実行可能な次のアクションと明確なタイムラインを必ず記載してください。",
),
RelevanceToQuery(), # メールがユーザーのリクエストに対応しているかをチェック
Safety(), # 有害または不適切な内容が含まれていないかをチェック
]
# 定義済みスコアラーで評価を実行
eval_results = mlflow.genai.evaluate(
data=eval_dataset,
predict_fn=generate_sales_email,
scorers=email_scorers,
)
結果の表示と解釈
mlflow.genai.evaluate()
を実行すると、評価データセット内のすべての行のトレースと、各スコアラーからのフィードバックが関連付けられた評価ランが作成されます。
評価ランを使用して、次のことを行います。
- 集計メトリクスの参照 : それぞれのスコアラーのすべてのテストケースにおける平均パフォーマンス
- 個々の障害ケースのデバッグ : 障害が発生した理由を理解し、将来のバージョンで行うべき改善点を特定します
- 故障解析 :採点者が課題を特定した具体例
今回の評価では、いくつかの問題が見られます。
- 不適切な指示フォロー - エージェントは、簡単なチェックインを求められたときに詳細な製品情報を送信したり、熱心なお礼のメッセージを求められたときにサポートチケットの更新を提供したりするなど、ユーザーのリクエストと一致しない応答を頻繁に提供します
- 簡潔さの欠如 - ほとんどのEメールは不必要に長く、重要なメッセージを薄めるほど詳細が多すぎて、Eメールを「簡潔でパーソナライズ」に保つように指示されているにもかかわらず、効率的にコミュニケーションをとることができません。
- 具体的な次のステップが欠けている - Eメールの大部分は、必須要素として特定された具体的なタイムラインを含む、具体的で実行可能な次のステップで終わらない
では、さっそく評価結果をエクスペリメントの評価から確認しましょう。
全てのアセスメントを表示すると以下のようになります。
(Safetyは環境制約でエラーになっている模様)
また、コードでも評価結果を確認できます。
# 評価実行のトレースを取得
eval_traces = mlflow.search_traces(run_id=eval_results.run_id)
# eval_tracesは評価されたトレースを含むPandas DataFrameです。`assessments`列には各スコアラーのフィードバックが含まれます。
print(eval_traces)
trace_id ... assessments
0 tr-f61047a886c18bdc4a4faa8b7dcb3502 ... [Feedback(name='safety', source=AssessmentSour...
1 tr-f975a936f29b5a4771fe1e4741165384 ... [Feedback(name='includes_next_steps', source=A...
2 tr-c2900e95bbc4a2a1f68fb45d7bc71321 ... [Feedback(name='professional_tone', source=Ass...
3 tr-b8fee8e33925b8ce47c0902fe82a097a ... [Feedback(name='concise_communication', source...
4 tr-8ccc7fcefcc1ec32ab476f71bf5944f3 ... [Feedback(name='agent/total_token_count', sour...
5 tr-f383143bca179fe41e90769f361cc33d ... [Feedback(name='retrieval_groundedness', sourc...
6 tr-68d82a14d9ec188f364155ba9cea1469 ... [Feedback(name='relevance_to_query', source=As...
[7 rows x 12 columns]
改良版を作成する
評価結果に基づいて、特定された問題に対処する改善バージョンgenerate_sales_email_v2
を作成しましょう。
新しいバージョンの generate_sales_email_v2()
関数では、最初に定義したら retrieve_customer_info()
関数を内部で使用します。
# 新しいLoggedModelを作成・設定
active_model_info = mlflow.set_active_model(name="sales_email_v2")
@mlflow.trace
def generate_sales_email_v2(
customer_name: str, user_instructions: str
) -> Dict[str, str]:
"""顧客データと営業担当者の指示に基づいてパーソナライズされた営業メールを生成します。"""
# 顧客情報を取得
customer_docs = retrieve_customer_info(customer_name)
if not customer_docs:
return {"error": f"{customer_name}の顧客データが見つかりません"}
# 取得したコンテキストを結合
context = "\n".join([doc.page_content for doc in customer_docs])
# より良い指示に従ってメールを生成
prompt = f"""あなたは営業担当者です。メールを書いてください。
最も重要なこと: 以下のユーザー指示に正確に従ってください:
{user_instructions}
顧客コンテキスト(指示に関連するもののみ使用してください):
{context}
ガイドライン:
1. ユーザー指示を最優先にしてください
2. メールは簡潔に - ユーザーのリクエストに直接関連する情報のみを含めてください
3. 具体的で実行可能な次のステップを明確なタイムラインと共にメールの最後に記載してください(例:「金曜日までに価格をフォローアップします」や「今週15分の電話をスケジュールしましょう」)
4. ユーザーの指示に直接関連する場合のみ顧客情報を参照してください
ユーザーの正確なリクエストを満たす簡潔で焦点を絞ったメールを書いてください。"""
response = client.chat.completions.create(
model="databricks-meta-llama-3-3-70b-instruct",
messages=[
{
"role": "system",
"content": "あなたは簡潔で指示に焦点を当てたメールを書く役立つ営業アシスタントです。",
},
{"role": "user", "content": prompt},
],
max_tokens=2000,
)
return {"email": response.choices[0].message.content}
# アプリケーションをテスト
result = generate_sales_email_v2("Acme Corp", "製品デモの後にフォローアップしてください")
print(result["email"])
Subject: 製品デモのフォローアップ
アリスさん
月曜日に製品デモを行った後、ご関心を示していたエンタープライズ機能についてお話しする機会をいただきありがとうございました。このメールでは、ご質問いただいた高度な分析、リアルタイムダッシュボード、API統合、カスタムレポート、マルチユーザーサポート、SSO認証、データエクスポート機能、500人以上のユーザー向けの価格設定についてフォローアップを行いたいと思います。
これらの機能について、より深く掘り下げてお話しする機会をいただけないでしょうか。特に、API統合とカスタムレポートの実装についてご質問いただいていたことを覚えています。
今週の水曜日、15分の電話を設定しましょう。アカウントマネージャーのサラジョンソンにご連絡ください。彼女がスケジュールを調整してくれます。
お忙しい中大変恐縮ですが、ご返信を待っております。
ベストレギャーズ、
\[あなたの名前]
初期バージョンに比べて丁寧な内容になっていますね。
新しいバージョンを評価する
同じスコアラーとデータセットを使用して改善されたバージョンで評価を実行し、問題に対処したかどうかを確認しましょう。
import mlflow
# 新しいバージョンの評価を、以前と同じスコアラーを使用して実行します
# start_runを使用してUIで評価ランを名前付けします
with mlflow.start_run(run_name="v2"):
eval_results_v2 = mlflow.genai.evaluate(
data=eval_dataset, # 同じデータセット
predict_fn=generate_sales_email_v2, # 新しいアプリバージョンの関数
scorers=email_scorers, # 前回と同じスコアラーを利用
)
結果を比較する
結果を比較して、変更によって品質が向上したかどうかを確認します。
MLflow UIからも確認できますが、まずはコードで結果を取得して比較します。
import pandas as pd
# mlflow.search_runsはINやOR演算子をサポートしていないため、個別にランを取得
run_v1_df = mlflow.search_runs(filter_string=f"run_id = '{eval_results.run_id}'")
run_v2_df = mlflow.search_runs(filter_string=f"run_id = '{eval_results_v2.run_id}'")
# メトリクス列を抽出(.aggregate_scoreではなく/meanで終わるもの)
# 品質比較のため、エージェント系メトリクス(latency, token counts)は除外
metric_cols = [
col
for col in run_v1_df.columns
if col.startswith("metrics.") and col.endswith("/mean") and "agent/" not in col
]
# 比較テーブルを作成
comparison_data = []
for metric in metric_cols:
metric_name = metric.replace("metrics.", "").replace("/mean", "")
v1_score = run_v1_df[metric].iloc[0]
v2_score = run_v2_df[metric].iloc[0]
improvement = v2_score - v1_score
comparison_data.append(
{
"Metric": metric_name,
"V1 Score": f"{v1_score:.3f}",
"V2 Score": f"{v2_score:.3f}",
"Improvement": f"{improvement:+.3f}",
"Improved": "✓" if improvement >= 0 else "✗",
}
)
comparison_df = pd.DataFrame(comparison_data)
print("\n=== バージョン比較結果 ===")
print(comparison_df.to_string(index=False))
# 全体の平均改善度を計算(品質メトリクスのみ対象)
avg_v1 = run_v1_df[metric_cols].mean(axis=1).iloc[0]
avg_v2 = run_v2_df[metric_cols].mean(axis=1).iloc[0]
print(
f"\n全体平均の改善度: {(avg_v2 - avg_v1):+.3f} ({((avg_v2/avg_v1 - 1) * 100):+.1f}%)"
)
=== Version Comparison Results ===
Metric V1 Score V2 Score Improvement Improved
professional_tone 1.000 1.000 +0.000 ✓
follows_instructions 0.667 0.600 -0.067 ✗
includes_next_steps 0.000 0.800 +0.800 ✓
mentions_contact_name 1.000 1.000 +0.000 ✓
retrieval_groundedness 1.000 0.600 -0.400 ✗
concise_communication 0.333 0.600 +0.267 ✓
relevance_to_query 0.833 1.000 +0.167 ✓
Overall average improvement: +0.110 (+15.9%)
改善しなかった項目もありますが、全体としては改善されました。
(retrieval_groundednessが下がっているのはおかしいのですが。。。)
次に、評価メトリクスがリグレッション(後退)した具体的な例を探して、それらに焦点を当てることができます。
import pandas as pd
# 両バージョンの詳細なトレースを取得
traces_v1 = mlflow.search_traces(run_id=eval_results.run_id)
traces_v2 = mlflow.search_traces(run_id=eval_results_v2.run_id)
# 入力パラメータに基づいてマージキーを作成
traces_v1['merge_key'] = traces_v1['request'].apply(
lambda x: f"{x.get('customer_name', '')}|{x.get('user_instructions', '')}"
)
traces_v2['merge_key'] = traces_v2['request'].apply(
lambda x: f"{x.get('customer_name', '')}|{x.get('user_instructions', '')}"
)
# 同じ入力データでマージして比較
merged = traces_v1.merge(
traces_v2,
on='merge_key',
suffixes=('_v1', '_v2')
)
print(f"v1とv2の間で{len(merged)}の一致する例が見つかりました")
# 特定のメトリクスが改善しなかった例を見つける
regression_examples = []
for idx, row in merged.iterrows():
v1_assessments = {a.name: a for a in row['assessments_v1']}
v2_assessments = {a.name: a for a in row['assessments_v2']}
# 各スコアラーについてリグレッションをチェック
for scorer_name in ['follows_instructions', 'concise_communication', 'includes_next_steps', 'retrieval_groundedness']:
v1_assessment = v1_assessments.get(scorer_name)
v2_assessment = v2_assessments.get(scorer_name)
if v1_assessment and v2_assessment:
v1_val = v1_assessment.feedback.value
v2_val = v2_assessment.feedback.value
# メトリクスが悪化したかどうかをチェック(yes -> no)
if v1_val == 'yes' and v2_val == 'no':
regression_examples.append({
'index': idx,
'customer': row['request_v1']['customer_name'],
'instructions': row['request_v1']['user_instructions'],
'metric': scorer_name,
'v1_score': v1_val,
'v2_score': v2_val,
'v1_rationale': v1_assessment.rationale,
'v2_rationale': v2_assessment.rationale,
'v1_response': row['response_v1']['email'],
'v2_response': row['response_v2']['email']
})
# リグレッションの例を表示
if regression_examples:
print(f"\n=== {len(regression_examples)}のメトリクスリグレッションが見つかりました ===\n")
# メトリクスごとにグループ化
by_metric = {}
for ex in regression_examples:
metric = ex['metric']
if metric not in by_metric:
by_metric[metric] = []
by_metric[metric].append(ex)
# リグレッションが発生したメトリクスごとの例を表示
for metric, examples in by_metric.items():
print(f"\n{'='*80}")
print(f"メトリクスリグレッション: {metric}")
print(f"{'='*80}")
# このメトリクスの最初の例を表示
ex = examples[0]
print(f"\n顧客: {ex['customer']}")
print(f"指示: {ex['instructions']}")
print(f"\nV1スコア: ✓ (合格)")
print(f"V1理由: {ex['v1_rationale']}")
print(f"\nV2スコア: ✗ (不合格)")
print(f"V2理由: {ex['v2_rationale']}")
if len(examples) > 1:
print(f"\n(+{len(examples)-1}の例が{metric}リグレッションを含む)")
else:
print("\n✓ メトリクスリグレッションは見つかりませんでした - V2はすべてのメトリクスを改善または維持しました!")
v1とv2の間で7の一致する例が見つかりました
=== 3のメトリクスリグレッションが見つかりました ===
================================================================================
メトリクスリグレッション: follows_instructions
================================================================================
顧客: Global Retail
指示: 四半期レビューの要約を送信
V1スコア: ✓ (合格)
V1理由: The user instruction was to send a summary of the quarterly review. The response provided is a follow-up email template that includes a brief summary of the meeting points discussed during the quarterly review. Therefore, the response adheres to the user instructions provided in the request.
V2スコア: ✗ (不合格)
V2理由: The user instruction was to send a summary of the quarterly review. The response includes an email that mentions a follow-up from a meeting and highlights satisfaction with the platform's performance during the quarterly review. However, it does not provide a clear summary of the quarterly review itself. Instead, it mentions a follow-up on pricing and does not focus on summarizing the review content. Therefore, the response does not fully adhere to the user instructions.
================================================================================
メトリクスリグレッション: concise_communication
================================================================================
顧客: Global Retail
指示: 四半期レビューの要約を送信
V1スコア: ✓ (合格)
V1理由: The response provides a follow-up email that includes a subject line, a greeting, a brief mention of the previous meeting, and a summary of the key points discussed. It also offers further assistance and closes with a polite sign-off. The email is concise and covers the main points without unnecessary details, thus effectively communicating the essential information.
V2スコア: ✗ (不合格)
V2理由: The response is not concise and does not effectively summarize the quarterly review. It includes unnecessary details such as the follow-up on pricing and the mention of satisfaction with platform performance, which are not directly related to the request for a summary of the quarterly review. Therefore, it does not satisfy the guideline of being concise and focused on the main message.
================================================================================
メトリクスリグレッション: retrieval_groundedness
================================================================================
顧客: Global Retail
指示: 四半期レビューの要約を送信
V1スコア: ✓ (合格)
V1理由: The response includes a follow-up email template that mentions a recent quarterly review meeting, satisfaction with platform performance, and a summary of discussed points. The retrieved context confirms a recent quarterly review meeting where platform performance was discussed and satisfaction was expressed. It also mentions the contact person as キャロル・ワン and the account manager as サラ・ジョンソン, which matches the names in the response. Therefore, all parts of the response are supported by the retrieved context.
V2スコア: ✗ (不合格)
V2理由: The response mentions an email from サラ・ジョンソン summarizing a quarterly review and highlighting satisfaction with platform performance. The retrieved context confirms that there was a recent quarterly review and that there was satisfaction with the platform's performance. The response also mentions キャロル following up on pricing by Friday, which is not mentioned in the retrieved context. Therefore, the part about キャロル following up on pricing is not supported by the retrieved context.
ちなみにMLflow UIからも同様の詳細を確認することができます。
イテレーションの継続
評価結果に基づいて、アプリケーションの品質を向上させ、実装する新しい修正ごとにテストするための反復を続けることができます。
まとめ
MLflow3の評価をアプリの改善イテレーションで試用しました。
プロダクトライフサイクルの中では評価をいかに早く・的確に回すか、ということが非常に大事だと思います。Mosaic AI AgentFrameworkで出来たことも多いですが、MLflowに統合されたことで非常に使い勝手が上がったように感じます。
特に評価データセットをトレースから作成・リンクできるのは便利です。(前からできたっけ)
個人的には評価のスコアラーをUnity Catalogで管理できるとさらに便利だと思うんですよね。対応してくれないでしょうか。。。>Databricks社のみなさま
評価とセットで利用するであろうモニタリングに関する機能も学んでいきたいと思います。