メインコンテンツまでスキップ

チュートリアル: GenAI アプリケーションの評価と改善

このチュートリアルでは、評価データセットを使用して品質を評価し、問題を特定し、生成AIアプリケーションを反復的に改善する方法を示します。

このガイドでは、検索拡張生成 (RAG) を使用する電子メール生成アプリを評価する手順を説明します。 このアプリは、データベースから顧客情報を取得することをシミュレートし、取得した情報に基づいてパーソナライズされたフォローアップ電子メールを生成します。

評価の簡単な紹介については、 「10 分間のデモ: GenAI アプリを評価する」をご覧ください。

このチュートリアルには次のステップが含まれています。

  • 実際の使用データから評価データセットを作成します。
  • 評価ハーネス を使用して、MLflow のLLM ジャッジ で品質を評価します。
  • 結果を解釈して、品質の問題を特定します。
  • 評価結果に基づいてアプリを改善します。
  • バージョンを比較して、改善が機能し、回帰が発生しなかったことを確認します。

このチュートリアルでは、デプロイされたアプリからのトレースを使用して評価データセットを作成しますが、評価データセットをどのように作成したかに関係なく、同じワークフローが適用されます。評価データセットを作成するその他のアプローチについては、 MLflow評価データセットの構築」を参照してください。 トレースの詳細については、 MLflow Tracing - GenAI の可観測性」を参照してください。

オフラインモニタリングのワークフロー図

前提 条件

  1. 必要なパッケージをインストールします。

    Python
    %pip install -q --upgrade "mlflow[databricks]>=3.1.0" openai
    dbutils.library.restartPython()
  2. MLflowエクスペリメントを作成します。 Databricksノートブックを使用している場合は、このステップをスキップして、デフォルトのノートブック体験を使用できます。 それ以外の場合は、環境設定のクイックスタートに従ってエクスペリメントを作成し、 MLflowトラッキング サーバーに接続します。

  3. 評価データセットを作成するには、Unity Catalog 内のスキーマに対するCREATE TABLE権限が必要です。

    Databricks 試用アカウントを使用している場合は、Unity Catalog スキーマworkspace.defaultに対する CREATE TABLE 権限が必要です。

注記

複雑なエージェントの実行には長い時間がかかる場合があります。並列化を構成するには、 「(オプション) 並列化を構成する」を参照してください。

ステップ 1: アプリケーションを作成する

最初のステップは、電子メール生成アプリを作成することです。 検索コンポーネントは、MLflow の検索固有の LLM ジャッジを有効にするためにspan_type="RETRIEVER"でマークされています。

  1. OpenAI クライアントを初期化して、Databricks でホストされている LLM または OpenAI でホストされている LLM に接続します。

databricks-openaiを使用して、Databricks がホストする LLM に接続する OpenAI クライアントを取得します。利用可能なプラットフォームモデルからモデルを選択します。

Python
import mlflow
from databricks_openai import DatabricksOpenAI

# Enable MLflow's autologging to instrument your application with Tracing
mlflow.openai.autolog()

# Set up MLflow tracking to Databricks
mlflow.set_tracking_uri("databricks")
mlflow.set_experiment("/Shared/docs-demo")

# Create an OpenAI client that is connected to Databricks-hosted LLMs
client = DatabricksOpenAI()

# Select an LLM
model_name = "databricks-claude-sonnet-4"
  1. Eメール生成アプリを作成します。

    Python
    from mlflow.entities import Document
    from typing import List, Dict

    # Simulated customer relationship management database
    CRM_DATA = {
    "Acme Corp": {
    "contact_name": "Alice Chen",
    "recent_meeting": "Product demo on Monday, very interested in enterprise features. They asked about: advanced analytics, real-time dashboards, API integrations, custom reporting, multi-user support, SSO authentication, data export capabilities, and pricing for 500+ users",
    "support_tickets": ["Ticket #123: API latency issue (resolved last week)", "Ticket #124: Feature request for bulk import", "Ticket #125: Question about GDPR compliance"],
    "account_manager": "Sarah Johnson"
    },
    "TechStart": {
    "contact_name": "Bob Martinez",
    "recent_meeting": "Initial sales call last Thursday, requested pricing",
    "support_tickets": ["Ticket #456: Login issues (open - critical)", "Ticket #457: Performance degradation reported", "Ticket #458: Integration failing with their CRM"],
    "account_manager": "Mike Thompson"
    },
    "Global Retail": {
    "contact_name": "Carol Wang",
    "recent_meeting": "Quarterly review yesterday, happy with platform performance",
    "support_tickets": [],
    "account_manager": "Sarah Johnson"
    }
    }

    # Use a retriever span to enable MLflow's predefined RetrievalGroundedness judge to work
    @mlflow.trace(span_type="RETRIEVER")
    def retrieve_customer_info(customer_name: str) -> List[Document]:
    """Retrieve customer information from CRM database"""
    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]:
    """Generate personalized sales email based on customer data & a sale's rep's instructions."""
    # Retrieve customer information
    customer_docs = retrieve_customer_info(customer_name)

    # Combine retrieved context
    context = "\n".join([doc.page_content for doc in customer_docs])

    # Generate email using retrieved context
    prompt = f"""You are a sales representative. Based on the customer information below,
    write a brief follow-up email that addresses their request.

    Customer Information:
    {context}

    User instructions: {user_instructions}

    Keep the email concise and personalized."""

    response = client.chat.completions.create(
    model=model_name, # This example uses a Databricks hosted LLM - you can replace this with any AI Gateway or Model Serving endpoint. If you provide your own OpenAI credentials, replace with a valid OpenAI model e.g., gpt-4o, etc.
    messages=[
    {"role": "system", "content": "You are a helpful sales assistant."},
    {"role": "user", "content": prompt}
    ],
    max_tokens=2000
    )

    return {"email": response.choices[0].message.content}

    # Test the application
    result = generate_sales_email("Acme Corp", "Follow up after product demo")
    print(result["email"])

評価アプリ トレース

ステップ 2: 本番運用のトラフィックをシミュレートする

このステップでは、デモンストレーションの目的でトラフィックをシミュレートします。実際には、実際の使用状況からのトレースを活用して評価データセットを作成します。

Python
# Simulate beta testing traffic with scenarios designed to fail guidelines
test_requests = [
{"customer_name": "Acme Corp", "user_instructions": "Follow up after product demo"},
{"customer_name": "TechStart", "user_instructions": "Check on support ticket status"},
{"customer_name": "Global Retail", "user_instructions": "Send quarterly review summary"},
{"customer_name": "Acme Corp", "user_instructions": "Write a very detailed email explaining all our product features, pricing tiers, implementation timeline, and support options"},
{"customer_name": "TechStart", "user_instructions": "Send an enthusiastic thank you for their business!"},
{"customer_name": "Global Retail", "user_instructions": "Send a follow-up email"},
{"customer_name": "Acme Corp", "user_instructions": "Just check in to see how things are going"},
]

# Run requests and capture traces
print("Simulating production traffic...")
for req in test_requests:
try:
result = generate_sales_email(**req)
print(f"✓ Generated email for {req['customer_name']}")
except Exception as e:
print(f"✗ Error for {req['customer_name']}: {e}")

ステップ 3: 評価データセットを作成する

このステップでは、トレースを評価データセットに保存します。トレースを評価データセットに保存すると、評価結果をデータセットにリンクできるため、データセットの変更を時間の経過とともに追跡し、このデータセットを使用して生成されたすべての評価結果を確認できます。

  1. サイドバーの 「体験」 をクリックして「体験」ページを表示します。

  2. 体験の名前をクリックして開きます。

    オープンエクスペリメント

  3. 左側のサイドバーで、 [Traces] をクリックします。

  4. トレース リストの左側にあるチェック ボックスを使用して、追加するトレースを選択します。現在のページのすべてのトレースを選択するには、列ヘッダーの トレース ID の横にあるチェックボックスをクリックします。

    トレースを選択する

  5. [アクション] をクリックします。ボタンのラベルには、選択されたトレースの数が表示されます (例: Actions (3) )

    アクションメニュー

  6. [評価に使用] の下で、 [評価データセットに追加] を選択します。 「評価データセットにトレースを追加」 ダイアログが開きます。

  7. このエクスペリメントの評価データセットが存在しない場合、または新しいデータセットにトレースを追加したい場合は、次のステップに従って新しい評価データセットを作成します。

    1. [新しいデータセットの作成] をクリックします。
    2. 新しいデータセットを保持するUnity Catalogスキーマを選択します。
    3. データセットの名前を入力し、 「データセットの作成」を クリックします。
    4. [エクスポート] をクリックし、 [完了] をクリックします。

    評価データセットが存在しない場合はトレースダイアログを追加

    エクスペリメントの評価データセットがすでに存在する場合は、トレースを追加するデータセットの右側にある [エクスポート] をクリックします。 複数のデータセットにエクスポートできます。エクスポートが完了したら、 「完了」 をクリックします。

    既存の評価データセットがある場合はトレースダイアログを追加

ステップ 4: LLMジャッジによる実行評価

このステップでは、MLflow の組み込み LLM ジャッジを使用して、GenAI アプリの品質のさまざまな側面を自動的に評価します。詳細については、 「LLM 審査員コードベースの採点者」を参照してください。

Python
from mlflow.genai.scorers import (
RetrievalGroundedness,
RelevanceToQuery,
Safety,
Guidelines,
)

# Save the LLM judges as a variable so you can re-use them in step 7

email_judges = [
RetrievalGroundedness(), # Checks if email content is grounded in retrieved data
Guidelines(
name="follows_instructions",
guidelines="The generated email must follow the user_instructions in the request.",
),
Guidelines(
name="concise_communication",
guidelines="The email MUST be concise and to the point. The email should communicate the key message efficiently without being overly brief or losing important context.",
),
Guidelines(
name="mentions_contact_name",
guidelines="The email MUST explicitly mention the customer contact's first name (e.g., Alice, Bob, Carol) in the greeting. Generic greetings like 'Hello' or 'Dear Customer' are not acceptable.",
),
Guidelines(
name="professional_tone",
guidelines="The email must be in a professional tone.",
),
Guidelines(
name="includes_next_steps",
guidelines="The email MUST end with a specific, actionable next step that includes a concrete timeline.",
),
RelevanceToQuery(), # Checks if email addresses the user's request
Safety(), # Checks for harmful or inappropriate content
]

# Run evaluation with LLM judges
eval_results = mlflow.genai.evaluate(
data=eval_dataset,
predict_fn=generate_sales_email,
scorers=email_judges,
)

ステップ 5: 結果の表示と解釈

mlflow.genai.evaluate()を実行すると評価実行が作成されます。詳細については、 「評価実行」を参照してください。

評価実行は、特定のデータセットに対するアプリのパフォーマンスに関するすべての情報を記録するテスト レポートのようなものです。評価実行には、各審査員からのフィードバックが注釈として付けられた評価データセットの各行のトレースが含まれます。

評価ランを使用すると、集計メトリクスを表示し、アプリのパフォーマンスが低下したテスト ケースを調査できます。

この評価ではいくつかの問題が示されています。

  • 不適切な指示フォロー - エージェントは、簡単なチェックインを求められたときに詳細な製品情報を送信したり、熱心なお礼のメッセージを求められたときにサポートチケットの更新を提供したりするなど、ユーザーの要求と一致しない応答を頻繁に提供します。
  • 簡潔さの欠如 - ほとんどのEメールは不必要に長く、重要なメッセージを薄めるほどの詳細が多すぎて、Eメールを「簡潔でパーソナライズ」に保つように指示されているにもかかわらず、効率的にコミュニケーションをとることができません。
  • 具体的な次のステップが欠けている - Eメールの大部分は、必須要素として特定された具体的なタイムラインを含む、具体的で実行可能な次のステップで終わらない。

評価概要

  1. サイドバーの 「体験」 をクリックして「体験」ページを表示します。

  2. 体験の名前をクリックして開きます。

  3. 左側のサイドバーで、 [評価実行] をクリックします。右側のペインにはトレースのテーブルが表示されます。

    評価実行表

    合格不合格の ラベルが付いた評価が表示されない場合は、右にスクロールするか、ペインの区切りにマウスを移動して左向きの矢印をクリックします。

    テーブルを展開

  4. 合格 または 不合格の ラベルの根拠を確認するには、ラベルの上にマウスを置きます。

    ラベルの上にマウスを移動すると根拠が表示されます

詳細とフィードバックの追加

各トレースの詳細を表示するには:

  1. 「リクエスト」 列のリクエスト ID をクリックします。各ステップの入力と出力を含む完全なトレースを表示するウィンドウが表示されます。

    リクエストの詳細ウィンドウ

  2. 右側では、このリクエストへの応答に適用するフィードバックまたは期待を追加できます。評価パネルが表示されない場合は、評価ボタン 。新しい評価を追加するには、下にスクロールしてクリックします。新しい評価を追加ボタン

  3. このウィンドウの両側にある矢印を使って、リクエストを順に処理できます。

    矢印を使用してリクエストをステップ実行する

ステップ 6: 改良版を作成する

評価結果を使用して、特定された問題に対処する改善バージョンを作成します。

改良版を作成する際には、評価結果に基づいて対象となる変更に重点を置きます。一般的な改善戦略は次のとおりです。

  • プロンプト エンジニアリング: 特定の障害パターンに対処したり、エッジ ケースに関する明示的なガイドラインを追加したり、正しい処理を示す例を含めたり、トーンやスタイルを調整したりするためにシステム プロンプトを調整します。
  • ガードレール: アプリケーション ロジックに検証ステップを実装し、ユーザーに提示する前に出力をチェックする後処理を追加します。
  • 改善点 (RAG アプリの場合): 検索範囲を調べたり、埋め込みモデルを改善したり、チャンク化戦略を改良したりして、関連するドキュメントが見つからない場合の検索メカニズムを強化します。
  • 推論の強化: 複雑なタスクを複数のスパンに分割したり、思考連鎖テクニックを実装したり、重要な出力に検証ステップを追加したりできます。

以下のコードは、評価結果に基づいた迅速なエンジニアリングの改善を示しています。

Python
@mlflow.trace
def generate_sales_email_v2(customer_name: str, user_instructions: str) -> Dict[str, str]:
"""Generate personalized sales email based on customer data & a sale's rep's instructions."""
# Retrieve customer information
customer_docs = retrieve_customer_info(customer_name) # retrive_customer_info is defined in Step 1

if not customer_docs:
return {"error": f"No customer data found for {customer_name}"}

# Combine retrieved context
context = "\n".join([doc.page_content for doc in customer_docs])

# Generate email using retrieved context with better instruction following
prompt = f"""You are a sales representative writing an email.

MOST IMPORTANT: Follow these specific user instructions exactly:
{user_instructions}

Customer context (only use what's relevant to the instructions):
{context}

Guidelines:
1. PRIORITIZE the user instructions above all else
2. Keep the email CONCISE - only include information directly relevant to the user's request
3. End with a specific, actionable next step that includes a concrete timeline (e.g., "I'll follow up with pricing by Friday" or "Let's schedule a 15-minute call this week")
4. Only reference customer information if it's directly relevant to the user's instructions

Write a brief, focused email that satisfies the user's exact request."""

response = client.chat.completions.create(
model="databricks-claude-sonnet-4-5",
messages=[
{"role": "system", "content": "You are a helpful sales assistant who writes concise, instruction-focused emails."},
{"role": "user", "content": prompt}
],
max_tokens=2000
)

return {"email": response.choices[0].message.content}

# Test the application
result = generate_sales_email("Acme Corp", "Follow up after product demo")
print(result["email"])

ステップ 7: 新しいバージョンを評価して比較する

同じジャッジとデータセットを使用して改善されたバージョンの評価を実行し、問題が正常に解決されたかどうかを確認します。

Python
import mlflow

# Run evaluation of the new version with the same judges as before
# Use start_run to name the evaluation run in the UI
with mlflow.start_run(run_name="v2"):
eval_results_v2 = mlflow.genai.evaluate(
data=eval_dataset, # same eval dataset
predict_fn=generate_sales_email_v2, # new app version
scorers=email_judges, # same judges as step 4
)

ステップ 8: 結果を比較する

結果を比較して、変更によって品質が向上したかどうかを確認します。

  1. サイドバーの 「体験」 をクリックして「体験」ページを表示します。

  2. 体験の名前をクリックして開きます。

  3. 左側のサイドバーで、 [評価実行] をクリックします。左側のペインには、このエクスペリメントの評価実行のリストが表示されます。

    実行ペイン

  4. 比較したい実行のボックスをチェックします。

  5. [アクション] ドロップダウン メニューから、 [比較] を選択します。

    比較する実行を選択

  6. 右側のペインには、選択した実行における各トレースの比較が表示されます。

    トレース比較画面

  7. 詳細については、 「リクエスト」 列のリクエスト ID をクリックしてください。比較のために選択された各実行からのリクエストの完全なトレースを表示するウィンドウが表示されます。

    比較詳細ウィンドウ

    各評価の詳細を表示するには、 「詳細を表示」 をクリックします。トレースの詳細を表示するには、 [詳細なトレース ビューを表示] をクリックします。

ステップ 9: 反復を続ける

評価結果に基づいて、アプリケーションの品質を向上させ、新しい修正をそれぞれテストするために反復を続行できます。

ノートブックの例

次のノートブックには、このページのすべてのコードが含まれています。

GenAI アプリの評価クイックスタートノートブック

ノートブックを新しいタブで開く

次のステップ

リファレンスガイド